Export for Screens: a document row for an artboard keeps only that artboard's art (#3868)

This commit is contained in:
bflatastic
2026-10-24 03:52:22 +07:00
parent 9985d587f7
commit 60107cd33a
3 changed files with 29 additions and 9 deletions
+7 -3
View File
@@ -385,15 +385,19 @@ fn separate_boards(cmd: &str, f: &Format, doc: &Document, p: &Value) -> Result<V
pub(super) fn artboard_doc(doc: &Document, i: usize) -> 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`.
+9 -1
View File
@@ -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)?)?
+13 -5
View File
@@ -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]