Fix CBDT emoji font crash and COLR v1/composite glyph crashes#366
Open
jspears wants to merge 8 commits intofoliojs:masterfrom
Open
Fix CBDT emoji font crash and COLR v1/composite glyph crashes#366jspears wants to merge 8 commits intofoliojs:masterfrom
jspears wants to merge 8 commits intofoliojs:masterfrom
Conversation
Agent-Id: agent-9256c1ef-d67c-4777-af65-729a56806d97 Linked-Note-Id: e547533f-3492-4e79-b31b-f63b18b084e0
Agent-Id: agent-035b8bf0-d70e-4c95-ac0d-1b3dad51c12e Linked-Note-Id: 5b8e8269-583a-4cfd-910b-007d58db224b
Agent-Id: agent-6f8ac66c-00ba-478e-acc3-163077223271 Linked-Note-Id: 02ec8fd8-557c-40a6-afa7-2f5111c133c5
…Apple Emoji Adds test fonts and test cases to verify PR foliojs#366 (CBDT glyph support) works with multiple emoji font formats: - OpenMoji CBDT (CBDT/CBLC tables) - tests the new CBDTGlyph code path - OpenMoji COLRv1+SVG (COLR/CPAL tables) - tests COLR glyph handling - Twemoji Mozilla (COLR/CPAL tables) - tests COLR glyph handling - Apple emoji (SBIX table) - tests existing SBIX support Tests cover: basic glyph creation, layout, advance width, ZWJ sequences, skin tone modifiers, and flag sequences. All 563 tests pass. Agent-Id: agent-45802c07-04d0-4e6c-80db-653eaa3c7b6f
Test data for emoji font compatibility tests: - OpenMoji-color-cbdt.ttf (CBDT/CBLC bitmap emoji) - OpenMoji-color-colr1_svg.ttf (COLRv1 + SVG emoji) - Twemoji.Mozilla.ttf (COLR/CPAL emoji) Agent-Id: agent-45802c07-04d0-4e6c-80db-653eaa3c7b6f
Two fixes for COLR emoji font handling:
1. COLRGlyph.layers getter: COLR v1 fonts (e.g. OpenMoji COLRv1) use
paint-based records instead of v0 baseGlyphRecord. fontkit only
supports v0, so the layers getter now returns null instead of
crashing with:
TypeError: Cannot read properties of null (reading 'length')
2. TTFGlyph._getContours: When a composite TTF glyph references a
component glyph ID that getGlyph() resolves as a COLRGlyph,
calling _getContours() crashes because COLRGlyph doesn't have
that method. Fixed by using _getBaseGlyph() to get the TTF outline
for component resolution, skipping components that lack _getContours.
TypeError: this._font.getGlyph(...)._getContours is not a function
Added test cases for both issues using OpenMoji COLR v0 and v1 fonts.
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.
Summary
Fixes three crash scenarios when working with color emoji fonts:
1. CBDT emoji font crash (NotoColorEmoji)
Fonts using CBDT color bitmaps instead of glyf/CFF outlines cause
getGlyph()to return null, crashinglayout()with "Cannot read properties of null".Fix: Wrapped
layout()in try-catch with fallback that extracts CBDT bitmaps directly via_cmapProcessor.lookup()and renders as square images.2. COLR v1 null
baseGlyphRecordcrashCOLR v1 fonts (e.g. OpenMoji COLRv1) use paint-based records instead of v0
baseGlyphRecord. TheCOLRGlyph.layersgetter crashes with:at
colr.baseGlyphRecord.lengthbecausebaseGlyphRecordis null in v1 fonts.Fix: Added null guard in
COLRGlyph.layers— returnsnullwhenbaseGlyphRecordis missing, allowing callers to fall back gracefully.Repro:
fontkit.openSync('OpenMoji-color-colr1_svg.ttf').glyphsForString('😀')[0].layers3. Composite glyph
_getContourscrash in COLR fontsIn COLR fonts (e.g. OpenMoji COLRv0), composite TTF glyphs reference component glyph IDs via
getGlyph(). Since the font has COLR+CPAL tables,getGlyph()returns aCOLRGlyph— butCOLRGlyphdoesn't have_getContours(), crashing with:Fix: In
TTFGlyph._getContours(), use_getBaseGlyph()to get the TTF outline for composite component resolution. Skip components that lack_getContours.Repro:
fontkit.openSync('OpenMoji-color-glyf_colr_0.ttf').layout('😀🚀✅')Changes
src/glyph/COLRGlyph.jsbaseGlyphRecordinlayersgettersrc/glyph/TTFGlyph.js_getBaseGlyph()for composite component resolutiontest/glyphs.jstest/data/OpenMoji/Testing
All 568 tests pass (5 new). The only pre-existing failure is an unrelated i18n test (
fontkit.setDefaultLanguage).