diff --git a/crates/engine/src/cmd/newart.rs b/crates/engine/src/cmd/newart.rs index c7bd4ffbf..ce8029e71 100644 --- a/crates/engine/src/cmd/newart.rs +++ b/crates/engine/src/cmd/newart.rs @@ -217,13 +217,15 @@ impl Session { /// After a command changed the selection, with New Art Has Basic Appearance on: the fill and /// stroke proxies and the weight take what the selection shows in them, so new art looks like /// it. A paint the selected objects don't share (a "?" proxy) stays as it was, and art without - /// paint (a placed image, whose None would make new art invisible) changes nothing. The - /// template is left alone, and without a stroke to show the weight stays too. + /// paint (a placed image that isn't colorized, whose None would make new art invisible) changes + /// nothing. The template is left alone, and without a stroke to show the weight stays too. pub(crate) fn load_selection_paints(&mut self) { if !self.prefs.new_art_basic { return; } - let has_paint = self.proxy_source(false).is_some_and(|(n, _)| matches!(n.kind, NodeKind::Text(_)) || !n.appearance.items.is_empty()); + let has_paint = self + .proxy_source(false) + .is_some_and(|(n, _)| matches!(n.kind, NodeKind::Text(_)) || !n.appearance.items.is_empty() || n.extras().colorize.is_some()); if !has_paint { return; } diff --git a/crates/engine/src/tests/colorize.rs b/crates/engine/src/tests/colorize.rs index 2dba3f6e0..c71014eb1 100644 --- a/crates/engine/src/tests/colorize.rs +++ b/crates/engine/src/tests/colorize.rs @@ -173,6 +173,22 @@ fn blend_recolors_a_colorized_gray_image_without_alpha() { assert_eq!(colorize(&s, middle), Some(Paint::solid(Color::rgb(0.5, 0.5, 0.5)))); } +/// A colorized image shows a fill and no stroke, so selecting it loads them for new art as any +/// object without a stroke does (the weight stays). +#[test] +fn selecting_a_colorized_image_gives_new_art_its_fill_and_no_stroke() { + let mut s = session(); + let id = image(&mut s, "gray", gray(false)); + s.execute("paint.setFill", &json!({"color": "#336699"})).unwrap(); + s.execute("select.none", &json!({})).unwrap(); + s.execute("paint.setFill", &json!({"color": "#ff0000"})).unwrap(); + s.execute("paint.setStroke", &json!({"color": "#00ff00"})).unwrap(); + s.execute("stroke.set", &json!({"weight": 5.0})).unwrap(); + s.execute("select.set", &json!({"ids": [id.0]})).unwrap(); + assert_eq!(s.paint.fill.color().map(|c| c.to_hex()), Some("#336699".into())); + assert_eq!((s.paint.stroke.clone(), s.paint.stroke_width), (Paint::None, 5.0)); +} + #[test] fn fill_proxy_invert_recolors_a_colorized_gray_image_and_undo_restores_it() { let mut s = session(); diff --git a/docs/mcp.md b/docs/mcp.md index 45ddabf8f..43d69f269 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -4199,8 +4199,8 @@ selected) on top of a template. With nothing selected, `stroke.set` / `stroke.se arrowheads, profile…) and `graphicStyle.apply` (every fill, stroke and effect, opacity, blend mode and the link to the style; `add: true` stacks it) set that template instead of editing art. With the Appearance panel's New Art Has Basic Appearance on (the default), a `select.*` command or `layer.target` that changes the selection loads the proxies and -the weight from it: only a paint or weight the selected objects share, and art without paint (a placed image) changes -nothing. With the option off (`appearance.setNewArtBasic {on: false}`, the preference `newArtBasic`) new art takes the +the weight from it: only a paint or weight the selected objects share, and art without paint (a placed image that isn't +colorized) changes nothing. With the option off (`appearance.setNewArtBasic {on: false}`, the preference `newArtBasic`) new art takes the whole appearance of the last selected object. `appearance.newArt` reports what the next object gets; `paint.default` resets it. `appearance.setNewArtBasic` rejects an `on` value that is not a boolean. Omitting `on` toggles the current preference.