Skip to content

Select ZHS or ZHT from a Chinese script subtag, ZHS for zh alone, and ZHTM then ZHH for Macao (#201) - #220

Merged
jakejackson1 merged 6 commits into
gravitypdffrom
recover/201-chinese-script-subtags
Sep 17, 2026
Merged

jakejackson1 merged 6 commits into
gravitypdffrom
recover/201-chinese-script-subtags

Conversation

@jakejackson1

Copy link
Copy Markdown
Member

Closes #201.

This carries PR #207's change to gravitypdf. #207 was merged into its stacked base branch after that branch had already been squash-merged into gravitypdf, so its commits never reached gravitypdf and #201 stayed open. The commits are #207's own, replayed with git rebase --onto and patch-for-patch identical per git range-diff. See #207 for the full description, measurements and review.

This branch also contains the #192 and #191 recovery PRs, and is merged after them.

🤖 Generated with Claude Code

jakejackson1 and others added 6 commits September 17, 2026 12:48
OtlTags::script() walked the v2-to-original table from the run's own
entry to the end, so a v2 tag the font did not offer reached the
original tag of every script listed after it: Bengali was laid out with
a font's deva lookups and the original specification's reordering, but
Devanagari never reached beng. HarfBuzz asks for dev3, dev2 and deva for
Devanagari (hb_ot_all_tags_from_script) and then DFLT, dflt and latn
(hb_ot_layout_table_select_script), never another script's tag. The
walk is now one lookup of the run's own original tag.

NotoSansBengali-DevaScript-Synthetic makes it visible: a subset of Noto
Sans Bengali with its GSUB replaced by a DFLT and a deva script, each
with a 'locl' lookup giving KA a different glyph. KA drew deva's KHA; it
now draws DFLT's GA, as hb-shape does.

One existing fixture moves. NotoSansGurmukhiUI-GPOS71-Subset offers
only gur2 and guru, so the golden master's Devanagari and Bengali runs
used to reach guru and be reordered to the original specification. They
now find no script and are left unshaped, as a run is in any font with
no entry for its script. The font has no glyph for either run.

Test font: NotoSansBengali-DevaScript-Synthetic (Noto Sans Bengali
3.011, OFL 1.1), built in fontTools 4.59.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… what they cover (#192)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

OtlTags::language() fell back from the language subtag to the language
and region run together, 'zhhk', but the only region keys in
Ucdn::$ot_languages are written with a hyphen, 'zh-hk'. The branch could
never match, so zh-HK, zh-TW, zh-MO, zh-CN and zh-SG all laid text out
with the script's DFLT entry. It now joins them with the hyphen.

No font in tests/data/ttf or packages/ has a Chinese language system.
NotoSansTC-RegionLangSys-Synthetic is a subset of Noto Sans TC whose
GSUB offers hani with a 'locl' lookup under each of ZHH, ZHS and ZHT,
giving the same character a different glyph under each. For every row
of the issue's table and zh-Hant-HK, mPDF now draws the glyph
hb-shape --language draws. No existing fixture moves: the golden
masters set no language.

HarfBuzz also reads the script subtag, takes ZHS for bare zh, and
ZHTM then ZHH for Macao. That is #201, and OtlTagsTest pins zh, zh-Hant
and zh-Hans as they stand.

Test font: NotoSansTC-RegionLangSys-Synthetic (Noto Sans TC 2.004, OFL
1.1), built in fontTools 4.59.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
)

OtlTagsTest covers every row of the issue's table; the shaping test
needs only show that each of ZHH, ZHS and ZHT reaches GSUB.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… ZHTM then ZHH for Macao (#201)

OtlTags::language() read the language subtag, then the language and
region. Nothing mapped a script subtag and bare zh had no key, so zh,
zh-Hans and zh-Hant laid text out with the script's DFLT entry, and a
script that disagreed with its region took the region's tag: zh-Hans-HK
got ZHH, zh-Hant-CN got ZHS. Macao got ZHT.

Chinese now follows HarfBuzz 14.3.1's hb_ot_tags_from_complex_language():
Traditional in Hong Kong or Macao keeps the region's tag, then Hans is
ZHS and Hant is ZHT whatever the region, then a hk, mo or tw subtag
gives ZHH, ZHTM then ZHH, or ZHT, and anything else is ZHS. language()
tries each candidate against the script in turn, so its return value and
Otl.php are unchanged.

zh on its own now selects ZHS where a font offers it. No font in
tests/data/ttf or packages/ has a Chinese language system other than the
synthetic test fonts, and no golden master or snapshot sets lang="zh".

NotoSansTC-MacaoLangSys-Synthetic is #191's font with 四 under a fourth
language system, ZHTM. For every case in ChineseLangSysTest mPDF draws
the glyph hb-shape --language draws.

Test font: NotoSansTC-MacaoLangSys-Synthetic (Noto Sans TC 2.004, OFL
1.1), built in fontTools 4.59.2.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… one place (#201)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@jakejackson1 jakejackson1 added bug Something isn't working create-upstream-pr labels Sep 17, 2026
@jakejackson1
jakejackson1 merged commit 91feb69 into gravitypdf Sep 17, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working create-upstream-pr

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A Chinese script subtag never selects ZHS or ZHT, and bare zh and zh-MO pick different language systems from HarfBuzz

1 participant