Commit Graph
3328 Commits
Author SHA1 Message Date
dotCooCoo 21b4e70150 Shaper: an arrow widget switches a Shaper Group between Face Selection and Construction mode
A Shaper Group had no arrow widget for switching between Face Selection
and Construction mode.

With the Shaper or Selection tool active, a selected Shaper Group, or a
group with one of its faces selected, now shows an arrow beside the
middle of the right side of its source shapes' bounds. A click on it
isolates the source shapes (object.isolate). A second click leaves
isolation with the group selected (object.exitIsolation). The arrow
points right in Face Selection mode and left in Construction mode.

In Construction mode a Shaper click selects an original shape of the
isolated group. Before, it selected the whole group outside the
isolation, and shaper.select with source could pick an original of
another Shaper Group lying above it.

Docs: docs/shaper.md, docs/target-app-parity.md.
2026-10-16 15:00:07 +07:00
dotCooCoo 6dfdf643d9 Type: Cmd/Ctrl+Shift+X resets horizontal scale to 100%
The reference app resets the horizontal scale of type to 100% with
Cmd/Ctrl+Shift+X. VectorCraft had no command for it, and the chord
cut the selection: egui reports it as a Cut with Shift held.

type.resetHorizontalScale (Reset Horizontal Scale, default
Cmd+Shift+X) sets the horizontal scale to 100% in the text the Type
tool has selected, or else in all the text of every selected type
object, in one undo step. The value is the one the Character panel
shows, so a type object stretched to twice its width keeps 50% stored.
The vertical scale does not change. At a caret the command leaves the
text as it is. Type objects given in ids are reset in full, as
type.resetTracking does.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:09 +07:00
dotCooCoo ad1e8d1112 Type: Cmd/Ctrl+Alt+Shift+. and , step the font size by five increments
No command held Cmd/Ctrl+Alt+Shift+. and Cmd/Ctrl+Alt+Shift+,, so the
chords reached Increase and Decrease Font Size (Cmd/Ctrl+Shift+. and ,)
and changed the size by one Size/Leading increment.

Two commands, type.size.increaseByFive and type.size.decreaseByFive,
now hold the chords. They step the font size of the selected type, or
of the text the Type tool has selected, by five times the Size/Leading
increment (Preferences › Type). Agents reach them with press_key too.
Their labels have rows in every complete catalog.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:09 +07:00
dotCooCoo f46b0f7dc4 PDF export: a page larger than 14,400 pt is written with a UserUnit
PDF export and .ai saves wrote every page in points. ISO 32000-1
(Annex C.2) gives 14,400 units as the longest page side, and a page
with a longer side got a media box past that limit. A PDF/A-2b file
with such a page failed veraPDF's page size rule (6.1.13).

Such a page now gets a UserUnit (PDF 1.6): its longer side divided by
14,400 and rounded up to the next thousandth, with the page's sizes
and coordinates in those units. A 20,000 × 10,000 pt artboard is
written as a 14,398.85 × 7,199.42 page with /UserUnit 1.389, and
VectorCraft's PDF import reads it back at 20,000 × 10,000 pt. Pages
up to 14,400 pt, PDF 1.3 to 1.5 files, PDF/X files and printing are
written as before.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:09 +07:00
dotCooCoo cc3299dc0f Artboards: Fit to Artwork Bounds fits each selected artboard to the art on it
Fit to Artwork Bounds resized the active artboard to the bounds of all
the art in the document, wherever that art was. With art on two
artboards, fitting one of them stretched it over both.

