patchFontLineMetrics function
bytes with the ascent and descent centred on the font's Latin ink.
Flutter places the baseline at the font's ascent, so a font with spare
room for another script sits off-centre when TextStyle.height shrinks its
line: the cut is split evenly, but the spare room is not. This is the
equivalent of CSS ascent-override and descent-override.
The new line box is lineHeightForFontFamily at clearance, centred on
the ink: half the space above the highest letter, half below the lowest.
Text with no TextStyle.height gets that line height. A different
TextStyle.height keeps the letters centred, with even leading.
Rewrites hhea (ascender, descender, lineGap), and OS/2 (typo and win
metrics), so every platform reads the same values. Recomputes the
checksums. Returns bytes if the font has no Latin ink data, or is not a
TrueType or OpenType file.
Implementation
ByteData patchFontLineMetrics(
ByteData bytes,
String fontFamily, {
double clearance = kLineHeightClearance,
}) {
final ink = latinInkForFontFamily(fontFamily);
final height = lineHeightForFontFamily(fontFamily, clearance: clearance);
if (ink == null || height == null) return bytes;
final pad = (height - ink.$1 - ink.$2) / 2;
return patchFontAscentDescent(bytes, ink.$1 + pad, ink.$2 + pad);
}