This commit adds the codespace range parser for CMap streams. The parser extracts the begincodespacerange / endcodespacerange blocks that define legal byte-width boundaries for character codes in a CMap. ## Implementation - CodespaceRange: Single range with lo/hi bounds (stored as [u8; 4]) and width (1-4 bytes) - CodespaceRanges: Collection with SmallVec<[CodespaceRange; 8]> - CodespaceParser: PostScript-style tokenizer for begincodespacerange blocks ## Acceptance Criteria (all PASS) - Parse <00> <7F> → 1 range, width=1 ✅ - Parse <00> <7F> <8000> <FFFF> in one block → 2 ranges ✅ - Width inference: 2-char hex → width=1; 4-char hex → width=2 ✅ - Case-insensitive hex (<C0> and <c0> equivalent) ✅ - Malformed range (width mismatch) → diagnostic + skipped ✅ - Empty CMap → empty ranges ✅ - JIS range <8140> <FEFE> → 2-byte CJK ✅ - 3-byte and 4-byte range support ✅ Also adds encrypted fixture provenance entries to PROVENANCE.md. Co-Authored-By: Claude Code <noreply@anthropic.com>
1.4 KiB
EC-04-rc4-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, RC4 encryption (V=1, R=2), 40-bit key, user password: "user40" Generated: 2026-05-28
EC-05-aes128-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, AES-128 encryption (V=2, R=3), 128-bit key, user password: "user128" Generated: 2026-05-28
EC-06-aes256-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 2.0, AES-256 encryption (V=5, R=5), 256-bit key, user password: "user256" Generated: 2026-05-28
EC-empty-password.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, no encryption (control fixture) Generated: 2026-05-28
EC-04-rc4-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, RC4 encryption (V=1, R=2), 40-bit key, user password: "user40" Generated: 2026-05-28
EC-05-aes128-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, AES-128 encryption (V=2, R=3), 128-bit key, user password: "user128" Generated: 2026-05-28
EC-06-aes256-encrypted.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 2.0, AES-256 encryption (V=5, R=5), 256-bit key, user password: "user256" Generated: 2026-05-28
EC-empty-password.pdf
Generated by tests/fixtures/generate_encrypted_fixtures.py PDF 1.7, no encryption (control fixture) Generated: 2026-05-28