The page shown was drawn through a fresh renderer each time, which parsed
the whole unmarked document on the UI thread; UnmarkedPages now parses it
once and keeps it. An error from rendering a page ahead (the pool retiring
its parser, a cancelled request) no longer marks that page failed: only
drawing it when shown decides, and a page that has a picture keeps it. On
the web, where the pool renders on the UI thread, nothing renders ahead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The preview showed the page's thumbnail, old marks and all, until the
unmarked page rendered, and one page that failed to render switched the
unmarked preview off for every page. The page shown is now drawn from the
unmarked document straight away at the preview's size; the pages a step
goes to render ahead off the UI thread; a page that fails falls back to
its own thumbnail while the others keep theirs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The preview cloned and wrote the whole document on the UI thread for every
page it stepped to, and showed a blank sheet while the page rendered.
Document::without_marks now removes the marks of a kind from every page
once per dialog (UnmarkedPages), each page shown renders from it off the
UI thread, and the page's thumbnail stays until it arrives.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main split lib.rs: the unmarked_page field stays on PdfCraftApp in lib.rs,
its init and the render_pending check moved to app.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
craft-libs#366 drops the default-features override on craft-keymap that
older Cargo rejects. FreeBSD aarch64 builds with Rust 1.98.1 and failed
with "no matching package named craft-menu found" (craft-libs#364).
* Refactor annot for strict Clippy checks
* Refactor automation for strict Clippy checks
* Refactor cos for strict Clippy checks
* Refactor edit for strict Clippy checks
* Refactor engine for strict Clippy checks
* Refactor export for strict Clippy checks
* Refactor forms for strict Clippy checks
* Refactor js for strict Clippy checks
* Refactor organize for strict Clippy checks
* Refactor pdfcraft-cli for strict Clippy checks
* Refactor preflight for strict Clippy checks
* Refactor print for strict Clippy checks
* Refactor redact for strict Clippy checks
* Refactor render for strict Clippy checks
* Refactor sign for strict Clippy checks
* Refactor ui canvas for strict Clippy checks
* Refactor ui commands for strict Clippy checks
* Refactor ui dialogs for strict Clippy checks
* Refactor ui support for strict Clippy checks
* Refactor ui tools for strict Clippy checks
* Refactor ui workflows for strict Clippy checks
* Refactor xfa for strict Clippy checks
* Refactor xfdf for strict Clippy checks
* Enforce workspace Clippy standards and document lint policy
* Fix menu overflow and form pointer handling
* Group annotation, form and document operation parameters
* Group signing and timestamp validation inputs
* Group demo form field properties
* Group UI interaction and rendering parameters
* Restore translated security and shortcut labels
* Fix platform-gated imports for Windows and wasm builds
* Qualify signing calls for macOS and Windows builds
* Restore the preflight check flow and the overflow menu title
The pre-signing check matched any folder named Program Files, so it rejected
a valid MSI when Windows resolves Program Files elsewhere, accepted the 64-bit
root for an x86 package and accepted a different app name. Build the expected
folder from the package architecture's resolved root and the policy name.
Export > Image spent its time in the PNG, JPEG and TIFF encoders, one
page after another: on a 55-page manual at 150 dpi, drawing every page
took about 0.34 s and encoding it 1.1 s (PNG) to 2.0 s (JPEG).
Exporter::images exports a list of pages, drawing and encoding several
at once on worker threads, each with its own PageRenderer (as
automation's extract_parallel does), and hands the files to a sink in
page order on the calling thread. Workers draw at most one page ahead
of the sink and fewer run when 1 GiB can't hold that many of the
largest page. The first page or sink error stops the export with every
earlier page handed over, as before. A page panic becomes that page's
error, and a panicking sink stops the workers. One page, one core or
wasm keeps the per-page loop. Export > Image and the doc_export_images
tool use it.
Files are byte-identical. One core is left for the interface (at most
8 workers). With examples/export_bench, on a Ryzen with 16 threads
(shared), mean of two medians of 21 runs:
PNG 150 dpi 1874 -> 340 ms (-82%)
JPEG 150 dpi 2106 -> 340 ms (-84%)
TIFF 150 dpi 2032 -> 375 ms (-82%)
PNG 300 dpi 3804 -> 590 ms (-84%)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Real msiexec runs (per-user and all-users, silent and wizard) found two defects
that the metadata fixtures cannot see:
- "Only for me" published ALLUSERS=2, so FindRelatedProducts treated the run as
per-machine and skipped the existing per-user copy. An interactive upgrade
left two registered products and uninstall left files behind. The page now
leaves ALLUSERS unset for a per-user choice.
- Windows Installer resolves Program Files once, for the context it started in,
so choosing "Everyone" in the wizard installed into the user profile with a
machine-wide registration. The wizard now sets the new-install folder itself
after the choice (Program Files, Program Files (x86) for 32-bit, or the
per-user Programs folder). Silent installs are unchanged.
check-install-policy.ps1 now fails if either regresses.