From 60107cd33a101e3f40ba5674637b854179239d0d Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sat, 24 Oct 2026 03:34:41 +0700 Subject: [PATCH] Export for Screens: a document row for an artboard keeps only that artboard's art (#3868) --- crates/engine/src/cmd/fileio/save.rs | 10 +++++++--- crates/engine/src/cmd/fileio/screens.rs | 10 +++++++++- crates/engine/src/cmd/fileio/tests_batch.rs | 18 +++++++++++++----- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/crates/engine/src/cmd/fileio/save.rs b/crates/engine/src/cmd/fileio/save.rs index 166eda8b9..316f42270 100644 --- a/crates/engine/src/cmd/fileio/save.rs +++ b/crates/engine/src/cmd/fileio/save.rs @@ -385,15 +385,19 @@ fn separate_boards(cmd: &str, f: &Format, doc: &Document, p: &Value) -> Result Document { let mut d = doc.clone(); let Some(a) = doc.artboards.get(i) else { return d }; - let r = a.rect; d.artboards = vec![a.clone()]; - // It opens fitted to its artboard, not at the master file's view. + keep_art_on(&mut d, a.rect); + d +} + +/// Reduce `d` to the objects touching `r`, in their layers (resources are kept), opening +/// fitted to its artboard rather than at the master file's view. +pub(super) fn keep_art_on(d: &mut Document, r: vectorcraft_geom::Rect) { d.last_view = None; d.layers_open = None; for layer in &mut d.layers { keep_on(layer, r); } - d } /// Keep in layer `n` (and its sublayers) only the objects touching `r`. diff --git a/crates/engine/src/cmd/fileio/screens.rs b/crates/engine/src/cmd/fileio/screens.rs index 9c33d7e24..28c3358ca 100644 --- a/crates/engine/src/cmd/fileio/screens.rs +++ b/crates/engine/src/cmd/fileio/screens.rs @@ -784,7 +784,15 @@ fn encode_and_write(export: ScreenExport, writer: &mut dyn FnMut(&str, &[u8]) -> write(all, "pdf", &options)? } else if r.whole_document() && item.artboard.is_some() { let b = item.artboard.unwrap_or(0); - let d = board_docs.entry(b).or_insert_with(|| Arc::new(single_artboard(&item.doc, item.region, &item.name))).clone(); + // That artboard alone, as Save's separateArtboards writes it: its art, not the others' (#3868). + let d = board_docs + .entry(b) + .or_insert_with(|| { + let mut d = single_artboard(&item.doc, item.region, &item.name); + super::save::keep_art_on(&mut d, item.region); + Arc::new(d) + }) + .clone(); write(&d, r.format.id, &r.options_for(item.region, None)?)? } else { write(&item.doc, r.format.id, &r.options_for(item.region, item.artboard)?)? diff --git a/crates/engine/src/cmd/fileio/tests_batch.rs b/crates/engine/src/cmd/fileio/tests_batch.rs index 5535d8ed6..b889eb2d4 100644 --- a/crates/engine/src/cmd/fileio/tests_batch.rs +++ b/crates/engine/src/cmd/fileio/tests_batch.rs @@ -134,17 +134,25 @@ fn layers_and_the_selection_are_exported_by_name() { assert!(s.execute("document.exportForScreens", &json!({"selection": "one"})).is_err(), "nothing selected"); } -/// Document formats write each artboard as a document of its own: one artboard, its art. +/// Document formats write each artboard as a document of its own: one artboard, its art and +/// not the other artboards' (#3868). #[test] fn document_formats_write_one_artboard_each() { let mut s = session(2); + let second = s.doc().unwrap().doc.artboards[1].rect; + s.execute("shape.ellipse", &json!({"x": second.x0 + 5.0, "y": 5, "width": 10, "height": 10})).unwrap(); let r = export(&mut s, json!({"formats": [{"format": "vectorcraft"}, {"format": "ai"}, {"format": "eps"}]})); let n = names(&r); assert_eq!(n, ["Artboard-1.vectorcraft", "Artboard-1.ai", "Artboard-1.eps", "Artboard-2.vectorcraft", "Artboard-2.ai", "Artboard-2.eps"]); - let native = &files(&r)[0].1; - let mut t = Session::new(); - t.execute("document.open", &json!({"name": "a.vectorcraft", "dataBase64": vectorcraft_format::base64_encode(native)})).unwrap(); - assert_eq!(t.doc().unwrap().doc.artboards.len(), 1, "that artboard alone"); + let all = files(&r); + for (name, bytes) in &all { + let mut t = Session::new(); + t.execute("document.open", &json!({"name": name, "dataBase64": vectorcraft_format::base64_encode(bytes)})).unwrap(); + let d = &t.doc().unwrap().doc; + assert_eq!(d.artboards.len(), 1, "{name}: that artboard alone"); + let objects: usize = d.layers.iter().filter_map(|l| l.children()).map(|c| c.len()).sum(); + assert_eq!(objects, 1, "{name}: only its own artboard's art"); + } } #[test]