* M10: exported images keep their transparency, JPEG cut-outs included (#645)
Export all images and Save image as wrote a JPEG with a soft mask as the
bare JPEG and dropped soft masks of another size, JPEG-compressed soft
masks, stencil /Mask images and colour-key /Mask arrays, so cut-out
images came out on a solid white or black background.
- An image with transparency (/SMask, stencil /Mask, colour-key /Mask) is
written as a PNG with it as alpha, JPEG images included (decoded with
the image crate's JPEG decoder, already in the tree). JPEGs without
transparency are still written byte for byte.
- Soft and stencil masks of another size are scaled to the image's size;
/Decode inversion is honoured and /Matte pre-blending is undone.
- Image sizes are checked (positive, at most 100 Mpx) before use, so a
negative /Width no longer overflows in Save image as.
- Regression tests: JPEG + soft mask, scaled soft mask, stencil mask,
colour key, matte, and damaged masks/sizes (all fail or panic on main).
Fixes#645
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M10: use as_chunks for colour-key pairs (clippy 1.99 chunks_exact_to_as_chunks) (#645)
Rust 1.99's clippy denies chunks_exact with a constant size, which failed
the Clippy step on all CI targets. as_chunks::<2> also drops the indexing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: DWAA1660 <DWAA1660@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Create from images (doc_create, and image_xobject for stamps, signatures and
inserted images) dropped a JPEG's or PNG's embedded ICC profile, so a CMYK
JPEG became untagged /DeviceCMYK.
- JPEG: the APP2 ICC_PROFILE chunks are joined by sequence number; a profile
with a missing or repeated chunk is ignored.
- PNG: the iCCP profile is read.
- A profile whose header is sound (acsp) and whose colour space matches the
image (GRAY/RGB/CMYK for 1/3/4 components) becomes [/ICCBased <stream>]
with /N and the device space as /Alternate. Anything else keeps the device
space, as before. JPEG data and an Adobe CMYK /Decode are unchanged.
- Images in one document that carry the same profile share one profile
object.
TIFF profiles are not read yet.
Co-authored-by: lloyd <lloyd@stackworx.io>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* create: lift TIFF decoding buffer limit to allow print-sized images (#665)
By default, the tiff crate limits decoded buffer size to 256 MiB.
Set Decoder::with_limits(Limits::unlimited()) to match PNG decoding
behavior and prevent 'decoder limits exceeded' on large images.
* create: cap the TIFF decode buffer at 2 GiB instead of lifting it entirely (#665)
A few bytes claiming enormous dimensions must still be refused, not allocated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* M10.2: create PDF from multiple files
Create a PDF ▸ Multiple files takes PDFs, images and .txt files, lets the
user reorder them, and makes one combined PDF (a bookmark and an optional
page range per file) or one PDF per file in a chosen folder, never
overwriting what is there.
- create: source_kind() tells PDFs, images and text apart (moved from the shell)
- engine: Session::convert_to_pdf, shared by Open, the dialog and the tool
- automation: doc_create_multiple (combine or separate)
- ui: Multiple files dialog reusing the Combine files list; translations
- parity entry and ROADMAP updated; catalog hashes refreshed
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M10.2: multiple files open in the page grid; insert files at any gap
Create a PDF ▸ Multiple files now opens the picked files as one unsaved
document in the Organize page grid instead of a file-list dialog: pages
are removed and reordered there, and Save pages writes what is shown.
- grid: a "+" at every gap inserts files right there; Save pages button
- insert from file: several files in order, images and text converted,
inserted pages selected
- the file-list dialog is removed; one PDF per file stays in the
doc_create_multiple tool
- translations, catalog hashes, parity notes and ROADMAP updated
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M4: insert files by dropping them on the page grid
On desktop, PDFs, images and .txt files dropped on the Organize page grid
are inserted at the gap under the pointer, in order, and selected; a
dropped file still opens as a document everywhere else.
winit does not report the pointer while files are dragged over the
window on every platform, so a drop waits (up to a second) for the
pointer to show up and otherwise appends at the end.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* M4: files dragged over the page grid follow the pointer (macOS)
winit sends no pointer moves while files are dragged over the window, so
egui kept the place the pointer entered at: the insertion bar froze there
and the files were inserted there. During a file drag the pointer is now
read from AppKit (safe objc2 calls, crates already in the tree) and fed
to egui, so the bar and a "+" badge follow the pointer and the files go
where they are released.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.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>
`add_page` returns the crate's error when the new document has no page tree, and text pages are
filled with `if let`. 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>