Repository navigation
Harfbuzz 14.5 and Unicode 18 - #300
Open
benoitkugler wants to merge 35 commits into
Open
benoitkugler wants to merge 35 commits into
benoitkugler wants to merge 35 commits into
Conversation
A zero-valued PairPos record can select a different, non-zero record if the second glyph changes, so keep the pair unsafe to concat even when no positioning was applied.
Correct the ArabicPUATraditional.txt entry for 0xF295 which should be isolated not final form. Also enable 0xFC43 ligature so the ligature is actually used.
Insertion state machines may emit glyphs during the end-of-text transition, when the buffer has no current input glyph. Emit the glyph first in that case and apply AAT metadata to the new output glyph instead of buffer->cur().
Contextual and non-contextual AAT subtables replace glyphs in place. When such a replacement produced the AAT deleted glyph, we changed only the glyph ID and did not set the AAT-deleted metadata that later cleanup uses to remove deleted glyphs from the buffer. Make replace_glyph_inplace() match the other AAT replacement helpers by setting the deleted scratch flag and glyph-info marker for glyph 0xFFFF.
move_to()'s two memmoves - the forward copy into out_info and the rewind copy-back - were not charged against max_ops, while shift_forward() already charges its moved tail. A morx insertion subtable that keeps its mark far behind the insertion point can force an O(distance) rewind plus re-copy per insertion action, for O(N^2) total work that the max_ops budget never sees. Charge count in both branches, mirroring shift_forward()'s failure pattern. Charging only the rewind branch would also bound the quadratic, but both memmoves are attacker-drivable work, and symmetric accounting is simpler to reason about.
When the skipping iterator fails to find another kernable glyph, resume at the position it reports instead of retrying from the next glyph. This prevents a suffix of ignored marks from being scanned repeatedly while preserving later feature ranges.
Non-first pieces of a MultipleSubst now add no extra component, so a decomposed glyph absorbed into a ligature counts as the single component it started as, and its marks attach where MarkBasePos would. Part of harfbuzz/harfbuzz#4969
Unbounded syllables can make the USE and Myanmar reordering passes perform quadratic work. Process syllables in configurable chunks of at most 64 glyphs to bound the work performed by each reordering pass.
Cluster merges serve two distinct purposes that require different level gates: - Grapheme grouping: combining marks merged into their base cluster. Correct gate: IS_GRAPHEMES (levels 0 and 3). New functions: merge_grapheme_clusters / merge_out_grapheme_clusters. - Monotonicity maintenance: clusters merged to prevent non-monotone output after ligature formation, reordering, etc. Correct gate: IS_MONOTONE (levels 0 and 1). Existing functions: merge_clusters / merge_out_clusters. Previously both paths shared merge_clusters_impl's single IS_MONOTONE gate, so GRAPHEMES (level 3) was incorrectly blocked from merging grapheme clusters. This also caused a regression in the Thai and Hangul shapers for MONOTONE_CHARACTERS (level 1): when their explicit == MONOTONE_GRAPHEMES call-site guards were removed in #5069, the impls' IS_MONOTONE gate no longer protected them.
The buffer digest is only consumed by the OT lookup-apply loop. After morx substitution it exists solely for a following GPOS pass; when positioning goes through kerx/kern instead, rebuilding it is wasted work. Speeds up the Menlo/en-thelittleprince benchmark by 2%; shaping outputs are unchanged on the AAT benchmark fonts.
Cap each stch run to at most 256 output glyphs. This keeps pathological stretch runs from expanding to unbounded size.
U+180F MONGOLIAN FREE VARIATION SELECTOR FOUR was added in Unicode 14.0 and has Default_Ignorable_Code_Point=Yes, but is_default_ignorable() only covered U+180B..180E, so FVS4 was never hidden and leaked a .notdef into the output.
Contributor
|
I expect applying the equivalent to this fixes it: go-gl/glfw@0e60a4a Static check does not yet support 1.27 |
Contributor
Author
|
Thanks @andydotxyz, the CI is fixed ! |
andydotxyz
approved these changes
Oct 13, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Hello,
This PR update our Harfbuzz and Unicode implementation to follow Harfbuzz v14.5 and Unicode 18.
I've tried to split it in small commits, so that the change set is reviewable...
As an aside, the CI seems to have an issue with staticcheck, and I'm not sure what the proper fix is. Perhaps @andydotxyz has an idea ? Perhaps we have to bump staticcheck version ?
Edit : that seems to be dominikh/go-tools#1832