Image Trace: a library colour changed meanwhile makes a background trace stale, and running traces keep frames coming

From the review of #4605. TraceParams::swatches isn't in the settings' JSON (serde skip), so a Document Library trace whose swatches were edited while it ran still applied, with the old colours; the trace's inputs now hold them. The 100 ms repaint that keeps background work moving left traces out, so without input a finished trace could wait for the next event.
This commit is contained in:
VoiceLessQ
2026-10-30 00:15:59 +07:00
committed by bflatastic
parent 887328db03
commit 2e54e882d6
3 changed files with 22 additions and 3 deletions
+6 -3
View File
@@ -377,8 +377,11 @@ fn grouped(d: &mut Document, nodes: Vec<Node>, parents: &[Option<usize>]) -> Vec
struct TraceInputs {
target: NodeId,
image: Box<ImageObject>,
/// The settings traced with, as JSON, the library's colours in.
/// The settings traced with, as JSON.
params: Value,
/// Document Library: the library's colours, which the JSON leaves out
/// ([`tr::TraceParams::swatches`]).
swatches: Vec<[u8; 3]>,
}
/// What `imageTrace.make` and `imageTrace.makeAndExpand` take from the session before they trace.
@@ -431,7 +434,7 @@ fn prepare(s: &Session, c: &str, p: &Value) -> Result<Prepared> {
let bytes = Arc::clone(&blob.bytes);
let library = trace_library(c, s, &mut params)?;
let traced_with = serde_json::to_value(&params).map_err(|e| EngineError::Other(e.to_string()))?;
let inputs = TraceInputs { target, image, params: traced_with };
let inputs = TraceInputs { target, image, params: traced_with, swatches: params.swatches.clone() };
Ok(Prepared { inputs, trace: params, view, params_json, preset_label, library, bytes })
}
@@ -544,7 +547,7 @@ pub(super) fn trace_make(s: &mut Session, p: &Value, expand: bool) -> Result<Val
Some(traced) if traced.inputs == inputs => traced,
_ => trace_now(&inputs, &trace, &bytes, &|_, _| true)?,
};
let TraceInputs { target, image: img, params: _ } = inputs;
let TraceInputs { target, image: img, .. } = inputs;
let warnings = trace_warnings((img.width, img.height), raster, res.worked_at);
// Pixel space of the decoded raster → the image object's pixel space → document.
let sx = img.width.max(1) as f64 / raster.0.max(1) as f64;
+15
View File
@@ -2768,6 +2768,21 @@ fn a_trace_run_hands_its_trace_to_the_command() {
assert!((bb.center().x - 160.0).abs() < 1.5, "traced where the image is now: {bb:?}");
}
/// A Document Library trace made away from its command no longer applies once the library's
/// colours change: the settings' JSON leaves them out (#4605 review).
#[test]
fn a_trace_run_needs_the_library_colours_it_traced_with() {
let mut s = session();
image_doc(&mut s);
let p = json!({"preset": "6 Colors", "params": {"palette": "documentLibrary"}});
let run = cmd::TraceRun::prepare(&s, "imageTrace.make", &p).unwrap();
assert!(run.current(&s));
let swatch = |w: &&vectorcraft_color::Swatch| matches!(w.paint, Paint::Solid { .. }) && !w.name.starts_with('[');
let name = s.doc().unwrap().doc.swatches_iter().find(swatch).map(|w| w.name.clone()).unwrap();
s.execute("swatch.edit", &json!({"name": name, "color": "#123456"})).unwrap();
assert!(!run.current(&s), "{name} changed");
}
/// Shapes: the disc of the test image comes out as a live ellipse where the image lies, the same
/// circle as its traced path; without the option it is a plain path.
#[test]
+1
View File
@@ -298,6 +298,7 @@ impl VectorcraftApp {
|| !self.opening.pending.is_empty()
|| !self.plugin_runs.running.is_empty()
|| !self.placing.pending.is_empty()
|| !self.trace_runs.running.is_empty()
{
// Keep the status bar's progress moving and pick the result up when it arrives.
ctx.request_repaint_after(std::time::Duration::from_millis(100));