From c7d6227befef09a607b4b1c3858902c3a02eaf85 Mon Sep 17 00:00:00 2001 From: Qwerasd Date: Mon, 23 Sep 2024 19:18:44 -0600 Subject: [PATCH] freetype: improve strikethrough position guess by using ex height --- src/font/face/freetype.zig | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/font/face/freetype.zig b/src/font/face/freetype.zig index 5004a040a..04f037c85 100644 --- a/src/font/face/freetype.zig +++ b/src/font/face/freetype.zig @@ -607,6 +607,20 @@ pub const Face = struct { break :cell_width f26dot6ToFloat(size_metrics.max_advance); }; + // Ex height is calculated by measuring the height of the `x` glyph. + // If that fails then we just pretend it's 65% of the ascent height. + const ex_height: f32 = ex_height: { + if (face.getCharIndex('x')) |glyph_index| { + if (face.loadGlyph(glyph_index, .{ .render = true })) { + break :ex_height f26dot6ToFloat(face.handle.*.glyph.*.metrics.height); + } else |_| { + // Ignore the error since we just fall back to 65% of the ascent below + } + } + + break :ex_height f26dot6ToFloat(size_metrics.ascender) * 0.65; + }; + // Cell height is calculated as the maximum of multiple things in order // to handle edge cases in fonts: (1) the height as reported in metadata // by the font designer (2) the maximum glyph height as measured in the @@ -689,7 +703,9 @@ pub const Face = struct { }, .thickness = @max(@as(f32, 1), fontUnitsToPxY(face, os2.yStrikeoutSize)), } else .{ - .pos = cell_baseline * 0.6, + // Exactly 50% of the ex height so that our strikethrough is + // centered through lowercase text. This is a common choice. + .pos = cell_baseline - ex_height * 0.5 + 1, .thickness = underline_thickness, };