mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Merge pull request #3313 from dotCooCoo/feat/view-show-live-paint-gaps
View: Show Live Paint Gaps highlights the gaps of the selected Live Paint groups
This commit is contained in:
@@ -662,6 +662,12 @@ fn open_gaps(group: &Node, options: GapOptions) -> Vec<[Point; 2]> {
|
||||
po::find_gaps(&source_shapes(&source_nodes(group)).0, options.size.points())
|
||||
}
|
||||
|
||||
/// The gaps View › Show Live Paint Gaps shows on `group`: those up to its Gap Options' size wide,
|
||||
/// as `livePaint.info` lists them. None when `group` is not a Live Paint group.
|
||||
pub fn live_paint_gaps(group: &Node) -> Vec<[Point; 2]> {
|
||||
if is_live_paint(group) { open_gaps(group, group.gap_options()) } else { vec![] }
|
||||
}
|
||||
|
||||
fn lp_gap_options(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
const C: &str = "livePaint.gapOptions";
|
||||
let detect = match p.get("detect").filter(|v| !v.is_null()) {
|
||||
|
||||
@@ -525,6 +525,9 @@ pub use flatten::FlattenerPreset;
|
||||
/// The shapes a group selected alone gives the Pathfinder panel.
|
||||
pub use pathops::shape_count;
|
||||
|
||||
/// The gaps View › Show Live Paint Gaps shows on a Live Paint group.
|
||||
pub use buildcmds::live_paint_gaps;
|
||||
|
||||
/// Command ids kept only so older scripts keep working: `(alias, the command it duplicates)`.
|
||||
/// They run as before but the command palette leaves them out (it lists the command once).
|
||||
pub const ALIASES: &[(&str, &str)] = &[("object.convertDocumentColorMode", "file.documentColorMode")];
|
||||
|
||||
@@ -553,6 +553,9 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
if app.ui.view.text_threads {
|
||||
thread_overlay(app, &painter, &xf);
|
||||
}
|
||||
if app.ui.view.live_paint_gaps {
|
||||
overlays.extend(live_paint_gap_overlays(app));
|
||||
}
|
||||
if app.ui.view.hidden_chars {
|
||||
app.canvas.hidden_chars = hidden_chars;
|
||||
hidden_chars_overlay(app, &painter, &xf);
|
||||
@@ -2246,6 +2249,22 @@ fn thread_overlay(app: &VectorcraftApp, p: &egui::Painter, xf: &Xf) {
|
||||
}
|
||||
}
|
||||
|
||||
/// View → Show Live Paint Gaps: the gaps of the selected Live Paint groups in each group's Gap
|
||||
/// Preview Color ([`crate::dialogs::live_paint_gaps::selected_gaps`]). Cached per revision.
|
||||
fn live_paint_gap_overlays(app: &mut VectorcraftApp) -> Vec<Overlay> {
|
||||
let Some(st) = app.session.active() else { return vec![] };
|
||||
let key = (st.uid, st.revision);
|
||||
let gaps = match &app.canvas.live_paint_gaps {
|
||||
Some((k, gaps)) if *k == key => gaps.clone(),
|
||||
_ => {
|
||||
let gaps = std::sync::Arc::new(crate::dialogs::live_paint_gaps::selected_gaps(app));
|
||||
app.canvas.live_paint_gaps = Some((key, gaps.clone()));
|
||||
gaps
|
||||
}
|
||||
};
|
||||
gaps.to_vec()
|
||||
}
|
||||
|
||||
/// Simplify's Show Original Path: the paths its preview ran on, as they were before it, in a band
|
||||
/// 3 screen points wide of their layer's color at 40%, under the selection's outlines. Nothing is drawn
|
||||
/// when they have more than [`OVERLAY_MAX_ANCHORS`] anchor points.
|
||||
@@ -5840,6 +5859,71 @@ mod tests {
|
||||
assert!(area(&app), "a double-click on the widget converts to area type");
|
||||
}
|
||||
|
||||
/// View → Show Live Paint Gaps draws the gaps of each selected Live Paint group in the group's
|
||||
/// Gap Preview Color, and nothing for a group or path that is not a selected Live Paint group;
|
||||
/// Hide Live Paint Gaps and Hide Edges hide them.
|
||||
#[test]
|
||||
fn show_live_paint_gaps_draws_the_selected_groups_gaps_in_their_preview_color() {
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.session.execute("file.new", &json!({"width": 400, "height": 300})).unwrap();
|
||||
// Open paths round a square, each ending 2 pt short of its start: one Small Gap each.
|
||||
let square = |app: &mut VectorcraftApp, x: i64| {
|
||||
let anchors = [(0, 0), (100, 0), (100, 100), (0, 100), (0, 2)].map(|(dx, y)| json!({"x": x + dx, "y": y}));
|
||||
app.session.execute("path.create", &json!({ "anchors": anchors })).unwrap()["id"].as_u64().unwrap()
|
||||
};
|
||||
let mut groups = vec![];
|
||||
for (x, color) in [(0, "#123456"), (150, "#654321")] {
|
||||
let p = square(&mut app, x);
|
||||
app.session.execute("select.set", &json!({"ids": [p]})).unwrap();
|
||||
let g = app.session.execute("livePaint.make", &json!({})).unwrap()["id"].as_u64().unwrap();
|
||||
app.session.execute("livePaint.gapOptions", &json!({"id": g, "color": color})).unwrap();
|
||||
groups.push(g);
|
||||
}
|
||||
let plain = square(&mut app, 300);
|
||||
let ctx = egui::Context::default();
|
||||
let gaps = |app: &mut VectorcraftApp, rgb: [u8; 3]| {
|
||||
let solid = egui::epaint::ColorMode::Solid(c32(rgb));
|
||||
shapes(app, &ctx).iter().filter(|s| matches!(s, Shape::Path(ps) if ps.stroke.color == solid && ps.stroke.width == 2.0)).count()
|
||||
};
|
||||
let (first, second) = ([0x12, 0x34, 0x56], [0x65, 0x43, 0x21]);
|
||||
// The color the plain path's gaps would be drawn in.
|
||||
let plain_color = vectorcraft_doc::GapOptions::default().color;
|
||||
app.session.execute("select.set", &json!({"ids": [groups[0], plain]})).unwrap();
|
||||
assert_eq!((gaps(&mut app, first), gaps(&mut app, second)), (0, 0), "off until the item is chosen");
|
||||
// View → Show Live Paint Gaps runs the command.
|
||||
let tree = crate::menus::menu_tree();
|
||||
let (_, view) = tree.iter().find(|(t, _)| *t == "View").unwrap();
|
||||
assert!(view.iter().any(|i| matches!(i, crate::menus::Item::Cmd("Show Live Paint Gaps", "view.livePaintGaps", _))), "{view:?}");
|
||||
crate::menus::invoke(&mut app, "view.livePaintGaps", json!({}));
|
||||
assert!(app.ui.view.live_paint_gaps);
|
||||
assert_eq!(
|
||||
(gaps(&mut app, first), gaps(&mut app, second), gaps(&mut app, plain_color)),
|
||||
(1, 0, 0),
|
||||
"the selected group only; the plain path shows none"
|
||||
);
|
||||
app.session.execute("select.set", &json!({"ids": [groups[1]]})).unwrap();
|
||||
assert_eq!((gaps(&mut app, first), gaps(&mut app, second)), (0, 1));
|
||||
// The lines follow the group's Gap Preview Color and Paint Stops At size.
|
||||
app.session.execute("livePaint.gapOptions", &json!({"id": groups[1], "color": "#123456"})).unwrap();
|
||||
assert_eq!((gaps(&mut app, first), gaps(&mut app, second)), (1, 0));
|
||||
app.session.execute("livePaint.gapOptions", &json!({"id": groups[1], "size": 1})).unwrap();
|
||||
assert_eq!(gaps(&mut app, first), 0, "a 2 pt gap is wider than 1 pt");
|
||||
app.session.execute("livePaint.gapOptions", &json!({"id": groups[1], "size": "small"})).unwrap();
|
||||
app.ui.view.edges = false;
|
||||
assert_eq!(gaps(&mut app, first), 0, "Hide Edges hides them");
|
||||
app.ui.view.edges = true;
|
||||
assert_eq!(gaps(&mut app, first), 1);
|
||||
app.run("view.livePaintGaps", json!({})).unwrap();
|
||||
assert!(!app.ui.view.live_paint_gaps);
|
||||
assert_eq!(gaps(&mut app, first), 0, "View → Hide Live Paint Gaps");
|
||||
// The setting is kept with the interface state; a state saved before it existed loads with it off.
|
||||
app.ui.view.live_paint_gaps = true;
|
||||
let mut saved = serde_json::to_value(&app.ui).unwrap();
|
||||
assert_eq!(saved["view"]["live_paint_gaps"], json!(true));
|
||||
saved["view"].as_object_mut().unwrap().remove("live_paint_gaps");
|
||||
assert!(!serde_json::from_value::<crate::UiState>(saved).unwrap().view.live_paint_gaps);
|
||||
}
|
||||
|
||||
/// #511: a star shows a widget in each of its ten corners with Direct Selection (none with
|
||||
/// the Selection tool: it isn't a live shape); View → Hide Corner Widget hides them.
|
||||
#[test]
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
//! or Custom with its size), Gap Preview Color (a layer color or a custom color) and Close Gaps
|
||||
//! With Paths for the selected Live Paint groups, opened on the first group's options. With Preview
|
||||
//! on, the options apply to the groups live and the gaps they find draw on the canvas in the preview
|
||||
//! color; OK keeps them as one undo step (`livePaint.gapOptions`).
|
||||
//! color; OK keeps them as one undo step (`livePaint.gapOptions`). View › Show Live Paint Gaps
|
||||
//! draws the gaps of the selected groups the same way ([`selected_gaps`]).
|
||||
//!
|
||||
//! Fields: `detect`, `size` (`small` | `medium` | `large` | `custom`), `custom` (pt), `color`
|
||||
//! (`#rrggbb`, or a preset's name such as "Red"), `closeGaps`, `preview`, `__ids` (the groups) and
|
||||
@@ -139,14 +140,32 @@ pub(crate) fn overlays(app: &VectorcraftApp) -> Vec<Overlay> {
|
||||
.filter_map(|gap| {
|
||||
let v: Vec<f64> = gap.as_array()?.iter().filter_map(Value::as_f64).collect();
|
||||
let [x0, y0, x1, y1] = v.as_slice() else { return None };
|
||||
let mut path = BezPath::new();
|
||||
path.move_to(Point::new(*x0, *y0));
|
||||
path.line_to(Point::new(*x1, *y1));
|
||||
Some(Overlay::Path { path, color: [r, g, b], width: 2.0, dashed: false })
|
||||
Some(gap_line(Point::new(*x0, *y0), Point::new(*x1, *y1), [r, g, b]))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// View › Show Live Paint Gaps: the gaps of the selected Live Paint groups, as lines in each
|
||||
/// group's Gap Preview Color, drawn as the preview draws them.
|
||||
pub(crate) fn selected_gaps(app: &VectorcraftApp) -> Vec<Overlay> {
|
||||
let Some(st) = app.session.active() else { return vec![] };
|
||||
let groups = st.selection.objects.iter().filter_map(|id| st.doc.node(*id)).filter(|n| vectorcraft_tools::builder::is_live_paint(n));
|
||||
groups
|
||||
.flat_map(|n| {
|
||||
let color = n.gap_options().color;
|
||||
vectorcraft_engine::cmd::live_paint_gaps(n).into_iter().map(move |[a, b]| gap_line(a, b, color))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// A gap from `a` to `b` as a line in `color`, 2 screen points wide.
|
||||
fn gap_line(a: Point, b: Point, color: [u8; 3]) -> Overlay {
|
||||
let mut path = BezPath::new();
|
||||
path.move_to(a);
|
||||
path.line_to(b);
|
||||
Overlay::Path { path, color, width: 2.0, dashed: false }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
@@ -1175,6 +1175,8 @@
|
||||
Large Gaps Големи пролуки
|
||||
Gap Preview Color: Цвят за преглед на пролуките:
|
||||
Close Gaps With Paths Затваряне на пролуките с пътища
|
||||
Show Live Paint Gaps Показване на пролуките на динамичното оцветяване
|
||||
Hide Live Paint Gaps Скриване на пролуките на динамичното оцветяване
|
||||
Select Fills Избиране на запълвания
|
||||
Select Strokes Избиране на щрихове
|
||||
Gaussian Blur… Гаусово размазване…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -265,6 +265,8 @@
|
||||
Large Gaps Velké mezery
|
||||
Gap Preview Color: Barva náhledu mezer:
|
||||
Close Gaps With Paths Uzavřít mezery cestami
|
||||
Show Live Paint Gaps Zobrazit mezery živé malby
|
||||
Hide Live Paint Gaps Skrýt mezery živé malby
|
||||
Select Fills Vybírat výplně
|
||||
Select Strokes Vybírat tahy
|
||||
Image Trace Vektorizace obrazu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5093,6 +5093,8 @@ swatch Bright Violet Kraftig violet
|
||||
Gap Detection Registrering af huller
|
||||
Gap Options Indstillinger for huller
|
||||
Gap Preview Color: Eksempelfarve for huller:
|
||||
Show Live Paint Gaps Vis huller i live-maling
|
||||
Hide Live Paint Gaps Skjul huller i live-maling
|
||||
Graph Column Diagramsøjle
|
||||
JavaScript Files JavaScript-filer
|
||||
JavaScript: JavaScript:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1193,6 +1193,8 @@ file-filter Templates Vorlagen
|
||||
Large Gaps Große Lücken
|
||||
Gap Preview Color: Vorschaufarbe für Lücken:
|
||||
Close Gaps With Paths Lücken mit Pfaden schließen
|
||||
Show Live Paint Gaps Lücken beim interaktiven Malen einblenden
|
||||
Hide Live Paint Gaps Lücken beim interaktiven Malen ausblenden
|
||||
Select Fills Flächen auswählen
|
||||
Select Strokes Konturen auswählen
|
||||
Gaussian Blur… Gaußscher Weichzeichner…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1140,6 +1140,8 @@
|
||||
Large Gaps Μεγάλα διάκενα
|
||||
Gap Preview Color: Χρώμα προεπισκόπησης διακένων:
|
||||
Close Gaps With Paths Κλείσιμο διακένων με διαδρομές
|
||||
Show Live Paint Gaps Εμφάνιση διακένων δυναμικής βαφής
|
||||
Hide Live Paint Gaps Απόκρυψη διακένων δυναμικής βαφής
|
||||
Select Fills Επιλογή γεμισμάτων
|
||||
Select Strokes Επιλογή περιγραμμάτων
|
||||
Gaussian Blur… Θόλωση Γκάους…
|
||||
|
||||
|
@@ -1200,6 +1200,8 @@
|
||||
Large Gaps Huecos grandes
|
||||
Gap Preview Color: Color de previsualización de huecos:
|
||||
Close Gaps With Paths Cerrar huecos con trazados
|
||||
Show Live Paint Gaps Mostrar huecos de pintura interactiva
|
||||
Hide Live Paint Gaps Ocultar huecos de pintura interactiva
|
||||
Select Fills Seleccionar rellenos
|
||||
Select Strokes Seleccionar trazos
|
||||
Gaussian Blur… Desenfoque gaussiano…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -272,6 +272,8 @@
|
||||
Large Gaps Suuret aukot
|
||||
Gap Preview Color: Aukkojen esikatseluväri:
|
||||
Close Gaps With Paths Sulje aukot poluilla
|
||||
Show Live Paint Gaps Näytä elävän maalauksen aukot
|
||||
Hide Live Paint Gaps Piilota elävän maalauksen aukot
|
||||
Select Fills Valitse täytöt
|
||||
Select Strokes Valitse viivat
|
||||
Image Trace Kuvan jäljitys
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1199,6 +1199,8 @@
|
||||
Large Gaps Grands espaces
|
||||
Gap Preview Color: Couleur d’aperçu des espaces :
|
||||
Close Gaps With Paths Fermer les espaces avec des tracés
|
||||
Show Live Paint Gaps Afficher les espaces de peinture dynamique
|
||||
Hide Live Paint Gaps Masquer les espaces de peinture dynamique
|
||||
Select Fills Sélectionner les fonds
|
||||
Select Strokes Sélectionner les contours
|
||||
Gaussian Blur… Flou gaussien…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1505,6 +1505,8 @@ file-filter Templates Sablonok
|
||||
Large Gaps Nagy hézagok
|
||||
Gap Preview Color: Hézagok előnézeti színe:
|
||||
Close Gaps With Paths Hézagok lezárása útvonalakkal
|
||||
Show Live Paint Gaps Élő festés hézagainak megjelenítése
|
||||
Hide Live Paint Gaps Élő festés hézagainak elrejtése
|
||||
Select Fills Kitöltések kijelölése
|
||||
Select Strokes Körvonalak kijelölése
|
||||
Gaussian Blur Gauss-elmosás
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5093,6 +5093,8 @@ swatch Bright Violet Violet cerah
|
||||
Gap Detection Deteksi celah
|
||||
Gap Options Opsi celah
|
||||
Gap Preview Color: Warna pratinjau celah:
|
||||
Show Live Paint Gaps Tampilkan celah Live Paint
|
||||
Hide Live Paint Gaps Sembunyikan celah Live Paint
|
||||
Graph Column Kolom grafik
|
||||
JavaScript Files File JavaScript
|
||||
JavaScript: JavaScript:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 3775 and column 19.
|
@@ -1209,6 +1209,8 @@ file-filter Templates Modelli
|
||||
Large Gaps Spazi vuoti grandi
|
||||
Gap Preview Color: Colore anteprima spazi vuoti:
|
||||
Close Gaps With Paths Chiudi spazi vuoti con tracciati
|
||||
Show Live Paint Gaps Mostra spazi vuoti pittura dinamica
|
||||
Hide Live Paint Gaps Nascondi spazi vuoti pittura dinamica
|
||||
Select Fills Seleziona riempimenti
|
||||
Select Strokes Seleziona tracce
|
||||
Gaussian Blur… Sfocatura gaussiana…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -263,6 +263,8 @@
|
||||
Large Gaps 大きい間隔
|
||||
Gap Preview Color: 間隔のプレビューカラー:
|
||||
Close Gaps With Paths パスで間隔を閉じる
|
||||
Show Live Paint Gaps ライブペイントの間隔を表示
|
||||
Hide Live Paint Gaps ライブペイントの間隔を隠す
|
||||
Select Fills 塗りを選択
|
||||
Select Strokes 線を選択
|
||||
Image Trace 画像トレース
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -4980,6 +4980,8 @@ imageTrace Outline კონტური
|
||||
Gap Detection ღრეჩოების აღმოჩენა
|
||||
Gap Options ღრეჩოს პარამეტრები
|
||||
Gap Preview Color: ღრეჩოს ნახვის ფერი:
|
||||
Show Live Paint Gaps ცოცხალი შეღებვის ღრეჩოების ჩვენება
|
||||
Hide Live Paint Gaps ცოცხალი შეღებვის ღრეჩოების დამალვა
|
||||
Glow Brightness ნათების სიკაშკაშე
|
||||
Glow Size ნათების ზომა
|
||||
Graph Column დიაგრამის სვეტი
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -259,6 +259,8 @@
|
||||
Large Gaps 큰 간격
|
||||
Gap Preview Color: 간격 미리 보기 색상:
|
||||
Close Gaps With Paths 패스로 간격 닫기
|
||||
Show Live Paint Gaps 라이브 페인트 간격 표시
|
||||
Hide Live Paint Gaps 라이브 페인트 간격 숨기기
|
||||
Select Fills 칠 선택
|
||||
Select Strokes 선 선택
|
||||
Image Trace 이미지 추적
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -5105,6 +5105,8 @@ swatch Bright Violet Felviolet
|
||||
Gap Detection Openingen detecteren
|
||||
Gap Options Openingsopties
|
||||
Gap Preview Color: Voorbeeldkleur openingen:
|
||||
Show Live Paint Gaps Live Paint-openingen tonen
|
||||
Hide Live Paint Gaps Live Paint-openingen verbergen
|
||||
Graph Column Grafiekkolom
|
||||
JavaScript Files JavaScript-bestanden
|
||||
JavaScript: JavaScript:
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -230,6 +230,8 @@
|
||||
Large Gaps Duże przerwy
|
||||
Gap Preview Color: Kolor podglądu przerw:
|
||||
Close Gaps With Paths Zamknij przerwy ścieżkami
|
||||
Show Live Paint Gaps Pokaż przerwy aktywnego malowania
|
||||
Hide Live Paint Gaps Ukryj przerwy aktywnego malowania
|
||||
Select Fills Zaznaczaj wypełnienia
|
||||
Select Strokes Zaznaczaj obrysy
|
||||
Image Trace Obrys obrazu
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1057,6 +1057,8 @@
|
||||
Large Gaps Lacunas Grandes
|
||||
Gap Preview Color: Cor de Visualização das Lacunas:
|
||||
Close Gaps With Paths Fechar Lacunas com Caminhos
|
||||
Show Live Paint Gaps Mostrar Lacunas da Pintura ao Vivo
|
||||
Hide Live Paint Gaps Ocultar Lacunas da Pintura ao Vivo
|
||||
Select Fills Selecionar Preenchimentos
|
||||
Select Strokes Selecionar Traçados
|
||||
Gaussian Blur… Desfoque Gaussiano…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -1207,6 +1207,8 @@ file-filter Templates Шаблоны
|
||||
Large Gaps Большие зазоры
|
||||
Gap Preview Color: Цвет просмотра зазоров:
|
||||
Close Gaps With Paths Закрыть зазоры контурами
|
||||
Show Live Paint Gaps Показать зазоры быстрой заливки
|
||||
Hide Live Paint Gaps Скрыть зазоры быстрой заливки
|
||||
Select Fills Выделять заливки
|
||||
Select Strokes Выделять обводки
|
||||
Gaussian Blur… Размытие по Гауссу…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1177,6 +1177,8 @@
|
||||
Large Gaps Stora mellanrum
|
||||
Gap Preview Color: Förhandsgranskningsfärg för mellanrum:
|
||||
Close Gaps With Paths Stäng mellanrum med banor
|
||||
Show Live Paint Gaps Visa mellanrum i direktmålning
|
||||
Hide Live Paint Gaps Dölj mellanrum i direktmålning
|
||||
Select Fills Markera fyllningar
|
||||
Select Strokes Markera konturer
|
||||
Gaussian Blur… Gaussisk oskärpa…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 5 and column 25.
|
@@ -931,6 +931,7 @@ fn toggled_labels() -> Vec<String> {
|
||||
"view.textThreads",
|
||||
"type.hiddenCharacters",
|
||||
"view.gradientAnnotator",
|
||||
"view.livePaintGaps",
|
||||
"view.artboards",
|
||||
"view.template",
|
||||
"view.rulers",
|
||||
|
||||
@@ -1203,6 +1203,8 @@ file-filter Templates Шаблони
|
||||
Large Gaps Великі проміжки
|
||||
Gap Preview Color: Колір перегляду проміжків:
|
||||
Close Gaps With Paths Закрити проміжки контурами
|
||||
Show Live Paint Gaps Показати проміжки швидкої заливки
|
||||
Hide Live Paint Gaps Приховати проміжки швидкої заливки
|
||||
Select Fills Виділяти заливки
|
||||
Select Strokes Виділяти обведення
|
||||
Gaussian Blur… Розмиття за Гауссом…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 725 and column 40.
|
@@ -1395,6 +1395,8 @@ file-filter Templates Mẫu
|
||||
Large Gaps Khoảng cách lớn
|
||||
Gap Preview Color: Màu xem trước khoảng cách:
|
||||
Close Gaps With Paths Đóng khoảng cách bằng đường dẫn
|
||||
Show Live Paint Gaps Hiện khoảng cách tô trực tiếp
|
||||
Hide Live Paint Gaps Ẩn khoảng cách tô trực tiếp
|
||||
Select Fills Chọn vùng tô
|
||||
Select Strokes Chọn nét
|
||||
Gaussian Blur Mờ Gaussian
|
||||
|
||||
|
@@ -1156,6 +1156,8 @@ file-filter Templates 模板
|
||||
Large Gaps 大间隙
|
||||
Gap Preview Color: 间隙预览颜色:
|
||||
Close Gaps With Paths 用路径封闭间隙
|
||||
Show Live Paint Gaps 显示实时上色间隙
|
||||
Hide Live Paint Gaps 隐藏实时上色间隙
|
||||
Select Fills 选择填色
|
||||
Select Strokes 选择描边
|
||||
Gaussian Blur… 高斯模糊…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 2 and column 73.
|
@@ -1180,6 +1180,8 @@ file-filter Templates 範本
|
||||
Large Gaps 大間隙
|
||||
Gap Preview Color: 間隙預覽顏色:
|
||||
Close Gaps With Paths 以路徑封閉間隙
|
||||
Show Live Paint Gaps 顯示即時上色間隙
|
||||
Hide Live Paint Gaps 隱藏即時上色間隙
|
||||
Select Fills 選取填色
|
||||
Select Strokes 選取筆畫
|
||||
Gaussian Blur… 高斯模糊…
|
||||
|
||||
|
Can't render this file because it contains an unexpected character in line 6 and column 47.
|
@@ -321,6 +321,8 @@ pub struct CanvasCache {
|
||||
pub slices: Option<SliceCache>,
|
||||
/// The print tiling's pages for (document uid, revision) (View → Show Print Tiling).
|
||||
pub print_tiling: Option<PrintTilingCache>,
|
||||
/// The gap lines View → Show Live Paint Gaps draws for (document uid, revision).
|
||||
pub live_paint_gaps: Option<LivePaintGapsCache>,
|
||||
/// The marks Type → Show Hidden Characters drew on each text object in the last frame. A frame
|
||||
/// that does not draw them drops them ([`canvas::show`]).
|
||||
pub hidden_chars: canvas::HiddenChars,
|
||||
@@ -337,6 +339,10 @@ pub struct CanvasCache {
|
||||
/// [`CanvasCache::slices`]: the layout of the slices of (document uid, revision).
|
||||
pub type SliceCache = ((u64, u64), std::sync::Arc<Vec<vectorcraft_doc::SliceArea>>);
|
||||
|
||||
/// [`CanvasCache::live_paint_gaps`]: the gap lines of the selected Live Paint groups of (document
|
||||
/// uid, revision).
|
||||
pub type LivePaintGapsCache = ((u64, u64), std::sync::Arc<Vec<vectorcraft_tools::Overlay>>);
|
||||
|
||||
/// [`CanvasCache::print_tiling`]: the print tiling of (document uid, revision).
|
||||
pub type PrintTilingCache = ((u64, u64), std::sync::Arc<Vec<vectorcraft_pdf::TilingPage>>);
|
||||
|
||||
@@ -539,6 +545,7 @@ impl VectorcraftApp {
|
||||
worker_started: false,
|
||||
slices: None,
|
||||
print_tiling: None,
|
||||
live_paint_gaps: None,
|
||||
hidden_chars: Default::default(),
|
||||
selection_box: None,
|
||||
selection_bounds: None,
|
||||
|
||||
@@ -207,6 +207,12 @@ pub const UI_COMMANDS: &[(&str, &str, &str, &str)] = &[
|
||||
),
|
||||
("view.textThreads", "Hide Text Threads", "Cmd+Shift+Y", "{} toggle the thread lines between threaded text frames"),
|
||||
("view.gradientAnnotator", "Hide Gradient Annotator", "Cmd+Alt+G", "{} toggle the Gradient tool's annotator"),
|
||||
(
|
||||
"view.livePaintGaps",
|
||||
"Show Live Paint Gaps",
|
||||
"",
|
||||
"{} toggle drawing the gaps of the selected Live Paint groups (those livePaint.info lists) in each group's Gap Preview Color while edges show → true when on",
|
||||
),
|
||||
("type.hiddenCharacters", "Show Hidden Characters", "Cmd+Alt+I", "{} toggle markers for spaces, paragraph ends and story ends"),
|
||||
("type.alignLeft", "Align left", "Cmd+Shift+L", "{} align the selected type's paragraphs (or those the Type tool's selection touches) left"),
|
||||
(
|
||||
@@ -1231,6 +1237,7 @@ pub fn run_ui_command(app: &mut VectorcraftApp, id: &str, p: &Value) -> Option<R
|
||||
crate::panels::paragraph::align(app, justify)
|
||||
}
|
||||
"view.gradientAnnotator" => flag(&mut app.ui.view.gradient_annotator),
|
||||
"view.livePaintGaps" => flag(&mut app.ui.view.live_paint_gaps),
|
||||
"effect.last" => match app.last_effect.clone() {
|
||||
Some((e, params)) => {
|
||||
let label = vectorcraft_effects::effect_info(&e).map(|i| i.label.trim_end_matches('…').to_string()).unwrap_or_else(|| e.clone());
|
||||
@@ -1872,6 +1879,7 @@ pub fn dynamic_label(app: &VectorcraftApp, id: &str, label: &str) -> String {
|
||||
"view.textThreads" => if v.text_threads { "Hide Text Threads" } else { "Show Text Threads" }.into(),
|
||||
"type.hiddenCharacters" => if v.hidden_chars { "Hide Hidden Characters" } else { "Show Hidden Characters" }.into(),
|
||||
"view.gradientAnnotator" => if v.gradient_annotator { "Hide Gradient Annotator" } else { "Show Gradient Annotator" }.into(),
|
||||
"view.livePaintGaps" => if v.live_paint_gaps { "Hide Live Paint Gaps" } else { "Show Live Paint Gaps" }.into(),
|
||||
"effect.last" => match &app.last_effect {
|
||||
Some((e, _)) => format!("Last Effect: {}", vectorcraft_effects::effect_info(e).map(|i| i.label).unwrap_or(e.as_str())),
|
||||
None => label.into(),
|
||||
@@ -2900,6 +2908,7 @@ pub fn menu_tree_named(english_names: bool) -> Vec<(&'static str, Vec<Item>)> {
|
||||
c("Hide Text Threads", "view.textThreads"),
|
||||
c("Hide Gradient Annotator", "view.gradientAnnotator"),
|
||||
c("Hide Corner Widget", "view.cornerWidget"),
|
||||
c("Show Live Paint Gaps", "view.livePaintGaps"),
|
||||
Sep,
|
||||
sub(
|
||||
"Guides",
|
||||
@@ -3970,6 +3979,8 @@ pub const DYNAMIC_LABELS: &[&str] = &[
|
||||
"Show Hidden Characters",
|
||||
"Hide Gradient Annotator",
|
||||
"Show Gradient Annotator",
|
||||
"Hide Live Paint Gaps",
|
||||
"Show Live Paint Gaps",
|
||||
"Hide Artboards",
|
||||
"Show Artboards",
|
||||
"Hide Rulers",
|
||||
@@ -4243,6 +4254,7 @@ mod tests {
|
||||
for (id, on, off) in [
|
||||
("view.textThreads", "Hide Text Threads", "Show Text Threads"),
|
||||
("view.gradientAnnotator", "Hide Gradient Annotator", "Show Gradient Annotator"),
|
||||
("view.livePaintGaps", "Show Live Paint Gaps", "Hide Live Paint Gaps"),
|
||||
("type.hiddenCharacters", "Show Hidden Characters", "Hide Hidden Characters"),
|
||||
("view.template", "Hide Template", "Show Template"),
|
||||
] {
|
||||
|
||||
@@ -231,6 +231,10 @@ pub struct ViewFlags {
|
||||
pub text_threads: bool,
|
||||
/// View → Show/Hide Gradient Annotator.
|
||||
pub gradient_annotator: bool,
|
||||
/// View → Show/Hide Live Paint Gaps: draw the gaps of the selected Live Paint groups in their Gap
|
||||
/// Preview Color.
|
||||
#[serde(default)]
|
||||
pub live_paint_gaps: bool,
|
||||
/// Type → Show Hidden Characters.
|
||||
pub hidden_chars: bool,
|
||||
/// View → Hide/Show Template: template layers drawn (dimmed) or left out of the canvas.
|
||||
@@ -258,6 +262,7 @@ impl Default for ViewFlags {
|
||||
snap_to_glyph: false,
|
||||
text_threads: true,
|
||||
gradient_annotator: true,
|
||||
live_paint_gaps: false,
|
||||
hidden_chars: false,
|
||||
templates: true,
|
||||
}
|
||||
|
||||
@@ -1270,6 +1270,9 @@ already walks Image Trace. Short agent entry points:
|
||||
and `livePaint.info` list the gaps up to `size` wide that no path closes, as `[x0, y0, x1, y1]`. `livePaint.merge`
|
||||
keeps the bottom group's options when its Gap Detection is on, and otherwise turns Gap Detection on with `small`
|
||||
when another merged group has it on. When Gap Detection is off in every merged group, it stays off.
|
||||
`view.livePaintGaps` (View › Show Live Paint Gaps, or Hide Live Paint Gaps while it is on) turns the drawing of
|
||||
those gaps on or off. While it is on and edges show, the canvas draws the gaps of each selected Live Paint group in
|
||||
that group's Gap Preview Color. The reply is the new state (`true` when on).
|
||||
The Live Paint Selection tool's options (`tool.setOption {tool: "livePaintSelection", values}`; double-clicking the
|
||||
tool opens them, dialog `livePaintSelectionOptions`) are `selectFills` and `selectStrokes` (both on), `color` (the
|
||||
highlight color, `#rrggbb` or a layer color's name; `#ff2a2a`) and `width` (the highlight's width, 1 to 20 screen
|
||||
|
||||
@@ -669,6 +669,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
|
||||
- **Advanced art:** live Blends (steps/distance/smooth colour, editable spine, anchor-targeted Blend tool, faithful interpolation, knockout), Envelope Distort (warp/mesh/top object, Reset, full Envelope Options, mesh handles, Edit Contents; type, images, symbols, gradients, patterns and appearance distorted everywhere), Liquify tools with options and pen pressure, Puppet Warp with rotating pins, Perspective Grid with presets, movable planes and projected type (choosing a perspective tool shows the grid; Hide Grid hides it with the tool still chosen), Gradient Mesh, Shape Builder (stroke-only open paths and lines cut the regions they cross and enclose regions of their own, and regions they bound merge without seams where the lines cross at rounded coordinates (#893); filled open paths count as closed; erase mode while Alt/Option is held: a minus pointer, red highlights of what will go, a click or drag deletes the regions touched, the pieces of open lines and the edges (outline pieces between the points where paths meet, opening their paths there) it passes over, one undo step, `shapeBuilder.merge {erase}` and `shapeBuilder.regions` edges over MCP), Live Paint (every path an edge, open lines included), Image Trace (12 presets, colour layers traced in parallel; a trace past two million anchor points is refused with advice rather than running out of memory, an image over 64 megapixels is traced scaled down to that size (aspect kept, paths at the image's own size) and one over 192 megapixels is refused, and a selection too large to outline shows its bounds (#525); Object › Image Trace › Make and Make and Expand trace at once with the Default preset, #543; with an image selected the Control bar and the Properties panel show Image Trace, whose arrow traces with any preset, Mask (`object.maskImage`: a clipping path on the image's outline, selected so its handles crop), Crop Image (a crop box on the image, starting on its part over the artboard, dragged by its handles or inside it, the outside dimmed, with X/Y/W/H, Apply and Cancel in the Control bar, Enter and Escape, #734; `object.cropImage {rect}` for agents, `{trim: true}` cuts an image to its pixels that aren't fully transparent, pixel for pixel) and Embed or Unembed in place of Fill and Stroke; with an Image Trace object selected, its Preset (choosing another traces again), View, the Image Trace panel and Expand, plus Release in Properties; the five View modes (Tracing Result, with Outlines, Outlines, Outlines with Source Image, Source Image) redraw a trace on screen without tracing again, are saved with it and `imageTrace.setView` sets them, while exports and Expand keep the result; the panel's Advanced section is a header that stays open or closed as it was left (part of #641); Color mode's Palette: Limited, Full Tone (as many colours as the tones need, Less … More), Automatic (flat art with its own colours, else Full Tone; a heuristic) and Document Library (the most used colours of the document's swatches or a swatch library, filled with the swatch colours as they are), part of #641; Advanced › Create: Fills and/or Strokes, where lines up to the Stroke width trace as stroked centre lines (distance transform, thinning, a skeleton graph with spurs pruned, curve fitting; one width per line; without Fills, wider areas become stroked outlines), part of #641), pattern swatches with pattern editing mode, live Repeat (radial/grid/mirror). A single selected mirror repeat shows a prominent axis with a center move handle and two rotation handles. Drag the line or center to change spacing, or an end to change angle; Shift snaps rotation to 45°. The original artwork stays in place, the reflected copy previews live, Escape cancels and each drag takes one undo step through `object.repeat.options`. Controls follow zoom/view rotation and hide with edges or the bounding box. Engine and headless canvas regressions passed for gestures, history and visibility; native move, rotation and Escape screenshots were reviewed. [Public mirror-repeat reference](https://helpx.adobe.com/illustrator/desktop/paint-and-fill/create-and-edit-patterns/set-mirror-repeat-options.html). Object › Expand turns radial, grid and mirror repeats into groups of their instances (#1765, #1756).
|
||||
- Create Strokes uses exact squared Euclidean distances and Guo–Hall thinning in bounded per-blob crops. Maximal-disc pruning, split-crossing merges and degree-two joins simplify its skeleton graph. The whole-blob width rule and ink fitting remain; 46 code-drawn inputs measure ends and junctions in [`image-trace-quality.md`](image-trace-quality.md#centre-lines). Junction degrees measure 44/45 correct in each input variant; remaining spurs are recorded. This is a measured skeleton improvement; the Image Trace score, missing per-feature selection and width controls, and estimates remain unchanged.
|
||||
Live Paint Gap Options (Object › Live Paint › Gap Options…, `livePaint.gapOptions`): with Gap Detection on, paint stops at the gaps that run from a loose end of a path to the nearest path, up to Small (3 pt), Medium (6 pt), Large (12 pt) or a custom size; Close Gaps With Paths adds an unpainted path across each gap; Preview applies the options live and draws the gaps in the Gap Preview Color. The options are saved, copied and undone with the group, and Merge keeps the bottom group's options when its Gap Detection is on, or else turns Gap Detection on with Small when another merged group has it on. When Gap Detection is off in every merged group, it stays off.
|
||||
View › Show Live Paint Gaps (`view.livePaintGaps`) draws the gaps of the selected Live Paint groups up to their Paint Stops At size, each in its group's Gap Preview Color, until Hide Live Paint Gaps or Hide Edges hides them ([Live Paint gaps](https://web.archive.org/web/20260105111201/https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/find-and-close-gaps-in-live-paint-groups.html)).
|
||||
Double-clicking the Live Paint Selection tool opens its Tool Options ([Live Paint Selection tool options](https://web.archive.org/web/20250904012025/https://helpx.adobe.com/illustrator/using/selecting-objects.html)): with Select Fills off, a click selects an edge instead of a face; with Select Strokes off, Alt-click selects a face instead of an edge; Color and Width set the color and width of the highlight on the face or edge under the pointer (red and 4 px by default). The options last across tool switches and are saved with the preferences (`tool.setOption {tool: "livePaintSelection"}`).
|
||||
Window › Blend opens the Blend panel: Make, the selected blend's Spacing and Orientation (with no blend selected, the options new blends start with), Reverse Front to Back, Reverse Spine, Replace Spine, Expand and Release, each running its Object › Blend command. Make is dimmed until two or more objects are selected. Spacing and Orientation are dimmed until a blend or two or more objects are selected, and the other buttons are dimmed until a blend is selected.
|
||||
Objects on Path (#2545): a click with the Objects on Path tool (in Edit Toolbar's Modify section and the Blend tool's flyout; Object › Objects on Path › Attach and the context menu with two or more objects selected choose it) attaches the selected objects to the path clicked, open or closed, in an Objects on Path group with the path at its bottom. The objects go along the path column by column from left to right, spread evenly from its first anchor (the last one sits on the end of an open path), each turned to the path at its attachment point; Pivot and Rotate set where each one attaches and how far it tilts (`object.objectsOnPath.attach`, `object.objectsOnPath.options`). Editing the path moves the objects, an object moved on its own goes back, objects moved into or out of the group in the Layers panel join or leave the path, and Object › Objects on Path › Expand leaves a plain group. The group saves and reopens live and exports as plain art. The Space, Move All, Rotate All and Select/Move widgets, Detach, the tool's options dialog and the Properties panel section are missing.
|
||||
|
||||
Reference in New Issue
Block a user