-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support SkFontArguments::Palette #297
Conversation
I have let CI started, but I wish you have got in touch earlier, as I have already got some of this overlapping in my hard disk already. See #259 |
@khaledhosny ci failed on mac os (which has python 3.13.1). You need to pull in the fix for #295 , which is #296 , to pass ci. |
FWIW, even namespacing these classes under |
I’m not sure I get the namespacing comments. The classes are already nested in Python, |
0441314
to
3bab798
Compare
This #298 isn't how it is on my hard disk (I have neighbouring code with does something else, so there are collisions while cherry-picking), nor ready for used or tested, but I think if it works, together with your pull, should mostly just be the other half of allowing one to address #259 , loading COLRv1 fonts with custom / non-default palettes. |
With the two together, you should be able to do something like this to load a colrv1 font with custom palette:
|
With this PR I can already select non-default palettes and override their colors in COLR (v0 and v1) fonts, but I’m testing only with FreeType fonts: fontMgr = skia.FontMgr.New_Custom_Empty()
face1 = fontMgr.makeFromFile(fontpath)
font1 = skia.Font(face, face.getUnitsPerEm())
fontArgs2 = skia.FontArguments()
fontArgs2.setPalette(1)
face2 = face1.makeClone(fontArgs2)
font2 = skia.Font(face2, size)
fontArgs3 = skia.FontArguments()
palette3 = skia.FontArguments.Palette(
1,
skia.FontArguments.Palette.Overrides(
[
skia.FontArguments.Palette.Override(0, skia.ColorMAGENTA),
skia.FontArguments.Palette.Override(6, skia.ColorBLUE),
skia.FontArguments.Palette.Override(7, skia.ColorGREEN),
skia.FontArguments.Palette.Override(8, skia.ColorCYAN),
]
),
)
fontArgs3.setPalette(palette3)
face3 = face1.makeClone(fontArgs3)
font3 = skia.Font(face3, size)
string = "\u06DD"
text1 = skia.TextBlob.MakeFromShapedText(string, font1)
text2 = skia.TextBlob.MakeFromShapedText(string, font2)
text3 = skia.TextBlob.MakeFromShapedText(string, font3)
bounds = text.bounds()
width = math.floor(bounds.width() * 3)
height = math.floor(bounds.height())
surface = skia.Surface(width, height)
with surface as canvas:
canvas.drawColor(skia.ColorWHITE)
paint = skia.Paint()
canvas.drawTextBlob(text1, -bounds.x(), -bounds.y(), paint)
canvas.drawTextBlob(text2, bounds.width() - bounds.x(), -bounds.y(), paint)
canvas.drawTextBlob(text3, bounds.width() * 2 - bounds.x(), -bounds.y(), paint) |
Interesting. Thanks for the code - some of it can go into the tests directory. (skia's resources/fonts/ is available for tests). FWIW, I have some incomplete code which supposedly let you do |
If the asserts are not logically independent I.e. you just want an exact match of a composite structure, it might be clearer to do |
I think |
|
See for example the fixture at skia-python/tests/test_paragraph.py Line 12 in db7d7fc
|
And all the fxtures finally get passed to the usage test at skia-python/tests/test_paragraph.py Line 45 in db7d7fc
|
To allow selecting color fonts palette.
3bab798
to
6e18951
Compare
That would be nice, but testing palette overrides will requiring checking the rendered output (possibly against a reference image), but I don’t see any tests doing something like this. |
Well, setting and getting it back should work. It is probably possible to render to a surface and detect it is "mostly red", say, just by count the red pixels. I have a test in the paragraph part, which used to have trouble with rendering "\n" as a new line rather than .notdef. The test is simply that the rendered area should be tall than wide, whichever the default font is. |
@@ -46,6 +46,44 @@ def test_FontArguments_setCollectionIndex(fontarguments): | |||
fontarguments.setCollectionIndex(0) | |||
|
|||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there needs to be a dozen more tests for each of the new properties/methods of the new classes added.
return std::vector<Override>( | ||
self.overrides, self.overrides + self.overrideCount); | ||
}, | ||
&SetPaletteOverrides) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't you need a keep_Alive policy here too? On the set method.
I am starting to see the variationposition code from which this modelled from a bit buggy about life times and zero length arguments... |
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})" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would probably not have a repr test - since the __repr__
method itself is somewhat a personal choice and subjected to changes later too.
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})" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto on testing the precise form of repr
outcome.
Specify a palette to use and overrides for palette entries. | ||
)docstring", | ||
py::arg("palette")) | ||
.def("setPalette", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some setPaletteIndex/getPaletteIndex
methods in other classes. Perhaps do both?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also wonder whether this should be a read/write property instead.
You added 3 classes, so there should be 3 init tests, in addition to the class method tests... |
self.overrides, self.overrides + self.overrideCount); | ||
}, | ||
&SetPaletteOverrides) | ||
.def_readwrite("index", &SkFontArguments::Palette::index) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PaletteIndex
might be a better choice of name, given font argument might have other indices.
I have had a better look at the example code. I think this pull is substantially incomplete (in addition to all the detailed comments so far) - to be of any use to somebody who isn't the font author, it really needs the So this is not going to be merged without substantially additional work. |
I see your example must have used one of your own authored arabic fonts (Amiri Quran?). That's fair enough, but an example with one of the English fonts would be preferred; as well as some tests with the font files in skia/resources/fonts/ . I"d have preferred that this stays open until you or somebody else improves on it. Nevermind. |
To allow selecting color fonts palette.