The content raster's fully transparent pixels were RGB 0,0,0. A viewer that
smooths the image blends colour and mask separately, so the black showed as a
grey hairline around white pictures and white-filled shapes.
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 denylist can't keep up with OS protocol handlers: ms-msdt:, ms-word:
with a share path, ldap: and file:///%5C%5Chost/share still went into
exported PDFs. PDF export now writes a URL link only when safe_url
allows it, the check the slide show already uses on a click: http,
https and mailto. Links between slides are unchanged, and any other
link's text stays on the page without the link.
safe_url moves from deckcraft-anim to deckcraft-model, which both
crates use; deckcraft_anim::safe_url stays as a re-export. Local file:
and relative links are left out for now, as asked in review.
Windows Search's search: and search-ms: links can name a folder on
another machine through crumb=location:, and opening one connects to
that host and sends the user's NTLM credentials. They are now left out
of the PDF like the other network-share links, and the test covers both.
An smb://host/share link is a path to another machine too: opening it
connects to that host (macOS and Linux file managers open these links).
It is now left out of the PDF like the other network-share links, and
the test covers it.
A slide hyperlink from an untrusted deck became a PDF link whatever it
pointed at. Script and data links, and links to another machine (UNC
\\host\share, //host/share, file://host/...), are now left out of the
PDF; the text stays. On Windows, opening a network path sends the
user's NTLM credentials to that host.
Web, mail, local file: and relative links are kept. The scheme is read
the way a browser reads it: control characters dropped, leading spaces
trimmed, any case. The slide show already refuses these links
(safe_url), and cadcraft's PDF export drops script and data links.
* chore: resolve SonarCloud maintainability issues
* fix: address shellcheck SC2059 and fix generic cast ambiguity
* style: apply rustfmt formatting
* fix: restore compile and behaviour in Sonar refactors
- fonts: char::is_alphanumeric takes &self, so filter needs a closure
- h264: keep the mvd accumulator as i32 (prefix is usize)
- model: annotate the non-stacked range accumulators as f64
- engine: chart.options still clears the raw chart XML for upDownBars
and quartiles; smartart goes back to the glob import (cmd! macro)
- web: keep the original viewport meta (behaviour change)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Assign positional parameters to locals in sha256 verification
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Dylan Taylor <dylan@craftmaker.dev>
PDF export rasterized every slide as one full-page bitmap, so the
background, master and layout graphics a deck repeats were stored once
per slide. Draw each slide as its backdrop plus the slide's own shapes;
equal backdrops become equal images and the writer stores each once.
Preserve notes and handout master export, visible text and native parallel
compression while propagating shared font errors through each export path.
Keep the dependency check accurate for native and WASM feature resolution.
PR #708.
- #178: ToUnicode ranges looked up without indexing
- #465: frame_num gaps are concealed (bounded) even when the SPS forbids them; cut streams keep playing
- #471: control request lines up to 256 MB so picture/media inserts still fit
- #473: a merge that loses its only row or column is removed, with regression tests
- #521: AutoCorrect no longer rewrites real words (cant, wont, im)
- #654: inherit_placeholder_geometry's doc comment back on its function
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pdf::master_text_pieces turns the text engine's layout of the notes
master's header, date, footer and page number into per-run, per-line
pieces scaled to the page; the Notes Page view paints them in their
sizes and colours. Stacked on #583.
Notes pages and handouts lay out the master's header, date, footer and
page-number placeholders with deckcraft-text (render::place_master_texts),
so their text wraps in the placeholder and keeps mixed run formatting,
drawn as visible glyphs. Stacked on #580.
Notes Master view draws the current slide inside the slide-image
placeholder. Header, date, footer and page-number text on notes pages
and handouts (PDF and the Notes Page view) uses the placeholder's
resolved font, size, weight, slant and colour, scaled with the page.
Stacked on #577.
PDF notes pages and the Notes Page view put the slide (keeping its aspect)
and the notes where the notes master's slide-image and body placeholders
are, scaled from the notes size to the paper, and print the master's
header, date, footer and page number. PDF handouts print the handout
master's. Decks without these masters keep the old layout. Stacked on #573.
krilla compressed each slide's print-resolution artwork on the export
thread; with its rayon feature (desktop only) the deflate runs in the
background while the next slide renders. The rendered pixels are also
moved into the image instead of copied.
The Print page always laid notes pages and handouts out on portrait US
Letter. It now offers Letter, A4, Legal and A3 in portrait or landscape,
as PowerPoint's Print settings do, and the preview shows the chosen
page. file.export, app.print and the MCP export tool take the same
`paper` and `orientation` params; unknown values are an error. A notes
page keeps its slide within the top half of the page, so landscape
paper still leaves room for the notes. Full-page slides still print on
slide-shaped pages.
Co-authored-by: Cursor <cursoragent@cursor.com>