Image Trace: pressing and holding the eye button shows the source image

The Image Trace panel had no way to compare a trace with its source
image except changing View and changing it back.

The panel now has an eye button to the right of View, enabled with an
Image Trace object selected. While it is held down, the canvas draws the
selected Image Trace objects with their source image, whatever their
View, and draws their View again on release. The document, its View and
the undo history are unchanged. The renderer takes the objects in
RenderOptions::trace_source, which is also part of the canvas frame key
and the raster-effect cache key.
This commit is contained in:
dotCooCoo
2026-10-24 19:02:08 +07:00
committed by bflatastic
parent bef464ea97
commit 2ff8699989
33 changed files with 166 additions and 3 deletions
+1
View File
@@ -2130,6 +2130,7 @@ impl Renderer {
if reads.images {
let o = f.opts;
(doc.images, self.dim_images.map(f32::to_bits), o.smooth_images, o.image_mips, o.trace_views, o.progressive_placed).hash(&mut h);
o.trace_source.as_deref().hash(&mut h);
}
if reads.brushes {
self.brushes.library_key(f.doc, self.stamp).hash(&mut h);
+16 -2
View File
@@ -159,6 +159,10 @@ pub struct RenderOptions {
/// Screen view: Image Trace objects draw as their View asks (outlines, the source image…);
/// off, they draw their tracing result, as exports and printing do.
pub trace_views: bool,
/// Screen view with `trace_views` on: the Image Trace objects drawn with the Source Image view
/// for this render only, whatever View they have (the Image Trace panel's eye button, while it
/// is held down).
pub trace_source: Option<Arc<Vec<NodeId>>>,
/// Images are sampled smoothly when scaled or rotated; off, each pixel takes its nearest image
/// pixel (Pixel Preview with File Handling › Display Bitmaps as Anti-aliased Images off).
pub smooth_images: bool,
@@ -266,6 +270,7 @@ impl Default for RenderOptions {
anti_alias: AntiAlias::Art,
progressive_placed: false,
trace_views: false,
trace_source: None,
smooth_images: true,
isolated: None,
precise: false,
@@ -1301,8 +1306,8 @@ impl Renderer {
/// What `n` draws inside its transparency group (`knockout`: its children knock each other out).
fn draw_content(&mut self, ctx: &mut RenderContext, f: &Frame, n: &Node, knockout: bool) {
match &n.kind {
NodeKind::Group { children, clip: false } if f.opts.trace_views && !f.opts.outline && n.trace_view() != TraceView::Result => {
self.draw_trace_view(ctx, f, children, n.trace_view(), knockout)
NodeKind::Group { children, clip: false } if f.opts.trace_views && !f.opts.outline && Self::trace_view(f, n) != TraceView::Result => {
self.draw_trace_view(ctx, f, children, Self::trace_view(f, n), knockout)
}
NodeKind::Layer { children, clip: false, .. } | NodeKind::Group { children, clip: false } => {
self.draw_children(ctx, f, children, knockout)
@@ -1429,6 +1434,15 @@ impl Renderer {
self.live_root = outer;
}
/// The View `n` draws with on screen: Source Image when it is an Image Trace object listed in
/// [`RenderOptions::trace_source`], else its own.
fn trace_view(f: &Frame, n: &Node) -> TraceView {
match &f.opts.trace_source {
Some(ids) if n.extras().trace.is_some() && ids.contains(&n.id) => TraceView::Source,
_ => n.trace_view(),
}
}
/// An Image Trace object's `children` (the hidden source image, then the traced shapes) as
/// `view` shows them on screen.
fn draw_trace_view(&mut self, ctx: &mut RenderContext, f: &Frame, children: &[Arc<Node>], view: TraceView, knockout: bool) {
+51
View File
@@ -579,6 +579,57 @@ fn outline_view_draws_paths_from_kept_geometry() {
}
}
/// An Image Trace object listed in `trace_source` draws its source image on screen whatever its
/// View, also inside a group whose raster effect a renderer keeps; without the list, and in
/// exports, it draws its result. A group that is not an Image Trace object draws its members.
#[test]
fn trace_source_draws_the_source_image_of_the_listed_objects() {
use vectorcraft_doc::{ImageBlob, ImageObject};
let img = image::RgbaImage::from_pixel(1, 1, image::Rgba([255, 0, 0, 255]));
let mut png = vec![];
img.write_to(&mut std::io::Cursor::new(&mut png), image::ImageFormat::Png).unwrap();
let mut d = Document::new(100.0, 100.0);
d.images.insert("red".into(), ImageBlob::new("image/png", png));
// A group at `x`: the hidden red source image, then a blue traced square over it.
let group = |d: &mut Document, x: f64, traced: bool| {
let xf = Affine::translate((x, 10.0)) * Affine::scale(20.0);
let im = ImageObject { key: "red".into(), width: 1, height: 1, xf, link: None, placement: Default::default(), pixels: None };
let mut source = Node::new(d.alloc_id(), NodeKind::Image(Box::new(im)));
source.visible = false;
let shape = rect_node(d, Rect::new(x, 10.0, x + 20.0, 30.0), Paint::solid(Color::rgb(0.0, 0.0, 1.0)), Paint::None, 0.0);
let mut g = Node::group(d.alloc_id(), vec![Arc::new(source), Arc::new(shape)]);
if traced {
g.extras_mut().trace = Some(Box::new(serde_json::json!({ "view": "tracingResult" })));
}
g
};
let plain = group(&mut d, 10.0, true);
let blurred = group(&mut d, 40.0, true);
let other = group(&mut d, 70.0, false);
let ids = Arc::new(vec![plain.id, blurred.id, other.id]);
let mut holder = Node::group(d.alloc_id(), vec![Arc::new(blurred)]);
holder.appearance.effects.push(vectorcraft_doc::Effect { id: "blur.gaussian".into(), params: serde_json::json!({ "radius": 1 }), visible: true });
let l = d.layers[0].id;
for n in [plain, holder, other] {
d.insert(Some(l), usize::MAX, n).unwrap();
}
let screen = RenderOptions { trace_views: true, background: Some([255; 4]), ..Default::default() };
let held = RenderOptions { trace_source: Some(ids.clone()), ..screen.clone() };
let export = RenderOptions { trace_source: Some(ids), background: Some([255; 4]), ..Default::default() };
let red = |p: [u8; 4]| p[0] > 200 && p[2] < 60;
let blue = |p: [u8; 4]| p[2] > 200 && p[0] < 60;
let mut kept = Renderer::new();
for (opts, source) in [(&screen, false), (&held, true), (&screen, false), (&export, false)] {
for r in [kept.render(&d, 100, 100, Affine::IDENTITY, opts), Renderer::new().render(&d, 100, 100, Affine::IDENTITY, opts)] {
for (x, what) in [(20, "the Image Trace object"), (50, "the one in the blurred group")] {
let p = r.pixel(x, 20);
assert!(if source { red(p) } else { blue(p) }, "{what} with trace_source {source}: {p:?}");
}
assert!(blue(r.pixel(80, 20)), "the plain group draws its square: {:?}", r.pixel(80, 20));
}
}
}
#[test]
fn artboards_white_on_pasteboard() {
let d = Document::new(50.0, 50.0);
+4
View File
@@ -419,6 +419,8 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
rich_black: app.session.prefs.black_on_screen == "rich",
// A tool's drag on the canvas, during an interaction (not a dialog's preview).
dragging: app.session.in_interaction() && ui.data(|d| d.get_temp::<Drag>(drag_id())) == Some(Drag::Tool),
// The Image Trace panel's eye button, only while a pointer button is down.
trace_source: app.ui.trace_hold_source.clone().filter(|_| ui.input(|i| i.pointer.any_down())),
};
// Placed documents' bitmaps are being made: draw again when they are ready.
if vectorcraft_render::placed_document::busy() {
@@ -487,6 +489,8 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
anti_alias: if app.session.prefs.anti_aliased_artwork { vectorcraft_render::AntiAlias::Art } else { vectorcraft_render::AntiAlias::None },
progressive_placed: true,
trace_views: true,
// Image Trace › the eye button held: the source image of the selected objects.
trace_source: key.trace_source.clone(),
smooth_images,
// Isolation mode: the art around the isolated group or layer is dimmed (#833).
isolated: key.isolated.map(vectorcraft_doc::NodeId),
+1
View File
@@ -3013,6 +3013,7 @@ font-technology Variable Променливи
Outlines Контури
Outlines with Source Image Контури с изходно изображение
Source Image Изходно изображение
Press and hold to view the source image Задръжте натиснато, за да видите изходното изображение
Image Trace View Изглед на трасиране на изображение
Snap Options Опции за прилепване
Snap to Glyph Прилепване към глиф
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3932,6 +3932,7 @@ font-technology Variable Variabilní
View: Zobrazení:
Tracing Result Výsledek vektorizace
Outlines with Source Image Obrysy se zdrojovým obrazem
Press and hold to view the source image Podržením zobrazíte zdrojový obraz
SVG Options Možnosti SVG
Maximize Maximalizovat
Restore Obnovit
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3675,6 +3675,7 @@ font-technology Variable Variable
View: Visning:
Tracing Result Sporingsresultat
Outlines with Source Image Konturer med kildebillede
Press and hold to view the source image Hold nede for at se kildebilledet
SVG Options SVG-indstillinger
Maximize Maksimér
Restore Gendan
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3051,6 +3051,7 @@ effect Points Punkte
Outlines Pfade
Outlines with Source Image Pfade mit Quellbild
Source Image Quellbild
Press and hold to view the source image Gedrückt halten, um das Quellbild anzuzeigen
Image Trace View Bildnachzeichner-Ansicht
Snap Options Einrastoptionen
Snap to Glyph An Glyphe ausrichten
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -1881,6 +1881,7 @@ font-technology Variable Μεταβλητές
Absolute Απόλυτο
View: Προβολή:
Outlines Περιγράμματα
Press and hold to view the source image Πατήστε παρατεταμένα για να δείτε την αρχική εικόνα
Snap to Grid Προσκόλληση στο πλέγμα
Snap to Pixel Προσκόλληση σε εικονοστοιχείο
Snap to Point Προσκόλληση σε σημείο
1 # Ελληνικά (el) — VectorCraft
1881
1882
1883
1884
1885
1886
1887
+1
View File
@@ -3081,6 +3081,7 @@ font-technology Variable Variables
Outlines Contornos
Outlines with Source Image Contornos con imagen de origen
Source Image Imagen de origen
Press and hold to view the source image Mantén pulsado para ver la imagen de origen
Image Trace View Vista del calco de imagen
Snap Options Opciones de ajuste
Snap to Glyph Ajustar a glifo
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3856,6 +3856,7 @@ font-technology Variable Muuttuvat
View: Näkymä:
Tracing Result Jäljityksen tulos
Outlines with Source Image Ääriviivat ja lähdekuva
Press and hold to view the source image Pidä painettuna nähdäksesi lähdekuvan
SVG Options SVG-asetukset
Maximize Suurenna
Restore Palauta
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3078,6 +3078,7 @@ font-technology Variable Variables
Outlines Contours
Outlines with Source Image Tracés avec l’image source
Source Image Image source
Press and hold to view the source image Maintenez le bouton enfoncé pour afficher l’image source
Image Trace View Affichage de la vectorisation de l’image
Snap Options Options de magnétisme
Snap to Glyph Magnétisme du glyphe
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2039,6 +2039,7 @@ file-filter Templates Sablonok
The file writes keys and modifiers as codes. Check the proposed meanings and answer the codes that are not known yet. A fájl a billentyűket és a módosítóbillentyűket kódként tárolja. Ellenőrizd a javasolt jelentéseket, és add meg a még ismeretlen kódok jelentését.
Click, then press the key this code stands for (Esc cancels) Kattints, majd nyomd le azt a billentyűt, amelyet ez a kód jelöl (Esc: mégse)
Press a key… Nyomj le egy billentyűt…
Press and hold to view the source image Tartsd lenyomva a forráskép megtekintéséhez
from your earlier imports a korábbi importálásaidból
from the format's public description a formátum nyilvános leírásából
not known yet még ismeretlen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3675,6 +3675,7 @@ font-technology Variable Variabel
View: Tampilan:
Tracing Result Hasil penelusuran
Outlines with Source Image Kontur dengan gambar sumber
Press and hold to view the source image Tekan dan tahan untuk melihat gambar sumber
SVG Options Opsi SVG
Maximize Maksimalkan
Restore Pulihkan
1 # Indonesian (id) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
3675
3676
3677
3678
3679
3680
3681
+1
View File
@@ -3115,6 +3115,7 @@ mark-style Japanese Giapponese
Outlines Contorni
Outlines with Source Image Contorni con immagine di origine
Source Image Immagine di origine
Press and hold to view the source image Tieni premuto per visualizzare l'immagine di origine
Image Trace View Vista del ricalco immagine
Snap Options Opzioni di aggancio
Snap to Glyph Aggancia a glifo
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2889,6 +2889,7 @@ mark-style Japanese 日本式
Outlines アウトライン
Outlines with Source Image アウトライン(元画像付き)
Source Image 元画像
Press and hold to view the source image 押している間、元画像を表示
Image Trace View 画像トレースの表示
Snap Options スナップオプション
Snap to Unit 単位にスナップ
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3456,6 +3456,7 @@ font-technology Variable ცვლადი
View: ხედი:
Tracing Result ვექტორიზაციის შედეგი
Outlines with Source Image კონტურები საწყისი გამოსახულებით
Press and hold to view the source image ხანგრძლივად დააჭირეთ საწყისი გამოსახულების სანახავად
SVG Options SVG-ის პარამეტრები
Maximize გაშლა
Restore აღდგენა
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -2883,6 +2883,7 @@ mark-style Japanese 일본식
Outlines 윤곽선
Outlines with Source Image 원본 이미지 포함 윤곽선
Source Image 원본 이미지
Press and hold to view the source image 누르고 있는 동안 원본 이미지 보기
Image Trace View 이미지 추적 보기
Snap Options 스냅 옵션
Snap to Unit 단위에 스냅
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3689,6 +3689,7 @@ font-technology Variable Variabel
View: Weergave:
Tracing Result Traceringresultaat
Outlines with Source Image Contouren met bronafbeelding
Press and hold to view the source image Ingedrukt houden om de bronafbeelding te bekijken
SVG Options SVG-opties
Maximize Maximaliseren
Restore Herstellen
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3771,6 +3771,7 @@ font-technology Variable Zmienne
View: Widok:
Tracing Result Wynik obrysu
Outlines with Source Image Kontury z obrazem źródłowym
Press and hold to view the source image Przytrzymaj, aby wyświetlić obraz źródłowy
SVG Options Opcje SVG
Maximize Maksymalizuj
Restore Przywróć
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3294,6 +3294,7 @@ font-technology Variable Variáveis
Outlines Contornos
Outlines with Source Image Contornos com imagem de origem
Source Image Imagem de origem
Press and hold to view the source image Mantenha pressionado para ver a imagem de origem
Image Trace View Exibição de vetorização de imagem
Stroke (X), double-click for the Color Picker Traço (X), clique duas vezes para o seletor de cores
Swap Fill and Stroke (Shift+X) Trocar preenchimento e traço (Shift+X)
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1
View File
@@ -3111,6 +3111,7 @@ mark-style Japanese Японский
Outlines Контуры
Outlines with Source Image Контуры с исходным изображением
Source Image Исходное изображение
Press and hold to view the source image Удерживайте, чтобы увидеть исходное изображение
Image Trace View Просмотр трассировки изображения
Snap Options Параметры привязки
Snap to Glyph Привязать к глифу
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3013,6 +3013,7 @@ font-technology Variable Variabla
Outlines Konturlinjer
Outlines with Source Image Konturlinjer med källbild
Source Image Källbild
Press and hold to view the source image Håll ned för att visa källbilden
Image Trace View Vy för bildkalkering
Snap Options Fästalternativ
Snap to Glyph Fäst mot glyf
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -2921,6 +2921,7 @@ font-technology Variable Değişken
Outlines Ana hatlar
Outlines with Source Image Kaynak Resimli Ana Hatlar
Source Image Kaynak Resim
Press and hold to view the source image Kaynak resmi görmek için basılı tutun
Image Trace View Görüntü İzleme Görünümü
Snap Options Yapış Seçenekleri
Snap to Glyph Glif'e Yapış
Can't render this file because it contains an unexpected character in line 5 and column 25.
+1
View File
@@ -3108,6 +3108,7 @@ effect Points Точки
Outlines Контури
Outlines with Source Image Контури з вихідним зображенням
Source Image Вихідне зображення
Press and hold to view the source image Утримуйте, щоб побачити вихідне зображення
Image Trace View Перегляд трасування зображення
Snap Options Параметри прив’язки
Snap to Glyph Прив’язати до гліфу
Can't render this file because it contains an unexpected character in line 747 and column 40.
+1
View File
@@ -1779,6 +1779,7 @@ file-filter Templates Mẫu
The file writes keys and modifiers as codes. Check the proposed meanings and answer the codes that are not known yet. Tệp ghi phím và phím bổ trợ dưới dạng mã. Hãy kiểm tra các nghĩa được đề xuất và trả lời những mã chưa biết.
Click, then press the key this code stands for (Esc cancels) Bấm, rồi nhấn phím mà mã này biểu thị (Esc để hủy)
Press a key… Nhấn một phím…
Press and hold to view the source image Nhấn giữ để xem ảnh nguồn
from your earlier imports từ các lần nhập trước của bạn
from the format's public description từ mô tả công khai của định dạng
not known yet chưa biết
1 # Vietnamese (vi) catalog. Same format as zh-hant.tsv: context <TAB> source <TAB> translation
1779
1780
1781
1782
1783
1784
1785
+1
View File
@@ -2947,6 +2947,7 @@ font-script Japanese 汉字
Outlines 轮廓
Outlines with Source Image 轮廓(带源图像)
Source Image 源图像
Press and hold to view the source image 按住以查看源图像
Image Trace View 图像描摹视图
Snap Options 对齐选项
Snap to Glyph 靠齐字符
Can't render this file because it contains an unexpected character in line 2 and column 73.
+1
View File
@@ -3878,6 +3878,7 @@ font-script Japanese 漢字
Outlines 外框
Outlines with Source Image 外框(含來源影像)
Source Image 來源影像
Press and hold to view the source image 按住以檢視來源影像
Image Trace View 影像描圖檢視
Snap Options 靠齊選項
Snap to Glyph 靠齊字符
Can't render this file because it contains an unexpected character in line 6 and column 47.
+3
View File
@@ -430,6 +430,9 @@ pub struct CacheKey {
pub rich_black: bool,
/// Colour and style of guide paths ([`vectorcraft_render::RenderOptions::guide`]).
pub guide: ([u8; 3], bool),
/// The Image Trace objects drawn with their source image
/// ([`vectorcraft_render::RenderOptions::trace_source`]).
pub trace_source: Option<std::sync::Arc<Vec<vectorcraft_doc::NodeId>>>,
}
#[derive(Clone, Copy, Debug, Default)]
+60 -1
View File
@@ -135,6 +135,25 @@ fn set_view(app: &mut VectorcraftApp, view: TraceView) {
}
}
/// While `down`, the selected Image Trace objects show their source image on the canvas, whatever
/// their View. The document and the undo history stay as they are. The panel's eye button next to
/// View calls it; per the public documentation of the panel, that control is pressed and held to
/// view the source image
/// (<https://web.archive.org/web/20250831090623/https://helpx.adobe.com/illustrator/using/image-trace.html>).
fn hold_source(app: &mut VectorcraftApp, ctx: &egui::Context, down: bool) {
let ids = app
.session
.active()
.filter(|_| down)
.map(|st| st.selection.objects.iter().copied().filter(|id| st.doc.node(*id).is_some_and(is_trace)).collect::<Vec<_>>())
.filter(|ids| !ids.is_empty())
.map(std::sync::Arc::new);
if ids != app.ui.trace_hold_source {
app.ui.trace_hold_source = ids;
ctx.request_repaint();
}
}
/// The selected Image Trace object's View row (Control bar, Properties).
pub(crate) fn view_row(app: &mut VectorcraftApp, ui: &mut Ui, current: TraceView, width: f32) {
widgets::dim_label(ui, tl!("View:"));
@@ -295,12 +314,19 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
}
ui.horizontal(|ui| {
widgets::dim_label(ui, tl!("View:"));
if let Some(v) = view_dropdown(ui, st.view, 170.0) {
let eye = 24.0;
if let Some(v) = view_dropdown(ui, st.view, (ui.available_width() - eye - ui.spacing().item_spacing.x).min(170.0)) {
st.view = v;
if is_trace {
set_view(app, v);
}
}
let held = app.ui.trace_hold_source.is_some();
let r = widgets::icon_button_enabled(ui, "eye", tl!("Press and hold to view the source image"), held, is_trace, eye);
if cfg!(test) {
ui.ctx().data_mut(|d| d.insert_temp(egui::Id::new("trace-hold-source"), r.rect));
}
hold_source(app, ui.ctx(), is_trace && r.is_pointer_button_down_on());
});
ui.horizontal(|ui| {
widgets::dim_label(ui, tl!("Mode:"));
@@ -837,6 +863,39 @@ mod tests {
}
}
/// Holding the eye button next to View down lists the selected Image Trace object for the
/// canvas to draw with its source image; releasing it shows the object's View again. The
/// document, its View and the undo history stay as they were. With a plain image selected the
/// button is disabled.
#[test]
fn holding_the_eye_button_shows_the_source_image_until_released() {
let mut app = traced_app();
let ctx = egui::Context::default();
crate::theme::install_fonts(&ctx);
frame(&mut app, &ctx, vec![]);
let id = first_selected(&app).unwrap().id;
let undo = |app: &VectorcraftApp| app.session.active().unwrap().history.undo.len();
let revision = |app: &VectorcraftApp| app.session.active().unwrap().revision;
let (steps, rev) = (undo(&app), revision(&app));
let at = ctx.data(|d| d.get_temp::<Rect>(egui::Id::new("trace-hold-source"))).unwrap().center();
let press = |pressed| Event::PointerButton { pos: at, button: PointerButton::Primary, pressed, modifiers: Default::default() };
frame(&mut app, &ctx, vec![Event::PointerMoved(at), press(true)]);
assert_eq!(app.ui.trace_hold_source.as_deref(), Some(&vec![id]), "held: the object shows its source image");
frame(&mut app, &ctx, vec![]);
assert!(app.ui.trace_hold_source.is_some(), "still held on the next frame");
frame(&mut app, &ctx, vec![press(false)]);
assert_eq!(app.ui.trace_hold_source, None, "released: the object shows its View again");
assert_eq!(undo(&app), steps, "no undo step");
assert_eq!(revision(&app), rev, "the document is unchanged");
assert_eq!(selected_trace(&app).map(|t| t.1), Some(TraceView::Result), "its View is unchanged");
app.run("imageTrace.release", json!({})).unwrap();
assert!(matches!(first_selected(&app).unwrap().kind, NodeKind::Image(_)));
frame(&mut app, &ctx, vec![]);
frame(&mut app, &ctx, vec![Event::PointerMoved(at), press(true)]);
assert_eq!(app.ui.trace_hold_source, None, "a plain image has no source image to show");
frame(&mut app, &ctx, vec![press(false)]);
}
#[test]
fn properties_can_reopen_the_trace_controls() {
let mut app = traced_app();
+5
View File
@@ -549,6 +549,10 @@ pub struct UiState {
/// becoming active, leaves it.
#[serde(skip)]
pub home: Option<(Option<u64>, usize)>,
/// The Image Trace objects the canvas draws with the Source Image view while the Image Trace
/// panel's eye button is held down ([`vectorcraft_render::RenderOptions::trace_source`]).
#[serde(skip)]
pub trace_hold_source: Option<std::sync::Arc<Vec<vectorcraft_doc::NodeId>>>,
/// Layers panel › Panel Options… (row size, thumbnails, Show Layers Only, Locate Selected Objects).
#[serde(default)]
pub layers_panel: crate::panels::layers::PanelOptions,
@@ -902,6 +906,7 @@ impl Default for UiState {
move_options: Value::Null,
dxf_import: Value::Null,
home: None,
trace_hold_source: None,
layers_panel: Default::default(),
layers_filter: Default::default(),
image_trace_advanced: true,
+1
View File
@@ -788,6 +788,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur
- **Image Trace, thin closed outlines:** generated `fit::snap_area_tests` verify nonzero interiors after straightening, opposite closed-boundary winding and Noise controls; see [quality notes](image-trace-quality.md#thin-closed-outlines-with-snap-curves-to-lines). Scores and hours unchanged; open-piece fitting is unchanged.
- **Image Trace, flattened slivers:** in a Color, Grayscale or Black and White trace with Fills, a traced region whose outline straightens onto one line (a single pixel, or a one-pixel row along an edge, its pieces shared with the regions beside it) is left out instead of becoming a selectable path with no area, which paints nothing. Snap Curves To Lines straightens more outlines, so it leaves out more of these. Without Fills, the region's 1 px stroke draws it, and it is kept. Code-drawn tests in `crates/trace`.
- **Image Trace, Auto Color rare colours:** the Automatic palette keeps colours too rare for its area count when they are distinct (Oklab) and drawn as coherent regions, at most six, protected from mixed-colour merging and Noise; code-drawn stem, highlight, low-contrast and scattered-noise tests (see [quality notes](image-trace-quality.md#auto-color-keeps-rare-colours)).
- **Image Trace, source image on hold:** while the eye button next to the Image Trace panel's View is held down, the canvas shows the selected Image Trace objects' source image whatever their View, and shows their View again on release, with no change to the document or the undo history.
- **Image Trace, large images:** images over 1500 px on a side trace with a warning in the result and the status bar; the anchor limit is 8,000,000 (2,000,000 on the web), measured at about 90 bytes an anchor (see [quality notes](image-trace-quality.md#large-images)).
- **Image Trace, Preview:** the Image Trace panel's Preview checkbox, before Trace, is on by default, and a setting change traces the selected Image Trace object again at once. Off, changes wait in the panel until Trace applies them as one undo step, or until Preview is turned on again. Preview is kept with the UI preferences, and Reset to Default leaves it.
- **Image Trace small contours:** closed fits too small to form an editable subpath retain their positioned outline, including holes. Source-generated island, hole/winding and stepped-region regressions cover Corners and Noise; defaults, parity scores and estimates are unchanged.
+1
View File
@@ -274,6 +274,7 @@ empty), without opening the dialog.
| Panels outside the app window (another monitor) | missing | single OS window |
| Edit Toolbar (•••): the All Tools drawer opens beside the toolbar by its button (Escape or a click outside closes it), dims the tools already in the toolbar; while it is open, tools drag from it onto the toolbar (between two tools, or onto one to join its group), from the toolbar into it, and within the toolbar; each toolbar keeps its edits | done | #1018; `window.editToolbar`, `toolbar.addTool`/`removeTool`/`reset`; the drawer's Reset (Illustrator has it in a drawer menu); dragging a toolbar button moves the tool it shows, not its whole group; New/Manage Toolbars missing; tool flyouts are as wide as their longest translated name and shortcut need (#1616) |
| Quick Image Trace presets trace at once and leave the panel as it was; the Image Trace button (Control bar, Properties) opens the editable controls | done | Per the public documentation, choosing a preset traces the image with it straight away, and the panel is opened with the Image Trace button in the Control panel or in Properties' Image Trace section (<https://helpx.adobe.com/illustrator/using/image-trace-results-optimization.html>). The controls show Threshold, Paths, Corners and Noise with Advanced open; `panels/image_trace.rs` headless tests (`a_quick_trace_leaves_the_panel_as_it_was`, `sketch_quick_trace_reveals_all_adjustments_and_keeps_the_source` for the button's route). No algorithm parity claim. |
| Image Trace panel: holding the eye button next to View down shows the selected Image Trace objects' source image on the canvas | done | Per the public documentation, the control next to View is pressed and held to compare the trace result with the source image (<https://web.archive.org/web/20250831090623/https://helpx.adobe.com/illustrator/using/image-trace.html>). On release the objects show their View again; the document, its View and the undo history are unchanged. `RenderOptions::trace_source`; `panels/image_trace.rs` headless test `holding_the_eye_button_shows_the_source_image_until_released`, render test `trace_source_draws_the_source_image_of_the_listed_objects`. The Control bar and Properties have no such button |
| Live trace result bounds and selection highlights exclude the retained bitmap; source-image views retain it | done | All TraceView modes and rotated result bounds regression-covered; ordinary hidden group behavior retained |
| Image Trace panel: the Preview checkbox before Trace chooses whether a setting change traces the selected Image Trace object again at once | done | Per the public documentation, Preview shows the result of the current settings and Trace traces with them (<https://web.archive.org/web/20250831090623/https://helpx.adobe.com/illustrator/using/image-trace.html>). Preview is on by default and kept with the UI preferences; Reset to Default leaves it. Off, changes wait in the panel until Trace applies them as one undo step, or until Preview is turned on again. `ui.set {imageTracePreview}`; `panels/image_trace.rs` headless tests (`with_preview_off_a_slider_change_waits_for_trace`, `turning_preview_on_traces_the_changes_that_waited`, `preview_turned_on_with_nothing_selected_traces_when_the_object_is_selected_again`, `settings_that_wait_stay_with_their_object`, `preview_is_kept_with_the_preferences_and_reset_to_default_leaves_it`) |
| Toolbar without group labels by default, one or two columns; All Tools drawer by flyout group with shortcuts, its menu (Reset, Basic, Advanced) and Show section | done | #1751; a preference brings the labels back; `toolbar.show` sets the Fill/Stroke, Coloring, Draw Mode and Screen Mode controls |