The dates don't match since the change is from 4 months ago and 23.04 was released on April. So it was some other change.
Em ter., 12 de dez. de 2023 13:03, Thiago Milczarek Sayão < thiago.sa...@gmail.com> escreveu: > Fonts started to look better on Ubuntu 23.04 > > https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6190 > > May be related to this change. > > Em ter., 12 de dez. de 2023 11:10, Mark Raynsford <org.open...@io7m.com> > escreveu: > >> Hello! >> >> I've never been particularly satisfied with the font rendering in >> JavaFX. In particular, on Linux, the text always appears very soft and >> blurry compared to non-JavaFX applications on the same system. Even >> applications that render antialiased text with Java2D seem to look >> better. >> >> I decided to take a look into it to see if anything could be done about >> this, and I have some questions. I'm only looking at the Freetype >> implementation in Prism currently, as that's all I can realistically >> test on at the moment. >> >> For reference, here's how text rendered at 16px using Terminus TTF >> looks today: >> >> https://ataxia.io7m.com/2023/12/12/hinting_nobitmaps_normal.png >> >> I'm not sure if I'm alone on this, but I find this almost migraine- >> inducing. No other application on my system, including those that use >> Freetype, using that font at that size will render as blurry as that. >> >> Looking at >> modules/javafx.graphics/src/main/java/com/sun/javafx/font/freetype/FTFo >> ntFile.java, I see this in initGlyph(): >> >> ``` >> int flags = OSFreetype.FT_LOAD_RENDER | OSFreetype.FT_LOAD_NO_HINTING | >> OSFreetype.FT_LOAD_NO_BITMAP; >> ``` >> >> Additionally, the code might also add the FT_LOAD_TARGET_NORMAL >> or FT_LOAD_TARGET_LCD flags later, but I'll assume >> FT_LOAD_TARGET_NORMAL for the sake of avoiding combinatorial explosions >> in testing at this point. >> >> Essentially, we discard hinting information, and we discard bitmap >> information. I'm not sure why we do either of these things. I decided >> to try different combinations of flags to see what would happen. >> >> Here's FT_LOAD_RENDER | FT_LOAD_NO_BITMAP (no bitmaps, but using >> hinting data): >> >> https://ataxia.io7m.com/2023/12/12/hinting_nobitmaps_normal.png >> >> That's no real improvement. Here's FT_LOAD_RENDER | FT_LOAD_NO_HINTING >> (ignore hinting data, but use bitmaps if they are included): >> >> https://ataxia.io7m.com/2023/12/12/nohinting_bitmaps_normal.png >> >> That, to my poor suffering eyes, is already a _vast_ improvement. >> >> Let's try including both hinting and bitmaps (FT_LOAD_RENDER): >> >> https://ataxia.io7m.com/2023/12/12/hinting_bitmaps_normal.png >> >> Inspecting that in an image editor shows the pixels of the text to be >> identical. >> >> So, clearly, Terminus TTF includes bitmaps for smaller text sizes. >> Let's try another font such as Droid Sans that renders crisply at ~10pt >> sizes on my system, and that I'm reasonably confident doesn't include >> any bitmaps. >> >> Here's the JavaFX default (FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP): >> >> https://ataxia.io7m.com/2023/12/12/droid_12_nohinting_nobitmaps.png >> >> That's pretty nasty. Let's enable hinting (FT_LOAD_NO_BITMAP): >> >> https://ataxia.io7m.com/2023/12/12/droid_12_hinting_nobitmaps.png >> >> That's already a lot better. If you overlay the two images in an image >> editor, it's clear that the glyph shapes are not quite the same (with >> hinting, some glyphs are ever-so-slightly taller). >> >> For completeness, let's allow bitmaps: >> >> https://ataxia.io7m.com/2023/12/12/droid_12_hinting_bitmaps.png >> >> The rendered glyphs are pixel-identical. >> >> Now, most modern desktops have options to disable antialiasing for text >> under a given size. Antialiasing on 10pt text is rarely an improvement >> over just not having it as there are so few pixels to work with. I >> decided to experiment a bit with turning off antialiasing. This >> requires setting the load target to FT_LOAD_TARGET_MONO so that >> Freetype returns a monochrome image instead of what amounts to an alpha >> coverage map. Unfortunately, this does also change the format of the >> image returned to a 1bpp image instead of an 8bpp greyscale image, and >> JavaFX isn't equipped to handle that. However, we can do the conversion >> manually if we see that bitmap.pixel_mode == 1, and then the rest of >> JavaFX doesn't need to care about it: >> >> ``` >> if (bitmap.pixel_mode == 1) { >> byte[] newBuffer = new byte[width * height]; >> for (int y = 0; y < height; y++) { >> final var rowOffset = y * width; >> for (int x = 0; x < width; x++) { >> final var byteOffset = rowOffset + x; >> newBuffer[byteOffset] = bitAt(buffer, x, y, pitch); >> } >> } >> buffer = newBuffer; >> } >> >> private static byte bitAt(byte[] buffer, int x, int y, int pitch) >> { >> final var byteOffset = (y * pitch) + (x / 8); >> final var bitOffset = 7 - (x % 8); >> final var bit = (buffer[byteOffset] >>> bitOffset) & 1; >> return (byte) (bit == 1 ? 0xff : 0x00); >> } >> ``` >> >> Here's the JavaFX default of (FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP) >> combined with FT_LOAD_TARGET_MONO: >> >> https://ataxia.io7m.com/2023/12/12/droid_12_nohinting_nobitmaps_mono.png >> >> That's not a typeface even a mother could love. :) >> >> However, what happens if we enable hinting? >> >> Here's (FT_LOAD_NO_BITMAP | FT_LOAD_TARGET_MONO): >> >> https://ataxia.io7m.com/2023/12/12/droid_12_hinting_nobitmaps_mono.png >> >> I mean, it's not exactly wonderful for Droid Sans 12 (the O is a little >> mangled), but that's more an issue with the font itself. It's certainly >> better than the result _without_ hinting. >> >> Amusingly, here's DejaVu Sans at 7pt, (FT_LOAD_NO_BITMAP | >> FT_LOAD_TARGET_MONO): >> >> https://ataxia.io7m.com/2023/12/12/dejavu_12_hinting_nobitmaps_mono.png >> >> That, to my eyes, looks pretty good. The JavaFX defaults for the same >> font are not good: >> >> >> https://ataxia.io7m.com/2023/12/12/dejavu_12_nohinting_nobitmaps_normal.png >> >> I've tried on multiple systems (all Linux, however), and I've yet to be >> able to contrive a situation where the JavaFX defaults give better >> rendering results with any combinations of font sizes, with or without >> AA. A brief inspection of the JDK's Java2D sources show that it does >> conditionally use FT_LOAD_NO_HINTING depending on various settings >> (there are comments about FT_LOAD_NO_HINTING yielding constant-sized >> glyphs, which supposedly can make things easier in some cases). The >> Java2D results on the systems I tested are consistently better. >> >> So I guess my questions are: >> >> * Why do we discard hinting information? >> * Why do we discard bitmaps? >> * Would JavaFX accept patches to allow hinting, bitmaps, and >> FT_LOAD_TARGET_MONO? Ideally this should be developer-controlled, so I >> would need to come up with a pleasant API for it. >> >> My experience has been that most JavaFX applications tend to bundle >> fonts rather than relying on anything the system has. I suspect that, >> given that developers are including their own fonts, they are the best >> equipped to answer questions about hinting and AA, rather than just >> setting values and hoping that the font they get will work well, so an >> explicit API might be fine. >> >> -- >> Mark Raynsford | https://www.io7m.com >> >>