font: Default to light hinting in FreeType (#9253)

This changes the default FreeType load target to `FT_LOAD_TARGET_LIGHT`,
giving the hinter a lighter touch in line with the default behavior in
most other GTK apps, and adds a load flag such that the old hinting
behavior can be restored via config.

As discussed in
https://github.com/ghostty-org/ghostty/issues/8674#issuecomment-3417082534.
However, this doesn't close that issue, as it still doesn't respect
custom Fontconfig settings. It's just a stopgap solution bringing
Ghostty's defaults more in line with the typical results of not
customizing Fontconfig.
pull/9256/head
Mitchell Hashimoto 2025-10-17 17:14:57 -07:00 committed by GitHub
commit e4db7f5487
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 2 deletions

View File

@ -476,6 +476,11 @@ pub const compatibility = std.StaticStringMap(
/// ///
/// * `autohint` - Enable the freetype auto-hinter. Enabled by default. /// * `autohint` - Enable the freetype auto-hinter. Enabled by default.
/// ///
/// * `light` - Use a light hinting style, better preserving glyph shapes.
/// This is the most common setting in GTK apps and therefore also Ghostty's
/// default. This has no effect if `monochrome` is enabled. Enabled by
/// default.
///
/// Example: `hinting`, `no-hinting`, `force-autohint`, `no-force-autohint` /// Example: `hinting`, `no-hinting`, `force-autohint`, `no-force-autohint`
@"freetype-load-flags": FreetypeLoadFlags = .{}, @"freetype-load-flags": FreetypeLoadFlags = .{},
@ -7886,11 +7891,15 @@ pub const BackgroundImageFit = enum {
pub const FreetypeLoadFlags = packed struct { pub const FreetypeLoadFlags = packed struct {
// The defaults here at the time of writing this match the defaults // The defaults here at the time of writing this match the defaults
// for Freetype itself. Ghostty hasn't made any opinionated changes // for Freetype itself. Ghostty hasn't made any opinionated changes
// to these defaults. // to these defaults. (Strictly speaking, `light` isn't FreeType's
// own default, but appears to be the effective default with most
// Fontconfig-aware software using FreeType, so until Ghostty
// implements Fontconfig support we default to `light`.)
hinting: bool = true, hinting: bool = true,
@"force-autohint": bool = false, @"force-autohint": bool = false,
monochrome: bool = false, monochrome: bool = false,
autohint: bool = true, autohint: bool = true,
light: bool = true,
}; };
/// See linux-cgroup /// See linux-cgroup

View File

@ -378,6 +378,10 @@ pub const Face = struct {
// else it won't look very good at all. // else it won't look very good at all.
.target_mono = self.load_flags.monochrome, .target_mono = self.load_flags.monochrome,
// Otherwise we select hinter based on the `light` flag.
.target_normal = !self.load_flags.light and !self.load_flags.monochrome,
.target_light = self.load_flags.light and !self.load_flags.monochrome,
// NO_SVG set to true because we don't currently support rendering // NO_SVG set to true because we don't currently support rendering
// SVG glyphs under FreeType, since that requires bundling another // SVG glyphs under FreeType, since that requires bundling another
// dependency to handle rendering the SVG. // dependency to handle rendering the SVG.
@ -1143,7 +1147,7 @@ test {
ft_font.glyphIndex('A').?, ft_font.glyphIndex('A').?,
.{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) }, .{ .grid_metrics = font.Metrics.calc(ft_font.getMetrics()) },
); );
try testing.expectEqual(@as(u32, 20), g2.height); try testing.expectEqual(@as(u32, 21), g2.height);
} }
} }