diff --git a/crates/engine/src/cmd/textedit.rs b/crates/engine/src/cmd/textedit.rs index df19ec002..ac0af5867 100644 --- a/crates/engine/src/cmd/textedit.rs +++ b/crates/engine/src/cmd/textedit.rs @@ -1616,27 +1616,3 @@ fn discard_empty(s: &mut Session, p: &Value) -> Result { s.edit("Discard Empty Type", |d, _| d.remove(id).map(|_| ()).map_err(|_| EngineError::NoNode(id)))?; Ok(json!({"removed": true})) } - -#[cfg(test)] -mod range_stroke_tests { - use super::*; - - #[test] - fn range_stroke_gains_a_default_weight_and_scales_explicit_weight() { - let mut s = Session::new(); - s.execute("file.new", &json!({"width": 400, "height": 300})).unwrap(); - let id = s.execute("text.create", &json!({"x": 10, "y": 50, "text": "ABCD"})).unwrap()["id"].as_u64().unwrap(); - let weights = |s: &Session| { - let NodeKind::Text(t) = &s.doc().unwrap().doc.node(NodeId(id)).unwrap().kind else { panic!("text missing") }; - t.runs.iter().map(|r| r.style.stroke_width).collect::>() - }; - s.execute("text.setRangeStyle", &json!({"id": id, "start": 0, "end": 2, "stroke": "#ff0000"})).unwrap(); - assert_eq!(weights(&s), [1.0, 0.0], "a newly painted range has a visible default stroke"); - - s.execute("object.scale", &json!({"ids": [id], "sx": 200, "sy": 200})).unwrap(); - s.execute("text.setRangeStyle", &json!({"id": id, "start": 0, "end": 2, "strokeWidth": 2.0})).unwrap(); - assert_eq!(weights(&s), [1.0, 0.0], "two document points become one text-space point at 200% scale"); - s.execute("text.setRangeStyle", &json!({"id": id, "start": 2, "end": 4, "stroke": "#0000ff", "strokeWidth": 4.0})).unwrap(); - assert_eq!(weights(&s), [1.0, 2.0], "a different range receives its scaled weight"); - } -} diff --git a/crates/engine/src/tests/charstroke.rs b/crates/engine/src/tests/charstroke.rs index ba948cb66..2c34e697e 100644 --- a/crates/engine/src/tests/charstroke.rs +++ b/crates/engine/src/tests/charstroke.rs @@ -91,6 +91,21 @@ fn range_stroke_options_split_runs() { assert!(s.execute("text.setRangeStyle", &json!({"id": id.0, "strokeOptions": 3})).is_err()); } +#[test] +fn range_stroke_gains_a_default_weight_and_scales_explicit_weight() { + let mut s = session(); + let id = NodeId(run(&mut s, "text.create", json!({"x": 10, "y": 50, "text": "ABCD"}))["id"].as_u64().unwrap()); + let weights = |s: &Session| text(s, id).runs.iter().map(|r| r.style.stroke_width).collect::>(); + run(&mut s, "text.setRangeStyle", json!({"id": id.0, "start": 0, "end": 2, "stroke": "#ff0000"})); + assert_eq!(weights(&s), [1.0, 0.0], "a newly painted range has a visible default stroke"); + + run(&mut s, "object.scale", json!({"ids": [id.0], "sx": 200, "sy": 200})); + run(&mut s, "text.setRangeStyle", json!({"id": id.0, "start": 0, "end": 2, "strokeWidth": 2.0})); + assert_eq!(weights(&s), [1.0, 0.0], "two document points become one text-space point at 200% scale"); + run(&mut s, "text.setRangeStyle", json!({"id": id.0, "start": 2, "end": 4, "stroke": "#0000ff", "strokeWidth": 4.0})); + assert_eq!(weights(&s), [1.0, 2.0], "a different range receives its scaled weight"); +} + #[test] fn eyedropper_and_outlines_carry_the_character_stroke() { let mut s = session(); diff --git a/docs/mcp.md b/docs/mcp.md index 8a2551ffc..864a1af92 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -2404,6 +2404,8 @@ dash?, dashOffset?, alignDashes?}}`. `text.setStyle {ids?, stroke?, strokeWidth? and weight of the characters of each object given (without `start` and `end`: all of its text), with its other keys in one undo step; `strokeWidth` is in document points, as `stroke.set` gives the weight of scaled type. A `stroke` color without `strokeWidth` gives characters that have no stroke weight 1 pt, as `paint.setStroke` does. +`text.setRangeStyle` does the same for its range, and its `strokeWidth` and `strokeOptions` lengths are in document +points too. `align: "inside"|"outside"` keeps the characters' stroke on that side of the glyph outlines, drawn at twice the weight and clipped, while the type stays editable (beyond Illustrator); SVG export writes the text live and that stroke as glyph outlines over it. `inspect_document` reports each object's stroke as `strokeOptions` (type: its first