UPDATE_APP (native builds; craft-update is a native-only dependency) carries our 128 px icon and accent (#f07a1e, its colour in ArtCraft Launcher). The updater, the self-update
helper and craft-update's startup prompt all get them through crate::UPDATE_APP; the
prompt draws the icon, the accent and "by ArtCraft" (craft-update's default developer).
craft-update is pinned to storytold/craft-libs main at 1065653e7 (#434).
Clippy fixes for Rust 1.99 in untouched code (same logic):
- crates/engine/src/tools/click.rs
- crates/engine/src/tools/pointer.rs
- crates/metafile/src/emfplus.rs
- crates/model/src/trendline.rs
- crates/pptx/src/read/dml.rs
- xtask/src/layers.rs
PDF export rasterises every slide as a backdrop and a content layer and
hands both to the writer. Profiling (gdb stack sampling) showed most of
the main thread outside rendering going to per-pixel work on those
rasters: compositing the backdrop onto white (not vectorised), the
writer hashing every backdrop to deduplicate it, and the straight-alpha
conversion scanning every content pixel.
- Composite the backdrop with saturating adds and skip 16-pixel blocks
that are already opaque; skip blocks with no partly transparent pixel
in the straight-alpha conversion. Same formulas, same bytes.
- Keep the last opaque backdrops (up to 32 MiB of pixels) and hand the
writer the same image again when a slide renders an identical
backdrop. The writer stored equal backdrops once already; now it also
skips hashing and compressing the copies. Output is byte-identical.
deckcraft-cli bench, export .pdf step, 15 interleaved runs each on a
16-thread Ryzen (A/A noise +0.9 %):
- sample x4 (32 slides): median 531 -> 322 ms (-39 %), min 529 -> 317 ms
- same deck, every slide a different background: 557 -> 441 ms (-21 %)
- sample (8 slides): 149 -> 103 ms (-31 %)
Exported PDFs are byte-identical.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A harness runs frames until no repaint is asked for, so the preview had
already landed when its first assertion ran. One raw frame now shows the
preview pending and one render started, and the paging test pins a pending
job and checks a page turn starts no other render.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Turning the page with Presenter View on re-rendered the next-slide preview
synchronously, single-threaded, on the UI thread. The preview now renders
on a worker thread and arrives on a later frame; the web build (no
threads), or a worker that dies, renders it inline. At most one render runs:
paging faster than it asks for the newest preview once it is done, and a
finished one no longer wanted is dropped. Job and texture are keyed by the
presentation as well as the slide, so a preview rendered before an edit is
rendered again. While a preview is on its way the box stays empty rather
than saying "End of slide show".
Rebased onto the show module split: show/presenter.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>