artboard.fitToArt now takes `indices` and fits each artboard to the
art on it, in one undo step. An object counts for every artboard its
drawn bounds overlap, and the artboard is fitted to all of its bounds,
also where it reaches past the artboard's edge. Art flush with an edge
from outside does not count. An artboard with no art on it keeps its
size and place, and the command fails with "no artwork" when none of
its artboards has art. Object › Artboards and the Artboards panel menu
pass the selected artboards (the Artboard tool's, else the active one),
and a recorded action leaves them out. Fit to Selected Art still
resizes the active artboard.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:09 +07:00
dotCooCoo 467c47b719 Transform: Ctrl/Cmd+Enter in W or H scales the selection proportionally
In the Transform panel, the Properties panel's Transform section and
the Control bar, Ctrl+Enter (Cmd+Return on a Mac) in W or H left the
field active and applied nothing. Now it applies the value as Enter
does and sends `proportional: true` to `object.setBounds`, so the other
side scales by the same factor with the Constrain Width and Height
Proportions link off. With the Artboard tool, the Transform panel's W
and H keep the active artboard's proportions the same way. X, Y,
Rotate, Shear and the number fields of dialogs keep Ctrl/Cmd+Enter as
it was.

- widgets::size_field is a num_field that Ctrl/Cmd+Enter also commits.
- transform::proportional gives the `proportional` param of the W and
  H fields: the link, or true after Ctrl/Cmd+Enter.

Docs: docs/target-app-parity.md.
2026-10-16 14:58:09 +07:00
dotCooCoo 03ffe790be View: Rotate View to Selection turns the view square to the selected object
A rotated object's bounding box stands at the object's angle. No
command turned the view to the angle of the selection: `view.rotate`
turns the view only to an angle passed to it.

View › Rotate View to Selection, between the Rotate View submenu and
Reset Rotate View, runs a new UI command, `view.rotateToSelection`. It
turns the view about the center of the canvas to the angle the
selected objects share, the angle `document.inspect` reports as
`selectionRotation`, so their bounding box is square to the window.
Objects turned to different angles share no angle, and the view turns
back to 0. The zoom and the view's center stay as they were. The
command returns `{angle}`. With nothing selected it returns "nothing
selected" and the menu item is disabled; without a document it
returns "no document".

Every catalog that translates the menus has a new "Rotate View to
Selection" row.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
dotCooCoo ebc2857549 Align: Distribute Objects uses the spacing value with a key object
With a key object, the Align panel's six Distribute Objects buttons
ignored the Distribute Spacing value. They kept the outermost objects
in place, spaced the others evenly between them and could move the
key object.

object.distribute now takes spacing. While the selection has a key
object, the key object stays in place, with the compound path or
selected group that contains it, and the objects' left edges, centers
or right edges (top edges, centers or bottom edges) end up spacing
points apart, outward from the key object's, in their order on that
line. With 0, the field's default, every object ends on the key
object's line. Two objects are enough, and to and artboard are not
used. The panel sends the value with the Distribute Objects buttons
while there is a key object, as it does with the Distribute Spacing
buttons. Without a key object, or with anchor points selected,
object.distribute does not use spacing and works as before. A spacing
that is not a number is an error.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
dotCooCoo fb13a1e1f1 Rotate View: Escape pressed twice resets a rotated view
Escape never changed the view's rotation.

Now a second Escape less than a second after the first runs Reset
Rotate View (`view.rotateReset`) when the view is rotated and the
second press has nothing else to end: no Presentation Mode, pattern
editing, isolation mode or open tool flyout, no tool that is busy or
takes the key, no open menu, dialog, command palette or Edit Toolbar
drawer, no text field or input method that takes the key, no number
field being dragged and no drag of the ruler origin. The first Escape
may end something, such as isolation mode, but it does not count as the
first when a menu, a dialog, the command palette, the drawer, a field
or an input method takes it. After a click, a press of another key that
is not a modifier (Shift, Control, Alt/Option or Command) or a held
Escape's repeats, the next Escape counts as the first. With the Rotate
View tool chosen, one Escape resets the view.

Docs: docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
VictorandClaude Opus 5.5 d049e69b95 G1: Remove Anchor Points selects the next anchor (#2241)
After Object › Path › Remove Anchor Points the anchor that follows each
removed one is selected: round the end of a closed subpath, or the one
before it at an open subpath's end. Running the command again goes on
along the path, without picking each anchor first. Several anchors,
subpaths and paths each get their own next anchor; a path that goes
leaves nothing selected; one undo step restores the anchors and the
selection.

The Delete key still selects the remainder whole so a second Delete
removes it, and the Delete Anchor Point tool still leaves the path
selected whole.

Fixes #2241

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:58:08 +07:00
dotCooCoo 288037543e Window: a second Tab shows only the bars the first Tab hid
Tab set the panels, the toolbar and the Control bar to one value on
each press. Two presses turned on a Control bar that had been off.
When the toolbar was hidden with Window › Tools, Tab showed the toolbar
and the Control bar instead of hiding the panels.

Tab now records which of the three showed when it hides them, and the
next Tab shows those again. Panels shown with Shift+Tab in between
stay shown. While the panels are hidden and the toolbar or the
Control bar shows, as after Shift+Tab, Tab hides those bars instead of
showing all three. When the toolbar or the Control bar was shown another way
after Tab hid them, the next Tab hides what shows and records that
instead. A switch of workspace clears the record. When none of the
three shows and Tab hid none, Tab shows all three, as before. The
record is saved with the other UI settings, so the first Tab after a
restart shows the same bars.

Docs: docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
dotCooCoo f554c699a1 Cursors: the canvas shows only the system pointer on macOS while another app or a sheet has the focus
On macOS the canvas paints the tool cursor into the window and hides
the system pointer. winit hides the pointer with a cursor rect that
holds a transparent cursor, and AppKit applies cursor rects only in the
key window. Over a VectorCraft window behind another app, or under its
own File › Open… sheet, macOS showed its arrow next to the painted tool
cursor.

On macOS the canvas now paints the tool cursor only while the window
has the focus. Without the focus it sets the tool's system cursor icon,
and the system pointer shows alone. Windows, X11, Wayland and the web
are unchanged.

Part of #2020.

Docs: docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
dotCooCoo 9336111655 Swatches: Alt-dragging a swatch onto another replaces that swatch's color
In the Swatches panel, a swatch dragged onto another swatch moved next
to it whether or not Alt was held. With Alt held at the release, a
swatch dropped on a swatch of its kind now gives that swatch its color,
gradient or pattern in one undo step, and the swatch keeps its name and
place. Art linked to a global swatch takes the new color. Drags of
None, Registration or color groups, and drops on a tint swatch or on a
swatch of another kind, work as before.

A color dragged in from outside the panel, such as from a Fill/Stroke
proxy, and Alt-dropped on a tint swatch failed with an error that the
swatch is a tint. It now becomes a new swatch, as a drop on a swatch of
another kind does.

Docs: docs/control-protocol.md, docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
Marco Arnulfo bb66070841 Anchor Point tool: a click on a handle end retracts that handle only (fixes #2267) 2026-10-16 14:58:08 +07:00
Marco Arnulfo f88242f576 Fix #2120: a nearly level or upright segment still lines up with its other end; Curvature keeps to the extension too 2026-10-16 14:58:08 +07:00
Marco Arnulfo 54a8d60dae Fix #2120: Smart Guides keep a dragged end of a straight segment on its extension at any angle 2026-10-16 14:58:08 +07:00
Gert Pellin b9069e761e .ai import: a rotated image in the editing data lands where its raster matrix puts it (#2269)
The raster matrix [a b c d tx ty] is an art-space matrix (y up) applied to
the pixels with their rows running downwards, (u, -v). The reader flipped
the matrix's result instead, which only agrees when b = c = 0, so a rotated
image came in turned 180 degrees around its corner. The legacy version 7
writer and its prolog used the same convention; they now write and draw
the matrix the reader takes.
2026-10-16 14:58:08 +07:00
dotCooCoo 88088e99bb Variables: selecting a data set reports the area type it overflows
dataset.select, dataset.next and dataset.prev rewrite bound type with
the data set's text but replied only {name, applied, skipped}. A long
value could push lines out of a fixed frame and the reply had no
overflow key, while text.setText answers overflow: [id] for the same
text.

The three commands now add overflow: [id...] with the area type and
type on a path whose text they rewrote and that doesn't fit, through
typecmd::with_overflow, as text.setText does. An object that two text
variables rewrite is named once. Type that the data set left alone is
not named, and the key is left out when all of the rewritten text
fits.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:58:08 +07:00
VictorandClaude Opus 5.5 a3adaca19e G1: Image Trace, Crop Image and Expand in the Contextual Task Bar
As in the reference app's Contextual Task Bar, which offers "options like
Image Trace, Retype, and Crop Image" for images and lets you "quickly
expand traced artwork from the bar" (public announcement:
https://community.adobe.com/announcements-651/contextual-task-bar-in-illustrator-2025-quick-actions-when-you-need-them-1546580):

- One image selected: Image Trace traces it at once with the Default
  preset, leaving the Image Trace panel as it was (like the quick trace
  from Properties and the Control bar); Crop Image shows the crop box.
  Offset Path and Simplify, which don't apply to an image, are gone.
- One Image Trace object selected: Expand keeps only the traced paths,
  in place of Ungroup and Isolate.

Retype isn't offered: the app doesn't have it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:58:07 +07:00
dotCooCoo 837d2b5667 Variables: a quoted text cell in a data set CSV keeps its leading and trailing spaces
dataset.import trimmed every cell, quoted or not. dataset.export quotes
a text value with leading or trailing spaces, so a value such as
"  padded " came back from its own export as "padded".

The CSV reader now trims an unquoted cell as before and keeps a quoted
cell as written between its quotes, spaces included. White space
between the closing quote and the next comma or line end is still
dropped. Image, graph and visibility cells, data set names and header
cells are trimmed as before.
2026-10-16 14:57:25 +07:00
dotCooCoo 04806a98bf .ai import: text on a layer that doesn't print stays on that layer
A `.ai` opened from its editing data lost a text object on a layer that
shows and has Print off when its page drew no type for it. prune_unseen
weighs each text object made from the text document that the page's
type doesn't match against the page, and the layers are drawn for that
comparison as they print (as_printed), with such layers hidden. Taking
one of these objects out never changed the comparison, so each was
removed with the note "text objects that the file keeps but its page
doesn't draw ... are left out".

unmark now carries a print flag next to the shown flag, and a layer
with printable off clears it for everything it holds. Only made text
objects that show and print are weighed against the page; the others
stay on their layer.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 14:57:24 +07:00
Marco Arnulfo c91405dbea Window menu: a panel's item hides it while it shows and shows it again where it was (part of #2361) 2026-10-16 14:57:23 +07:00
Marco Arnulfo 80b7aee756 Isolation mode: a path of the isolated compound path moves on its own (fixes #2354) 2026-10-16 14:57:22 +07:00
Ayberk A. d838af024b MCP: command listings take query, menu and brief (#2173)
The command catalogue is about 340,000 characters, more than many MCP
clients show, and `query` (the name agents reach for first) was refused as
an unknown argument. command_list and list_commands now take `query` as
another name for `filter`, `menu` to keep the commands under a menu path
("Object > Path"), and `brief` to leave out each command's params text,
which is most of the catalogue; the params of one command are a filtered
listing away.
2026-10-16 14:57:21 +07:00
NetterSilverandClaude Haiku 5.5 e510190867 Keep Layers panel selection inside the isolated group
Fixes #2286

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:57:21 +07:00
NetterSilverandClaude Haiku 5.5 ee6cd6de55 Keep paragraph styles aligned in Find and Replace with line breaks
Found while testing crates/engine/src/cmd/typemenu.rs:668 (find_replace / edit_runs)

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-16 14:57:20 +07:00
Ayberk A. f14f8d8eb7 Font menu: the scroll bar no longer covers the favourite stars (#2277)
The family list scrolled with egui's floating scroll bar, which is drawn
over the rows' right ends, where each family's star is: with the pointer
there the bar widened over the star and a click went to the bar. The list
now takes the scroll bar the menus got for the same reason (#2086), slim
and in a column of its own; `widgets::list_scroll_style` holds it for both.
2026-10-16 14:57:19 +07:00
Marco Arnulfo 3b00334c41 Graph Type: the graph kind is a dropdown of the nine types (fixes #2175) 2026-10-16 14:57:18 +07:00
Dylan M. Taylor e9edc49977 ci: switch to shared nix workflow from craft-common-actions 2026-10-16 14:57:18 +07:00
Dylan M. Taylor f9092edfe3 ci: standardize FreeBSD workflow on shared FreeBSD 15.1 action 2026-10-16 14:57:17 +07:00
Patrik LermonandClaude Opus 5.5 54e43d0a97 i18n(sv): review of the rows drafted for the strings main added
- "Font Style:" in Dimension Tool Options is Teckensnittsstil: Teckenstil
  is already Character Style.
- The drawing-scale help reads "1:10 visar 1 enhet på sidan som 10".
- The layered-file fallback message and "Check an artboard to save" read
  more naturally.
- "File › Place…" names the menu as the menus do (Fil, not Arkiv).
- The rows are reviewed, so the "machine-drafted; review welcome" note
  above them goes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:57:16 +07:00
Marco Arnulfo c5e38a309c Contributors: add my name for the About window 2026-10-16 14:57:15 +07:00
BFlat 842656f240 Merge pull request #2378 from storytold/ui/classic-theme
UI: Classic colour scheme
2026-10-16 14:39:52 +07:00
bflatastic a64a5a9911 UI: Classic colour scheme (User Interface › Color Scheme)
A second colour scheme next to Modern: the neutral greys and blue accent of
earlier versions, on the same cards, corners and layout. Picked in
Preferences › User Interface › Color Scheme (pref uiColorScheme:
modern|classic); Accent Color is dimmed while Classic is chosen, which has
its own blue.
2026-10-16 14:29:33 +07:00
skylar taylor-barrick ae6dc17ffe Merge pull request #1184 from dylanmtaylor/refactor/dry-github-actions
ci: refactor workflows to use storytold/craft-common-actions and add nix check
2026-10-15 21:46:35 -06:00
skylartaylor 2fa10c957c ci: retain VectorCraft package and release checks 2026-10-16 05:43:40 +02:00
BFlat deff5b8f42 Merge pull request #2339 from storytold/readme/screenshots
README: new screenshots, with 3D Revolve and Dimension tool showcases
2026-10-16 09:57:55 +07:00
bflatastic c334aa7e66 README: new screenshots of the current interface, with 3D Revolve and Dimension tool showcases
Seven app screenshots retaken at 2240x1400 (UI at 1.6x), two of them new: a 3D still life with the Revolve dialog (examples/still-life.vectorcraft) and a bracket drawing with linked dimensions (examples/bracket-drawing.vectorcraft). The still life also joins Made in VectorCraft. The older examples are saved again in the current native format; they render the same.
2026-10-16 09:53:12 +07:00
BFlat 3f33e854d4 Merge pull request #2331 from storytold/ui/restyle
UI: restyled interface
2026-10-16 09:11:04 +07:00
bflatastic 257217a2e3 UI: restyled interface with a choice of accent colours 2026-10-16 09:00:14 +07:00
Dylan M. Taylor f08f3619e3 ci: refactor workflows to use storytold/craft-common-actions and add nix check 2026-10-15 21:38:50 -04:00
BFlat 8770d2a96c Merge pull request #1902 from Messhias/feat/g12-layers-collect-export
G12: Collect for Export on Layers (≡ and row menu)
2026-10-16 06:37:53 +07:00
BFlat c64c0120f5 Merge pull request #1918 from sanyamsingh001/codex/r65-guide-origin
G1: align guide snapping and readouts with ruler origin
2026-10-16 06:37:36 +07:00
BFlat 40fe3154ee Merge pull request #1912 from p0lyg0n/i18n/ja-swatches
i18n: the Swatches panel shows the default swatches' names in Japanese
2026-10-16 06:37:17 +07:00
BFlat a812bb7dcc Merge pull request #1900 from imachus/pr/ja-whitespace-fallback
Type: whitespace the primary font doesn't map takes the fallback face too (#1844)
2026-10-16 06:36:58 +07:00
BFlat 756ec5c5e3 Merge pull request #2281 from limackk/fix/round-corners-curve-line
Effects: Round Corners also rounds corners where a curve meets a line
2026-10-16 06:36:40 +07:00
BFlat 0bd4ce2260 Merge pull request #2280 from guillehr2/fix/transform-copies-symbol-instances-and-reach
effects: a Transform effect copies a group's symbol instances too, and stops image copies at MAX_REACH
2026-10-16 06:36:13 +07:00
BFlat 06fdeeef6c Merge pull request #2283 from marcoarnulfo/fix/svg-mask-type-alpha
SVG import: an alpha mask counts by its art's alpha, not its luminance
2026-10-16 06:35:54 +07:00
BFlat 9da787f951 Merge pull request #1888 from dotCooCoo/fix/brush-art-own-stroke-outlines
Render: the strokes of brush art are no longer drawn with old outlines
2026-10-16 06:35:36 +07:00
BFlat 2853d78e66 Merge pull request #1889 from dotCooCoo/fix/commands-with-nested-ids
Commands: ids leave out an object listed with a group that holds it, as the selection does
2026-10-16 06:35:21 +07:00