diff --git a/crates/engine/src/cmd/hatch.rs b/crates/engine/src/cmd/hatch.rs index a8801cc0..6a549266 100644 --- a/crates/engine/src/cmd/hatch.rs +++ b/crates/engine/src/cmd/hatch.rs @@ -404,3 +404,33 @@ impl Interactive for BoundaryM { } } } + +#[cfg(test)] +mod tests { + use serde_json::json; + + use super::*; + + /// The drawing's only hatch and its handle (hatches go to the back of the draw order, so not the last entity). + fn only_hatch(s: &Session) -> (String, Hatch) { + let d = s.doc().unwrap(); + d.model.iter().find_map(|e| if let EntityKind::Hatch(h) = &e.kind { Some((e.handle.hex(), h.clone())) } else { None }).unwrap() + } + + #[test] + fn hatchedit_pattern_replaces_gradient() { + let mut s = Session::new(); + s.execute("rectang", &json!({ "p1": [0, 0], "p2": [10, 10] })).unwrap(); + s.execute("gradient", &json!({ "points": [[5, 5]], "color1": "1", "color2": "3" })).unwrap(); + let (h, hatch) = only_hatch(&s); + assert!(hatch.gradient.is_some()); + // Scale-only and angle-only edits keep the gradient. + s.execute("hatchedit", &json!({ "handles": [h.clone()], "scale": 2, "angle": 30 })).unwrap(); + assert!(only_hatch(&s).1.gradient.is_some()); + s.execute("hatchedit", &json!({ "handles": [h], "pattern": "ANSI31" })).unwrap(); + let hatch = only_hatch(&s).1; + assert_eq!(hatch.pattern, "ANSI31"); + assert!(!hatch.solid); + assert!(hatch.gradient.is_none()); + } +} diff --git a/crates/engine/src/cmd/props.rs b/crates/engine/src/cmd/props.rs index a0c36d34..25498a02 100644 --- a/crates/engine/src/cmd/props.rs +++ b/crates/engine/src/cmd/props.rs @@ -271,6 +271,10 @@ fn run_set(s: &mut Session, p: &Value) -> Result { if let Some(v) = str_param(p, "pattern") { h.pattern = v.to_ascii_uppercase(); h.solid = h.pattern == "SOLID"; + if !h.solid { + // A named pattern replaces the gradient fill; the renderer draws the gradient first when it is set. + h.gradient = None; + } } if let Some(x) = num("scale").filter(|x| *x > 0.0) { h.scale = x;