Commit Graph
3351 Commits
Author SHA1 Message Date
BFlat 80be476b04 Merge pull request #2264 from andeecollard/fix/trace-grayscale-gradients
Image Trace: grayscale gradients use grey stops
2026-10-16 04:30:29 +07:00
BFlat cddc5a6848 Merge pull request #2263 from andeecollard/fix/trace-seam-guard
Image Trace: keep shared corners identical at nearby junctions
2026-10-16 04:30:23 +07:00
BFlat d6f6cb9b5f Merge pull request #2025 from andeecollard/fix/trace-snap-collapsed-loops
Image Trace: preserve thin closed outlines after straightening
2026-10-16 04:30:15 +07:00
BFlat 5aab51bf87 Merge pull request #2012 from andeecollard/fix/trace-small-closed-contours
Image Trace: retain tiny components and holes after fitting
2026-10-16 04:29:57 +07:00
BFlat 3bcce6593a Merge pull request #2144 from dotCooCoo/fix/twisted-walls-depth-order
3D and Materials: twisted walls and bevels are drawn back to front
2026-10-16 04:25:17 +07:00
BFlat 192ca0b8e6 Merge pull request #2180 from dotCooCoo/feat/scribble-separate-variations
Effects: Scribble has a Variation for Path Overlap, Curviness and Spacing, and stores 270° as -90°
2026-10-16 04:25:00 +07:00
BFlat b64c88b4d9 Merge pull request #2154 from dotCooCoo/feat/smart-blur-edge-modes
Effects: Smart Blur's Mode menu has Edge Only and Overlay Edge
2026-10-16 04:24:44 +07:00
BFlat 78c5973609 Merge pull request #1925 from dotCooCoo/feat/clipboard-flavors-off-ui-thread
Clipboard: Copy and Cut make the system clipboard's formats on the background thread
2026-10-16 04:24:28 +07:00
BFlat 99a6c06681 Merge pull request #2032 from dotCooCoo/fix/issue-1876
Artboards: the options icon and the panel menu open Artboard Options
2026-10-16 04:24:10 +07:00
BFlat c42b31f48a Merge pull request #2039 from dotCooCoo/fix/pathfinder-effect-keeps-type
Effects: Effect › Pathfinder uses the glyph outlines of type in the group
2026-10-16 04:23:53 +07:00
BFlat 4f794ea8db Merge pull request #2056 from dotCooCoo/feat/perf-deep-peak-working-set
CLI: perf --deep reports the peak working set on Windows and the peak resident memory on Linux
2026-10-16 04:23:37 +07:00
BFlat cc467d1ef4 Merge pull request #2063 from dotCooCoo/feat/plugin-geometry-follows-registry
Render: objects with plug-in effects follow the plug-ins installed
2026-10-16 04:23:18 +07:00
BFlat bfe6670539 Merge pull request #2064 from dotCooCoo/fix/fit-artboard-active
Artboards: Fit to Artwork Bounds and Fit to Selected Art resize the active artboard
2026-10-16 04:23:01 +07:00
BFlat bf10fd64f6 Merge pull request #2065 from dotCooCoo/feat/auto-size-type-fewer-layouts
Type: Auto Size area type in columns usually lays the columns out twice an edit
2026-10-16 04:22:45 +07:00
BFlat 2346a4acfb Merge pull request #2067 from dotCooCoo/feat/alt-drag-copies-once-more-tools
Part of #1429: Alt-drags of objects and plane widgets in perspective copy the objects once per drag
2026-10-16 04:22:29 +07:00
BFlat 5b9a9b6d6c Merge pull request #2068 from dotCooCoo/fix/active-artboard-outline
Artboards: the canvas outlines the active artboard in black
2026-10-16 04:22:13 +07:00
BFlat 82d9143502 Merge pull request #2087 from dotCooCoo/feat/layers-panel-filter
Layers: the panel filters its rows by object kind, lock and visibility
2026-10-16 04:21:55 +07:00
BFlat cebc4ed93e Merge pull request #2093 from dotCooCoo/feat/presentation-mode-artboard-keys
View: in Presentation Mode, the left and right arrow keys and a click go between artboards
2026-10-16 04:21:32 +07:00
BFlat 29bf7b7e06 Merge pull request #2099 from dotCooCoo/feat/artboard-navigator-list
Status bar: the artboard navigator lists the artboards by number and name
2026-10-16 04:21:15 +07:00
BFlat e965c0daa2 Merge pull request #2102 from dotCooCoo/feat/properties-artboard-name-options
Properties: Edit Artboards renames the active artboard and opens Artboard Options
2026-10-16 04:21:00 +07:00
BFlat aaeb658292 Merge pull request #2106 from dotCooCoo/feat/rotate-view-menu
View: Rotate View turns the view to a preset angle, and `view.rotate` sets any angle
2026-10-16 04:20:42 +07:00
BFlat d541eb9476 Merge pull request #2116 from dotCooCoo/feat/export-screens-selected-artboards
Export for Screens: the dialog opens with the Artboard tool's selected artboards checked
2026-10-16 04:20:26 +07:00
BFlat cf0be249ba Merge pull request #2134 from dotCooCoo/feat/free-distort-dialog-corners
Effects: Free Distort's corners are dragged in its dialog
2026-10-16 04:20:09 +07:00
BFlat 0594f04e30 Merge pull request #2136 from dotCooCoo/feat/color-panel-options-command
Color panel: Hide Options comes back after a restart, and `ui.colorPanel` sets the mode and options
2026-10-16 04:19:47 +07:00
BFlat b15c28b7c0 Merge pull request #2138 from dotCooCoo/fix/glowing-edges-raster-stylize
Effect menu: Glowing Edges moves to a Stylize submenu under Raster Effects
2026-10-16 04:19:23 +07:00
Murat Vural 1ab3940b3d feat: move and copy ruler guides and art together when selected 2026-10-16 04:19:06 +07:00
Lucas LerouxandClaude Opus 5.5 2abc1d61f7 xtask ci: test vectorcraft-text without its bundled fonts
`cargo test --workspace` builds vectorcraft-text with `bundled-fonts`
(the engine turns it on), so the configuration embedders use without it
was tested only by hand. A `no-bundled-fonts` step after `test` runs its
integration test.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:19:05 +07:00
Lucas LerouxandClaude Opus 5.5 1e8f5025c6 Render, SVG: vello_cpu and usvg without their text features: one skrifa, read-fonts and harfrust fewer in the engine
The default `text` features of vello_cpu (glyph runs, through glifo) and
usvg (fontdb, harfrust 0.12, skrifa 0.44 and its read-fonts 0.41) build
another copy of the font stack into the engine, next to the workspace's
skrifa 0.47 and harfrust 0.13. Neither is used: the renderer draws the
glyph outlines vectorcraft-text gives it, and SVG import reads <text>
from the XML itself and never gives usvg a font (usvg leaves out text it
has no font for).

