From 39148311f4dbd378db73a17d75d04c4478499fda Mon Sep 17 00:00:00 2001 From: jedarden Date: Sun, 5 Jul 2026 18:30:57 -0400 Subject: [PATCH] docs(bf-29ioc): document ToUnicode entry creation code locations --- notes/bf-e4uvb-child-2-tounicode-search.md | 112 +++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 notes/bf-e4uvb-child-2-tounicode-search.md diff --git a/notes/bf-e4uvb-child-2-tounicode-search.md b/notes/bf-e4uvb-child-2-tounicode-search.md new file mode 100644 index 0000000..d1cbba3 --- /dev/null +++ b/notes/bf-e4uvb-child-2-tounicode-search.md @@ -0,0 +1,112 @@ +# ToUnicode Entry Creation Code Search + +**Task**: Search and identify ToUnicode entry creation code +**Bead**: bf-29ioc +**Date**: 2026-07-05 + +## Primary Location + +**File**: `/home/coding/pdftract/crates/pdftract-core/src/font/cmap.rs` + +### Core Function: `ToUnicodeMap::add_mapping()` + +**Lines**: 86-88 + +```rust +/// Add a single mapping from source bytes to destination chars. +/// +/// MARKER: CMAP entry creation point - this is where individual ToUnicode +/// mappings are stored. Called by parse_beginbfchar() and parse_beginbfrange(). +/// See notes/bf-e4uvb-child-1.md for documentation. +pub fn add_mapping(&mut self, src: Vec, dst: Vec) { + self.mappings.insert(src, dst); +} +``` + +This is the **primary entry creation point** where individual ToUnicode mappings are stored in the internal HashMap. + +### Functions that Call `add_mapping()` + +#### 1. `parse_beginbfchar()` +**Lines**: 190-216 +- Called at line 209: `map.add_mapping(src, dst);` +- Handles single-character mappings from `beginbfchar...endbfchar` blocks +- Format: `beginbfchar ... endbfchar` + +#### 2. `parse_beginbfrange()` - Two Forms +**Lines**: 223-309 + +**a) Explicit Array Form** (line 279): +```rust +map.add_mapping(current.clone(), dst); +``` +- Format: `beginbfrange [ ...] endbfrange` +- Each element in the array is mapped individually + +**b) Contiguous Range Form** (line 292): +```rust +map.add_mapping(current.clone(), dst.clone()); +``` +- Format: `beginbfrange endbfrange` +- Range is expanded with incrementing destination values + +### Public Parser Functions + +- `parse_to_unicode()` (line 493) - Convenience function, returns map only +- `parse_to_unicode_with_diags()` (line 502) - Returns map + diagnostics + +### Related Test Functions + +Lines 508-732 contain comprehensive tests: +- `test_parse_single_bfchar` (line 520) +- `test_parse_bfchar_ligature` (line 532) +- `test_parse_bfrange_contiguous` (line 570) +- `test_parse_bfrange_explicit_array` (line 586) +- And 14 more tests covering edge cases + +## Usage Location (Query Side) + +**File**: `/home/coding/pdftract/crates/pdftract-core/src/font/resolver.rs` + +### `resolve_level1()` Function +**Lines**: 383-399 + +```rust +fn resolve_level1(char_code: &[u8], to_unicode: Option<&ToUnicodeMap>) -> ResolvedGlyph { + let Some(cmap) = to_unicode else { + return ResolvedGlyph::failure(); + }; + + let Some(chars) = cmap.lookup(char_code) else { + return ResolvedGlyph::failure(); + }; + // ... returns resolved glyph with UnicodeSource::ToUnicode +} +``` + +This function **queries** the ToUnicode entries created by `add_mapping()`, using `ToUnicodeMap::lookup()` (line 93-95 in cmap.rs). + +## Summary + +| Aspect | Location | Lines | +|--------|----------|-------| +| **Entry creation** | `cmap.rs::ToUnicodeMap::add_mapping()` | 86-88 | +| **Single mapping parser** | `cmap.rs::parse_beginbfchar()` | 190-216 (calls at 209) | +| **Range mapping parser** | `cmap.rs::parse_beginbfrange()` | 223-309 (calls at 279, 292) | +| **Entry query/lookup** | `cmap.rs::ToUnicodeMap::lookup()` | 93-95 | +| **Usage in resolver** | `resolver.rs::resolve_level1()` | 383-399 | + +## Data Structure + +The `ToUnicodeMap` struct (lines 67-71 in cmap.rs) stores: +```rust +pub struct ToUnicodeMap { + /// Mapping from source byte sequence to destination Unicode codepoints. + /// Uses `Vec` as key (source bytes) and `Vec` as value (destination chars). + mappings: HashMap, Vec>, +} +``` + +This allows: +- Variable-length source byte sequences (1-4 bytes) +- Multi-codepoint destinations (for ligature expansion like `fi` → U+0066 U+0069)