Re-verified per-page Resource dictionary inheritance implementation: - All 33 tests pass (resources + pages) - Arc sharing optimization confirmed (Arc::ptr_eq test) - INV-8 maintained (proptests pass) Acceptance criteria: - ✅ 3-level resource inheritance - ✅ Per-key override semantics - ✅ Arc sharing when no merge needed - ✅ ColorSpace inline arrays preserved - ✅ Empty root /Resources propagation Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
3.1 KiB
3.1 KiB
pdftract-dejqs: Per-page Resource Dictionary Inheritance
Summary
Implemented per-page Resource dictionary inheritance as specified in PDF 1.7 Section 7.7.3.3. The implementation was already complete in resources.rs and pages.rs; this task verified the implementation and added missing test coverage for Arc sharing.
Changes Made
-
Added Arc sharing test (
test_resource_inheritance_page_without_resources):- Modified existing test to verify that when multiple pages have no
/Resources, they share the sameArc<ResourceDict>instance - Uses
Arc::ptr_eqto verify pointer equality (memory efficiency)
- Modified existing test to verify that when multiple pages have no
-
Added public API exports in
parser/mod.rs:pub use resources::{ResourceDict, merge_resources, extract_resources};pub use pages::{PageDict, flatten_page_tree, DEFAULT_MEDIABOX};
Acceptance Criteria Status
| Criterion | Status | Test |
|---|---|---|
| 3-level resource inheritance | ✅ PASS | test_resource_inheritance_three_level |
| Per-key override (page's /F1 wins) | ✅ PASS | test_merge_fonts_last_write_wins |
| Arc sharing when /Resources missing | ✅ PASS | test_resource_inheritance_page_without_resources (new Arc::ptr_eq check) |
| ColorSpace inline array preserved | ✅ PASS | test_merge_colorspace_inline_array |
| Empty root /Resources propagates | ✅ PASS | test_resource_inheritance_empty_root |
| INV-8 maintained (no panics) | ✅ PASS | proptests::fuzz_* tests verify no panics on arbitrary input |
Implementation Details
The merge_resources function in resources.rs implements per-namespace merging:
- Font namespace: IndexMap<Arc, ObjRef> - per-key last-write-wins
- XObject namespace: IndexMap<Arc, ObjRef>
- ExtGState namespace: IndexMap<Arc, ObjRef>
- ColorSpace namespace: IndexMap<Arc, PdfObject> - preserves inline arrays
- Shading namespace: IndexMap<Arc, ObjRef>
- Pattern namespace: IndexMap<Arc, ObjRef>
- Properties namespace: IndexMap<Arc, ObjRef>
- ProcSet: Vec<Arc> - deprecated, informational only
The flatten_page_tree function in pages.rs calls merge_resources during traversal:
- Ancestor resources are accumulated in
InheritedAttrs.resources - Each leaf page merges its own
/Resourceswith inherited resources - When a page has no
/Resources, it directly clones the Arc (pointer-sharing, not deep copy)
Files Modified
crates/pdftract-core/src/parser/pages.rs: Enhanced Arc sharing testcrates/pdftract-core/src/parser/mod.rs: Added public API exportsnotes/pdftract-dejqs.md: This verification note
Test Results (2026-05-22 verification)
All tests pass:
cargo test --lib -- parser::resources parser::pages
test result: ok. 33 passed; 0 failed; 0 ignored
Breakdown:
- 9 tests in
parser::resources::tests - 20 tests in
parser::pages::tests(excluding 4 proptests) - 4 proptests for INV-8 compliance (no panics on arbitrary input)
No Breaking Changes
The implementation was already complete and tested. This task only added:
- One additional test assertion for Arc sharing
- Public API exports that were previously internal