Add invoice fixture with ground truth text for OCR testing.
Files:
- tests/fixtures/scanned/invoice/invoice-300dpi.pdf: 300 DPI scanned invoice
- tests/fixtures/scanned/invoice/invoice-300dpi-ground-truth.txt: complete text content
- tools/generate_invoice_pdf_fixtures.py: fixture generator script
- tests/fixtures/PROVENANCE.md: added provenance entries for new fixtures
- notes/bf-337i2.md: verification note
Verification:
- PDF is image-based (type=image, not text-embedded)
- Resolution: 300 DPI (x-ppi=300, y-ppi=300)
- Dimensions: 2550 x 3300 pixels (letter size at 300 DPI)
- Ground truth contains complete invoice text with headers, addresses, line items, totals
Closes bf-337i2
Successfully executed generate_unicode_recovery_fixtures_bin to create
no-mapping.pdf fixture (650 bytes). Validated PDF structure includes
custom /CustomNoMap font with /Differences encoding, non-AGL glyph
names, and no ToUnicode entry. Ground truth contains U+FFFD × 3.
Closes bf-ttbb5.
The no-mapping.pdf fixture uses custom glyph names (/g001, /g002, /g003)
that are not in the Adobe Glyph List and cannot be recovered through any
Unicode recovery mechanism (no ToUnicode CMap, no standard encoding,
no AGL match).
The ground truth has been corrected from 'ABC' to three U+FFFD replacement
characters (���), which is the expected output when all encoding recovery
methods fail per the Failure Mode Taxonomy.
Also updated PROVENANCE.md with new SHA256 hashes for encoding fixtures
that were regenerated on 2026-07-02.
This fixture correctly exercises the ENCODING_NO_MAPPING failure mode as
specified in the plan (line 733).
Closes bf-f0xqd.
CJK fixtures and tests already exist from previous work:
- tests/fixtures/cjk/ contains all 4 required PDFs
- Ground truth files for each encoding (GB18030, Shift-JIS, EUC-KR, Big5)
- Tests in crates/pdftract-core/tests/cjk_encoding.rs and tests/test_encoding.rs
- Tests fail due to unimplemented CJK encoding (expected for Phase 2.3)
- Updated PROVENANCE.md with CJK fixture entries
Fixtures are ready for CJK encoding implementation.
Closes bf-3ourh
- no-mapping.txt: fix garbled unicode to correct 'ABC' output
- shape-match.txt: fix from 'Shape' to 'S' (actual PDF content)
- Add PROVENANCE.md entries for all 4 encoding fixtures
- PDFs remain unchanged (already valid)
Fixes ground truth for Level 2-4 Unicode recovery fixtures:
- no-mapping.pdf: PDF with no ToUnicode, no standard encoding
- agl-only.pdf: PDF with AGL glyph names only
- fingerprint-match.pdf: PDF with embedded font for fingerprint matching
- shape-match.pdf: PDF with subset font for shape recognition
Closes bf-512z1
All three required features were already implemented:
- Hover tooltips with 50ms response (CSS transition:opacity 0s)
- JSON-tree click navigation with scroll + highlight
- Search filter UI with Enter cycling and Escape clear
Acceptance criteria: 6/6 PASS
Add image_coverage_fraction signal evaluator that computes the union
image coverage fraction from individual image XObject areas.
- Computes total image coverage as sum of image_xobject_areas
- Divides by page area (width * height) to get coverage fraction
- Clamps to [0.0, 1.0] to handle overlapping images (defensive)
- Returns Some(Vote::scanned(0.85)) if fraction > 0.85
Implementation uses sum for simplicity (overestimates coverage when
images overlap), which is acceptable for the 0.85 threshold as it's
a conservative signal. Can be revisited with Klee's algorithm for
greater accuracy if needed.
Acceptance criteria PASS:
✓ Page with one image covering 90% area → Some(Vote { 0.85, Scanned })
✓ Page with multiple small images totaling 50% → None (below threshold)
✓ Page with no images → None
✓ Coverage clamped to 1.0 on overlapping images
Also includes pre-existing infrastructure:
- tr3_op_count field in PageContext
- image_xobject_areas field in PageContext
- all_tr3_with_full_page_image function
- CharDensityRatioSignal evaluator
These were necessary dependencies for the new evaluator to function.
Refs: Plan section Phase 5.1.2, coordinator pdftract-22p