diff --git a/src/skia/Font.cpp b/src/skia/Font.cpp index 307ff100..de7cb024 100644 --- a/src/skia/Font.cpp +++ b/src/skia/Font.cpp @@ -54,7 +54,9 @@ sk_sp SkFontMgr_RefDefault() { using Axis = SkFontParameters::Variation::Axis; using Coordinate = SkFontArguments::VariationPosition::Coordinate; +using Override = SkFontArguments::Palette::Override; PYBIND11_MAKE_OPAQUE(std::vector); +PYBIND11_MAKE_OPAQUE(std::vector); namespace { @@ -65,6 +67,12 @@ void SetVariationPositionCoordinates( vp.coordinateCount = coords.size(); } +void SetPaletteOverrides( + SkFontArguments::Palette& palette, + const std::vector& overrides) { + palette.overrides = overrides.empty() ? nullptr : &overrides[0]; + palette.overrideCount = overrides.size(); +} py::tuple SkFontStyleSet_getStyle(SkFontStyleSet* self, int index) { SkFontStyle style; @@ -342,6 +350,59 @@ variationposition &SkFontArguments::VariationPosition::coordinateCount) ; +py::class_ palette( + fontarguments, "Palette", + R"docstring( + A a palette to use and overrides for palette entries. + )docstring"); + +py::class_(palette, "Override") + .def(py::init( + [] (uint16_t index, SkColor color) { + return Override({index, color}); + }), + py::arg("index"), py::arg("color")) + .def("__repr__", + [] (const Override& self) { + return py::str("Override(index={}, color={})").format( + self.index, self.color); + }) + .def_readwrite("index", &Override::index) + .def_readwrite("color", &Override::color) + ; + +py::bind_vector>(palette, "Overrides"); + +palette + .def(py::init( + [] (int index, const std::vector& overrides) { + SkFontArguments::Palette palette; + palette.index = index; + SetPaletteOverrides(palette, overrides); + return palette; + }), + py::keep_alive<1, 3>(), + py::arg("index"), py::arg("overrides")) + .def(py::init( + [] (int index) { + return SkFontArguments::Palette({index, nullptr, 0}); + }), + py::arg("index")) + .def("__repr__", + [] (const SkFontArguments::Palette& self) { + return py::str("Palette(index={}, overrideCount={})").format( + self.index, self.overrideCount); + }) + .def_property("overrides", + [] (const SkFontArguments::Palette& self) { + return std::vector( + self.overrides, self.overrides + self.overrideCount); + }, + &SetPaletteOverrides) + .def_readwrite("index", &SkFontArguments::Palette::index) + .def_readonly("overrideCount", &SkFontArguments::Palette::overrideCount) + ; + fontarguments .def(py::init<>()) .def("setCollectionIndex", &SkFontArguments::setCollectionIndex, @@ -352,6 +413,19 @@ fontarguments actually be indexed collections of fonts. )docstring", py::arg("collectionIndex")) + .def("setPalette", &SkFontArguments::setPalette, + R"docstring( + Specify a palette to use and overrides for palette entries. + )docstring", + py::arg("palette")) + .def("setPalette", + [](SkFontArguments& self, int index) { + return self.setPalette(SkFontArguments::Palette({index, nullptr, 0})); + }, + R"docstring( + Specify a palette index to use. + )docstring", + py::arg("index")) .def("setVariationDesignPosition", &SkFontArguments::setVariationDesignPosition, R"docstring( @@ -365,6 +439,7 @@ fontarguments )docstring", py::arg("position")) .def("getCollectionIndex", &SkFontArguments::getCollectionIndex) + .def("getPalette", &SkFontArguments::getPalette) .def("getVariationDesignPosition", &SkFontArguments::getVariationDesignPosition) ; diff --git a/tests/test_font.py b/tests/test_font.py index 8e1d78e5..a58214c6 100644 --- a/tests/test_font.py +++ b/tests/test_font.py @@ -46,6 +46,44 @@ def test_FontArguments_setCollectionIndex(fontarguments): fontarguments.setCollectionIndex(0) +@pytest.mark.parametrize( + "index, overrides", + [ + (0, [(0, skia.ColorBLACK), (1, skia.ColorRED), (5, skia.ColorBLUE)]), + (1, []), + (2, None), + ], +) +def test_FontArguments_setPalette(fontarguments, index, overrides): + if overrides is None: + palette = skia.FontArguments.Palette(index) + else: + palette = skia.FontArguments.Palette( + index, + skia.FontArguments.Palette.Overrides( + [ + skia.FontArguments.Palette.Override(*override) + for override in overrides + ] + ), + ) + + len_overrides = len(overrides) if overrides is not None else 0 + assert palette.index == index + assert len(palette.overrides) == len_overrides + assert palette.overrideCount == len_overrides + assert repr(palette) == f"Palette(index={index}, overrideCount={len_overrides})" + for i, override in enumerate(palette.overrides): + assert repr(override) == f"Override(index={override.index}, color={override.color})" + assert override.index == overrides[i][0] + assert override.color == overrides[i][1] + fontarguments.setPalette(palette) + + +def test_FontArguments_setPalette_Index(fontarguments): + fontarguments.setPalette(1) + + def test_FontArguments_setVariationDesignPosition(fontarguments): coordinates = skia.FontArguments.VariationPosition.Coordinates([ skia.FontArguments.VariationPosition.Coordinate(0x00, 0.), @@ -58,6 +96,10 @@ def test_FontArguments_getCollectionIndex(fontarguments): assert isinstance(fontarguments.getCollectionIndex(), int) +def test_FontArguments_getPalette(fontarguments): + assert isinstance(fontarguments.getPalette(), skia.FontArguments.Palette) + + def test_FontArguments_getVariationDesignPosition(fontarguments): assert isinstance( fontarguments.getVariationDesignPosition(),