Pencil: Alt key toggles to Smooth Tool (#2001)

This commit is contained in:
krinry
2026-10-20 01:18:45 +07:00
committed by bflatastic
parent 035f1cb2f6
commit de985a46e6
27 changed files with 139 additions and 19 deletions
+4
View File
@@ -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
+97 -10
View File
@@ -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<Vec<Action>> {
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);
}
}
+13 -7
View File
@@ -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);
+1
View File
@@ -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 Правило за запълване
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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.
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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 Κανόνας γεμίσματος
1 # Ελληνικά (el) — VectorCraft
1024
1025
1026
1027
1028
1029
1030
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
2064
2065
2066
2067
2068
2069
2070
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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: 塗り:
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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: 칠:
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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.
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -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 Цвет заливки
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -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 Колір заливки
Can't render this file because it contains an unexpected character in line 725 and column 40.
+1
View File
@@ -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ỗ
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
1243
1244
1245
1246
1247
1248
1249
+1
View File
@@ -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 填色
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -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 以預留位置文字填滿新文字物件
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1 -1
View File
@@ -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 |
+2 -1
View File
File diff suppressed because one or more lines are too long