Pencil: Live preview option, a thin line while drawing when it is off

A Pencil stroke always previewed as the path it draws, with its full
appearance: with a fill set, the fill flipped between the shape and its
inside-out as the stroke crossed itself or curved back, and hid the line
being drawn.

Pencil Tool Options get a Live preview checkbox, above Live curve
fitting, on by default and kept with the tool's other options
(`livePreview`, settings.rs). With it off, the stroke previews nothing
while it is drawn: a thin line follows the pen (the drag overlay the
Knife and Blob Brush already show), and the release, or a switch of
tool mid-stroke, draws the path with its fill and stroke, as one undo
step, as before. Escape still cancels the stroke. With it on nothing
changes. The Paintbrush has no such option and keeps previewing.

Public reference: Draw and edit paths using the Pencil tool,
https://helpx.adobe.com/illustrator/using/tool-techniques/pencil-tool.html
(lists Live preview and Live curve fitting among the Pencil's options).

The checkbox label is translated in all 24 catalogs.

Tests: pencil_with_live_preview_off_shows_a_thin_line_until_the_release
(tools), pencil_with_live_preview_off_draws_the_filled_path_on_release
(engine), and the freehand dialog test shows the checkbox for the Pencil
only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ncic
2026-10-26 12:52:32 +07:00
committed by bflatastic
co-authored by Claude Opus 5.5
parent 9a9d6dae3e
commit 21e9c8ff31
29 changed files with 141 additions and 11 deletions
+26
View File
@@ -2771,3 +2771,29 @@ fn pencil_redraws_a_selected_compound_path() {
assert_eq!(s.doc().unwrap().selection.objects, compound);
assert!(members(&s)[1] != before[1], "the hole is redrawn");
}
/// With the Pencil's Live preview off, nothing is added to the document while a filled stroke is
/// drawn; the release draws the path with its fill, as one undo step.
#[test]
fn pencil_with_live_preview_off_draws_the_filled_path_on_release() {
let mut s = session();
s.execute("select.none", &json!({})).unwrap();
s.execute("paint.setFill", &json!({"color": "#ff0000"})).unwrap();
s.set_tool_option_cmd(&json!({"tool": "pencil", "values": {"livePreview": false, "fill": true}})).unwrap();
assert_eq!(s.tool_options_of("pencil")["livePreview"], json!(false));
let v = view();
s.select_tool("pencil", v).unwrap();
let count = |s: &Session| s.doc().unwrap().doc.layers[0].children().map_or(0, |c| c.len());
let (before, undo) = (count(&s), s.doc().unwrap().history.undo.len());
s.pointer(&PointerEvent::new(PointerKind::Down, 100.0, 100.0), v).unwrap();
for (x, y) in [(160.0, 110.0), (190.0, 170.0), (120.0, 190.0), (105.0, 120.0)] {
s.pointer(&PointerEvent::new(PointerKind::Drag, x, y), v).unwrap();
assert_eq!(count(&s), before, "nothing drawn while the stroke is drawn");
}
s.pointer(&PointerEvent::new(PointerKind::Up, 105.0, 120.0), v).unwrap();
assert_eq!(count(&s), before + 1, "the release draws the path");
let doc = &s.doc().unwrap().doc;
let n = doc.layers[0].children().unwrap().last().unwrap();
assert!(n.path_data().is_some() && !n.appearance.fill_paint().is_none(), "{:?}", n.appearance);
assert_eq!(s.doc().unwrap().history.undo.len(), undo + 1, "one undo step");
}