diff --git a/contributors/people.toml b/contributors/people.toml index 7686bc4e2..d2f765745 100644 --- a/contributors/people.toml +++ b/contributors/people.toml @@ -127,6 +127,10 @@ sync_github_name = true [people.dennismutuku2005] sync_github_name = true +[people.krinry] +display_name = "krinry" +sync_github_name = true + [people.makesomethingshit] sync_github_name = true diff --git a/crates/tools/src/draw2/gesture.rs b/crates/tools/src/draw2/gesture.rs index c7cf84f9f..b40bd1a2b 100644 --- a/crates/tools/src/draw2/gesture.rs +++ b/crates/tools/src/draw2/gesture.rs @@ -39,6 +39,11 @@ pub struct GestureTool { /// "Keep selected": select the path a Pencil, Paintbrush or Blob Brush stroke draws, continues /// or merges into (on for the Pencil and Paintbrush, off for the Blob Brush). pub keep_selected: bool, + /// "Alt key toggles to Smooth Tool": holding Alt with the Pencil tool smooths selected paths + /// instead of closing the path (Pencil only, on by default). + pub alt_smooth: bool, + /// Active drag is smoothing with the Pencil tool. + smoothing: bool, /// "Merge only with selection": a Blob Brush stroke merges only with selected paths. pub merge_only_selection: bool, /// "Edit selected paths within N pixels". @@ -74,6 +79,8 @@ impl GestureTool { size: 10.0, fill: false, keep_selected: id != "blobBrush", + alt_smooth: id == "pencil", + smoothing: false, merge_only_selection: false, edit_within: 12.0, close_within: 15.0, @@ -181,13 +188,22 @@ impl GestureTool { let pts = &self.points; let has_sel = !cx.selection.is_empty(); let tol = cx.tol(self.edit_within); + if self.smoothing { + if has_sel && pts.len() >= 2 { + return vec![Action::Exec( + "path.smoothRegion".into(), + json!({"points": points_json(pts), "radius": tol, "fidelity": self.fidelity}), + )]; + } + return vec![]; + } match self.id { "pencil" | "paintbrush" => { if !self.began { return vec![]; } let near = pts.len() > 2 && pts[0].distance(pts[pts.len() - 1]) <= cx.tol(self.close_within); - let closed = m.alt || (self.extend.is_none() && near); + let closed = (m.alt && !self.alt_smooth) || (self.extend.is_none() && near); vec![Action::Preview("path.freehand".into(), self.freehand_params(closed)), Action::Commit] } "blobBrush" => vec![Action::Exec( @@ -228,10 +244,11 @@ impl Tool for GestureTool { PointerKind::Down => { self.active = true; self.began = false; - self.extend = if self.draws_path() { self.find_extend(cx, p) } else { None }; - self.redraw = if self.draws_path() && self.extend.is_none() { self.find_redraw(cx, p) } else { None }; + self.smoothing = self.id == "pencil" && self.alt_smooth && ev.mods.alt; + self.extend = if self.draws_path() && !self.smoothing { self.find_extend(cx, p) } else { None }; + self.redraw = if self.draws_path() && !self.smoothing && self.extend.is_none() { self.find_redraw(cx, p) } else { None }; // A path continued starts at its end, one redrawn on it; a new one where it snaps. - let start = if self.snaps() && self.extend.is_none() && self.redraw.is_none() { self.snap.press(cx, p, &[], None) } else { p }; + let start = if self.snaps() && !self.smoothing && self.extend.is_none() && self.redraw.is_none() { self.snap.press(cx, p, &[], None) } else { p }; self.clear(); self.push(start, ev.pressure); vec![] @@ -240,7 +257,10 @@ impl Tool for GestureTool { if !self.active { return vec![]; } - if self.snaps() { + if !self.began && self.id == "pencil" && self.alt_smooth && ev.mods.alt { + self.smoothing = true; + } + if self.snaps() && !self.smoothing { // Where the stroke would end: shown, taken on release. self.snap.drag(cx, p, None); } @@ -248,7 +268,7 @@ impl Tool for GestureTool { return vec![]; } self.push(p, ev.pressure); - if !self.draws_path() { + if !self.draws_path() || self.smoothing { return vec![]; } let mut out = vec![]; @@ -263,11 +283,11 @@ impl Tool for GestureTool { if !self.active { return vec![]; } - let end = if self.snaps() { self.snap.drag(cx, p, None) } else { p }; + let end = if self.snaps() && !self.smoothing { self.snap.drag(cx, p, None) } else { p }; self.snap.clear(); if self.points.last().is_some_and(|l| l.distance(p) >= cx.tol(1.0)) { self.push(end, ev.pressure); - } else if self.snaps() + } else if self.snaps() && !self.smoothing && self.points.len() > 1 && let Some(last) = self.points.last_mut() { @@ -277,6 +297,7 @@ impl Tool for GestureTool { let out = self.finish(cx, ev.mods); self.active = false; self.began = false; + self.smoothing = false; self.clear(); self.extend = None; self.redraw = None; @@ -296,6 +317,7 @@ impl Tool for GestureTool { self.snap.clear(); self.active = false; self.began = false; + self.smoothing = false; self.clear(); if began { vec![Action::Cancel] } else { vec![] } } @@ -331,7 +353,10 @@ impl Tool for GestureTool { o.push(Overlay::Path { path: polyline(&self.points), color, width, dashed: self.id == "knife" }); o } - fn cursor(&self, _cx: &ToolContext, _p: Point, _m: Mods) -> Cursor { + fn cursor(&self, _cx: &ToolContext, _p: Point, m: Mods) -> Cursor { + if self.id == "pencil" && self.alt_smooth && m.alt { + return Cursor::Smooth; + } match self.id { "paintbrush" => Cursor::Paintbrush, "blobBrush" => Cursor::BlobBrush, @@ -345,7 +370,17 @@ impl Tool for GestureTool { } fn options(&self) -> Value { match self.id { - "pencil" | "paintbrush" => { + "pencil" => { + json!({ + "fidelity": self.fidelity, + "fill": self.fill, + "altSmooth": self.alt_smooth, + "keepSelected": self.keep_selected, + "editWithin": self.edit_within, + "closeWithin": self.close_within + }) + } + "paintbrush" => { json!({ "fidelity": self.fidelity, "fill": self.fill, @@ -365,6 +400,7 @@ impl Tool for GestureTool { "fidelity" => self.fidelity = v.as_f64().unwrap_or(self.fidelity).clamp(0.05, 100.0), "size" => self.size = v.as_f64().unwrap_or(self.size).clamp(0.1, 1000.0), "fill" => self.fill = v.as_bool().unwrap_or(self.fill), + "altSmooth" => self.alt_smooth = v.as_bool().unwrap_or(self.alt_smooth), "keepSelected" => self.keep_selected = v.as_bool().unwrap_or(self.keep_selected), "mergeOnlySelection" => self.merge_only_selection = v.as_bool().unwrap_or(self.merge_only_selection), "editWithin" => self.edit_within = v.as_f64().unwrap_or(self.edit_within).clamp(0.0, 100.0), @@ -390,6 +426,16 @@ mod tests { v } + fn drag_held(t: &mut GestureTool, cx: &ToolContext, pts: &[(f64, f64)], m: Mods) -> Vec> { + let mut v = vec![t.pointer(cx, &PointerEvent::new(PointerKind::Down, pts[0].0, pts[0].1).with_mods(m))]; + for &(x, y) in &pts[1..] { + v.push(t.pointer(cx, &PointerEvent::new(PointerKind::Drag, x, y).with_mods(m))); + } + let l = pts[pts.len() - 1]; + v.push(t.pointer(cx, &PointerEvent::new(PointerKind::Up, l.0, l.1).with_mods(m))); + v + } + /// The Pencil's new path starts and ends on Smart Guides (#506), the points between where /// the hand went. #[test] @@ -540,4 +586,45 @@ mod tests { b.key(&cx, ToolKey::BracketRight, Mods::default()); assert_eq!(b.options()["size"], 11.0); } + + #[test] + fn pencil_alt_toggles_to_smooth_when_enabled_and_closes_when_disabled() { + let (d, id) = doc_with_rect(); + let mut s = Selection::default(); + s.set([id]); + let p = paint(); + let cx = cx(&d, &s, &p); + + // Pencil has alt_smooth on by default. + let mut t = GestureTool::new("pencil"); + assert_eq!(t.options()["altSmooth"], json!(true)); + + // When alt is pressed, cursor shows smooth tool. + let alt_mod = Mods { alt: true, ..Default::default() }; + assert_eq!(t.cursor(&cx, Point::new(50.0, 50.0), alt_mod), Cursor::Smooth); + assert_eq!(t.cursor(&cx, Point::new(50.0, 50.0), Mods::default()), Cursor::Pencil); + + // Alt-drag over selected path smooths it. + let acts = drag_held(&mut t, &cx, &[(50.0, 150.0), (150.0, 150.0), (250.0, 150.0)], alt_mod); + assert!(acts[1].is_empty(), "drag does not preview freehand path while smoothing"); + let last = acts.last().unwrap(); + assert!( + matches!(&last[0], Action::Exec(c, v) if c == "path.smoothRegion" && v["points"].as_array().unwrap().len() == 3), + "expected path.smoothRegion, got: {last:?}" + ); + + // When altSmooth is disabled: + t.set_option("altSmooth", &json!(false)); + assert_eq!(t.options()["altSmooth"], json!(false)); + assert_eq!(t.cursor(&cx, Point::new(50.0, 50.0), alt_mod), Cursor::Pencil); + + // Alt-drag draws a closed pencil path. + let empty_sel = Selection::default(); + let cx_empty = crate::testutil::cx(&d, &empty_sel, &p); + let acts = drag(&mut t, &cx_empty, &[(0.0, 0.0), (10.0, 5.0), (20.0, 0.0)], alt_mod); + assert_eq!(acts[1][0], Action::Begin("Pencil".into())); + let last = acts.last().unwrap(); + assert!(matches!(&last[0], Action::Preview(_, v) if v["closed"] == true && v["style"] == "pencil")); + assert_eq!(last[1], Action::Commit); + } } diff --git a/crates/ui-egui/src/dialogs/freehand.rs b/crates/ui-egui/src/dialogs/freehand.rs index 28592c85d..f5b60ef57 100644 --- a/crates/ui-egui/src/dialogs/freehand.rs +++ b/crates/ui-egui/src/dialogs/freehand.rs @@ -24,7 +24,7 @@ pub(super) const SPEC: DialogSpec = DialogSpec { heading, body, confirm, min_wid pub const TOOLS: [&str; 5] = ["pencil", "paintbrush", "smooth", "blobBrush", "eraser"]; /// The options the dialog edits, in the order it shows them (a tool has those it reports). -const KEYS: [&str; 7] = ["fidelity", "size", "fill", "keepSelected", "mergeOnlySelection", "closeWithin", "editWithin"]; +const KEYS: [&str; 8] = ["fidelity", "size", "fill", "altSmooth", "keepSelected", "mergeOnlySelection", "closeWithin", "editWithin"]; /// Width of the label column: wide enough for the tolerances' labels when there are any. fn label_w(d: &Dialog) -> f32 { @@ -103,6 +103,9 @@ fn body(_app: &mut VectorcraftApp, ui: &mut egui::Ui, d: &mut Dialog) -> bool { if d.fields.contains_key("fill") { check(ui, d, "fill", tl!("Fill new strokes")); } + if d.fields.contains_key("altSmooth") { + check(ui, d, "altSmooth", tl!("Alt key toggles to Smooth Tool")); + } if d.fields.contains_key("keepSelected") { check(ui, d, "keepSelected", tl!("Keep selected")); if d.fields.contains_key("mergeOnlySelection") { @@ -153,6 +156,7 @@ mod tests { "Accurate", "Smooth", "Fill new strokes", + "Alt key toggles to Smooth Tool", "Close paths when ends are within:", "Edit selected paths within:", ] { @@ -160,27 +164,29 @@ mod tests { } assert!(!text.contains("Size:"), "{text}"); let d = app.ui.dialog.as_mut().unwrap(); - assert_eq!((d.f64("fidelity", 0.0), d.bool("fill"), d.f64("closeWithin", 0.0), d.f64("editWithin", 0.0)), (1.5, false, 15.0, 12.0)); - for (k, v) in [("fidelity", json!(6.5)), ("fill", json!(true)), ("closeWithin", json!(0)), ("editWithin", json!(20))] { + assert_eq!((d.f64("fidelity", 0.0), d.bool("fill"), d.bool("altSmooth"), d.f64("closeWithin", 0.0), d.f64("editWithin", 0.0)), (1.5, false, true, 15.0, 12.0)); + for (k, v) in [("fidelity", json!(6.5)), ("fill", json!(true)), ("altSmooth", json!(false)), ("closeWithin", json!(0)), ("editWithin", json!(20))] { d.fields.insert(k.into(), v); } super::super::confirm(&mut app).unwrap(); assert!(app.ui.dialog.is_none()); let o = app.session.tool_options_of("pencil"); assert_eq!( - (o["fidelity"].as_f64(), o["fill"].as_bool(), o["closeWithin"].as_f64(), o["editWithin"].as_f64()), - (Some(6.5), Some(true), Some(0.0), Some(20.0)) + (o["fidelity"].as_f64(), o["fill"].as_bool(), o["altSmooth"].as_bool(), o["closeWithin"].as_f64(), o["editWithin"].as_f64()), + (Some(6.5), Some(true), Some(false), Some(0.0), Some(20.0)) ); // The Paintbrush keeps its own: the Pencil's change left it alone. app.run("tool.options", json!({"tool": "paintbrush"})).unwrap(); let d = app.ui.dialog.as_ref().unwrap(); assert_eq!((d.f64("fidelity", 0.0), d.bool("fill")), (1.5, false)); - assert!(painted(&mut app).contains("Paintbrush Tool Options")); + let pb_text = painted(&mut app); + assert!(pb_text.contains("Paintbrush Tool Options")); + assert!(!pb_text.contains("Alt key toggles to Smooth Tool")); // Smooth has Fidelity only, the Eraser Size only, and the Blob Brush Size, Keep selected and Merge only with selection. app.run("tool.options", json!({"tool": "smooth"})).unwrap(); let text = painted(&mut app); assert!(text.contains("Smooth Tool Options") && text.contains("Fidelity:"), "{text}"); - assert!(!text.contains("Fill new strokes") && !text.contains("Keep selected") && !text.contains("Size:"), "{text}"); + assert!(!text.contains("Fill new strokes") && !text.contains("Keep selected") && !text.contains("Alt key toggles to Smooth Tool") && !text.contains("Size:"), "{text}"); for tool in ["blobBrush", "eraser"] { app.run("tool.options", json!({"tool": tool})).unwrap(); let text = painted(&mut app); diff --git a/crates/ui-egui/src/i18n/bg.tsv b/crates/ui-egui/src/i18n/bg.tsv index 84ff3a8f5..98f1a3e67 100644 --- a/crates/ui-egui/src/i18n/bg.tsv +++ b/crates/ui-egui/src/i18n/bg.tsv @@ -1058,6 +1058,7 @@ Fill (X), double-click for the Color Picker Запълване (X), щракнете двукратно за избор на цвят Fill and Stroke Запълване и щрих Fill new strokes Запълване на нови щрихове + Alt key toggles to Smooth Tool Клавишът Alt превключва към инструмент „Гладкост“ Fill Color Цвят на запълване Fill New Type Objects With Placeholder Text Запълване на нови текстови обекти с примесен текст Fill Rule Правило за запълване diff --git a/crates/ui-egui/src/i18n/cs.tsv b/crates/ui-egui/src/i18n/cs.tsv index 38767b21e..8f7b9ce79 100644 --- a/crates/ui-egui/src/i18n/cs.tsv +++ b/crates/ui-egui/src/i18n/cs.tsv @@ -2250,6 +2250,7 @@ lighting Light Světlo Edit selected paths within: Upravovat vybrané cesty do: Fidelity: Věrnost: Fill new strokes Vyplňovat nové tahy + Alt key toggles to Smooth Tool Klávesa Alt přepíná na nástroj Vyhlazení Keep selected Ponechat vybrané Merge only with selection Sloučit jen s výběrem The document has no colour swatches. Dokument nemá ve vzorníku žádné barvy. diff --git a/crates/ui-egui/src/i18n/da.tsv b/crates/ui-egui/src/i18n/da.tsv index cc0b4372c..0018279a2 100644 --- a/crates/ui-egui/src/i18n/da.tsv +++ b/crates/ui-egui/src/i18n/da.tsv @@ -2064,6 +2064,7 @@ lighting Light Lys Edit selected paths within: Redigér markerede stier inden for: Fidelity: Præcision: Fill new strokes Udfyld nye konturer + Alt key toggles to Smooth Tool Alt-tasten skifter til Udglatningsværktøj The document has no colour swatches. Dokumentet har ingen farveprøver. Style Name: Typografinavn: Crop To Beskær til diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index 3af56b769..db7ea1dd4 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -1062,6 +1062,7 @@ Fill (X), double-click for the Color Picker Fläche (X), Doppelklick öffnet den Farbwähler Fill and Stroke Fläche und Kontur Fill new strokes Neue Striche füllen + Alt key toggles to Smooth Tool Alt-Taste schaltet auf Glätten-Werkzeug um Keep selected Ausgewählt lassen Merge only with selection Nur mit Auswahl zusammenfügen Fill Color Flächenfarbe diff --git a/crates/ui-egui/src/i18n/el.tsv b/crates/ui-egui/src/i18n/el.tsv index c3d0cae20..caa2c90df 100644 --- a/crates/ui-egui/src/i18n/el.tsv +++ b/crates/ui-egui/src/i18n/el.tsv @@ -1024,6 +1024,7 @@ Fill (X), double-click for the Color Picker Γέμισμα (X), διπλό κλικ για τον επιλογέα χρώματος Fill and Stroke Γέμισμα και περίγραμμα Fill new strokes Γέμισμα νέων περιγραμμάτων + Alt key toggles to Smooth Tool Το πλήκτρο Alt αλλάζει στο εργαλείο Εξομάλυνση (Smooth Tool) Fill Color Χρώμα γεμίσματος Fill New Type Objects With Placeholder Text Συμπλήρωση νέων αντικειμένων κειμένου με κείμενο υπόδειξης Fill Rule Κανόνας γεμίσματος diff --git a/crates/ui-egui/src/i18n/es.tsv b/crates/ui-egui/src/i18n/es.tsv index 006f293e9..e3dc401b4 100644 --- a/crates/ui-egui/src/i18n/es.tsv +++ b/crates/ui-egui/src/i18n/es.tsv @@ -1078,6 +1078,7 @@ Fill (X), double-click for the Color Picker Relleno (X), doble clic para el selector de color Fill and Stroke Relleno y trazo Fill new strokes Rellenar trazos nuevos + Alt key toggles to Smooth Tool La tecla Alt cambia a la herramienta Suavizar Keep selected Mantener seleccionado Merge only with selection Combinar solo con la selección Fill Color Color de relleno diff --git a/crates/ui-egui/src/i18n/fi.tsv b/crates/ui-egui/src/i18n/fi.tsv index 67cb355d8..669df6575 100644 --- a/crates/ui-egui/src/i18n/fi.tsv +++ b/crates/ui-egui/src/i18n/fi.tsv @@ -2207,6 +2207,7 @@ lighting Light Valo Edit selected paths within: Muokkaa valittuja polkuja etäisyydellä: Fidelity: Tarkkuus: Fill new strokes Täytä uudet viivat + Alt key toggles to Smooth Tool Alt-näppäin vaihtaa Tasoitustyökaluun The document has no colour swatches. Asiakirjassa ei ole värimalleja. Style Name: Tyylin nimi: Crop To Rajaa kohteeseen diff --git a/crates/ui-egui/src/i18n/fr.tsv b/crates/ui-egui/src/i18n/fr.tsv index 6b66c3301..68e5699a7 100644 --- a/crates/ui-egui/src/i18n/fr.tsv +++ b/crates/ui-egui/src/i18n/fr.tsv @@ -1078,6 +1078,7 @@ Fill (X), double-click for the Color Picker Fond (X), double-cliquez pour ouvrir le Sélecteur de couleurs Fill and Stroke Fond et contour Fill new strokes Remplir les nouveaux contours + Alt key toggles to Smooth Tool La touche Alt bascule sur l’outil Arrondi Keep selected Garder sélectionné Merge only with selection Fusionner uniquement avec la sélection Fill Color Couleur de fond diff --git a/crates/ui-egui/src/i18n/hu.tsv b/crates/ui-egui/src/i18n/hu.tsv index 0e6264219..ff455c9ce 100644 --- a/crates/ui-egui/src/i18n/hu.tsv +++ b/crates/ui-egui/src/i18n/hu.tsv @@ -1365,6 +1365,7 @@ Fill and Stroke Kitöltés és körvonal Fill Color Kitöltőszín Fill new strokes Új vonások kitöltése + Alt key toggles to Smooth Tool Az Alt billentyű a Simítás eszközre vált Keep selected Kijelölés megtartása Merge only with selection Összeolvasztás csak a kijelöléssel Fill New Type Objects With Placeholder Text Új szövegobjektumok kitöltése helykitöltő szöveggel diff --git a/crates/ui-egui/src/i18n/id.tsv b/crates/ui-egui/src/i18n/id.tsv index 95eb1a509..65190ac24 100644 --- a/crates/ui-egui/src/i18n/id.tsv +++ b/crates/ui-egui/src/i18n/id.tsv @@ -2064,6 +2064,7 @@ lighting Light Cahaya Edit selected paths within: Edit jalur terpilih dalam jarak: Fidelity: Fidelitas: Fill new strokes Isi stroke baru + Alt key toggles to Smooth Tool Tombol Alt beralih ke Alat penghalus The document has no colour swatches. Dokumen tidak memiliki swatch warna. Style Name: Nama gaya: Crop To Pangkas ke diff --git a/crates/ui-egui/src/i18n/it.tsv b/crates/ui-egui/src/i18n/it.tsv index 4ffe96e8c..fe0de9ba3 100644 --- a/crates/ui-egui/src/i18n/it.tsv +++ b/crates/ui-egui/src/i18n/it.tsv @@ -1078,6 +1078,7 @@ Fill (X), double-click for the Color Picker Riempimento (X), fai doppio clic per il selettore colore Fill and Stroke Riempimento e traccia Fill new strokes Riempi nuove tracce + Alt key toggles to Smooth Tool Il tasto Alt attiva lo strumento Smussa Keep selected Mantieni selezionato Merge only with selection Unisci solo con la selezione Fill Color Colore riempimento diff --git a/crates/ui-egui/src/i18n/ja.tsv b/crates/ui-egui/src/i18n/ja.tsv index d3aa0d99e..56ad5ab9a 100644 --- a/crates/ui-egui/src/i18n/ja.tsv +++ b/crates/ui-egui/src/i18n/ja.tsv @@ -1480,6 +1480,7 @@ Fill Rule 塗りのルール Fill and Stroke 塗りと線 Fill new strokes 新しいストロークに塗りを適用 + Alt key toggles to Smooth Tool Alt キーでスムーズツールに切り替え Keep selected 選択を保持 Merge only with selection 選択範囲とのみ結合 Fill: 塗り: diff --git a/crates/ui-egui/src/i18n/ko.tsv b/crates/ui-egui/src/i18n/ko.tsv index 378060525..d75734a88 100644 --- a/crates/ui-egui/src/i18n/ko.tsv +++ b/crates/ui-egui/src/i18n/ko.tsv @@ -1475,6 +1475,7 @@ Fill Rule 칠 규칙 Fill and Stroke 칠과 선 Fill new strokes 새 선 칠하기 + Alt key toggles to Smooth Tool Alt 키로 매끄럽게 도구로 전환 Keep selected 선택 유지 Merge only with selection 선택 영역과만 병합 Fill: 칠: diff --git a/crates/ui-egui/src/i18n/nl.tsv b/crates/ui-egui/src/i18n/nl.tsv index 5221574f9..915e0d510 100644 --- a/crates/ui-egui/src/i18n/nl.tsv +++ b/crates/ui-egui/src/i18n/nl.tsv @@ -2078,6 +2078,7 @@ lighting Light Licht Edit selected paths within: Geselecteerde paden bewerken binnen: Fidelity: Nauwkeurigheid: Fill new strokes Nieuwe lijnen vullen + Alt key toggles to Smooth Tool Alt-toets schakelt over naar Gladmaken-gereedschap The document has no colour swatches. Het document heeft geen kleurstalen. Style Name: Stijlnaam: Crop To Bijsnijden tot diff --git a/crates/ui-egui/src/i18n/pl.tsv b/crates/ui-egui/src/i18n/pl.tsv index f8d465ed5..ed914e79f 100644 --- a/crates/ui-egui/src/i18n/pl.tsv +++ b/crates/ui-egui/src/i18n/pl.tsv @@ -2165,6 +2165,7 @@ lighting Light Światło Edit selected paths within: Edytuj zaznaczone ścieżki w odległości: Fidelity: Wierność: Fill new strokes Wypełniaj nowe pociągnięcia + Alt key toggles to Smooth Tool Klawisz Alt przełącza na narzędzie Wygładzanie Keep selected Zachowaj zaznaczenie Merge only with selection Scalaj tylko z zaznaczeniem The document has no colour swatches. Dokument nie zawiera próbek kolorów. diff --git a/crates/ui-egui/src/i18n/pt-br.tsv b/crates/ui-egui/src/i18n/pt-br.tsv index 316fd2e50..0677e101a 100644 --- a/crates/ui-egui/src/i18n/pt-br.tsv +++ b/crates/ui-egui/src/i18n/pt-br.tsv @@ -963,6 +963,7 @@ Fill Rule Regra de Preenchimento Fill and Stroke Preenchimento e Traçado Fill new strokes Preencher novos traçados + Alt key toggles to Smooth Tool A tecla Alt alterna para a ferramenta Suavizar Keep selected Manter selecionado Merge only with selection Mesclar somente com a seleção Fill with Placeholder Text Preencher com Texto de Placeholder diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index b5b0b0a48..6e78153c2 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -1076,6 +1076,7 @@ Fill (X), double-click for the Color Picker Заливка (X), дважды щёлкните для палитры цветов Fill and Stroke Заливка и обводка Fill new strokes Заполнять новые обводки + Alt key toggles to Smooth Tool Клавиша Alt переключает на инструмент «Сглаживание» Keep selected Оставлять выбранным Merge only with selection Объединять только с выделенным Fill Color Цвет заливки diff --git a/crates/ui-egui/src/i18n/sv.tsv b/crates/ui-egui/src/i18n/sv.tsv index 4c80c2377..a402532ac 100644 --- a/crates/ui-egui/src/i18n/sv.tsv +++ b/crates/ui-egui/src/i18n/sv.tsv @@ -1060,6 +1060,7 @@ Fill (X), double-click for the Color Picker Fyllning (X), dubbelklicka för färgväljaren Fill and Stroke Fyllning och kontur Fill new strokes Fyll nya konturer + Alt key toggles to Smooth Tool Alt-tangenten växlar till Utjämningsverktyg Fill Color Fyllnadsfärg Fill New Type Objects With Placeholder Text Fyll nya textobjekt med platshållartext Fill Rule Fyllningsregel diff --git a/crates/ui-egui/src/i18n/uk.tsv b/crates/ui-egui/src/i18n/uk.tsv index 4eec82557..6fa711d05 100644 --- a/crates/ui-egui/src/i18n/uk.tsv +++ b/crates/ui-egui/src/i18n/uk.tsv @@ -1072,6 +1072,7 @@ Fill (X), double-click for the Color Picker Заливка (X), двічі клацніть на палітрі кольорів Fill and Stroke Заливка та обведення Fill new strokes Заповнювати нові обведення + Alt key toggles to Smooth Tool Клавіша Alt перемикає на інструмент «Згладжування» Keep selected Залишати вибраним Merge only with selection Об’єднувати лише з виділеним Fill Color Колір заливки diff --git a/crates/ui-egui/src/i18n/vi.tsv b/crates/ui-egui/src/i18n/vi.tsv index 0d510339d..7affdb91b 100644 --- a/crates/ui-egui/src/i18n/vi.tsv +++ b/crates/ui-egui/src/i18n/vi.tsv @@ -1243,6 +1243,7 @@ Fill Color Màu tô Fill Grid Tô lưới Fill new strokes Tô nét mới + Alt key toggles to Smooth Tool Phím Alt chuyển sang công cụ Làm mượt Keep selected Giữ trạng thái đã chọn Merge only with selection Chỉ hợp nhất với vùng chọn Fill New Type Objects With Placeholder Text Tô đối tượng chữ mới bằng văn bản giữ chỗ diff --git a/crates/ui-egui/src/i18n/zh-hans.tsv b/crates/ui-egui/src/i18n/zh-hans.tsv index d1631be8f..4e06b46b5 100644 --- a/crates/ui-egui/src/i18n/zh-hans.tsv +++ b/crates/ui-egui/src/i18n/zh-hans.tsv @@ -1026,6 +1026,7 @@ Fill (X), double-click for the Color Picker 填色 (X),双击打开拾色器 Fill and Stroke 填色和描边 Fill new strokes 为新描边应用填色 + Alt key toggles to Smooth Tool Alt 键切换为平滑工具 Keep selected 保持选择状态 Merge only with selection 仅与所选对象合并 Fill Color 填色 diff --git a/crates/ui-egui/src/i18n/zh-hant.tsv b/crates/ui-egui/src/i18n/zh-hant.tsv index 1b467c5a1..bfd52c8ea 100644 --- a/crates/ui-egui/src/i18n/zh-hant.tsv +++ b/crates/ui-egui/src/i18n/zh-hant.tsv @@ -1050,6 +1050,7 @@ Fill and Stroke 填色與筆畫 Fill Color 填色顏色 Fill new strokes 為新筆畫套用填色 + Alt key toggles to Smooth Tool Alt 鍵切換為平滑工具 Keep selected 保持選取狀態 Merge only with selection 僅與選取物件合併 Fill New Type Objects With Placeholder Text 以預留位置文字填滿新文字物件 diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index f75524886..f99ff869c 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -327,7 +327,7 @@ about 1–1.5 agent-hours each, so the other rows (estimated on the older scale) | Drawing tools | 7 | 85% | rough-square Shaper recognition and orientation steps corrected; editable Shaper Groups landed; remaining: Shaper construction widget/gesture refinements, pencil and the remaining pen modifier nuances, the freehand Tool Options' Keep selected, Alt to the Smooth tool, Blob Brush Merge Only with Selection and brush angle/roundness, Touch Type, Live Corners' Relative rounding (Curvature point display improved, #1236 in part) | 8–13 | | Selection, transform & align tools | 6 | 85% | Free Transform/Scale/Reflect along a rotated box, Start Global Edit, transform nuances (the rotated persistent bounding box is done; no-op anchor Align history regression-tested, #1180 follow-up) | 4–6 | | Selection, transform & align tools | 6 | 85% | Direct Selection segment click/Delete corrected (#1278); remaining: Free Transform/Scale/Reflect along a rotated box, Start Global Edit, transform nuances (the rotated persistent bounding box is done) | 4–6 | -| Drawing tools | 7 | 85% | rough-square Shaper recognition and orientation steps corrected; editable Shaper Groups landed; remaining: Shaper construction widget/gesture refinements, pencil and the remaining pen modifier nuances, the freehand Tool Options' Keep selected, Alt to the Smooth tool, Blob Brush Merge Only with Selection and brush angle/roundness, Touch Type, Live Corners' Relative rounding | 8–13 | +| Drawing tools | 7 | 86% | rough-square Shaper recognition and orientation steps corrected; editable Shaper Groups landed; Pencil: Alt key toggles to Smooth Tool (#2001); remaining: Shaper construction widget/gesture refinements, pencil and the remaining pen modifier nuances, Blob Brush Merge Only with Selection and brush angle/roundness, Touch Type, Live Corners' Relative rounding | 7–12 | | Path operations, Pathfinder, Shape Builder, Live Paint | 5 | 86% | Live Paint gap options, Shape Builder gap detection, options (Tool Options dialog, clicking a stroke in merge mode) and Shift-drag marquee | 3–6 | | Colour, swatches, gradients, patterns, mesh, recolor | 7 | 96% | freeform and mixed spot/process gradients in SVG/PDF (exported as stops or process colours), pattern fills in Expand | 2–4; Eyedropper source reads regression-tested (#1251) | | Strokes, brushes, width profiles | 5 | 90% | the Art brush's Overlap, auto-generated Pattern brush corners and new tile art in Pattern Brush Options (Brush Options for every brush type done), brush libraries (generated in code), pen pressure on macOS (the windowing layer reports none there), brushes driven by pen tilt, bearing and barrel rotation (6D art pens) | 8–15 | diff --git a/docs/ui-parity.md b/docs/ui-parity.md index a06ed0914..973acfefd 100644 --- a/docs/ui-parity.md +++ b/docs/ui-parity.md @@ -1,6 +1,6 @@ # UI and interaction parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-19 · **Change:** minor (status-readout sample widths cached by language, document unit and pixels per point; status messages and readouts use stable responsive allocations sized for localized labels and ordinary coordinates; cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; cached canvas reprojection preserves scale during resize, rotation and DPI changes; on-canvas Mirror Repeat axis, #2877; Background Export progress dialog with Cancel, #2564; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Blend spine Anchor Point conversions, selection/stacking priority and Shift regression coverage (#2544); scores and hours unchanged; Artboard Options' X and Y with a reference point, #1876; scores unchanged; library panels: one per library, dockable and tabbable, with Persistent, #2603; the Selection tool threads text from the out port, #2572 in part; scores unchanged; Group Selection picks and moves one path of a compound path, #2441 in part; the Move dialog opens on the last move and its last checkboxes; scores unchanged; transparency grid visibility saved in native documents, #1968; Live Corners radius up to the neighbouring cuts, #2332; Image Trace quick presets: wording corrected to the shipped behaviour, the Image Trace button opens the controls; batch exporting, #1935; document window scroll bars, #2322; Anchor Point tool: a click on a handle end retracts that handle only, #2267; scores unchanged; Smart Guides: the dragged end of a straight segment keeps to its extension at any angle, #2120; Warp Options controls verified by focused checks and original-image review; estimates unchanged; existing-guide Escape cancellation validated 2026-10-14; scores and hours unchanged; open-path anchor Delete keeps surviving runs separate; estimates unchanged; Artboard tab-switch follow-up historically validated on `a0671777`; scores and hours unchanged; Artboard clean active-tab close/Delete follow-up validated 2026-10-15; Curvature curve geometry, #1236 in part; Width-point finite-arithmetic follow-up validated; scores and hours unchanged; Image Trace adjustment discovery; later 2026-10-14 merges: macOS save sheet Format menu back to missing, #1855, #866 reopened; anchor X/Y/W/H in the Transform panel, Properties and Control bar, #1824; Snap to Grid over Snap to Pixel, #1816; toolbar labels, columns and the All Tools drawer, #1751; Actions panel selection, #1629 in part; scores unchanged; 2026-10-14 merges: anchor Align and Distribute, #1636; Delete on closed paths and whole objects, #1674; selection inside isolation, #1666; Escape in a Direct Selection drag and while typing, #1743, #1686; Pen clicks under 3 px, #1663; [ and ] on more tools, #1661 in part; fields commit on click away, #1787; command search keys, #1757; a guide's position in the Transform panel is a convenience with no parity claim, #1659; scores unchanged; intersect Smart Guides for drawn points and dragged anchors, #1602 in part; a ruler guide's position in the Transform panel, #1597 in part; Symbol Options before New Symbol, #1560; tool flyout widths, #1616; Pathfinder Trim, Merge and Crop strokes, #1570; scores unchanged; G1/M11: Artboard deletion and history selection normalization; history regressions and full workspace CI pass; scores and hours unchanged; Width Point Edit: Shift-double-click enables adjoining adjustment; plain double-click keeps it off; scores and hours unchanged; per-corner radius fields with a link toggle, split from #1594; Join merges anchors lying on one another, #1533; correction: Average and Join with a corner or smooth choice is missing, not done; guide objects take the guide colour and style and Lock Guides, #1534; Keyboard Shortcuts lists commands outside the menus, #1539; round corners next to curves and the Smooth tool's reach, #1512; Make Compound Path on a group, #1537; dialog slider rails, #1483; template layers stay in Preview in Outline view, #1486; Direct Selection takes the selected object's anchor where anchors coincide, #1508; Tabs panel stop drags, #1458; Split Into Grid dialog, #1462; Transform Objects and Reflect's angle, #1448 and #1460; Pathfinder panel on a group, #1450; value fields: readable selection, #1465 in part, and a focused field follows its value, #1457; scores unchanged; Transform dialogs have a live Preview and step with the arrow keys, #1412; transform tools, dialogs and Move act on direct-selected anchors, #1408; the bounding box hides during a corner drag, #1229; scores unchanged; dialogs focus their first field on every open, #1367, and a first field that starts greyed out once it is enabled, #1395; scores unchanged; Rectangular Grid and Polar Grid click dialogs take the skew, frame, compound path and Fill Grid options, #1377 in part, score unchanged; Live Corners: a Direct Selection click on a widget selects its corner, #1239; custom ruler origin, #1212; Artboard tool clicks fit the topmost editable object in one undo step (#1227); scores unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; DXF control-point SPLINE closure read, #1299 follow-up; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Simplify preview/counts and valid rewritten-path selection (#1272); parity remains partial; Texture-effect drag redraws optimized (#1257); idle Windows interaction still unverified; scores unchanged; Curvature point display improved (#1236, in part); scores unchanged; Direct Selection: no-op anchor Align preserves Undo, Redo and saved state (#1180 follow-up); Eyedropper cursor distinguished from precise crosshair (#1269); scores unchanged; Eyedropper can read visible locked and outside-isolation sources (#1251); scores unchanged; Direct Selection: independent segment picks and Delete (#1278); scores unchanged; Adding paint to an unpainted zero-width stroke restores the 1 pt default (#1253); scores unchanged; macOS save sheets offer a Format menu, #866; Attributes fill-rule controls edit the compound when a member is selected, #1197; a marquee needs to touch a path, not just lie inside its fill, #1103; earlier: Live Corners round corners between curved sides, #1144; interactive Mirror Repeat axis; Background Export progress dialog with Cancel, #2564; scores unchanged; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Blend spine Anchor Point conversions, selection/stacking priority and Shift regression coverage (#2544); scores and hours unchanged; Artboard Options' X and Y with a reference point, #1876; scores unchanged; library panels: one per library, dockable and tabbable, with Persistent, #2603; the Selection tool threads text from the out port, #2572 in part; scores unchanged; Group Selection picks and moves one path of a compound path, #2441 in part; the Move dialog opens on the last move and its last checkboxes; scores unchanged; transparency grid visibility saved in native documents, #1968; Live Corners radius up to the neighbouring cuts, #2332; Image Trace quick presets: wording corrected to the shipped behaviour, the Image Trace button opens the controls; batch exporting, #1935; document window scroll bars, #2322; Anchor Point tool: a click on a handle end retracts that handle only, #2267; scores unchanged; Smart Guides: the dragged end of a straight segment keeps to its extension at any angle, #2120; Warp Options controls verified by focused checks and original-image review; estimates unchanged; existing-guide Escape cancellation validated 2026-10-14; scores and hours unchanged; open-path anchor Delete keeps surviving runs separate; estimates unchanged; Artboard tab-switch follow-up historically validated on `a0671777`; scores and hours unchanged; Artboard clean active-tab close/Delete follow-up validated 2026-10-15; Curvature curve geometry, #1236 in part; Width-point finite-arithmetic follow-up validated; scores and hours unchanged; Image Trace adjustment discovery; later 2026-10-14 merges: macOS save sheet Format menu back to missing, #1855, #866 reopened; anchor X/Y/W/H in the Transform panel, Properties and Control bar, #1824; Snap to Grid over Snap to Pixel, #1816; toolbar labels, columns and the All Tools drawer, #1751; Actions panel selection, #1629 in part; scores unchanged; 2026-10-14 merges: anchor Align and Distribute, #1636; Delete on closed paths and whole objects, #1674; selection inside isolation, #1666; Escape in a Direct Selection drag and while typing, #1743, #1686; Pen clicks under 3 px, #1663; [ and ] on more tools, #1661 in part; fields commit on click away, #1787; command search keys, #1757; a guide's position in the Transform panel is a convenience with no parity claim, #1659; scores unchanged; intersect Smart Guides for drawn points and dragged anchors, #1602 in part; a ruler guide's position in the Transform panel, #1597 in part; Symbol Options before New Symbol, #1560; tool flyout widths, #1616; Pathfinder Trim, Merge and Crop strokes, #1570; scores unchanged; G1/M11: Artboard deletion and history selection normalization; history regressions and full workspace CI pass; scores and hours unchanged; Width Point Edit: Shift-double-click enables adjoining adjustment; plain double-click keeps it off; scores and hours unchanged; per-corner radius fields with a link toggle, split from #1594; Join merges anchors lying on one another, #1533; correction: Average and Join with a corner or smooth choice is missing, not done; guide objects take the guide colour and style and Lock Guides, #1534; Keyboard Shortcuts lists commands outside the menus, #1539; round corners next to curves and the Smooth tool's reach, #1512; Make Compound Path on a group, #1537; dialog slider rails, #1483; template layers stay in Preview in Outline view, #1486; Direct Selection takes the selected object's anchor where anchors coincide, #1508; Tabs panel stop drags, #1458; Split Into Grid dialog, #1462; Transform Objects and Reflect's angle, #1448 and #1460; Pathfinder panel on a group, #1450; value fields: readable selection, #1465 in part, and a focused field follows its value, #1457; scores unchanged; Transform dialogs have a live Preview and step with the arrow keys, #1412; transform tools, dialogs and Move act on direct-selected anchors, #1408; the bounding box hides during a corner drag, #1229; scores unchanged; dialogs focus their first field on every open, #1367, and a first field that starts greyed out once it is enabled, #1395; scores unchanged; Rectangular Grid and Polar Grid click dialogs take the skew, frame, compound path and Fill Grid options, #1377 in part, score unchanged; Live Corners: a Direct Selection click on a widget selects its corner, #1239; custom ruler origin, #1212; Artboard tool clicks fit the topmost editable object in one undo step (#1227); scores unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; DXF control-point SPLINE closure read, #1299 follow-up; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Simplify preview/counts and valid rewritten-path selection (#1272); parity remains partial; Texture-effect drag redraws optimized (#1257); idle Windows interaction still unverified; scores unchanged; Curvature point display improved (#1236, in part); scores unchanged; Direct Selection: no-op anchor Align preserves Undo, Redo and saved state (#1180 follow-up); Eyedropper cursor distinguished from precise crosshair (#1269); scores unchanged; Eyedropper can read visible locked and outside-isolation sources (#1251); scores unchanged; Direct Selection: independent segment picks and Delete (#1278); scores unchanged; Adding paint to an unpainted zero-width stroke restores the 1 pt default (#1253); scores unchanged; macOS save sheets offer a Format menu, #866; Attributes fill-rule controls edit the compound when a member is selected, #1197; a marquee needs to touch a path, not just lie inside its fill, #1103; earlier: Live Corners round corners between curved sides, #1144) · **Target:** Adobe Illustrator 2026 (30.x) +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-19 · **Change:** minor (Pencil: Alt key toggles to Smooth Tool, #2001; status-readout sample widths cached by language, document unit and pixels per point; status messages and readouts use stable responsive allocations sized for localized labels and ordinary coordinates; cached canvas dimensions match the renderer limit before cache-key creation, view construction and worker submission; cached canvas reprojection preserves scale during resize, rotation and DPI changes; on-canvas Mirror Repeat axis, #2877; Background Export progress dialog with Cancel, #2564; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Blend spine Anchor Point conversions, selection/stacking priority and Shift regression coverage (#2544); scores and hours unchanged; Artboard Options' X and Y with a reference point, #1876; scores unchanged; library panels: one per library, dockable and tabbable, with Persistent, #2603; the Selection tool threads text from the out port, #2572 in part; scores unchanged; Group Selection picks and moves one path of a compound path, #2441 in part; the Move dialog opens on the last move and its last checkboxes; scores unchanged; transparency grid visibility saved in native documents, #1968; Live Corners radius up to the neighbouring cuts, #2332; Image Trace quick presets: wording corrected to the shipped behaviour, the Image Trace button opens the controls; batch exporting, #1935; document window scroll bars, #2322; Anchor Point tool: a click on a handle end retracts that handle only, #2267; scores unchanged; Smart Guides: the dragged end of a straight segment keeps to its extension at any angle, #2120; Warp Options controls verified by focused checks and original-image review; estimates unchanged; existing-guide Escape cancellation validated 2026-10-14; scores and hours unchanged; open-path anchor Delete keeps surviving runs separate; estimates unchanged; Artboard tab-switch follow-up historically validated on `a0671777`; scores and hours unchanged; Artboard clean active-tab close/Delete follow-up validated 2026-10-15; Curvature curve geometry, #1236 in part; Width-point finite-arithmetic follow-up validated; scores and hours unchanged; Image Trace adjustment discovery; later 2026-10-14 merges: macOS save sheet Format menu back to missing, #1855, #866 reopened; anchor X/Y/W/H in the Transform panel, Properties and Control bar, #1824; Snap to Grid over Snap to Pixel, #1816; toolbar labels, columns and the All Tools drawer, #1751; Actions panel selection, #1629 in part; scores unchanged; 2026-10-14 merges: anchor Align and Distribute, #1636; Delete on closed paths and whole objects, #1674; selection inside isolation, #1666; Escape in a Direct Selection drag and while typing, #1743, #1686; Pen clicks under 3 px, #1663; [ and ] on more tools, #1661 in part; fields commit on click away, #1787; command search keys, #1757; a guide's position in the Transform panel is a convenience with no parity claim, #1659; scores unchanged; intersect Smart Guides for drawn points and dragged anchors, #1602 in part; a ruler guide's position in the Transform panel, #1597 in part; Symbol Options before New Symbol, #1560; tool flyout widths, #1616; Pathfinder Trim, Merge and Crop strokes, #1570; scores unchanged; G1/M11: Artboard deletion and history selection normalization; history regressions and full workspace CI pass; scores and hours unchanged; Width Point Edit: Shift-double-click enables adjoining adjustment; plain double-click keeps it off; scores and hours unchanged; per-corner radius fields with a link toggle, split from #1594; Join merges anchors lying on one another, #1533; correction: Average and Join with a corner or smooth choice is missing, not done; guide objects take the guide colour and style and Lock Guides, #1534; Keyboard Shortcuts lists commands outside the menus, #1539; round corners next to curves and the Smooth tool's reach, #1512; Make Compound Path on a group, #1537; dialog slider rails, #1483; template layers stay in Preview in Outline view, #1486; Direct Selection takes the selected object's anchor where anchors coincide, #1508; Tabs panel stop drags, #1458; Split Into Grid dialog, #1462; Transform Objects and Reflect's angle, #1448 and #1460; Pathfinder panel on a group, #1450; value fields: readable selection, #1465 in part, and a focused field follows its value, #1457; scores unchanged; Transform dialogs have a live Preview and step with the arrow keys, #1412; transform tools, dialogs and Move act on direct-selected anchors, #1408; the bounding box hides during a corner drag, #1229; scores unchanged; dialogs focus their first field on every open, #1367, and a first field that starts greyed out once it is enabled, #1395; scores unchanged; Rectangular Grid and Polar Grid click dialogs take the skew, frame, compound path and Fill Grid options, #1377 in part, score unchanged; Live Corners: a Direct Selection click on a widget selects its corner, #1239; custom ruler origin, #1212; Artboard tool clicks fit the topmost editable object in one undo step (#1227); scores unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; DXF control-point SPLINE closure read, #1299 follow-up; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Simplify preview/counts and valid rewritten-path selection (#1272); parity remains partial; Texture-effect drag redraws optimized (#1257); idle Windows interaction still unverified; scores unchanged; Curvature point display improved (#1236, in part); scores unchanged; Direct Selection: no-op anchor Align preserves Undo, Redo and saved state (#1180 follow-up); Eyedropper cursor distinguished from precise crosshair (#1269); scores unchanged; Eyedropper can read visible locked and outside-isolation sources (#1251); scores unchanged; Direct Selection: independent segment picks and Delete (#1278); scores unchanged; Adding paint to an unpainted zero-width stroke restores the 1 pt default (#1253); scores unchanged; macOS save sheets offer a Format menu, #866; Attributes fill-rule controls edit the compound when a member is selected, #1197; a marquee needs to touch a path, not just lie inside its fill, #1103; earlier: Live Corners round corners between curved sides, #1144; interactive Mirror Repeat axis; Background Export progress dialog with Cancel, #2564; scores unchanged; 3D lighting: one to ten colored lights, smooth colored Inflate, legacy white-light appearance preserved; surface batching and restored seam minimum; scores and estimates unchanged; Blend spine Anchor Point conversions, selection/stacking priority and Shift regression coverage (#2544); scores and hours unchanged; Artboard Options' X and Y with a reference point, #1876; scores unchanged; library panels: one per library, dockable and tabbable, with Persistent, #2603; the Selection tool threads text from the out port, #2572 in part; scores unchanged; Group Selection picks and moves one path of a compound path, #2441 in part; the Move dialog opens on the last move and its last checkboxes; scores unchanged; transparency grid visibility saved in native documents, #1968; Live Corners radius up to the neighbouring cuts, #2332; Image Trace quick presets: wording corrected to the shipped behaviour, the Image Trace button opens the controls; batch exporting, #1935; document window scroll bars, #2322; Anchor Point tool: a click on a handle end retracts that handle only, #2267; scores unchanged; Smart Guides: the dragged end of a straight segment keeps to its extension at any angle, #2120; Warp Options controls verified by focused checks and original-image review; estimates unchanged; existing-guide Escape cancellation validated 2026-10-14; scores and hours unchanged; open-path anchor Delete keeps surviving runs separate; estimates unchanged; Artboard tab-switch follow-up historically validated on `a0671777`; scores and hours unchanged; Artboard clean active-tab close/Delete follow-up validated 2026-10-15; Curvature curve geometry, #1236 in part; Width-point finite-arithmetic follow-up validated; scores and hours unchanged; Image Trace adjustment discovery; later 2026-10-14 merges: macOS save sheet Format menu back to missing, #1855, #866 reopened; anchor X/Y/W/H in the Transform panel, Properties and Control bar, #1824; Snap to Grid over Snap to Pixel, #1816; toolbar labels, columns and the All Tools drawer, #1751; Actions panel selection, #1629 in part; scores unchanged; 2026-10-14 merges: anchor Align and Distribute, #1636; Delete on closed paths and whole objects, #1674; selection inside isolation, #1666; Escape in a Direct Selection drag and while typing, #1743, #1686; Pen clicks under 3 px, #1663; [ and ] on more tools, #1661 in part; fields commit on click away, #1787; command search keys, #1757; a guide's position in the Transform panel is a convenience with no parity claim, #1659; scores unchanged; intersect Smart Guides for drawn points and dragged anchors, #1602 in part; a ruler guide's position in the Transform panel, #1597 in part; Symbol Options before New Symbol, #1560; tool flyout widths, #1616; Pathfinder Trim, Merge and Crop strokes, #1570; scores unchanged; G1/M11: Artboard deletion and history selection normalization; history regressions and full workspace CI pass; scores and hours unchanged; Width Point Edit: Shift-double-click enables adjoining adjustment; plain double-click keeps it off; scores and hours unchanged; per-corner radius fields with a link toggle, split from #1594; Join merges anchors lying on one another, #1533; correction: Average and Join with a corner or smooth choice is missing, not done; guide objects take the guide colour and style and Lock Guides, #1534; Keyboard Shortcuts lists commands outside the menus, #1539; round corners next to curves and the Smooth tool's reach, #1512; Make Compound Path on a group, #1537; dialog slider rails, #1483; template layers stay in Preview in Outline view, #1486; Direct Selection takes the selected object's anchor where anchors coincide, #1508; Tabs panel stop drags, #1458; Split Into Grid dialog, #1462; Transform Objects and Reflect's angle, #1448 and #1460; Pathfinder panel on a group, #1450; value fields: readable selection, #1465 in part, and a focused field follows its value, #1457; scores unchanged; Transform dialogs have a live Preview and step with the arrow keys, #1412; transform tools, dialogs and Move act on direct-selected anchors, #1408; the bounding box hides during a corner drag, #1229; scores unchanged; dialogs focus their first field on every open, #1367, and a first field that starts greyed out once it is enabled, #1395; scores unchanged; Rectangular Grid and Polar Grid click dialogs take the skew, frame, compound path and Fill Grid options, #1377 in part, score unchanged; Live Corners: a Direct Selection click on a widget selects its corner, #1239; custom ruler origin, #1212; Artboard tool clicks fit the topmost editable object in one undo step (#1227); scores unchanged; Pathfinder single-result source names and SVG IDs retained, #1293; DXF control-point SPLINE closure read, #1299 follow-up; Document Setup: Edit Artboards closes the modal after applying valid settings; pointer-click regressions; scores and hours unchanged; Artboards: Escape exits editing; an active drag cancels first; shortcut-routing regression; scores and hours unchanged; Simplify preview/counts and valid rewritten-path selection (#1272); parity remains partial; Texture-effect drag redraws optimized (#1257); idle Windows interaction still unverified; scores unchanged; Curvature point display improved (#1236, in part); scores unchanged; Direct Selection: no-op anchor Align preserves Undo, Redo and saved state (#1180 follow-up); Eyedropper cursor distinguished from precise crosshair (#1269); scores unchanged; Eyedropper can read visible locked and outside-isolation sources (#1251); scores unchanged; Direct Selection: independent segment picks and Delete (#1278); scores unchanged; Adding paint to an unpainted zero-width stroke restores the 1 pt default (#1253); scores unchanged; macOS save sheets offer a Format menu, #866; Attributes fill-rule controls edit the compound when a member is selected, #1197; a marquee needs to touch a path, not just lie inside its fill, #1103; earlier: Live Corners round corners between curved sides, #1144) · **Target:** Adobe Illustrator 2026 (30.x) How VectorCraft's tools, handles, snapping and panels behave next to Illustrator's. A vector illustrator's trust is in the details: where a handle lands, what Shift and Alt do mid-drag, what a smart guide snaps to, @@ -60,6 +60,7 @@ tools, never checked side by side) isn't captured row by row. | Curvature tool: click/drag points, double-click or Alt-click for a corner, temporary Direct Selection, point conversion | partial | circular point markers without direction handles or duplicate markers, Anchor Size and Hide Edges regression-tested (#1236, in part); curve geometry: each stretch of three points follows the circle through them (handles along its tangent, chord/(3·cos²(α/2)) long, shorter in a turn tighter than 30°), open ends curving in, the same rule for the rubber band, dragged, inserted and converted points (#1236, in part); neighbours of a point dragged on an existing path keep their tangents, and modifiers requested in #975 remain | | Blend spine Anchor Point conversion and handle editing (#2544) | implemented | symmetric handles, independent drag/retraction, visible-handle policy and selection/stacking covered by tool and engine regressions; Windows native canvas checks and screenshots reviewed in PR #2643 | | Add/Delete/Anchor Point tools; Anchor Point tool drags segments to reshape | done | #2267: a click on a handle end retracts that handle and leaves the anchor a corner with the other one; Shift held at the press on an anchor moves it, handles and all (Shift kept down: at 45° steps) instead of pulling out handles | +| Pencil: Fidelity, Keep selected, Alt to Smooth, edit selected paths, close by proximity | done | Alt key toggles to Smooth Tool (#2001); Edit Selected Paths continues a selected path from an end and, from a stroke that starts and ends on a selected path, redraws the section between (the shorter way round a closed path, #2850); with Keep selected (Pencil and Paintbrush, on by default) off, the path a stroke draws or continues is not selected afterwards; a filled Pencil path keeps a stroke of None (#1804, part of #1679) | | Pencil: Fidelity, Keep selected, Alt to Smooth, edit selected paths, close by proximity | partial | Alt to Smooth is missing; Edit Selected Paths continues a selected path from an end and, from a stroke that starts and ends on a selected path, redraws the section between (the shorter way round a closed path, #2850); with Keep selected (Pencil and Paintbrush, on by default) off, the path a stroke draws or continues is not selected afterwards; a filled Pencil path keeps a stroke of None (#1804, part of #1679) | | Join tool scrubbing, Average, Join | done | Join merges the direct-selected anchors lying on one another along a path, as after Average, into one (#1533) | | Average and Join in one step, with a corner or smooth choice for the joined anchor | missing | `path.join` and `path.average` are separate commands, and Join has no corner/smooth choice; [gap 1](gaps.md) |