diff --git a/crates/engine/src/cmd/style.rs b/crates/engine/src/cmd/style.rs index 0ff7c8a4f..76e878277 100644 --- a/crates/engine/src/cmd/style.rs +++ b/crates/engine/src/cmd/style.rs @@ -1536,13 +1536,16 @@ fn create_object(s: &mut Session, p: &Value) -> Result { } /// `p.stroke` merged over `base` (as [`group_param`]), refused when the weight isn't a number ≥ 0 -/// or the tint isn't finite. +/// or the tint isn't 0–1. fn stroke_param(cmd: &str, p: &Value, base: Option<&designcraft_doc::Stroke>) -> Result>> { let st = group_param(cmd, p, "stroke", base.unwrap_or(&designcraft_doc::Stroke::default()))?; - if let Some(Some(st)) = &st - && !(st.weight.is_finite() && st.weight >= 0.0 && st.tint.is_finite()) - { - return Err(bad(cmd, "stroke weight must be a number ≥ 0")); + if let Some(Some(st)) = &st { + if !(st.weight.is_finite() && st.weight >= 0.0) { + return Err(bad(cmd, "stroke weight must be a number ≥ 0")); + } + if !(0.0..=1.0).contains(&st.tint) { + return Err(bad(cmd, "stroke tint must be 0..1")); + } } Ok(st) } diff --git a/crates/engine/src/tests.rs b/crates/engine/src/tests.rs index 0441f9bd9..4770fb16a 100644 --- a/crates/engine/src/tests.rs +++ b/crates/engine/src/tests.rs @@ -730,6 +730,10 @@ fn object_styles_carry_corners_and_their_stroke_and_corners_can_be_edited() { for cmd in ["style.object.create", "style.object.edit"] { let e = s.execute(cmd, &json!({"name": "Framed", "stroke": {"weight": -3}})).unwrap_err(); assert!(e.to_string().contains("stroke weight"), "{cmd}: {e}"); + for tint in [-1.0, 1.5] { + let e = s.execute(cmd, &json!({"name": "Framed", "stroke": {"tint": tint}})).unwrap_err(); + assert!(e.to_string().contains("stroke tint"), "{cmd}: {e}"); + } } assert_eq!(s.doc().unwrap().doc.styles.object.len(), styles); // null: the style stops setting corners, the items keep theirs.