fix(text): hint TrueType fonts that need the interpreter (DFKai-SB, MingLiU) before outlining

DFKai-SB (kaiu.ttf), MingLiU and other early DynaLab fonts assemble each
ideograph from stroke components that only the TrueType instructions move
into place. ttf-parser's `outline_glyph` returns the raw, unhinted `glyf`
outline, so these fonts rendered with missing or displaced strokes
('自' drawn as '目'; 範, 直, 啟, 動 broken). FreeType calls them "tricky"
and always runs the interpreter for them.

Every non-test `outline_glyph` call site in ttf_glyph.rs (`glyph`,
`outline_char` - shared by both native fallback paths -, the web
`build_fallback`, and both `build_shaped` variants) now goes through
`outline_glyph_into`; `outline_char` takes the font data and face index
for that. When skrifa's `require_interpreter()` says the face
is hint-reliant, the glyph is hinted with the TrueType interpreter
(Target::Mono) at 512 ppem and scaled back to font units (x upem / 512);
every other font keeps the exact ttf-parser outline. The decision and the
HintingInstance are cached once per face, keyed by (byte length, face
index, head.checkSumAdjustment) because fontdb may hand out a new buffer
per call. The hinted path is recorded first and replayed only on success,
so a failed draw falls back to ttf-parser without a half-drawn glyph.

skrifa 0.42.1 is already in the lockfile (via hayro / glifo).

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
Chris YehandClaude Opus 5.5 committed 2026-09-27 21:44:52 +08:00
1 parent 78c9128a69
commit 5a36ecda74
3 files changed
+373 -10

No files matched your search

Generated
+1
View File
@@ -59,6 +59,7 @@ dependencies = [
"serde",
"serde_json",
"sha2 0.10.9",
"skrifa 0.42.1",
"ttf-parser",
"unicode-bidi",
"ureq",