Repository navigation
Walk GPOS on the buffer cursor, keep COLRv1 paint transforms, add cmap formats 6 and 10 - #565
Merged
Merged
Conversation
Positioning stepped one glyph after every lookup, so a matched contextual lookup was re-attempted on the glyphs it had consumed. With Segoe UI Emoji 1.70 the family sequence's chained context applied its nested lookups twice and the members overlapped. GPOS now walks the same buffer cursor GSUB uses: a lookup leaves the cursor after the records it consumed and the loop steps one record only when the cursor did not move. The GPOS ApplyLookupList ends with MoveTo(end), the three chained context formats call it instead of inlining nested application, and pair positioning moves the cursor to the second glyph, or past it when valueFormat2 is set. MoveTo takes the no-pass fast path outside a substitution pass. Adds the installed Segoe UI Emoji 1.70 and its HarfBuzz differential cases.
A default UVS range covers startUnicodeValue through startUnicodeValue + additionalCount, so the last code point of each range was never matched and U+FE0F fell through to the text presentation for it. Adds the presentation tests against HarfBuzz, the Segoe UI Emoji 1.70 font chain row and the 192pt toned thumbs-up row to the browser page.
Radial and sweep paints were flattened to device points, which reduced a PaintTransform to a similarity. The squashed shadow ellipses of the toned thumbs-up became large circles whose pad region painted the finger opaque dark. Paint.Transform is public and radial and sweep paints keep their geometry in the paint's y-down space with the whole transform, as FreeType and HarfBuzz hand it to the renderer. Linear paints stay flattened. The image comparison tests are disabled until Drawing 3.1.3 consumes the transform.
The corpus tests now also shape HarfBuzz's aots suite, which found: - cmap formats 6 and 10 were not read. - Format 4 dropped idDelta in the idRangeOffset branch and reported glyph 0 as found. - A glyph id past the font's glyph count threw in the CFF tables. They now return an empty charstring, the bounds finder returns an empty box when nothing was drawn, and hmtx and vmtx return zero past the glyph count. vmtx also applies the last record, not the first, past numberOfVMetrics.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## release/v3.1.x #565 +/- ##
===============================================
- Coverage 81% 81% -1%
===============================================
Files 406 408 +2
Lines 35747 35802 +55
Branches 5583 5586 +3
===============================================
- Hits 29241 29185 -56
- Misses 5341 5441 +100
- Partials 1165 1176 +11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Merged
4 tasks done
This was referenced Sep 17, 2026
Merged
This was referenced Oct 5, 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.
Prerequisites
Description
Fixes the faults behind SixLabors/ImageSharp.Drawing#418 that only show with the installed Segoe UI Emoji 1.70, and the cmap faults HarfBuzz's aots corpus found once it was wired in. HarfBuzz is the reference for every change.
GPOS walks the buffer cursor like GSUB. Positioning stepped one glyph after every lookup, so a matched contextual lookup was re-attempted on the glyphs it had consumed and the family sequence's members overlapped. GPOS now uses the same cursor GSUB uses (HarfBuzz
apply_forwardandapply_lookup): a lookup leaves the cursor after the records it consumed, the loop steps one record only when the cursor did not move, the GPOSApplyLookupListends withMoveTo(end), the three chained context formats call it instead of inlining nested application, and pair positioning moves the cursor to the second glyph, or past it whenvalueFormat2is set.cmap format 14 default UVS ranges are inclusive (
startUnicodeValuethroughstartUnicodeValue + additionalCount), so U+FE0F resolves for the last code point of each range.COLRv1 radial and sweep paints keep their geometry in paint space with the whole
PaintTransform, as FreeType and HarfBuzz hand it to the renderer. Flattening to device points reduced the transform to a similarity, which turned the toned thumbs-up's squashed shadow ellipses into circles that painted the finger dark.Paint.Transformis public. The image comparison tests are disabled until ImageSharp.Drawing 3.1.3 consumes the transform.cmap formats 6 and 10 are read (HarfBuzz
CmapSubtableTrimmed). Format 4 addsidDeltain theidRangeOffsetbranch and treats glyph 0 as missing. A glyph id past the font's glyph count no longer throws in the CFF tables: they return an empty charstring, the bounds finder returns an empty box when nothing was drawn, and hmtx and vmtx return zero past the glyph count. vmtx applies the last record pastnumberOfVMetrics, not the first.Tests. The corpus tests now shape HarfBuzz's aots suite as well (274 cases). New HarfBuzz differential cases for Segoe UI Emoji 1.70, presentation selector tests, the font chain and 192pt thumbs-up rows on the browser page, a radial gradient transform test, and unit tests for cmap formats 4, 6 and 10 and both metrics tables. Fonts: 11065 tests pass on net8.0.