M2: route PDF reading through shared craft-pdf

This commit is contained in:
skylar taylor-barrick committed 2026-10-13 23:14:03 -06:00
1 parent 3ef63cb4e7
commit 60a82e858f
200 files changed
+750 -59547

No files matched your search

+4 -4
View File
@@ -30,7 +30,7 @@ standalone and publishable.
| L0 foundation | `geom`, `filters`, `crypt` | Geometry; stream filters (Flate, LZW, predictors, ASCII85, ASCIIHex, RunLength); standard security handler R2–R6 (RC4, AES-128/256, SASLprep) |
| L1 objects | `cos` | Lazy, tolerant parser with xref repair; copy-on-write object graph; incremental and full writers with object streams; decryption on load and re-encryption on save |
| L2 core model | `content`, `model`, `fonts` | Content-stream operators with source spans and a serializer; typed page tree with inherited attributes and display geometry (`/UserUnit`, `/Rotate`); font metrics and encodings for generated appearances |
| L3 core services | `render`, `annot`, `forms`, `js`, `xfa` | Rendering and inspection (bootstrap: vendored `hayro`, `lopdf`); annotation builders and appearance streams; AcroForm model, filling, appearances; sandboxed JavaScript (boa) and FormCalc; XFA template layout and data |
| L3 core services | `render`, `annot`, `forms`, `js`, `xfa` | Rendering and inspection (bootstrap: shared `craft-pdf`/Hayro, local `lopdf`); annotation builders and appearance streams; AcroForm model, filling, appearances; sandboxed JavaScript (boa) and FormCalc; XFA template layout and data |
| L4 features | `edit`, `organize`, `redact`, `xfdf`, `sign`, `ocr`, `create`, `export`, `optimize`, `preflight`, `a11y`, `compare`, `measure`, `print` | One crate per Acrobat tool family |
| L6 façade | `engine` | Session, open documents, edit history, the command registry and tool catalogue. Frontends never reach past it |
| L7 platform and frontends | `platform`, `ui-egui`, `automation` | OS services; the egui shell (desktop and web); headless JSON-Schema tools, CLI and MCP |
@@ -55,9 +55,9 @@ The PDF object graph *is* the model (`crates/engine/README.md` §The editing mod
## Rendering and text
- Pages are rasterized on the CPU by the vendored `hayro` family (`hayro`, `hayro-interpret`,
`hayro-syntax`, `hayro-jbig2`), with local patches for appearance states, layers, resource
limits, cancellation, tiles and `/UserUnit` (`vendor/README.md`). A render pool renders visible
- Pages are rasterized on the CPU through the shared `craft-pdf` facade and its pinned
`hayro` family. The shared source retains patches for appearance states, layers, resource
limits, cancellation, tiles and `/UserUnit` ([PDF backend](pdf-backend.md)). A render pool renders visible
pages first, then neighbours and thumbnails; tiles keep deep zoom sharp; a watchdog skips
pathological pages.
- The raster is uploaded to the GPU as a texture; egui draws the interface through wgpu (OpenGL
+61
View File
@@ -0,0 +1,61 @@
# Shared PDF reader
`pdfcraft-render` uses `craft-pdf` for parser construction, backend types and bounded
raster execution. The workspace enables only its `raster` feature, which includes
reading and interpretation. PDF writing, the COS editor and the locally patched
`lopdf` inspector remain app-owned.
The shared package and the four root Hayro patches must resolve to one immutable
`storytold/craft-libs` Git revision. Cargo does not inherit dependency workspace
patches, so the consuming workspace carries all four entries. `cargo xtask pdf-deps`
checks their exact versions and source, the shared feature set, and the application's
production dependency boundary. Existing backend regression tests retain development
access to the same Hayro sources.
| Package | Version | Licence |
| --- | --- | --- |
| craft-pdf | 0.1.0 | MIT OR Apache-2.0 |
| hayro | 0.7.1 | MIT OR Apache-2.0 |
| hayro-interpret | 0.7.0 | MIT OR Apache-2.0 |
| hayro-syntax | 0.7.2 | MIT OR Apache-2.0 |
| hayro-jbig2 | 0.3.0 | MIT OR Apache-2.0 |
The exact revision is recorded in `Cargo.toml` and `Cargo.lock`. Its source and patch
ledger retain the application's existing Hayro fixes. Licence texts and dependency
asset notices remain in `licenses/pdf-backend/`, `NOTICE` and `ATTRIBUTION.toml` and
are included in package documentation. The shared revision must be published before
a fresh checkout can resolve it. Rust 1.95 remains the workspace minimum.
## Application policy
The general viewer accepts already-loaded inputs without adding the shared helper's
512 MiB default input cap: its explicit `OpenOptions` set `max_input_bytes` to
`usize::MAX`. File and remote-link entrypoints retain their own policies. Immutable
backend decode limits bound ordinary stream decoding, including parser repair paths;
they do not bound total document or process memory.
PdfCraft retains password compatibility, COS and `lopdf` inspection, its text extraction
device, font substitution, optional-content selection, annotation policy, reading
colours, print bypass, preview choice, worker scheduling, cancellation and watchdogs.
A native backend panic retires the affected parser/cache generation as before. Browser
rendering does not gain the native worker watchdog, and WASM aborts cannot be caught.
Raster entrypoints validate the explicit viewport before writing into the app's existing
word-aligned pixel buffer. Full pages keep rounded-up edge coverage within 8192 pixels
per side and 64 million pixels; tiles keep their own 4096-pixel bound. The GUI takes
ownership without another pixel copy. Known content omissions still reach the app's
`ContentTruncated` warning, but diagnostics describe only backend warnings that were
actually emitted; a successful render is not a fidelity guarantee.
## Updating the dependency
1. Review the shared source changes, patch ledger and regression evidence.
2. Advance `craft-pdf` and all four Hayro patches together, update the expected revision
in `xtask/src/pdf_deps.rs`, and refresh the lockfile without unrelated upgrades.
3. Run `cargo xtask pdf-deps` and `cargo xtask ci`; inspect the resolved feature graph.
4. Exercise native and browser rendering separately, including malformed input, passwords,
tiles, rotation, crop boxes, `/UserUnit`, text, layers and reading colours.
The `lopdf`, `winit` and `egui-wgpu` sources remain local and can advance independently.
The application regressions also retain missing-Encoding TrueType WinAnsi extraction and packed TIFF predictor row boundaries. Arabic ActualText editing order and Type 3 extraction resource ownership remain app-level behavior, with save/reopen coverage.
+4 -4
View File
@@ -89,11 +89,11 @@ total matches the parity estimate.
|---|---|---|---|---|---|
| M0 | Skeleton: workspace, xtask gates, CI | 15–30 | 98% | 1–2 | GitHub workflow, `deny.toml` (licence audit of every dependency), parity checklist (826 features, `xtask parity`) done. Missing: remaining crate stubs, testkit/oracle crates |
| M1 | COS: filters, crypt, parser, xref, writer | 120–200 | 80% | 20–40 | Done:<br>- filters and crypt: every standard-security revision R2–R6 (RC4, AES-128/256), SASLprep, permissions, creating encryption;<br>- cos: parse and repair (including invalid xref object-number ranges), decoded-stream limits including unfiltered data, decrypt on load, re-encrypt on save, incremental and full writing.<br>Corpus: open/edit/save passes on 958 files, and all 7 password-protected files open.<br>Full saves now pack objects into compressed object streams. An unchanged incremental save of a classic table writes a zero-length cross-reference subsection instead of a section with no subsections (#1339). Fuzzing runs nightly (`xtask fuzz`). Missing: ≥ 250 tests, own image codecs |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer (vendored patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings. Packed TIFF-predictor RGB rows retain later rows in decoding and rendering. |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer (vendored patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer through the shared `craft-pdf` facade (pinned patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings. Packed TIFF-predictor RGB rows retain later rows in decoding and rendering. |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer through the shared `craft-pdf` facade (pinned patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M3 | Viewer app (native + web) | 80–150 | 90% | 10–20 | Acrobat-style shell, find, select, panels, tiles, web build, UI control channel for agents (opt-in). Missing: 60 fps test on a 500-page document, snapshot tests of every panel<br>Done since: fit visible, document title in the window; Linux middle-button scrolling; shared three-state theme preferences in the toolbar, View menu and control channel; numeric Linux portal events and idle wakeups completing #881, with native appearance inheritance retained (#446); late browser startup downloads preserve the current document and Save target (#171). #1364 candidate: absolute local GoToR links ask before target access; headless callers explicitly opt in. Native-opening candidate: chosen tools survive preparation and password retries; startup intake waits for pending preparation. |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer (vendored patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. A custom text match that ends on a reconstructed separator stops before the next glyph (#1315). Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer (vendored patches); Lab Bradford adaptation uses LMS white-point ratios, covered by independent neutral/chromatic and direct/Indexed render oracles; inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer through the shared `craft-pdf` facade (pinned patches); inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. A custom text match that ends on a reconstructed separator stops before the next glyph (#1315). Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M2 | Model, render, text | 200–350 | 15% | 130–230 | hayro bootstrap renderer through the shared `craft-pdf` facade (pinned patches); Lab Bradford adaptation uses LMS white-point ratios, covered by independent neutral/chromatic and direct/Indexed render oracles; inspector predictor scratch is bounded by available input, and JPX sample rescaling handles 1–32 bits safely. Text extraction reaches word-F1 0.98 against pdftotext. Short same-line redraws split before placement rather than interleaving. Missing: model crate, fonts, DisplayList, renderer independent of hayro. Inspector page-label traversal and output are resource-bounded, with physical-number fallback warnings |
| M3 | Viewer app (native + web) | 80–150 | 90% | 10–20 | Acrobat-style shell, find, select, panels, tiles, web build, UI control channel for agents (opt-in). Missing: 60 fps test on a 500-page document, snapshot tests of every panel<br>Done since: fit visible, document title in the window; Linux middle-button scrolling; shared three-state theme preferences in the toolbar, View menu and control channel; numeric Linux portal events and idle wakeups completing #881, with native appearance inheritance retained (#446); late browser startup downloads preserve the current document and Save target (#171). |
| M4 | Engine, history, save, organize | 100–180 | 95% | 8–15 | Done:<br>- command registry (menus, shortcuts and palette all use it);<br>- undo/redo; incremental, atomic and encrypted saves;<br>- autosave and crash recovery;<br>- organize, combine, extract, split and insert-from-file, with identical fonts and images stored once;<br>- CLI `edit/combine/extract/split`.<br>Done since: Organize opens directly into the page overview, with checkbox selection, an editable page-range selection (#1092), and per-page rotate/delete controls; Combine files in its own tab (sortable, resizable columns; folders; early warnings; unlocking protected files), bookmark editing, page labels (Number pages), CLI `run`, Set Page Boxes, Crop tool, Duplicate pages, Ctrl+A / Cmd+A to select all pages in Organize, Replace pages, bookmarks from tagged headings. Extract and Split preserve shared Type 3 glyph resource graphs, retaining conservative pruning limits. Missing: page transitions, recovery on the web |
| M3 | Viewer app (native + web) | 80–150 | 90% | 10–20 | Acrobat-style shell, find, select, panels, tiles, web build, UI control channel for agents (opt-in). Missing: 60 fps test on a 500-page document, snapshot tests of every panel<br>Done since: fit visible, document title in the window; Linux middle-button scrolling; shared three-state theme preferences in the toolbar, View menu and control channel; numeric Linux portal events and idle wakeups completing #881, with native appearance inheritance retained (#446); late browser startup downloads preserve the current document and Save target (#171). Renderer-creation errors return to the existing OpenGL startup fallback; a real-GPU regression covers errors and device reuse. The underlying x86 DX12 shader compiler failure remains unresolved; see `windows-renderer-startup.md`. With Windows' Animation effects turned off, the wheel scrolls and zooms without easing and egui's animations take no time (`motion.rs`; macOS, Linux and the browser aren't asked yet); Preferences ▸ Animation effects (Use system setting, On, Off) decides it on every platform. |