Refs #434 (partial). Preserve displayed bounds and standard appearance orientation through stamp edits; image signatures and explicit rectangles remain outside this fix.
Assisted-by: OpenAI GPT-6.1 (gpt-6.1-sol)
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Combine, extract and split built the new document from copies of the
pages and carried bookmarks, fields, layers, attachments and four Info
keys, but not the catalog's /OutputIntents, the GTS_PDFXVersion,
GTS_PDFXConformance and Trapped Info entries, or the XMP pdfxid
identification. A PDF/X file stopped being one, and a RIP or preflight
lost the intended output condition.
Extract and split now carry the output intents (with their ICC
profiles, through the same object map as the pages), the Info entries
(the version read from Info, else XMP) and a new XMP packet holding the
identification, trapping and title. The source's packet is not copied:
it can claim standards the new file no longer meets, such as PDF/UA,
whose structure tree is not copied. Combine carries the first source's
standard only when every source declares the same version, trapping
and output intents (type, condition and profile bytes).
Not yet: a warning when combine's sources disagree, and XMP dates.
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
* Split: keep only the resources each part draws (#204)
In a book whose pages share one resource dictionary, every split part carried every XObject the source listed: a part saved out at the source's size although its pages drew a fraction of the images. extract_pages now walks each part's content (form XObjects included) and drops the /XObject entries no page names; the garbage-collecting rewrite on save then drops the objects themselves. Tests cover a one-page part that must lose the other page's image and a part that needs both.
* Split/Extract pruning never drops an XObject something might still draw
A resources dictionary is left untouched when one of its pages has content
that can't be decoded, when a form nests past the depth limit, or when it
lists a Type 3 font without its own /Resources (its glyphs draw through
the page's). Regression tests fail without this.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Mohammed Munzir <Mohammed.Munzir@iga.gov.bh>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The app, crates, binaries, bundle id, packaging, icons, screenshots and docs are now
PdfCraft / pdfcraft (repo storytold/pdfcraft). On first launch the desktop app moves the
PrintCraft settings and crash-recovery folders to the new name, and both apps read settings
saved under the old storage key, so upgrades keep recent files, preferences and unsaved work.
The signing test fixtures keep their PrintCraft subject names (they are binary).
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
The outline import, bookmark lookup and page-label code use `first`/`last`, a final `Err` and a
default range instead of `expect`/`unreachable!`. The crate now denies the panic lints.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stable clippy 1.99 denies chunks_exact/chunks_exact_mut with a constant
size (32 sites), which failed the test job on main and every open PR.
Behaviour unchanged; MSRV 1.90 has as_chunks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Delete Pages only took the pages out of the page tree, so a bookmark, link or form widget that
referenced a deleted page kept it (and its content) in a full save. Deleted page objects are now
freed; their widgets leave the form (with fields left without widgets), and bookmarks and links
to them lose that destination.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>