From 392734a135ed51ee5dd7cf8d0751efb1c302577e Mon Sep 17 00:00:00 2001 From: Gert Pellin Date: Fri, 16 Oct 2026 16:42:42 +0200 Subject: [PATCH] Export: transparent background docs and clearer refusal (#784) The error for a non-PNG export says the option is for PNG export. ROADMAP, file-format, UI parity and control protocol docs mention the option. --- ROADMAP.md | 2 ++ crates/engine/src/cmd/file.rs | 2 +- crates/engine/src/tests.rs | 2 +- crates/ui-egui/src/dialogs.rs | 2 +- docs/control-protocol.md | 2 +- docs/file-format-parity.md | 3 ++- docs/ui-parity.md | 3 ++- 7 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ROADMAP.md b/ROADMAP.md index 7dfa96f8..d31c2a30 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -131,6 +131,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | What landed | |---|---| +| 2026-10-16 | Export: PNG with a transparent background — the slide background is left out, only the slide's content is drawn (Export… dialog, File › Export, web download, `file.export`/`file.render` `transparentBackground`, `deckcraft-cli render --transparent`) (#784) | | 2026-10-15 | CLI: .txt and .md export includes table cell text, which it used to skip silently (#814) | | 2026-10-15 | PDF export and rendering: `anchorCtr` centres the drawn text block — right-aligned text no longer ran past the box edge (#736) | | 2026-10-14 | connected MCP rejects unrelated, malformed, incomplete and oversized replies without replay; buffered unsolicited bytes force a fresh connection before sending (#718) | @@ -227,6 +228,7 @@ app's JSON control channel (`deckcraft --control PORT`). | Date | Change | Summary | |---|---|---| +| 2026-10-16 | trivial | Progress log: PNG export with a transparent background (#784) | | 2026-10-14 | trivial | remote MCP checks reply IDs, envelopes and bounded newline framing (#718) | | 2026-10-14 | minor | Gray list markers on empty paragraphs while editing; caret keeps the list indent before typing | | 2026-10-14 | minor | Community PR wave folded: headline breadth 84% over 191 features (P0 92%, P1 82%, P2 55%) and the feature-area breadths from `cargo xtask parity`; one row per area; Upcoming item 2 merged; per-PR count notes dropped from the progress log. Ready stays ~55%, stage alpha | diff --git a/crates/engine/src/cmd/file.rs b/crates/engine/src/cmd/file.rs index 9be0863f..c4cb6de6 100644 --- a/crates/engine/src/cmd/file.rs +++ b/crates/engine/src/cmd/file.rs @@ -491,7 +491,7 @@ fn export(s: &mut Session, p: &Value) -> Result { let scale = finite_scale(f64_or(p, "scale", 2.0)); let transparent = bool_or(p, "transparentBackground", false); if transparent && format != "png" { - return Err(bad("file.export", format!("a transparent background needs PNG; {format} can't keep transparency"))); + return Err(bad("file.export", format!("a transparent background is for PNG export, not {format}"))); } match format.as_str() { "png" | "jpeg" | "jpg" => { diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index b4ca50e6..9b7115c5 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -2798,7 +2798,7 @@ fn a_png_export_can_leave_the_background_transparent() { for (name, format) in [("slide.jpg", "jpeg"), ("deck.pdf", "pdf"), ("deck.gif", "gif"), ("deck.pptx", "pptx")] { let path = dir.join(name); let e = s.execute("file.export", &json!({"path": path.to_str().unwrap(), "format": format, "transparentBackground": true})).unwrap_err(); - assert!(e.to_string().contains("needs PNG"), "{format}: {e}"); + assert!(e.to_string().contains("for PNG export"), "{format}: {e}"); assert!(!path.exists(), "{format}: nothing is written"); } let _ = std::fs::remove_dir_all(&dir); diff --git a/crates/ui-egui/src/dialogs.rs b/crates/ui-egui/src/dialogs.rs index f064b7b0..d37952ea 100644 --- a/crates/ui-egui/src/dialogs.rs +++ b/crates/ui-egui/src/dialogs.rs @@ -1599,7 +1599,7 @@ fn body(app: &mut SlideApp, ui: &mut Ui, d: &mut Dialog) -> bool { let mut clear = d.get("pngTransparent", "false") == "true"; if ui .checkbox(&mut clear, "Transparent background") - .on_hover_text("Leave the slide background out: only what is on the slide is drawn (#784)") + .on_hover_text("Leave the slide background out: only what is on the slide is drawn") .changed() { d.fields.insert("pngTransparent".into(), clear.to_string()); diff --git a/docs/control-protocol.md b/docs/control-protocol.md index e715d1c7..707b90b4 100644 --- a/docs/control-protocol.md +++ b/docs/control-protocol.md @@ -45,7 +45,7 @@ Coordinates are slide points (1/72 inch; a 16:9 slide is 960 × 540) unless note | `ui.render` | `{path?, slide?, scale?}` | Render a slide headlessly | | `ui.resize` / `ui.focus` | | Window control | | `show.start` / `show.end` | `{from?: slide index, custom?: name, reading?}` | Slide show. `custom` plays that custom show from its first slide and does not change Set Up. With no `from` and no `custom`, playback starts at the first slide of the show order | -| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, …}` | Files (export takes the `file.export` params, e.g. `{"path": "deck.pdf", "layout": "handouts", "perPage": 3}` or `{"path": "deck.gif", "width": "large", "secondsPerSlide": 3, "loop": false}`) | +| `app.open` / `app.save` / `app.export` / `app.quit` | `{path, …}` | Files (export takes the `file.export` params, e.g. `{"path": "deck.pdf", "layout": "handouts", "perPage": 3}` or `{"path": "deck.gif", "width": "large", "secondsPerSlide": 3, "loop": false}`, or `{"path": "slide.png", "transparentBackground": true}` for a PNG without the slide background) | The MCP server (`deckcraft-cli mcp`, see [mcp.md](mcp.md)) wraps the same methods for Claude and other agents; `deckcraft-cli app --method METHOD [PARAMS]` sends one request from a shell. diff --git a/docs/file-format-parity.md b/docs/file-format-parity.md index a5f72fe7..1532ff40 100644 --- a/docs/file-format-parity.md +++ b/docs/file-format-parity.md @@ -26,7 +26,7 @@ PowerPoint opens and saves; Viewer = opens only). | `.deckcraft` native (zip + JSON) | n/a | yes (also `.slidecraft`) | yes | Lossless for the DeckCraft model, forward compatible | `crates/format` tests | | PDF | export | no | yes | Slides, notes pages, handouts (1–9); real-text layer with embedded subsets, links, bookmarks. Slide artwork is a raster image at print resolution, not vector | `crates/pdf` tests | | Outline `.rtf` / `.txt` | export (RTF), import (outline) | `.txt` outline; `.md` as Markdown (headings are slides, list items bullets) (`slide.fromOutline`) | `.txt` outline | No RTF | engine tests | -| PNG / JPEG slide images | export | n/a | yes (`file.export`, `deckcraft-cli render`) | Matches the editor's renderer. PNG `pHYs` and JPEG JFIF density are `scale` × 72 dpi (default scale 2 is 144 dpi), so Preview shows the slide's real size | render and engine tests | +| PNG / JPEG slide images | export | n/a | yes (`file.export`, `deckcraft-cli render`) | Matches the editor's renderer. PNG `pHYs` and JPEG JFIF density are `scale` × 72 dpi (default scale 2 is 144 dpi), so Preview shows the slide's real size. PNG can leave the slide background out (`transparentBackground`, Export… “Transparent background”, `deckcraft-cli render --transparent`), so only the slide's content is opaque (#784) | render, engine, UI and CLI tests | | TIFF / BMP / GIF slide images | export | n/a | no | Easy (the `image` crate writes them) | none | | Animated GIF of the deck | export | n/a | yes (`file.export` format `gif`, Export…, `deckcraft-cli`, MCP `export`) | One frame per slide from the slide renderer; size small/medium/large/extra large or 16–3840 px wide, 0.1–600 s per slide, loop forever or play once, slide range, hidden slides skipped; a 256-colour palette per frame (exact, or NeuQuant above 256 colours). Transitions and build animations are not animated | `crates/engine/src/gif_export.rs` tests (decoded frames, size, delay, loop, hidden slides, hostile params), MCP, CLI and export dialog tests | | MP4 / MOV video of the deck | export | n/a | no | Needs timeline render + H.264 encode | none | @@ -103,6 +103,7 @@ the round trip even though DeckCraft doesn't model it. | Date | Change | Summary | |---|---|---| +| 2026-10-16 | minor | PNG slide export with a transparent background (#784) | | 2026-10-14 | minor | Community PR wave folded: one row each for `.pptx` (seven owned corpus files), outline, 3-D models, embedded fonts, text, effects, 3-D (extrusion sides draw now), SmartArt (written as a diagram) and VBA (tags and custom XML are kept) | | 2026-10-12 | minor | SmartArt import lays each shape's text out on its `dsp:txXfrm` text rectangle instead of the shape box | | 2026-10-13 | minor | EMF/WMF rectangle clip regions limit later drawing; EMF+ records remain | diff --git a/docs/ui-parity.md b/docs/ui-parity.md index cc97dae4..3b1fedf7 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -55,7 +55,7 @@ menu colours taken from the theme tokens (menu `chrome`, page `card`). | Save As | Places, folder, file name, type, Save, More options | Type (PowerPoint, DeckCraft, PDF, Outline, PNG, JPEG) and Save, which opens the system Save dialog (web: Download). .pptx/.deckcraft take the new file; the others are copies (`file.saveAs`, `file.export`) | | Print | Print and Copies, Printer, Print All / Selection / Current / Custom Range, Slides box, layout (Full Page Slides, Notes Pages, Outline, Handouts 1–9), sides, collation, colour, Edit Header & Footer; page preview with pager and zoom | Print, Print All Slides / Current Slide / Custom Range, Slides box (`1-3, 5`), Full Page Slides / Notes Pages / Handouts 1–9, Print Hidden Slides, Frame Slides, Edit Header & Footer; preview with pager. DeckCraft prints through a PDF (`file.export`) opened in the system viewer, which has the printers (web: downloaded). No printer list, copies, sides or colour | | Share | Cloud sharing | Not offered | -| Export | Create PDF/XPS Document, Create a Video, Create an Animated GIF, Package Presentation for CD, Create Handouts, Change File Type | Create PDF Document, Create Handouts (a PDF), Change File Type. No video, GIF or CD package | +| Export | Create PDF/XPS Document, Create a Video, Create an Animated GIF, Package Presentation for CD, Create Handouts, Change File Type | Create PDF Document, Create Handouts (a PDF), Change File Type (PNG with an optional transparent background, #784). No video, GIF or CD package | | Close | Closes; asks Save / Don't Save / Cancel about unsaved changes | Same (`file.close` after the prompt); Ctrl+W asks too | | Account | User information, sign-in, Office Background and Office Theme, product information, About | Appearance (light/dark, `view.dark`), product information, About DeckCraft. No accounts to sign in to | | Options | Opens the PowerPoint Options dialog | Opens Preferences | @@ -165,6 +165,7 @@ consistency is open (#73, #56). | Date | Change | Summary | |---|---|---| +| 2026-10-16 | minor | Export › Change File Type › PNG and the Export… dialog offer a transparent background (#784) | | 2026-10-14 | minor | Gray list markers on empty paragraphs while editing; caret keeps the list indent before typing | | 2026-10-14 | minor | Community PR wave folded: one row each for Format Shape, Dialogs (41, listed from `dialogs.rs`), Animation Pane (timeline is in), window, Quick Access Toolbar, Format Background, rulers, image paste, context menus, exact size and edit points; estimates re-totalled (~26–46 h) | | 2026-10-13 | trivial | Eyedropper in the colour menus (#367) |