- vello_cpu: its default features but `text` (std, png, u8_pipeline),
  plus f32_pipeline as before.
- usvg: `svgz` only, for gzipped SVG images inside an SVG; `text`,
  `system-fonts`, `memmap-fonts` and `writer` are off. text_layout.rs uses
  usvg as a reference viewer with a font, so crates/svg turns `text` on as
  a dev-dependency feature, as crates/pdf does for krilla's `simple-text`.
- A test pins `svgz`: SVGZ images, linked or as a data URL, import as
  vector art.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:19:05 +07:00
IanHollow 83f40f135a Text: make every supplied font family available to documents
Assisted-by: GPT-6
Signed-off-by: IanHollow <72767437+IanHollow@users.noreply.github.com>
2026-10-16 04:19:05 +07:00
YukiHiko 8b5e9e4927 G6: expose vertical writing in MCP add_text 2026-10-16 04:19:05 +07:00
YukiHiko 3a7d422046 G4: keep fullwidth punctuation upright without vertical alternates 2026-10-16 04:19:05 +07:00
ham9zah ad3531d464 Curvature: each three points follow the circle through them, curved ends (#1236, in part)
The Curvature tool built its curve as a uniform Catmull-Rom: both handles of a
smooth point a sixth of the chord between its neighbours, the ends of an open
path without handles. Uneven spacing overshot or looped, a J or U from three
points bent sharply at the middle with straight legs, and the end segments
looked flat.

- `curvature_spline` (draw2.rs) makes each stretch of three points follow the
  circle through them: a smooth point's tangent is that circle's
  (`smooth_handles`), each handle `chord / (3 cos²(α/2))` long, α between
  handle and chord capped at 90° (`arc_handle`). The ends of an open path
  mirror their neighbour's tangent in their chord (`end_handle`). A turn
  tighter than 30° (`TIGHT_TURN`) shortens its handles, so a narrow V comes to
  a point. Degenerate points become corners. `path.curvature` and the rubber
  band use it.
- `catmull_rom` is unchanged for the Pencil and Paintbrush fitting.
- `bend_last` (from: smooth), `curvature_move` on a smooth point, the point
  `curvature_insert` adds on a straight segment, and `path.convertAnchor` to
  smooth without x/y (`curvature_smooth`) use the same rule.
- `curvature_extend` gives the new end its end handle unless Alt-clicked
  (`corner` param on `path.curvatureEdit`).
- Neighbours of a point dragged on an existing path keep their tangents (a
  Pen-drawn shape isn't reshaped); the path being drawn re-curves throughout.
2026-10-16 04:19:05 +07:00
el-j 4913418d1c Type tool: Escape returns to the previous selection tool and preserves isolation mode
When entering text edit mode via double-click from a selection tool
(Selection or Direct Selection), pressing Escape now returns to the specific
tool used before double-clicking (rather than always falling back to
Selection).

Additionally, when editing text while in isolation mode (such as when drilling
into nested groups with the Selection tool), pressing Escape exits text editing
while keeping isolation mode active; a second Escape press is required to exit
isolation mode.

- Record the previous tool in TypeTool on double-click from canvas.
- Return to prev_tool on ToolKey::Escape, consuming the key in shortcuts when claimed.
- Add unit test in vectorcraft-tools verifying Escape returns to prev_tool.
- Add integration tests in vectorcraft-ui-egui verifying Escape returns to Direct
  Selection and that isolation mode persists until a second Escape.
- Update docs/target-app-parity.md and ROADMAP.md.
2026-10-16 04:19:05 +07:00
bflatastic 9e1590769e i18n(bg): Hide Template and Show Template 2026-10-16 04:19:05 +07:00
Lucas LerouxandClaude Opus 5.5 55fadb6afe Text: a bundled-fonts feature (on by default) lets embedders that bring their own fonts leave ours out
The nine OFL faces in `assets/fonts` are compiled into every build of
vectorcraft-text: 3.4 MB of the binary, about 1.6 MB of a gzipped wasm.
An embedder that loads every font at run time with `FontDb::add_font`
(a web app serving its own font catalogue, say) ships them twice and
can't turn them off.

- vectorcraft-text: `bundled-fonts`, a default feature, holds the
  `include_bytes!` list. Off, a database starts without them (craft-fonts
  and system fonts are unaffected) and text has no glyphs until a font
  is added, as when the bundled fonts fail to parse.
- vectorcraft-engine: a `bundled-fonts` default feature forwards to it,
  so the apps and any embedder using the engine keep the fonts unless
  they build it with `default-features = false`.
- The workspace declares vectorcraft-text without default features, so
  no library crate turns the fonts back on. The tests of cad, metafile
  and tools, which lay type out, ask for the feature in their
  dev-dependencies; the other crates' tests get it through testkit.

`cargo test --workspace` builds with the fonts, as before. A new
integration test, `without_bundled_fonts`, covers the configuration
without them (`cargo test -p vectorcraft-text --no-default-features
--test without_bundled_fonts`): the database starts without them, text
in no font lays out with no glyphs, and a font added later is used and
is the fallback for families the database lacks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:19:05 +07:00
el-j 28daaf473c Canvas: double-clicking type with the direct selection tool puts the caret there
With the Direct Selection tool ("white arrow", shortcut 'a'), double-clicking
a text element (either standalone or nested inside a group) now switches to
the Type tool and immediately positions the caret at the clicked character,
matching the behavior previously introduced for the Selection tool in #284.

- In DirectSelectionTool::pointer, detect double-click hits on NodeKind::Text
  when !self.group and emit Action::SwitchTool("type").
- Group Selection (group: true) retains its existing group cycling behavior.
- Add unit test in vectorcraft-tools verifying tool switch on both standalone
  and grouped text.
- Add headless egui integration test in vectorcraft-ui-egui verifying tool switch,
  caret positioning, and inline editing without triggering shortcuts.
- Update docs/target-app-parity.md and ROADMAP.md.
2026-10-16 04:19:05 +07:00
BFlat fc51d66659 Merge pull request #2140 from dotCooCoo/feat/save-template-ait
Templates: Save as Template can also write a PDF-compatible .ait
2026-10-16 04:19:04 +07:00
wstockandClaude Fable 5.1 7b8730ec14 View › Hide Template (Cmd+Shift+W): template layers leave the canvas and come back (#2000)
Illustrator's View menu has Hide/Show Template (Shift+Ctrl+W) to leave
template layers off the screen while tracing. VectorCraft drew them (dimmed)
whatever the view, with no way to hide them short of disabling the template
option on each layer and losing the dimming.

- `view.template` toggles `ViewFlags::templates` (default on, kept across
  settings files); the View menu lists Hide Template after Lock Slices, and
  the label flips to Show Template.
- The canvas renders with the new `RenderOptions::hide_templates`, which
  leaves template layers out and nothing else; `skip_templates` (exports and
  thumbnails) also drops guide paths, so it is not reused.
- The fifteen menu catalogs translate both labels; `DYNAMIC_LABELS` lists them.

Tests: render `hide_template_leaves_only_the_template_layers_out` (the
template layer's square and image go, a guide path on another layer stays);
canvas `hide_template_leaves_template_layers_off_the_canvas` (real egui
frames: painted pixels, none after Hide Template, the same after Show
Template, each re-rendering once); the dynamic-label and catalog tests cover
the new pair.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011K1peyrh5MdZ6ttHkVq8Gh
2026-10-16 04:08:44 +07:00
NetterSilverandClaude Haiku 5.5 c54a9b0bef Reveal the active layer in the Layers panel after a canvas selection
Fixes #2049

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:42 +07:00
Ayberk A. a86ff7f177 Document Info: Objects gives the paths' total length (#1958)
Document Info › Objects counts the paths but didn't say how long they are,
which sign and print work reads there (an LED strip along the letters, a
cut line). `document.info` now adds up the length of every path it counts,
the pieces of compound paths included and guides left out, and returns it
as `pathLength` (pt); the Objects section shows it as Path Length in the
document's units, right after the Paths count, so Selection Only gives the
selected paths' length. The label is translated in the catalogs that
cover the menus; pt-br only takes strings the UI itself shows.
2026-10-16 04:08:12 +07:00
Fabian GrajalesandClaude Opus 5.5 7135a377f8 Panel menus light up under the pointer, like the menu bar's
Panel (≡) menu rows, and the Control bar's image menu, had no frame at all,
so nothing showed which row the pointer was on. They now draw the hover
frame the menu bar's items draw.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:10 +07:00
Fabian GrajalesandClaude Opus 5.5 91e1434cbf Swatches panel follows the selection's swatch
Selecting art scrolls the tiles to its swatch once (centred) and clears the
panel's own selection, so the art's swatch is the one highlighted; so does a
change of the selection's paint (after Recolor Artwork). An unlinked process
colour highlights the swatch of that very colour. A selected image, or text
in a colour no swatch has, highlights nothing (not None).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:08 +07:00
Fabian GrajalesandClaude Opus 5.5 5a43337a42 Replace a selected image from the Control bar, with its own aspect ratio
The Control bar's file name is a menu: Replace…, Go To Link, Edit Original,
Update Link and Placement Options…. Replace… (also in the Properties panel,
in place of Relink…) puts the picked file in the image's place fitted inside
the old bounds and centred, keeping the new file's aspect ratio instead of
stretching it into the old one. links.relink takes `preserve` (transforms,
bounds, fileDimensions, fit or fill) to override the Placement Options for
that read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:06 +07:00
Fabian GrajalesandClaude Opus 5.5 5252c3d86a Recolor Artwork: library colours apply as their swatches; import a library
With Limit to Library, a row's new colour is the library swatch itself: art
links to a global or spot colour (a Pantone-style spot colour stays a spot
colour in its own model, tints keep their tint) and a process swatch gives
its colour in its own model, instead of being converted to the model of the
colour it replaces. The swatches used join the document's swatches (one the
document already has, same name and colour, is reused); recolor.apply
reports them as `swatches`. A folder button next to Limit to Library loads a
library file (.ase, .acb, .gpl, .vcswatches or a document's swatches) and
limits to it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:04 +07:00
Fabian GrajalesandClaude Opus 5.5 1ba448f7f3 Recolor Artwork from the Contextual Task Bar and the Control bar
A palette button opens Recolor Artwork when the selection has colours to
recolour (solid colours, gradient stops or mesh points, inside groups too):
in the Contextual Task Bar, before Lock, and in the Control bar, after the
Graphic Style picker. Art painted with None shows no button.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 04:08:01 +07:00
turtwig 032b7b7be1 Glyphs panel: zoom buttons resize the preview and the step is kept
Zoom Out and Zoom In sit to the right of the font family and style menus. They step the preview cells through 16, 22, 30, 42, 56, 72 and 96 pt; the grid still opens at 30 pt, and the buttons stop at the ends. The step is stored on the UI state and written with the other panel choices in ui.json when the app quits. Zero is the default and is left out of the file, so older preferences stay as they are.
2026-10-16 04:07:59 +07:00
andeecollardandClaude Opus 5.5 8fffa4f6f9 Image Trace: regression tests for shared closed boundaries
Abutting traces must draw each edge between two neighbouring regions once:
the filled paths on either side follow one curve, one of them reversed, and
together cover the image without gaps or overlaps. These tests check that
from the trace output alone, with no renderer: points along each path's
outline must lie within 0.001 px of another path's outline, the paths' areas
must sum to the image's, and every point of a 4 x 4 per-pixel grid must lie
in exactly one path.

The images are drawn in code, hard-edged and anti-aliased, and traced in
Color (Abutting) and Black and White, each at the default settings, Paths and
Corners 0 and 100, Snap Curves To Lines, and Shapes. They cover a closed island
in a background, a ring with and without a core of a third colour, a wavy
two-colour seam, a three-region junction, outlines that leave a junction and
return to it (the 111 / 101 / 110 pattern at 1, 2, 3 and 6 px, and framed),
squares touching at a corner, a one-pixel hole and a one-pixel island (kept at
Noise 1, dropped together with what they leave at Noise 25), separate areas of
one colour, and slanted hatches with one-pixel paper channels. A further test
shows the check finds a 0.01 px shift and stacked (Overlapping) layers.

Two tests are ignored as documented current gaps:
- At Paths 0 and Corners 0, a piece returning to its own junction collapses:
  its region is dropped and its area left uncovered (draft #2205 fixes it).
- With Shapes, a region whose outline runs through a junction becomes an exact
  shape its neighbour does not share (up to 0.0039 px in Black and White).

No tracer code changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tBcdwNhptqtmX32JCGFzB
2026-10-16 04:07:57 +07:00
andeecollardandClaude Opus 5.5 dbcd32d21a Image Trace: grayscale gradients use grey stops
In Grayscale mode with Gradients on, the trace could fill paths with
coloured linear gradients (for example a blue-to-orange ramp) beside
grey flat fills. Gradient detection ran on the RGB image, so the stops
and the gradient's palette colour (its middle) were the source colours,
while Grayscale's flat fills come from each pixel's luma.

Grayscale now finds gradients, and settles their edges, in a copy of the
image reduced to the same Rec. 601 luma the flat grays are quantised
from. Every channel of that copy is equal, so the fitted stops, the ends
carried to the area's edges and the palette entry are all grey. Color
mode is unchanged: it still detects on the RGB image (trace output for
gradient fixtures is byte-identical before and after).

Adds grayscale_gradients_are_grey: a code-drawn sky ramp over flat
shapes with a ramp rectangle, traced in Grayscale with 4 grays and
Gradients on, must still produce a gradient, and every path colour,
gradient stop and palette entry must be grey.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tBcdwNhptqtmX32JCGFzB
2026-10-16 04:07:55 +07:00
andeecollardandClaude Opus 5.5 5d8b5ddc6c Image Trace: keep shared corners identical at nearby junctions
When a long horizontal or vertical run crosses a three-colour junction one
or two pixels before a corner, the corner correction for that run borrowed
a neighbouring crack's shift that the region on the other side of the
junction never applied, leaving hairline gaps between abutting colours.
The correction now applies only when all three cracks it uses lie in the
same shared piece.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tBcdwNhptqtmX32JCGFzB
2026-10-16 04:07:53 +07:00
andeecollardandClaude Opus 5.5 75b91e9ef3 Docs: leave the status lines to main
The 'Last updated · Change' status lines in docs/roadmap.md, docs/target-app-parity.md and docs/image-trace-quality.md change with almost every merge to main, so this PR's edits to them conflicted each time main moved. They are reverted to main's text; this PR's evidence bullets, history rows and table entries stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018tBcdwNhptqtmX32JCGFzB
2026-10-16 04:07:51 +07:00