From 31a482bade85d167b949ae25bd80f36d7f5f2cad Mon Sep 17 00:00:00 2001 From: el-j Date: Thu, 29 Oct 2026 11:34:03 +0100 Subject: [PATCH] perf(engine): rerun objects_on_path when dimension refresh mutates artwork --- crates/engine/src/cmd/dimension.rs | 9 ++++++--- crates/engine/src/session/edit.rs | 5 +++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/crates/engine/src/cmd/dimension.rs b/crates/engine/src/cmd/dimension.rs index a26eee473..f63e0262b 100644 --- a/crates/engine/src/cmd/dimension.rs +++ b/crates/engine/src/cmd/dimension.rs @@ -197,9 +197,9 @@ fn replace(doc: &mut Document, id: NodeId, dim: Dimension) -> Result<()> { /// Called inside every edit, so dimensions and their undo history stay in step with the art they /// measure. Returns at once in documents without dimensions. -pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result<()> { +pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result { if !doc.dimensions { - return Ok(()); + return Ok(false); } let mut dimensions = Vec::new(); doc.walk(|n| { @@ -208,6 +208,7 @@ pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result<()> { } }); doc.dimensions = !dimensions.is_empty(); + let mut changed = false; for (id, old) in dimensions { let mut next = old.clone(); let moved = next.moved.take(); @@ -215,6 +216,7 @@ pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result<()> { // A deleted/degenerate source has no valid measurement. Remove its annotation in // this same undo step instead of keeping a silently wrong number. doc.remove(id)?; + changed = true; continue; } // Moved on its own (the art it measures stayed put): it keeps its new place. @@ -233,9 +235,10 @@ pub(crate) fn refresh(before: &Document, doc: &mut Document) -> Result<()> { || before.node(id).and_then(|n| n.extras().dimension.as_deref()).is_some_and(|d| d != &next) { replace(doc, id, next)?; + changed = true; } } - Ok(()) + Ok(changed) } /// Redraw the dimensions of an opened document whose art isn't in its colour mode: files saved diff --git a/crates/engine/src/session/edit.rs b/crates/engine/src/session/edit.rs index a15bc5422..df707de3a 100644 --- a/crates/engine/src/session/edit.rs +++ b/crates/engine/src/session/edit.rs @@ -19,6 +19,7 @@ impl Session { let doc = Arc::make_mut(&mut st.doc); // The Global Edit members the edit reached besides the selection. let mut spread = vec![]; + let mut dim_changed = false; // Objects attached to a path follow it, and dimensions follow the art they measure. let result = match f(doc, &mut st.selection).and_then(|v| { // Global Edit: the other members take what the edit changed about the one it edited. @@ -26,14 +27,14 @@ impl Session { spread = cmd::globaledit::propagate(&before, doc, ge, [&before_sel.objects, &st.selection.objects]); } cmd::objects_on_path::refresh(&before, doc); - cmd::dimension::refresh(&before, doc)?; + dim_changed = cmd::dimension::refresh(&before, doc)?; Ok(v) }) { Ok(v) => match cmd::shaper::refresh(&before, Arc::make_mut(&mut st.doc)) { Err(e) => Err(e), Ok(shaper_changed) => { // Attached Shaper groups whose art was rebuilt go back on their path. - if shaper_changed { + if shaper_changed || dim_changed { cmd::objects_on_path::refresh(&before, Arc::make_mut(&mut st.doc)); } // Inline graphics in text follow their symbols.