Skip to content

fix: remove erroneous GSUB substitutions from halt/palt/vhal/vpal (kanji switching to Chinese glyphs)#12

Draft
halken wants to merge 2 commits into
mainfrom
fix/halt-palt-remove-gsub-kanji-subs
Draft

fix: remove erroneous GSUB substitutions from halt/palt/vhal/vpal (kanji switching to Chinese glyphs)#12
halken wants to merge 2 commits into
mainfrom
fix/halt-palt-remove-gsub-kanji-subs

Conversation

@halken

@halken halken commented Jul 3, 2026

Copy link
Copy Markdown

Summary

Enabling halt (Alternate Half Widths) or palt (Proportional Alternate Widths) in Figma or via CSS font-feature-settings unexpectedly switched some Japanese kanji to Chinese (traditional) glyph forms (e.g. 亜→亞, 医→醫, 円→圓, 辺→邊).

Root cause: halt/palt — and their vertical counterparts vhal/vpal — were defined as GSUB substitution lookups instead of GPOS metric adjustments.
Each contained hundreds of ideograph substitutions copied from the traditional-forms (trad), JIS78/JIS90 (jp78/jp04) and vertical (vert/vrt2) features, so a feature meant only to adjust glyph width also changed the glyph shape.

The defect has existed since the initial import of the Glyphs source and affects all four weights (Thin / Regular / Bold / ExtraBold).

Changes

  • Clear the substitution code from halt, palt, vhal and vpal in all four fontinfo.plist sources so these features no longer substitute glyphs.
  • No other features are touched. Glyph-form switching remains fully available through the dedicated trad, jp78 and jp04 features.
Feature Before (subs) After (subs)
halt 784 0
palt 237 0
vhal 808 0
vpal 410 0

Verification

  • hb-shape: with halt=1 / palt=1, kanji glyphs no longer change; with trad=1, traditional-form conversion still works as expected.
  • GSUB: halt/palt/vhal/vpal substitution counts are 0 in all weights;
    trad (309) and jp78 (299) are preserved.
  • fontspector (googlefonts profile): results are identical before and after (PASS 313 / WARN 98 / FAIL 25 / ERROR 4) — no new failures introduced. The remaining FAIL/ERROR items are pre-existing (naming, versioning, metrics, vert+vrt2 coexistence) and unrelated to this change.

Notes

  • This change only stops the incorrect glyph substitution. Implementing proper half-/proportional-width GPOS metrics for halt/palt is out of scope and can be done in a follow-up.
  • Build tip: gftools builder caches LINESeedJP/sources/instance_ufos/.
    Remove that directory (and build.stamp) before rebuilding, otherwise source changes to feature code may not be reflected in the output fonts.

The `halt` (Alternate Half Widths) and `palt` (Proportional Alternate
Widths) features—together with their vertical counterparts `vhal` and
`vpal`—were defined as GSUB substitution lookups instead of GPOS metric
adjustments. These lookups contained hundreds of ideograph substitutions
copied from the traditional-forms (`trad`), JIS78/JIS90 (`jp78`/`jp04`)
and vertical (`vert`/`vrt2`) features, including many Japanese
shinjitai-to-traditional conversions (e.g. 亜→亞, 医→醫, 円→圓).

As a result, enabling `halt`/`palt` for width adjustment in Figma or via
CSS `font-feature-settings` unexpectedly switched Japanese kanji to
Chinese (traditional) glyph forms.

This defect was present from the initial import of the Glyphs source and
affects all four weights (Thin/Regular/Bold/ExtraBold).

Fix: clear the substitution code from `halt`/`palt`/`vhal`/`vpal` in all
four `fontinfo.plist` sources so these features no longer alter glyphs.
Glyph-form switching remains available through the dedicated `trad`,
`jp78` and `jp04` features, which are left untouched.

Verification:
- hb-shape: `halt=1`/`palt=1` no longer change kanji glyphs; `trad=1`
  still converts to traditional forms.
- GSUB: halt/palt/vhal/vpal substitution counts are 0 in all weights;
  trad (309) and jp78 (299) are preserved.
- fontspector (googlefonts profile): identical results before and after
  (PASS 313 / WARN 98 / FAIL 25 / ERROR 4); no new failures introduced.

Note: this change only stops the incorrect glyph substitution. Proper
half-/proportional-width GPOS metrics for halt/palt are out of scope and
can be added separately.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The build job only uploads the github-pages artifact on the main
branch, but the deploy job ran unconditionally. On PR branches the
deploy job tried to deploy a non-existent artifact and failed. Add
the same main-branch guard to the deploy job so it is skipped on
non-main branches.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant