diff --git a/crates/engine/src/cmd/recolor.rs b/crates/engine/src/cmd/recolor.rs index 731d9ea55..52431090c 100644 --- a/crates/engine/src/cmd/recolor.rs +++ b/crates/engine/src/cmd/recolor.rs @@ -31,7 +31,7 @@ pub fn specs() -> Vec { "Recolor Artwork", ["Edit", "Edit Colors"], None, - "{map: rows [{from: [colour keys (recolor.colors) or \"#rrggbb\" (every colour shown as that hex)], to: colour (hex, key, {c,m,y,k} or {l,a,b}) | null, exclude?: false (the row's colours are kept)}] | {\"key or #rrggbb\": colour, …} (one row per colour), method?: \"exact\" (default)|\"preserveTints\"|\"scaleTints\"|\"tintsShades\"|\"hueShift\" (how a row's colours take its new colour, relative to the row's darkest, average or most saturated colour), limitTo?: swatch library id or name; or \"document\" (the document's swatches): new colours snap to its nearest colour, group?: colour group to rewrite, groupColors?: [colour] (what `group` is rewritten with; default: the rows' new colours, in order, excluded rows left out), rename?: the group's new name, includeImages?: true, includePatterns?: true} recolour the selection (gradients, text, meshes, image pixels and pattern tiles included; each new colour keeps the model of the one it replaces (model?: \"keep\" default | \"new\" (the new colour's own model, so a CMYK colour replacing RGB art gives CMYK art) | \"document\" (the document's colour mode)), except a library swatch's with limitTo: art takes the swatch itself, linked to a global or spot colour at its tints, and the swatch joins the document's swatches; art linked to a global swatch of `group` that is rewritten with its row's new color stays linked to it, at its tint; other recolored art, and art in a row linked to a global swatch of `group` that is rewritten with another color, keeps its row's new color and loses its swatch link) and the group, as one undo step → {changed, swatches: [names added to the document's swatches], relinked?: with group, the other paints linked to its global swatches that took their new colors, note?: set when a colour kept a model other than its new colour's (see model)}", + "{map: rows [{from: [colour keys (recolor.colors) or \"#rrggbb\" (every colour shown as that hex)], to: colour (hex, key, {c,m,y,k} or {l,a,b}) | null, exclude?: false (the row's colours are kept)}] | {\"key or #rrggbb\": colour, …} (one row per colour), method?: \"exact\" (default)|\"preserveTints\"|\"scaleTints\"|\"tintsShades\"|\"hueShift\" (how a row's colours take its new colour, relative to the row's darkest, average or most saturated colour), limitTo?: swatch library id or name; or \"document\" (the document's swatches): new colours snap to its nearest colour, group?: colour group to rewrite, groupColors?: [colour] (what `group` is rewritten with; default: the rows' new colours, in order, excluded rows left out), rename?: the group's new name, includeImages?: true, includePatterns?: true} recolour the selection (gradients, text, meshes, image pixels and pattern tiles included; each new colour keeps the model of the one it replaces (model?: \"keep\" default | \"new\" (the new colour's own model, so a CMYK colour replacing RGB art gives CMYK art) | \"document\" (the document's colour mode)), except a library swatch's with limitTo: art takes the swatch itself, linked to a global or spot colour at its tints, and the swatch joins the document's swatches; art linked to a global swatch of `group` that is rewritten with its row's new color stays linked to it, at its tint, unless the row converts the color into the art's model; other recolored art, and art in a row linked to a global swatch of `group` that is rewritten with another color, keeps its row's new color and loses its swatch link) and the group, as one undo step → {changed, swatches: [names added to the document's swatches], relinked?: with group, the other paints linked to its global swatches that took their new colors, note?: set when a colour kept a model other than its new colour's (see model)}", has_doc, apply ), @@ -353,7 +353,8 @@ impl ColorMap { /// Recolour a colour that can link to a swatch: a row whose new colour is a global or spot /// swatch links its colours to it (at their tints; shades and other hues stay unlinked), a /// process swatch gives its colour in its own model; a color linked to a global swatch of the - /// rewritten group that takes the row's new color keeps its link (at its tint in the row); + /// rewritten group that takes the row's new color keeps its link (at its tint in the row) when + /// the row gives it the new color in that color's model; /// other rows map the colour, which loses its link when it changes or when the group's rewrite /// would change it. True when anything changed. fn map_link(&self, c: &mut Color, link: &mut Option, tint: &mut f32) -> bool { @@ -362,6 +363,7 @@ impl ColorMap { if l.is_none() && let Some(g) = link.as_deref().and_then(|n| self.group.iter().find(|g| g.name == n)) && self.tos.get(i) == Some(&g.color) + && !row.converts(*c) && let Some(t) = row.tint(*c) { let t = t.clamp(0.0, 1.0); diff --git a/crates/engine/src/tests_recolor.rs b/crates/engine/src/tests_recolor.rs index 49869369a..af53f15ec 100644 --- a/crates/engine/src/tests_recolor.rs +++ b/crates/engine/src/tests_recolor.rs @@ -438,6 +438,15 @@ fn apply_with_a_group_keeps_art_linked_to_its_global_swatches() { run(&mut s, "recolor.apply", json!({"map": {"#2878f0": "#2878f0"}, "group": "Brand", "groupColors": ["#123456"]})); assert_eq!(link(&s, full), (blue, None, 1.0)); assert_eq!(swatch_hex(&s), "#123456"); + // A CMYK new color for RGB art keeps the art's model (model: "keep"), so the art takes the + // color in RGB, unlinked, while the swatch takes it in CMYK. + run(&mut s, "edit.undo", json!({})); + select_all(&mut s); + let r = run(&mut s, "recolor.apply", json!({"map": {"#2878f0": {"c": 0, "m": 60, "y": 100, "k": 0}}, "group": "Brand"})); + assert!(r["note"].is_string(), "{r}"); + let (c, w, _) = link(&s, full); + assert!(matches!(c, Color::Rgb { .. }) && w.is_none(), "{c:?} {w:?}"); + assert!(matches!(s.doc().unwrap().doc.swatch(&name).unwrap().paint.color(), Some(Color::Cmyk { .. }))); // Without a group the swatch is unchanged, so the art takes the new color unlinked. run(&mut s, "edit.undo", json!({})); select_all(&mut s); diff --git a/docs/mcp.md b/docs/mcp.md index c3131f906..643ca72e2 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -1696,7 +1696,7 @@ group together. Art linked to one of the group's global swatches stays linked wh row's new color (the default without `groupColors` when the rows follow the group's order), so a later `swatch.edit` still reaches it; the reply's `relinked` counts the other linked paints that took the group's new colors. Art in a row that is linked to a swatch rewritten with another color keeps its row's new color, even an unchanged one, and is no longer -linked to the swatch. Without `group`, +linked to the swatch, as does art whose color the row converts into the art's own color model. Without `group`, the swatch keeps its color and the recolored art is no longer linked to it. ```json