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) <noreply@anthropic.com>
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

+4
View File
@@ -54,6 +54,10 @@ rustc-hash = "2"
sha2 = "0.10"
fontdb = "0.23"
ttf-parser = "0.25"
# TrueType 指令解譯器:標楷體/細明體等「筆畫拼字」字型要先 hinting 才有正確輪廓。
# TrueType interpreter for hint-reliant ("tricky") fonts such as DFKai-SB and
# MingLiU, whose raw outlines are missing strokes. Already in the tree (hayro).
skrifa = "0.42.1"
cosmic-text = "0.15"
unicode-bidi = "0.3"
lyon_tessellation = "1.0.20"