From f1f9ecfc0ffc92ff6871c1b2bd03cc7fabaa612e Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Thu, 12 Nov 2026 06:29:39 -0800 Subject: [PATCH] Cutting Tools: Weed Box and Lines leaves art in a hidden group unmeasured Selected art inside a hidden group or layer is skipped before its outlines are read, so it no longer counts toward the outline point limit. --- .../src/cmd/addons/cutting/weed/geometry.rs | 8 +++--- .../src/cmd/addons/cutting/weed/tests.rs | 25 +++++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/crates/engine/src/cmd/addons/cutting/weed/geometry.rs b/crates/engine/src/cmd/addons/cutting/weed/geometry.rs index 203329fe51..4642031e71 100644 --- a/crates/engine/src/cmd/addons/cutting/weed/geometry.rs +++ b/crates/engine/src/cmd/addons/cutting/weed/geometry.rs @@ -185,15 +185,15 @@ impl<'a> Reader<'a> { let mut parts = vec![]; 'ids: for path in &kept { let Some(n) = doc.node_at(path) else { continue }; + // Art in a hidden group or layer isn't shown, and isn't measured. + if (1..path.len()).any(|depth| path.get(..depth).and_then(|p| doc.node_at(p)).is_some_and(|c| !c.visible)) { + continue; + } let Some(mut region) = self.read(&[n])? else { continue }; // The containers around the object, innermost first. let mut child = n.id; for depth in (1..path.len()).rev() { let Some(container) = path.get(..depth).and_then(|p| doc.node_at(p)) else { break }; - // Art in a hidden group or layer isn't shown. - if !container.visible { - continue 'ids; - } if clips(container) && let Some(first) = container.editing_children().first().filter(|f| f.id != child) { diff --git a/crates/engine/src/cmd/addons/cutting/weed/tests.rs b/crates/engine/src/cmd/addons/cutting/weed/tests.rs index 76f5f656c6..1003ef1db3 100644 --- a/crates/engine/src/cmd/addons/cutting/weed/tests.rs +++ b/crates/engine/src/cmd/addons/cutting/weed/tests.rs @@ -451,6 +451,31 @@ fn art_in_a_hidden_group_is_left_out() { assert_eq!(weed_box(&w), Some(Rect::new(290.0, 290.0, 330.0, 330.0))); } +#[test] +fn art_in_a_hidden_group_is_not_measured() { + // Selected art in a hidden group with more outline points than the limit doesn't count toward + // it. + let mut s = session(); + let shown = rect(&mut s, 300.0, 300.0, 20.0, 20.0); + let mut p = BezPath::new(); + p.move_to((100.0, 100.0)); + for i in 1..=super::geometry::MAX_POINTS as u32 { + p.line_to((100.0 + f64::from(i) * 0.001, if i % 2 == 0 { 100.0 } else { 101.0 })); + } + let dense = insert(&mut s, |id| Node::path(id, PathData::from_bezpath(&p), Appearance::default())); + let g = id_of(&s.execute("object.group", &json!({})).unwrap()); + s.edit("hide", |d, _| { + if let Some(n) = d.node_mut(g) { + n.visible = false; + } + Ok(()) + }) + .unwrap(); + select(&mut s, &[dense, shown]); + let (_, w) = weed(&mut s, json!({"margin": 10})); + assert_eq!(weed_box(&w), Some(Rect::new(290.0, 290.0, 330.0, 330.0))); +} + #[test] fn clip_outlines_crossing_too_often_are_refused() { // A clipping path whose 700 edges each run across the art, and open art whose 700 segments