From ef2d678cbf5095b859d5b730449e0d0df5035d5a Mon Sep 17 00:00:00 2001 From: "Ayberk A." <105879357+AyberkA0@users.noreply.github.com> Date: Tue, 13 Oct 2026 21:04:22 +0300 Subject: [PATCH] Fix #1679: a filled pencil path keeps a stroke of None The Pencil gave every path a black stroke when the stroke was None. With Fill new pencil strokes on and a fill set, the path now keeps no stroke; only a path that would show nothing (no fill, no stroke) still gets black. --- crates/engine/src/cmd/draw2.rs | 5 ++++- crates/engine/src/tests_draw2.rs | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/draw2.rs b/crates/engine/src/cmd/draw2.rs index ea4439ce..f3258523 100644 --- a/crates/engine/src/cmd/draw2.rs +++ b/crates/engine/src/cmd/draw2.rs @@ -615,7 +615,10 @@ fn freehand(s: &mut Session, p: &Value) -> Result { } let sp = fit_freehand(&pts, tol, closed); let fill = if bool_or(p, "fill", false) { s.paint.fill.clone() } else { Paint::None }; - let mut look = s.new_art_look(fill, stroke_paint(s), s.paint.stroke_width.max(0.1)); + // A pencil path with a fill keeps a stroke of None (#1679); only one that would show nothing + // gets black. A brush is its stroke. + let stroke = if brush || fill.is_none() { stroke_paint(s) } else { s.paint.stroke.clone() }; + let mut look = s.new_art_look(fill, stroke, s.paint.stroke_width.max(0.1)); if let Some(st) = look.appearance.stroke_mut() { st.pressure = pressure; } diff --git a/crates/engine/src/tests_draw2.rs b/crates/engine/src/tests_draw2.rs index c722c906..4d3f9ab3 100644 --- a/crates/engine/src/tests_draw2.rs +++ b/crates/engine/src/tests_draw2.rs @@ -1235,3 +1235,21 @@ fn pen_with_alt_converts_the_anchors_of_a_path_in_a_selected_group() { assert_eq!(paths(&s).len(), 1, "{wrap}: no new path"); } } + +/// #1679: a filled pencil path keeps a stroke of None; an unfilled one with no stroke gets black, +/// or it would show nothing. +#[test] +fn a_filled_pencil_path_keeps_no_stroke() { + let mut s = Session::new(); + s.execute("file.new", &json!({"width": 200, "height": 200})).unwrap(); + s.execute("select.none", &json!({})).unwrap(); + s.execute("paint.setFill", &json!({"color": "#ff0000"})).unwrap(); + s.execute("paint.setStroke", &json!({"none": true})).unwrap(); + let pts = json!([[10, 10], [60, 20], [90, 80], [20, 90]]); + let id = NodeId(s.execute("path.freehand", &json!({"points": pts, "fill": true})).unwrap()["id"].as_u64().unwrap()); + let n = s.doc().unwrap().doc.node(id).unwrap().clone(); + assert!(n.appearance.stroke_paint().is_none(), "{:?}", n.appearance); + assert!(!n.appearance.fill_paint().is_none()); + let id = NodeId(s.execute("path.freehand", &json!({"points": pts})).unwrap()["id"].as_u64().unwrap()); + assert!(!s.doc().unwrap().doc.node(id).unwrap().appearance.stroke_paint().is_none()); +}