From c22700d3aff6c3f8939e337404abc7ef2f6e5e60 Mon Sep 17 00:00:00 2001 From: SBaksa Date: Sun, 1 Nov 2026 15:27:09 +1100 Subject: [PATCH] Plot: refuse several layouts for PNG and SVG output (review on #2585) An image holds one sheet, so layouts with more than one entry now report a clear error instead of pages:N with one render. --- crates/engine/src/cmd/layout.rs | 5 +++++ crates/engine/src/cmd/layout/tests.rs | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/crates/engine/src/cmd/layout.rs b/crates/engine/src/cmd/layout.rs index 94fd11c59..f253456b3 100644 --- a/crates/engine/src/cmd/layout.rs +++ b/crates/engine/src/cmd/layout.rs @@ -827,6 +827,11 @@ fn run_plot(s: &mut Session, p: &Value, cmd: &str) -> Result { None => o.remove("plotTransparency"), }; } + // A PNG or SVG holds one render: several sheets would report `pages: N` but write only one. + let image = opts.get("output").and_then(Value::as_str).is_some_and(|o| o.eq_ignore_ascii_case("png") || o.eq_ignore_ascii_case("svg")); + if image && sheets.as_ref().is_some_and(|names| names.len() > 1) { + return Err(bad(cmd, "`layouts` with several sheets needs PDF output; PNG and SVG hold one sheet, so plot each layout separately")); + } let bytes = hook(s.doc()?, &space, &opts).map_err(|e| bad(cmd, e))?; let layout = match &sheets { Some(names) => names.first().cloned().unwrap_or_default(), diff --git a/crates/engine/src/cmd/layout/tests.rs b/crates/engine/src/cmd/layout/tests.rs index 03356b892..df548fc7d 100644 --- a/crates/engine/src/cmd/layout/tests.rs +++ b/crates/engine/src/cmd/layout/tests.rs @@ -230,6 +230,13 @@ fn plot_goes_through_the_hook() { assert!(s.execute("plot", &json!({"layout": "Model", "plotArea": "window"})).is_err(), "window needs corners"); assert!(s.execute("plot", &json!({"layout": "Layout1", "plotArea": "display"})).is_err(), "layouts plot their sheet"); assert!(s.execute("plot", &json!({"layout": "Model", "scale": -1})).is_err()); + // Image output holds one sheet: several `layouts` would report pages:N but write one render. + for out in ["x.png", "x.svg"] { + let e = s.execute("plot", &json!({"path": out, "layouts": ["Layout1", "Layout2"]})).unwrap_err(); + assert!(e.to_string().contains("layouts"), "{e}"); + } + assert!(s.execute("plot", &json!({"output": "png", "layouts": ["Layout1", "Layout2"]})).is_err()); + assert!(s.execute("plot", &json!({"output": "png", "layouts": ["Layout1"]})).is_ok(), "one sheet still fine as an image"); #[cfg(not(target_arch = "wasm32"))] { let path = std::env::temp_dir().join(format!("cadcraft-plot-test-{}.pdf", std::process::id()));