All acceptance criteria verified: - Glyph names checked against unmapped_glyph_names config - Unmapped glyphs skipped during CMAP generation - Code compiles without errors - Tests demonstrate skip behavior The implementation was already complete in encoding.rs:200. See notes/bf-1puzp.md for detailed verification.
4.3 KiB
CMAP Skip Logic for Unmapped Glyphs - Verification
Bead ID: bf-1puzp Date: 2026-07-06 Status: VERIFIED - Already Implemented
Overview
The CMAP skip logic for unmapped glyphs was already implemented in the codebase. This note verifies the implementation meets all acceptance criteria.
Implementation Location
File: crates/pdftract-core/src/font/encoding.rs
Function: DifferencesOverlay::parse()
Lines: 194-203
Code
// MARKER: CMAP entry creation point - Type1 font encoding differences.
// See notes/bf-e4uvb-child-1.md for documentation.
if cursor <= 255 {
// Skip unmapped glyph names (e.g., .notdef) to prevent them from
// appearing in text extraction output. These glyphs have no valid
// Unicode mapping and should emit GLYPH_UNMAPPED diagnostics instead.
if !crate::font::is_unmapped_glyph_name(&name) {
overlay.entries.push((cursor as u8, Arc::clone(name)));
}
}
Acceptance Criteria Verification
✅ 1. Generator checks glyph name against unmapped_glyph_names config before CMAP entry creation
The code calls crate::font::is_unmapped_glyph_name(&name) at line 200, which checks the glyph name against the UNMAPPED_GLYPH_NAMES set defined in crates/pdftract-core/src/font/unmapped.rs.
✅ 2. Unmapped glyphs are skipped during CMAP generation
Glyphs that return true from is_unmapped_glyph_name() are skipped - the overlay.entries.push() call is only executed when the check returns false (note the ! negation).
✅ 3. Code compiles without errors
Verified with:
cargo build -p pdftract-core
Compilation successful with no errors.
✅ 4. Simple test demonstrating skip behavior
Two existing tests demonstrate the skip behavior:
Test 1: test_differences_overlay_skips_notdef (encoding.rs:676-693)
let arr = PdfObject::Array(Box::new(vec![
PdfObject::Integer(39),
PdfObject::Name(Arc::from(".notdef")),
PdfObject::Integer(96),
PdfObject::Name(Arc::from("grave")),
]));
let overlay = DifferencesOverlay::parse(&arr, &mut diagnostics);
// .notdef should be skipped, only grave should be present
assert_eq!(overlay.get(39), None); // .notdef was skipped
assert_eq!(overlay.get(96), Some(Arc::from("grave")));
assert_eq!(overlay.len(), 1);
Test 2: test_differences_overlay_skips_notdef_with_slash (encoding.rs:696-713)
let arr = PdfObject::Array(Box::new(vec![
PdfObject::Integer(10),
PdfObject::Name(Arc::from("/.notdef")),
PdfObject::Integer(11),
PdfObject::Name(Arc::from("A")),
]));
let overlay = DifferencesOverlay::parse(&arr, &mut diagnostics);
// /.notdef should be skipped, only A should be present
assert_eq!(overlay.get(10), None); // /.notdef was skipped
assert_eq!(overlay.get(11), Some(Arc::from("A")));
Both tests pass, confirming the skip behavior works correctly.
Test Execution
$ cargo test -p pdftract-core --lib -- encoding::tests::test_differences_overlay_skips_notdef
running 2 tests
test font::encoding::tests::test_differences_overlay_skips_notdef ... ok
test font::encoding::tests::test_differences_overlay_skips_notdef_with_slash ... ok
test result: ok. 2 passed; 0 failed; 0 ignored
Implementation Details
Unmapped Glyph Configuration
File: crates/pdftract-core/src/font/unmapped.rs
The UNMAPPED_GLYPH_NAMES set currently contains:
.notdef- The special fallback glyph defined by PDF/font specifications
Additional unmapped glyph names can be added to this set as needed.
Check Function
The is_unmapped_glyph_name() function:
- Strips leading
/if present (handles both.notdefand/.notdef) - Checks if the clean name is in
UNMAPPED_GLYPH_NAMES - Returns
trueif unmapped,falseotherwise
Summary
All acceptance criteria are met:
- ✅ Glyph names checked against unmapped_glyph_names config
- ✅ Unmapped glyphs skipped during CMAP generation
- ✅ Code compiles without errors
- ✅ Tests demonstrate skip behavior
The implementation is complete and working correctly.
Related Documentation
notes/bf-e4uvb-child-1.md- CMAP and ToUnicode entry creation points documentationcrates/pdftract-core/src/font/unmapped.rs- Unmapped glyph configurationcrates/pdftract-core/src/font/encoding.rs- CMAP entry creation with skip logic