From 9578b61d286e34ce7c8cb73da5dfaba9aa69c970 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 14 Nov 2026 09:27:38 -0800 Subject: [PATCH] Graphs: invert and complement remember the color of the first object they recolor With a graph design's art given first and an item without aligned, the art is left out, but paint.invert and paint.complement remembered the art's unchanged color as the last color. They now read the first object they recolor. --- crates/engine/src/cmd/graph/tests.rs | 6 ++++++ crates/engine/src/cmd/paint.rs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/graph/tests.rs b/crates/engine/src/cmd/graph/tests.rs index cefadcda76..a48f012e40 100644 --- a/crates/engine/src/cmd/graph/tests.rs +++ b/crates/engine/src/cmd/graph/tests.rs @@ -890,6 +890,9 @@ fn aligned_paint_rows_of_a_graph_designs_art_edit_the_equal_rows_of_the_other_ob assert_eq!(now.items[0].paint(), &green); let now = fill(&mut s, "paint.invert", json!({"ids": ids, "item": 1, "aligned": true})); assert_eq!(Some(s.last_solid), now.items[0].paint().color(), "the inverted color is the last color, not the art's"); + // Without `aligned`, the art is left out and the item is a row of the mark. + let now = fill(&mut s, "paint.invert", json!({"ids": ids, "item": 0})); + assert_eq!(Some(s.last_solid), now.items[0].paint().color(), "the mark's inverted color is the last color, not the art's"); let now = fill(&mut s, "paint.editGradient", json!({"ids": ids, "item": 1, "aligned": true, "kind": "linear"})); let Paint::Gradient(g) = now.items[0].paint() else { panic!("{:?}", now.items[0].paint()) }; assert_eq!(&s.last_gradient, &**g, "the mark's new gradient is the last gradient"); @@ -926,6 +929,9 @@ fn aligned_paint_rows_of_a_graph_designs_art_edit_the_equal_rows_of_the_other_ob ("paint.setFill", json!({"ids": [art.0], "item": 1, "aligned": true, "color": "#00ff00"}), "no appearance item 1"), ("stroke.set", json!({"ids": [art.0], "item": 1, "aligned": true, "weight": 5}), "appearance item 1 is not a stroke"), ("paint.editGradient", json!({"ids": [art.0], "item": 1, "aligned": true, "kind": "linear"}), "no appearance item 1"), + // The weight steps take no row: they step each object's active or top stroke. + ("stroke.weightUp", json!({"ids": ids, "item": 2}), "unknown parameter `item`"), + ("stroke.weightDown", json!({"ids": ids, "aligned": true}), "unknown parameter `aligned`"), ] { let defaults = format!("{:?}", (&s.paint.fill, &s.paint.stroke, &s.last_gradient)); let e = s.execute(cmd, &p).unwrap_err().to_string(); diff --git a/crates/engine/src/cmd/paint.rs b/crates/engine/src/cmd/paint.rs index 91e1efdbe3..6e2071d7f8 100644 --- a/crates/engine/src/cmd/paint.rs +++ b/crates/engine/src/cmd/paint.rs @@ -1025,7 +1025,7 @@ fn proxy_recolor(s: &mut Session, p: &Value, cmd: &str, label: &str, f: &dyn Fn( ItemTarget::Item { index, .. } => Some((id, Some(index))), ItemTarget::Top => None, }), - None => ids.first().map(|id| (*id, Some(index))), + None => targets.first().map(|id| (*id, Some(index))), }; let mut changed = 0; edit_items(s, &targets, item, of, cmd, label, !stroke, |n, i| {