kyamagu / skia-python

Python binding to Skia Graphics Library
https://kyamagu.github.io/skia-python/
BSD 3-Clause "New" or "Revised" License
246 stars 43 forks source link

Different behaviour on macOS and Linux platforms #271

Closed olebedev closed 1 month ago

olebedev commented 1 month ago

Describe the bug

On Linux, some fonts somehow became narrower, please find images attached below. For macOS the total width of the text below is 382.12890625 while for linux total width is 375.0. The same codebase produces two different results.

Platform Output
macOS macos
Linux linux

Expected behavior I expect Skia to be reproducible across platforms.

Desktop (please complete the following information):

For the context

I am not sure if this can affect the result, but I gave it a try since I could do that by myself first.

I had a chat with colleagues and they told me that they change build instructions of Skia to make the font rendering aligned with chromium on linux, so I made the same change in my fork of skia-python here https://github.com/olebedev/skia-python/pull/1. However, after testing I haven'd found any difference.

Any ideas on how we can make it behave similarly would be greatly appreciated!

olebedev commented 1 month ago

I found what was the problem after playing with configuration of a font. After setting this:

font.setLinearMetrics(True)

I started seeing consistent results across these two platforms.

It's interesting that defaults are different for both platforms though 🤔 . It's not related to this issue, but I also found that skia-python is capable to load .woff2 on macOS while on Linux it fails to do so.

It would be awesome to have sort of a single-pager that explains the differences between platforms so people like myself don't spend hours on debugging things that are already well known. :)

HinTak commented 1 month ago

Upgrade to m120 or above. If you want more or less identical result between mac os x and Linux, use the New_Custom_Empty: https://github.com/kyamagu/skia-python/blob/main/relnotes/README.m120.md

The problem with woff2 on Linux with m87 is likely we used to use the host freetype on the very old build host, which was 2014 I think! Now we use freetype fork from skia repo, which is a lot more up to date.

Just use m130, with or without New_Custom_Empty , should fix all of your font related problems.

HinTak commented 1 month ago

Upstream documentation on setLinearMetric: https://api.skia.org/classSkFont.html#a372d51cca2d6104e911d467aad4903a9 that pretty much explains it - Mac OS's CoreText doesn't hint, but relies on the much higher res display to do fractional scaling. FreeType does hint by default (glyphs are snapped to pixel grid), so that option basically turns FreeType to behave more like CoreText.

You'll find setHinting(None) alone more or less achieve setLinearMetric true, I believe.

M87 uses the build host's freetype, which is close to a decade old. Not surprised that it does not support woff2, which is within the last decade, I think!

HinTak commented 1 month ago

Hinting on, means each glyph will try to align with pixel grid. For 25 glyphs (as in your phrase), each glyph could differ in width by approx 1/2 pixel up or down. That means the whole thing can differ by about 12.5 pixels, so 7 pixels is about right.

You see 382.12890625 is fractional, while 375.0 is whole number.

HinTak commented 1 month ago

The "High-DPI displays" section of https://en.wikipedia.org/wiki/Font_hinting mentions that Apple's rendering ignore hinting completely. This is about as explicitly I can find quickly. (Microsoft is somewhat between the two, closer to FreeType, I think)

olebedev commented 1 month ago

👋 Hey @HinTak,

Thank you so much for so many useful tips and tricks! Greatly appreciated!

HinTak commented 1 month ago

Hinting itself is a fairly large topic; MS owns a few patents for two decades, the last of which only expired a few years ago. Before that, FreeType wasn't allowed to implement some of the ideas, so the difference between the renderers are fairly often discussed among the FreeType community. (And that Apple does not hint on their high res display). Adobe has their own secret sauce, and trademark "CoolType", on this.

@olebedev if you use skia-python at work or for some production use, please consider sponsor/donate, at my profile link, so we could move towards a proper release soon.

olebedev commented 1 month ago

Absolutely. As I mentioned earlier in the other conversation, once we have an open-source sponsorship planning going I will put you in the list!

And thanks again for your help.

Kind regards, Oleg

HinTak commented 1 month ago

@olebedev argh, it has been a while - m130 is out, with the skparagraph binding, so that's another reason for you to upgrade 😉. I think #269 is possibly a blocking task before a proper release - a fair number of static(?) effect filters in m87 were withdrawn upstream, because they are thought to be better done with runtime filters and shader code. If you use filter effect heavily, that might be a consideration. I just looked up what @Canva is - you should definitely try to persuade them to sponsor the work!

HinTak commented 1 month ago

@olebedev I think there are still two sizeable areas between m87 and m1xx (as in things in m87 got "missing" in m1xx, and things that can be done in m87 aren't possible in m1xxx) - one of which is a few effect filters.

HinTak commented 1 month ago

@olebedev the withdrawn image filters are marked skip... in the test files, such as this line https://github.com/kyamagu/skia-python/blob/57e705cccaeaf943bba5d3d561d8d38dda4b4e1b/tests/test_imagefilter.py#L89 - in case you want to know whether you are affected. (And greb for skip in that directory, especially when it says REVISIT.