Created comprehensive glyph selection document for unmapped glyph test fixture. Selected 4 unmapped glyph examples: - PUA glyphs: /g001, /g002, /g003 - Custom encoding: /CustomA, /CustomB - Orphaned codes: /NotAGlyph - Non-AGL algorithmic: /glyph_0041 Selected 4 mapped AGL glyphs for comparison: - /A, /B, /space (direct AGL entries) - /uni0041 (algorithmic pattern) Explained why each unmapped glyph fails all 4 mapping levels and provided recommended fixture structure with expected output. Closes bf-68f9i
8 KiB
Selected Unmapped Glyphs for Test Fixture
Task: Select target unmapped glyphs for fixture Bead ID: bf-68f9i Date: 2026-07-03 Based on: notes/bf-1cvmt.md
Overview
This document lists the specific glyphs selected for inclusion in the PDF test fixture for unmapped glyph testing. The fixture will demonstrate the 4-level fallback chain failure and the resulting GLYPH_UNMAPPED diagnostic emission.
Selected Unmapped Glyphs
1. /g001, /g002, /g003 (PUA - Private Use Area)
Category: Private Use Area (PUA) Glyphs
Source: tests/fixtures/encoding/no-mapping.pdf
Description: Arbitrary glyph names created by a PDF generator using a custom encoding scheme. These follow a simple numeric pattern but are not recognized by the Adobe Glyph List.
Why all 4 mapping levels fail:
- Level 1 (ToUnicode CMap): No
/ToUnicodeCMap exists in the PDF - Level 2 (AGL lookup):
/g001,/g002,/g003are not in the Adobe Glyph List and do not match AGL algorithmic patterns (uniXXXX,uXXXXXX) - Level 3 (Font fingerprint): The font is not in the fingerprint cache database
- Level 4 (Shape recognition): Feature-gated and disabled by default; even if enabled, these arbitrary glyphs likely have no match in the shape database
Expected output: <EFBFBD><EFBFBD><EFBFBD> (three U+FFFD replacement characters)
Content stream representation: <000102> Tj (byte codes 0, 1, 2)
2. /CustomA, /CustomB (Custom Encoding)
Category: Custom Encodings Without Standard Names
Source: Hypothetical encoding scenario (illustrative)
Description: PDF generator creates a custom encoding dictionary with non-standard glyph names that appear meaningful but are not recognized by the Adobe Glyph List.
Why all 4 mapping levels fail:
- Level 1 (ToUnicode CMap): No
/ToUnicodeCMap exists - Level 2 (AGL lookup):
/CustomAand/CustomBare not in the Adobe Glyph List. They do not match theuniXXXXoruXXXXXXalgorithmic patterns (require exactly 4 or up to 6 hex digits) - Level 3 (Font fingerprint): Font is not in the fingerprint cache database
- Level 4 (Shape recognition): Feature-gated; no shape database match expected
Expected output: <EFBFBD><EFBFBD> (two U+FFFD replacement characters)
Content stream representation: Hypothetically <0003> for code 0 mapping to /CustomA
3. /NotAGlyph (Orphaned Character Code)
Category: Orphaned Character Codes
Source: Type3 font scenario
Description: A glyph name that appears in the encoding dictionary but does not correspond to an actual glyph definition in the font's /CharProcs dictionary.
Why all 4 mapping levels fail:
- Level 1 (ToUnicode CMap): No
/ToUnicodeCMap exists - Level 2 (AGL lookup):
/NotAGlyphis not in the Adobe Glyph List - Level 3 (Font fingerprint): Type3 fonts are vector-based and don't have embedded font programs for fingerprinting
- Level 4 (Shape recognition): The glyph doesn't exist in
/CharProcs, so there's no shape to recognize. The resolver explicitly checks for glyph presence and emitsGLYPH_UNMAPPEDbefore reaching Level 4
Expected output: <EFBFBD> (one U+FFFD replacement character)
Code path: resolver.rs lines 627-636 explicitly handle this Type3 font case
4. /glyph_0041 (Non-AGL Algorithmic Pattern)
Category: Algorithmic Patterns Outside AGL Convention
Source: Illustrative example
Description: A glyph name that appears algorithmic (contains hex digits) but does not follow the Adobe Glyph List convention for algorithmic names.
Why all 4 mapping levels fail:
- Level 1 (ToUnicode CMap): No
/ToUnicodeCMap exists - Level 2 (AGL lookup):
/glyph_0041is not in AGL direct lookup. The algorithmic parser inagl.rsonly recognizes:uniXXXX(exactly 4 hex digits)uXXXXXX(up to 6 hex digits) The prefix/glyph_is not recognized, so the algorithmic match fails
- Level 3 (Font fingerprint): Font is not in the fingerprint cache database
- Level 4 (Shape recognition): Feature-gated; no match expected
Expected output: <EFBFBD> (one U+FFFD replacement character)
Note: This demonstrates the importance of using the correct AGL algorithmic naming convention
Selected Mapped AGL Glyphs (for Comparison)
These glyphs should be included in the same fixture to demonstrate successful mapping behavior when the fallback chain works:
1. /A (Standard AGL Glyph)
Category: Adobe Glyph List Direct Entry
Description: Standard uppercase letter A, direct entry in the Adobe Glyph List.
Mapping path:
- Level 1: If
/ToUnicodepresent → maps to U+0041 (confidence 1.0) - Level 2: If no
/ToUnicode→ glyph name/A→ AGL lookup → U+0041 (confidence 0.9)
Expected output: A
Content stream: <41> Tj
2. /B (Standard AGL Glyph)
Category: Adobe Glyph List Direct Entry
Description: Standard uppercase letter B, direct entry in the Adobe Glyph List.
Mapping path:
- Level 1: If
/ToUnicodepresent → maps to U+0042 (confidence 1.0) - Level 2: If no
/ToUnicode→ glyph name/B→ AGL lookup → U+0042 (confidence 0.9)
Expected output: B
Content stream: <42> Tj
3. /space (Standard AGL Glyph)
Category: Adobe Glyph List Direct Entry
Description: Standard space character, direct entry in the Adobe Glyph List.
Mapping path:
- Level 1: If
/ToUnicodepresent → maps to U+0020 (confidence 1.0) - Level 2: If no
/ToUnicode→ glyph name/space→ AGL lookup → U+0020 (confidence 0.9)
Expected output: (space)
Content stream: <20> Tj
4. /uni0041 (AGL Algorithmic Pattern)
Category: Adobe Glyph List Algorithmic Entry
Description: Algorithmic glyph name following the uniXXXX convention for direct Unicode codepoint mapping.
Mapping path:
- Level 1: If
/ToUnicodepresent → maps directly (confidence 1.0) - Level 2: If no
/ToUnicode→ glyph name/uni0041→ algorithmic parser → U+0041 (confidence 0.9)
Expected output: A
Content stream: Hypothetically <01> mapping to glyph ID 1 with name /uni0041
Recommended Fixture Structure
Based on these selections, the test fixture should include:
Unmapped glyphs (to test failure path):
- Character codes 0, 1, 2 →
/g001,/g002,/g003 - Character code 3 →
/CustomA - Character code 4 →
/CustomB - Character code 5 →
/NotAGlyph - Character code 6 →
/glyph_0041
Mapped glyphs (to test success path):
- Character code 65 (0x41) →
/A - Character code 66 (0x42) →
/B - Character code 32 (0x20) →
/space - Character code 99 →
/uni0041(algorithmic)
Expected extraction output:
<EFBFBD><EFBFBD><EFBFBD>ABCDE A
Where the first 6 positions are U+FFFD for the unmapped glyphs, followed by the mapped glyphs.
Acceptance Criteria
- ✅ Created
notes/bf-68f9i-glyphs.mddocumenting selected glyphs - ✅ Listed 4 unmapped glyphs with categories:
- PUA glyphs (
/g001,/g002,/g003) - Custom encoding glyphs (
/CustomA,/CustomB) - Orphaned code glyph (
/NotAGlyph) - Non-AGL algorithmic pattern (
/glyph_0041)
- PUA glyphs (
- ✅ Listed 4 mapped AGL glyphs for comparison
- ✅ Explained why each unmapped glyph fails all 4 mapping levels
- ✅ Provided recommended fixture structure with expected output
Summary
The selected glyphs represent the most common unmapped glyph patterns encountered in real-world PDFs:
- Private Use Area (PUA) names - Arbitrary numeric patterns
- Custom encoding names - Meaningful-looking but non-standard
- Orphaned codes - Missing glyph definitions
- Misformatted algorithmic names - Almost correct but invalid prefixes
By including both unmapped and mapped glyphs in the same fixture, we can verify that:
- The 4-level fallback chain correctly identifies unmapped glyphs
GLYPH_UNMAPPEDdiagnostics are emitted exactly once per (font_id, char_code)- Mapped glyphs continue to resolve correctly through AGL lookup
- U+FFFD is output for unmapped glyphs while mapped glyphs render correctly