slint
slint copied to clipboard
Subpixel font rendering
No renderer I tried (at least software, FemtoVG and Skia) rendered text on Windows 10 with ClearType, that is, utilizing the R, G, B hardware subpixels of the monitor. I have it turned on in my system (confirmed by screenshots with orange and blue sides on letters) and @tronical called the way Skia renders text the one and true way of doing it in another issue. ChatGPT with GPT-4o claimed that Skia is able to render using ClearType, but the text rendered with it in my Slint window only uses shades of gray.
same as me, i think anti-aliasing is broken with FemtoVG and winit-skia backend, for both win and linux. But winit-software and qt backend have normal smoothing, you can try
$env:SLINT_BACKEND='winit-software'; cargo run --release
I think that's a valid bug report. If I understand correctly, we're not setting the lcd config on the skia surface, and we should probably also set SK_FONT_HOST_USE_SYSTEM_SETTINGS when compiling skia to read the correct gramma correction values from the system.
You added issue labels specifying this as a Windows bug. But I have no idea whether it works on the other OSs. macOS has subpixel font antialiasing; and with Linux, there are apparently also ways to render text like this.
It's true that while macOS does support sub pixel anti-aliasing, it's not enabled by default. That said, AFAICS Skia uses glyphs rendered by CoreText that are LCD optimised.
On Linux, I don't see Skia supporting LCD filtering, i.e. I don't see it forwarding any filter setting to FreeType.
Setting the LCD config on the skia surface is a cross-platform matter, but we need to find a way to get the correct setting there. Unless... there isn't a way and we should just set it to kRGB_H_SkPixelGeometry?
If, after using Skia in a way that activates ClearType, ClearType in Slint windows can't be deactivated anymore by changing the system setting, Slint should read the system setting SPI_GETFONTSMOOTHINGTYPE (there's also the ClearType-related SPI_GETFONTSMOOTHINGORIENTATION and SPI_GETFONTSMOOTHINGCONTRAST), and possibly also SPI_GETFONTSMOOTHING. It would need to be tested how Slint behaves after the change.
Bump. Fonts look ugly for me on macOS.
I'm also running into this issue on linux, where qt and winit-software look good but winit does not:
As a disclaimer though, I'm on NixOS and might not have everything set up correctly.
As a complete guess, it looks like what could be happening is that the font glyphs are being rendered to a cache okay, but then shifted a half-pixel over and being drawn wrong as a result.
Okay, I've narrowed this down to a femtovg issue https://github.com/femtovg/femtovg/issues/233.
Things improve significantly if I just pass a scale of DPI 1 to femtovg. So something in that library is going wrong:
diff --git a/internal/renderers/femtovg/lib.rs b/internal/renderers/femtovg/lib.rs
index fc57c05e0..e157cfa1d 100644
--- a/internal/renderers/femtovg/lib.rs
+++ b/internal/renderers/femtovg/lib.rs
@@ -154,7 +154,7 @@ fn internal_render_with_post_callback(
// We pass an integer that is greater than or equal to the scale factor as
// dpi / device pixel ratio as the anti-alias of femtovg needs that to draw text clearly.
// We need to care about that `ceil()` when calculating metrics.
- femtovg_canvas.set_size(surface_size.width, surface_size.height, scale);
+ femtovg_canvas.set_size(surface_size.width, surface_size.height, 1.0);
// Clear with window background if it is a solid color otherwise it will drawn as gradient
if let Some(Brush::SolidColor(clear_color)) = window_background_brush {
In terms of subpixel font rendering specifically, it's something that can be looked into. But keep in mind that a significant issue is that different monitors use different subpixel arrangements, and there's no way to query that easily. So a type of subpixel rendering that great on one monitor might look worse than no subpixel rendering on another. https://osor.io/text goes into this.