font: FreeType backend should respect fontconfig's aa/hinting and fontfeatures options
Opened this issue · 7 comments
Right now we have our own opinionated load flag defaults for FreeType which may conflict with what the user expects due to the implicit defaults under fontconfig or their explicitly adjusted font settings on their system.
We need to respect these flags unless explicitly overridden by the user's Ghostty config (freetype-load-flags):
antialiashintstylehintingautohint
We should also make sure we're querying these per-font not just the global settings, since it is possible with fontconfig to adjust these per-font.
ref:
- https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-user.html
- https://fontconfig.pages.freedesktop.org/fontconfig/fontconfig-devel/
P.S. Do we even need freetype-load-flags if we respect the system configuration? Something to think about, since it feels like that config was really just added as a workaround for this issue.
Addendum
We should also support the fontfeatures key, see #8017
P.S. Do we even need freetype-load-flags if we respect the system configuration? Something to think about, since it feels like that config was really just added as a workaround for this issue.
Probably not. But I don't see a downside in letting people toy around with these flags. It can help debug things in situations like this too.
Depending on the magnitude of the change, I'm willing to accept this as a backport into 1.2.x.
As mentioned in #8125, ghostty also completely ignores the font families themselves too.
My local configuration sets Noto Sans Mono CJK SC as my default monospaced font and Twemoji as my default emoji font, but ghostty ignored both of these Fontconfig settings.
That is a separate question, ultimately. I think it probably is a good idea to use those defaults if they're configured, but that's a distinct change from these which apply to how we load fonts, not which fonts we load.
Shall I open a separate issue to track that instead? Or can we include that within scope for this issue?
I'm not really sure it makes any sense to respect the local antialias/hintstyle/hinting/autohint configuration but ignore the configured font-family itself.
I dug into Fontconfig and FreeType config in response to a Discord question, and found that
- Many (most?) distros set the default Fontconfig hintstyle to
hintslight(to check, see if/etc/fonts/conf.d/10-hinting-slight.confexists) - Pango, and hence a lot of the GNOME and GTK ecosystem, map both
hintslightandhintmediumto FreeType'sFT_LOAD_TARGET_LIGHTand has done so since 2007 (see GNOME/pango@217f405, though be warned, this is GPL).
Thus, users are very likely used to fonts being rendered with LIGHT hinting. Meanwhile, Ghostty always uses NORMAL hinting unless the monochrome flag is set. This explains the OP screenshot in #8671.
I've confirmed that when compiling Ghostty with the load target set to LIGHT, I get pixel identical rendering between Ghostty and Ptyxis, whereas by default, Ghostty's rendering can be almost uncomfortably sharp, especially for horizontal lines like hyphens and underscores.
I think there are three takeaways here:
-
There's not a 1-1 correspondence between Fontconfig options and FreeType flags. Even if we read the Fontconfig system/user configuration, we need to make choices about how to map it to FreeType.
-
The precedent set by distros and GNOME/GTK/Pango is to err on the side of lighter hinting, both by setting the default hintstyle to
hintslight, and by mapping bothhintslightandhintmediumto FreeType's LIGHT hinting. -
One could argue from this that, until Ghostty implements Fontconfig support, we should consider switching to
FT_LOAD_TARGET_LIGHTas the hardcoded choice if we don't want to be too opinionated. Any viewpoints on this?Proposed patch:
diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 4958c48c8..fe4b610f6 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -378,6 +378,10 @@ pub const Face = struct { // else it won't look very good at all. .target_mono = self.load_flags.monochrome, + // Otherwise, we should actually use light hinting, not + // normal. This is the norm on Linux these days. + .target_light = !self.load_flags.monochrome, + // NO_SVG set to true because we don't currently support rendering // SVG glyphs under FreeType, since that requires bundling another // dependency to handle rendering the SVG.
Thanks for the analysis.
One could argue from this that, until Ghostty implements Fontconfig support, we should consider switching to FT_LOAD_TARGET_LIGHT as the hardcoded choice if we don't want to be too opinionated. Any viewpoints on this?
Instead of your proposed patch, it'd probably be cleaner to introduce light as a new FreetypeLoadFlag in the config and default that to true. This would let users get the old behavior very easily by simply doing freetype-load-flags = no-light
I'd be open to this given the justification that exists out here.