Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e64786e8c |
No files matched your search
+1
-1
@@ -4,7 +4,7 @@ VectorCraft is a clean-room, open-source, pure-Rust reimplementation of the Adob
|
||||
|
||||
This file tracks **how far we are and what's left**. Time estimates are wall-clock hours of continuous Claude Opus 5.5 agent work (including builds and the CI gate), given both for **one agent** and for **4–6 parallel agents** on disjoint crates. They are counted from the remaining work (see [Parity estimate](#parity-estimate)), calibrated against measured throughput, and updated as work lands.
|
||||
|
||||
_Last updated: 2026-10-09 (after placed documents (File › Place of a `.vectorcraft` file, linked), M4.14–M4.98, M8.1–M8.20, M14.4–M14.7, the MCP prompts, resource templates, completions and logging, the 2026-10-07 issue fixes, the Layers panel rework and the 2026-10-08 community contributions: Pen and shape-tool modifiers, path editing, Layers, Artboards, Swatches/Brushes and dialogs, Japanese composition and PDF text, Hebrew/Arabic type, interface languages (Spanish among them), the font menu, saved selections, MCP and EPS, the missing-font export warning (#319), open paths in the Shape Builder (#374), PDF/`.ai` import keeping strokes live and hidden and nested layers (#372), per-corner Live Corners (#381), SVG type opening at the size it draws at (#396), the Wayland clipboard with copied-file paste (#398), ruler guides that can be selected, moved and deleted (#414), two batches of Preferences options that were stored but unused (#394), skeleton reads with `document.find` for large documents over MCP (#416) and anchors dragged with Direct Selection snapping to points, segments and smart guides, clipped SVG layers opening as clipping layers (#420), PDF/`.ai` layers read on pages of tens of millions of operators (#419), Document Color Mode putting RGB greys on the black plate on request and converting pattern tiles (#421) and movable dialogs with Offset Path's Joins dropdown (#423) and numeric fields scrubbed by dragging their label (#400), stroke weight presets in the stroke unit (#426), the Appearance panel's Opacity popup (#430), type on a path brackets, flip and Type on a Path Options that keep the type in place (#429), Layers rows dragged with a ghost and dropped on the trash or New Layer (#435), tool flyouts opening on a right or corner press (#436), tool flyouts torn off into floating toolbars (#437), the Shape Builder's erase mode deleting edges too (#439), installed fonts registered outside the font folders and fonts installed while the app runs listed in the font menus (#443), alike circular corners on rectangles that aren't square (#442), tool cursors as OS cursors so the pointer no longer trails over the canvas (#444), artboards copied and pasted with their art (#446), guides dragged out of the rulers snapping to the art's side midpoints and the artboards, artboard guides (#451), the toolbar's double arrow and Window › Toolbars › Double Column switching between one and two columns in any window height (#455), the Smart Guides display options and Snapping Tolerance (#394), Font Size and Leading combo boxes with preset lists in the Character and Properties panels and the Control bar (#458), screenshots pasted from the clipboard on macOS, Windows and the web (#457), the Properties panel's Fill and Stroke matching the Control bar's, Illustrator's Window menu panel keys (Shift+F7 for Align…) and Alt-wheel zoom whatever the wheel preference (Discord feedback), the point/area type widget (Discord feedback), groups in legacy Illustrator .ai files (Discord feedback), a rotating desktop log file (#465), image controls in the Control bar and Properties panel: Image Trace with its presets, Mask, Crop Image, Embed/Unembed, and an Image Trace object's preset, Expand and Release (Discord feedback), the Pen working as the Anchor Point tool with Alt held over a selected path's handles and anchors, and anchor buttons that convert, connect and cut paths at the selected anchors (Discord feedback), Japanese hanging punctuation (burasagari, #463), Escape leaving Presentation Mode with no screen mode saved across restarts, documents dropped on the desktop app opening as tabs of their own and a note that an `.ai` file's art off its artboards isn't in the part read (#472), Add/Delete Anchor Point tool icons drawn from the Pen tool's (#479), EPS import running more of PostScript Level 3 (patterns, Type 3 fonts, mesh shadings, masked images, VM and resource probes), and a preview that stands in saying why (Discord feedback, #466, #469, #474), chords with modifiers recorded in Edit › Keyboard Shortcuts (#487), Type Object Selection by Path Only (#394), Anti-aliased Artwork (#394), Show Pixel Grid (#394), pen and touch taps pressed and lifted within one frame clicking where they tapped and the Linux/Wayland pen-tablet workaround (#491), bounding-box resizes landing on the other objects' anchors and centres with labels, and the Rotate, Scale, Shear and Reflect tools snapping their drags (#482), Shift-drag marquees that toggle the objects or anchors they reach and a Lasso whose Alt subtraction keeps the rest of the selection (#483), the mouse wheel stepping the focused numeric field, the dialogs' and preferences' drag values made such fields (#485), Show The Home Screen When No Documents Are Open (#394), Numbers Without Units Are Points (#394), Auto-Collapse Iconic Panels (#394), the Contextual Task Bar moved by its handle and its More Options menu pinning and resetting its position, a designed macOS DMG windoLine truncated
|
||||
_Last updated: 2026-10-09 (after placed documents (File › Place of a `.vectorcraft` file, linked), M4.14–M4.98, M8.1–M8.20, M14.4–M14.7, the MCP prompts, resource templates, completions and logging, the 2026-10-07 issue fixes, the Layers panel rework and the 2026-10-08 community contributions: Pen and shape-tool modifiers, path editing, Layers, Artboards, Swatches/Brushes and dialogs, Japanese composition and PDF text, Hebrew/Arabic type, interface languages (Spanish among them), the font menu, saved selections, MCP and EPS, the missing-font export warning (#319), open paths in the Shape Builder (#374), PDF/`.ai` import keeping strokes live and hidden and nested layers (#372), per-corner Live Corners (#381), SVG type opening at the size it draws at (#396), the Wayland clipboard with copied-file paste (#398), ruler guides that can be selected, moved and deleted (#414), two batches of Preferences options that were stored but unused (#394), skeleton reads with `document.find` for large documents over MCP (#416) and anchors dragged with Direct Selection snapping to points, segments and smart guides, clipped SVG layers opening as clipping layers (#420), PDF/`.ai` layers read on pages of tens of millions of operators (#419), Document Color Mode putting RGB greys on the black plate on request and converting pattern tiles (#421) and movable dialogs with Offset Path's Joins dropdown (#423) and numeric fields scrubbed by dragging their label (#400), stroke weight presets in the stroke unit (#426), the Appearance panel's Opacity popup (#430), type on a path brackets, flip and Type on a Path Options that keep the type in place (#429), Layers rows dragged with a ghost and dropped on the trash or New Layer (#435), tool flyouts opening on a right or corner press (#436), tool flyouts torn off into floating toolbars (#437), the Shape Builder's erase mode deleting edges too (#439), installed fonts registered outside the font folders and fonts installed while the app runs listed in the font menus (#443), alike circular corners on rectangles that aren't square (#442), tool cursors as OS cursors so the pointer no longer trails over the canvas (#444), artboards copied and pasted with their art (#446), guides dragged out of the rulers snapping to the art's side midpoints and the artboards, artboard guides (#451), the toolbar's double arrow and Window › Toolbars › Double Column switching between one and two columns in any window height (#455), the Smart Guides display options and Snapping Tolerance (#394), Font Size and Leading combo boxes with preset lists in the Character and Properties panels and the Control bar (#458), screenshots pasted from the clipboard on macOS, Windows and the web (#457), the Properties panel's Fill and Stroke matching the Control bar's, Illustrator's Window menu panel keys (Shift+F7 for Align…) and Alt-wheel zoom whatever the wheel preference (Discord feedback), the point/area type widget (Discord feedback), groups in legacy Illustrator .ai files (Discord feedback), a rotating desktop log file (#465), image controls in the Control bar and Properties panel: Image Trace with its presets, Mask, Crop Image, Embed/Unembed, and an Image Trace object's preset, Expand and Release (Discord feedback), the Pen working as the Anchor Point tool with Alt held over a selected path's handles and anchors, and anchor buttons that convert, connect and cut paths at the selected anchors (Discord feedback), Japanese hanging punctuation (burasagari, #463), Escape leaving Presentation Mode with no screen mode saved across restarts, documents dropped on the desktop app opening as tabs of their own and a note that an `.ai` file's art off its artboards isn't in the part read (#472), Add/Delete Anchor Point tool icons drawn from the Pen tool's (#479), EPS import running more of PostScript Level 3 (patterns, Type 3 fonts, mesh shadings, masked images, VM and resource probes), and a preview that stands in saying why (Discord feedback, #466, #469, #474), chords with modifiers recorded in Edit › Keyboard Shortcuts (#487), Type Object Selection by Path Only (#394), Anti-aliased Artwork (#394), Show Pixel Grid (#394), pen and touch taps pressed and lifted within one frame clicking where they tapped and the Linux/Wayland pen-tablet workaround (#491), bounding-box resizes landing on the other objects' anchors and centres with labels, and the Rotate, Scale, Shear and Reflect tools snapping their drags (#482), Shift-drag marquees that toggle the objects or anchors they reach and a Lasso whose Alt subtraction keeps the rest of the selection (#483), the mouse wheel stepping the focused numeric field, the dialogs' and preferences' drag values made such fields (#485), Show The Home Screen When No Documents Are Open (#394), Numbers Without Units Are Points (#394), Auto-Collapse Iconic Panels (#394), the Contextual Task Bar moved by its handle and its More Options menu pinning and resetting its position, a designed macOS DMG windoLine truncated
|
||||
|
||||
## Where we are
|
||||
|
||||
|
||||
@@ -503,21 +503,33 @@ pub fn show(app: &mut VectorcraftApp, ui: &mut Ui) {
|
||||
let mut new: Option<(Color, Live, Vec<f32>)> = None;
|
||||
let mut behind: Option<(Color, Live)> = None;
|
||||
let mut tinted: Option<(f32, Live)> = None;
|
||||
let gamut = color.filter(|_| matches!(mode, Mode::Rgb | Mode::Hsb)).and_then(|c| gamut_fix(app, ui.ctx(), "color-gamut", &c));
|
||||
// The warnings the mode shows: out of gamut in RGB and HSB, out of web colours but in Web Safe
|
||||
// RGB and Grayscale.
|
||||
let (shows_gamut, shows_web) = (matches!(mode, Mode::Rgb | Mode::Hsb), !matches!(mode, Mode::WebSafe | Mode::Grayscale));
|
||||
let gamut = color.filter(|_| shows_gamut).and_then(|c| gamut_fix(app, ui.ctx(), "color-gamut", &c));
|
||||
ui.horizontal(|ui| {
|
||||
// Left column: proxy, out-of-gamut and out-of-web warnings.
|
||||
ui.vertical(|ui| {
|
||||
ui.set_width(44.0);
|
||||
super::proxy(app, ui, 40.0);
|
||||
let web = color.filter(|c| !matches!(mode, Mode::WebSafe | Mode::Grayscale) && !is_web_safe(c)).map(|c| web_safe(&c));
|
||||
for (warning, fix) in [(GAMUT_WARNING, gamut), (WEB_WARNING, web)] {
|
||||
if let Some(fix) = fix {
|
||||
ui.add_space(6.0);
|
||||
if warning_chip(ui, warning, &fix) {
|
||||
new = Some((fix, Live::Released, components(mode, &fix)));
|
||||
}
|
||||
let web = color.filter(|c| shows_web && !is_web_safe(c)).map(|c| web_safe(&c));
|
||||
let warnings: Vec<_> = [(GAMUT_WARNING, gamut), (WEB_WARNING, web)].into_iter().filter_map(|(w, fix)| Some((w, fix?))).collect();
|
||||
for (warning, fix) in &warnings {
|
||||
ui.add_space(6.0);
|
||||
if warning_chip(ui, *warning, fix) {
|
||||
new = Some((*fix, Live::Released, components(mode, fix)));
|
||||
}
|
||||
}
|
||||
// Room for the mode's other warnings: the panel keeps its height as the colour changes,
|
||||
// else the spectrum below moves under a dragging pointer and the colour flips every
|
||||
// frame, e.g. between a pale colour out of gamut and white above the spectrum (#578).
|
||||
for _ in warnings.len()..usize::from(shows_gamut) + usize::from(shows_web) {
|
||||
ui.add_space(6.0);
|
||||
ui.scope(|ui| {
|
||||
ui.set_invisible();
|
||||
warning_chip(ui, WEB_WARNING, &Color::WHITE)
|
||||
});
|
||||
}
|
||||
});
|
||||
// Sliders (Shift-drag moves them in tandem).
|
||||
ui.vertical(|ui| {
|
||||
@@ -705,6 +717,40 @@ mod tests {
|
||||
(f.color().map(|c| c.to_hex()).unwrap_or_default(), s.color().map(|c| c.to_hex()).unwrap_or_default())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_drag_on_the_spectrum_holds_still_near_white() {
|
||||
let mut app = app();
|
||||
let ctx = egui::Context::default();
|
||||
let none = egui::Modifiers::NONE;
|
||||
// White needs no warning, #fefefe the web one, a pale violet both: one panel height.
|
||||
let heights: Vec<f32> = ["#ffffff", "#fefefe", "#ded3ff"]
|
||||
.iter()
|
||||
.map(|c| {
|
||||
app.run("paint.setFill", json!({"color": c})).unwrap();
|
||||
frame(&mut app, &ctx, vec![], none);
|
||||
frame(&mut app, &ctx, vec![], none).1
|
||||
})
|
||||
.collect();
|
||||
assert!(heights.windows(2).all(|w| w[0] == w[1]), "{heights:?}");
|
||||
// Drag along the spectrum's top edge (pale colours, some out of gamut), stopping at each
|
||||
// point: the colour holds while the pointer does.
|
||||
let r = frame(&mut app, &ctx, vec![], none).0.expect("the spectrum is drawn");
|
||||
let at = |x: f32| egui::pos2(r.left() + x * r.width(), r.top() + 2.0);
|
||||
let button = |pressed| egui::Event::PointerButton { pos: at(0.02), button: egui::PointerButton::Primary, pressed, modifiers: none };
|
||||
frame(&mut app, &ctx, vec![egui::Event::PointerMoved(at(0.02)), button(true)], none);
|
||||
for i in 1..20 {
|
||||
frame(&mut app, &ctx, vec![egui::Event::PointerMoved(at(i as f32 * 0.05))], none);
|
||||
let fills: Vec<String> = (0..3)
|
||||
.map(|_| {
|
||||
frame(&mut app, &ctx, vec![], none);
|
||||
paints_hex(&app).0
|
||||
})
|
||||
.collect();
|
||||
assert!(fills.windows(2).all(|w| w[0] == w[1]), "at {}: {fills:?}", i as f32 * 0.05);
|
||||
}
|
||||
frame(&mut app, &ctx, vec![button(false)], none);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tandem_keeps_ratios() {
|
||||
let t = tandem(Mode::Rgb, &[100.0, 50.0, 25.0], 0, 200.0);
|
||||
|
||||
Reference in new issue
Block a user