From 56ad84266dabe5b2b6db9ccc634e361b8d4dac0c Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 7 Nov 2026 06:15:28 -0800 Subject: [PATCH] Color management: color.gamutCheck rejects a colors param that is not a list A colors value that is not an array, such as "#fff" or 5, was ignored and the command checked the selection or the whole document instead. It is now an error. A null colors still checks the selection or document, as an omitted one does. --- crates/engine/src/cmd/colormgmt.rs | 6 +++++- crates/engine/src/tests/colormgmt.rs | 15 +++++++++++++++ docs/mcp.md | 8 ++++---- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/crates/engine/src/cmd/colormgmt.rs b/crates/engine/src/cmd/colormgmt.rs index ccc5d4ece..37ccc3004 100644 --- a/crates/engine/src/cmd/colormgmt.rs +++ b/crates/engine/src/cmd/colormgmt.rs @@ -683,7 +683,11 @@ fn convert_color(_: &mut Session, p: &Value) -> Result { fn gamut_check(s: &mut Session, p: &Value) -> Result { let mut cols: Vec = vec![]; - if let Some(a) = p.get("colors").and_then(Value::as_array) { + let colors = p.get("colors").filter(|v| !v.is_null()); + if let Some(v) = colors.filter(|v| !v.is_array()) { + return Err(bad("color.gamutCheck", format!("bad color {v}"))); + } + if let Some(a) = colors.and_then(Value::as_array) { for v in a { cols.push(color_value(v).ok_or_else(|| bad("color.gamutCheck", format!("bad color {v}")))?); } diff --git a/crates/engine/src/tests/colormgmt.rs b/crates/engine/src/tests/colormgmt.rs index 1ca956794..4ce1ba466 100644 --- a/crates/engine/src/tests/colormgmt.rs +++ b/crates/engine/src/tests/colormgmt.rs @@ -631,3 +631,18 @@ fn set_spot_refuses_a_param_of_the_wrong_type() { s.execute("swatch.setSpot", &json!({"name": "Ink", "spot": null})).unwrap(); assert!(s.doc().unwrap().doc.swatch("Ink").unwrap().spot, "a null `spot` is the default, true"); } + +#[test] +fn gamut_check_refuses_colors_that_are_not_a_list() { + let _g = GLOBAL.lock().unwrap_or_else(|e| e.into_inner()); + let mut s = session(); + rect(&mut s, 0.0, 0.0, 10.0, 10.0, json!("#0000ff")); + s.execute("select.set", &json!({"ids": []})).unwrap(); + refused(&mut s, "color.gamutCheck", json!({"colors": "#00ff00"}), "bad color \"#00ff00\""); + refused(&mut s, "color.gamutCheck", json!({"colors": 5}), "bad color 5"); + refused(&mut s, "color.gamutCheck", json!({"colors": {"c": 100, "m": 0, "y": 0, "k": 0}}), "bad color"); + // A null list checks the document, as an omitted one does. + let r = s.execute("color.gamutCheck", &json!({"colors": null})).unwrap(); + assert_eq!(r, s.execute("color.gamutCheck", &json!({})).unwrap()); + assert!(r["outOfGamut"].as_array().unwrap().iter().any(|v| v["hex"] == "#0000ff"), "{r}"); +} diff --git a/docs/mcp.md b/docs/mcp.md index c978252f4..d953a310d 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -662,10 +662,10 @@ them. `grays: "black"` puts RGB greys with R = G = B on the black plate instead, Convert to Grayscale before the switch would give); other colors convert as usual. The reply's `changed` counts the colors that changed in the art, symbols, graph designs and pattern tiles; it does not count the colors of graphic styles and brushes. -`edit.colorSettings`, `file.documentColorMode`, `color.convert`, `color.loadProfile`, `color.removeProfile`, -`view.proofSetup`, `view.proofColors`, `view.overprintPreview`, `view.separationsPreview` and `swatch.setSpot` reject a -param of the wrong type, such as `"bpc": "no"`, `"on": 1` or `"to": 5`, and change nothing. Omitting a param or giving -null keeps its default. +`edit.colorSettings`, `file.documentColorMode`, `color.convert`, `color.gamutCheck`, `color.loadProfile`, +`color.removeProfile`, `view.proofSetup`, `view.proofColors`, `view.overprintPreview`, `view.separationsPreview` and +`swatch.setSpot` reject a param of the wrong type, such as `"bpc": "no"`, `"on": 1`, `"to": 5` or `"colors": "#fff"`, +and change nothing. Omitting a param or giving null keeps its default. SVG import keeps what the canvas edits live. `` becomes a pattern swatch. A `` with `` becomes a symbol (named after its `data-name`, else its id) with an instance per ``; a `` that shows it differently