Commit Graph
2051 Commits
Author SHA1 Message Date
dotCooCoo 817bfceda3 Resolve GDEF contour-point ligature carets 2026-11-04 08:12:22 +07:00
dotCooCoo dfc25c85e4 Type: move right-to-left characters with Touch Type 2026-11-03 23:57:53 +07:00
dotCooCoo bbbce4318f Add Enclosing Lasso as an optional tool
Squashed from #5362 onto main.
2026-11-03 23:30:06 +07:00
dotCooCoo 63ac1395fd Type: control Kashidas for selected characters 2026-11-03 23:29:52 +07:00
bflatastic 28b87faeee Type on a Path Options: docs say where the Preview checkbox comes from 2026-11-03 22:54:12 +07:00
ruchirguitarandClaude Opus 5.5 f53ebdf7c0 Fix #5360: Type on a Path Options has a Preview checkbox
With Preview on, the selected type on a path follows Effect, Flip, Align
to Path and Spacing while the dialog is open. Cancel puts it back with no
history step; OK keeps the previewed values as one undo step. Preview
starts off. The public pages list no Preview for this dialog, so this is
a VectorCraft choice, recorded as such in the parity docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:53:39 +07:00
NetterSilverandClaude Opus 5.5 2264edd0c9 Lasso picks gradient mesh points instead of dropping the mesh
Fixes #5351

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:16:53 +07:00
dotCooCoo 2b63bf1b67 Type: keep composition spacing along the line when characters rotate 2026-11-03 21:38:02 +07:00
dotCooCoo 0f5e4c261a Transform previews typed values in its effect dialog 2026-11-03 21:09:55 +07:00
dotCooCoo 0a9d65175a Docs: record Find Font replacement sources 2026-11-03 21:09:53 +07:00
dotCooCoo e9a3ca2c81 Character style evidence links to help without copied instructions 2026-11-03 21:09:52 +07:00
bflatastic 14b0667e95 Actions: docs describe function keys as they now work (no Replace, keys kept) 2026-11-03 20:27:30 +07:00
dotCooCoo 40ed074cae Actions: New Action asks for the action's name, set, function key and color
Squashed from #5270 onto main.
2026-11-03 20:27:02 +07:00
dotCooCoo 4db6e7b448 Paint: use the document color model for new gradient defaults 2026-11-03 20:18:34 +07:00
ruchirguitarandClaude Opus 5.5 8850b923ce Fix #4924: Text Tweaker ramps or randomises one character attribute letter by letter
A built-in Type Tools add-on (Object › Plug-ins › Type Tools › Text Tweaker…,
`addon.type.textTweaker`): size, baseline shift, rotation, horizontal or vertical
scale, tracking, leading or stroke weight go from a start value to an end value
along a straight ramp, an ease, a bow, a spike or at random with a seed, set as
the Character panel sets them, while the text stays live. One undo step, a
dialog with Preview, catalog rows in all 26 languages, docs/mcp.md and the
parity docs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 20:07:58 +07:00
Brandon Thomas 9933deeebc Merge pull request #5352 from dotCooCoo/docs/assessment-target
Docs: consolidate assessment target metadata
2026-11-03 08:05:33 -05:00
ruchirguitarandClaude Opus 5.5 46f1ddf170 Fix #5236: find PhotoCraft where its Windows installer puts it
Per CodeRabbit on #5327: on Windows Edit Original looked for photocraft.exe
only on the PATH, but PhotoCraft's MSI installs it to ArtCraft\PhotoCraft
under %LOCALAPPDATA%\Programs (per user, the default) or Program Files (for
everyone), neither on the PATH. Look first at the path the installer
registers under App Paths (HKCU, then HKLM; `reg query`, as i18n reads the
locale, which also covers a folder chosen in setup), then those two default
folders, then the PATH. Each candidate must still be an .exe.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:57:04 +07:00
ruchirguitarandClaude Opus 5.5 d7aa1c561f Fix #5236: Edit Original is one checkbox, Use System Defaults for Edit Original
Per review on #5327: Preferences › File Handling › Edit Original With (an app
path and Choose…) becomes the checkbox Use System Defaults for Edit Original,
on by default. Off, Edit Original opens a raster image in the app that made
it, PhotoCraft, looked for only where it installs; any other file, or no
PhotoCraft, goes to the system's default app. The preference is a boolean, so
prefs.set over control or MCP can no longer name an executable. The label has
a row in all 26 catalogs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:57:04 +07:00
ruchirguitarandClaude Opus 5.5 d11764c117 Fix #5236: Edit Original opens linked files in a chosen app
Preferences › File Handling › Edit Original With picks the app Links
panel › Edit Original opens a linked file in: System Default (as before),
PhotoCraft (found in /Applications or ~/Applications on macOS, on the
PATH elsewhere) or Other Application, with a path field and Choose….

The desktop host's new `open_file_with` service starts only an
application (an .app bundle on macOS, an .exe on Windows, an executable
file elsewhere), with the path as its only argument and never through a
shell. Edit Original still refuses control requests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 19:57:04 +07:00
dotCooCoo 4e75f135e9 Docs: consolidate assessment target metadata 2026-11-03 04:50:29 -08:00
dotCooCoo a870da6c7d .ai import: Effect › Pathfinder on a group opens as a live effect
Squashed from #5150 onto main.
2026-11-03 16:38:47 +07:00
dotCooCoo f62e502f1c .ai import: version 7 pattern definitions come in as pattern swatches
Squashed from #5189 onto main.
2026-11-03 16:38:42 +07:00
dotCooCoo e1ea0ecad1 Type: the caret, a click and the arrow keys reach the characters inside a ligature
Squashed from #5225 onto main.
2026-11-03 16:38:36 +07:00
dotCooCoo 86deb546ad Variables: Import Data Sets reads every column as a variable and replaces the data sets
Squashed from #5151 onto main.
2026-11-03 16:38:29 +07:00
dotCooCoo fbab0bdd43 Type: Find Font's Replace With Font From lists the document's, recent or installed fonts
Squashed from #5217 onto main.
2026-11-03 16:38:24 +07:00
Ahmed Gomaa 1d011ab8ad Render: a compound path's members are assembled once and kept with the node
A compound path was assembled from its members in every frame it was
drawn, and Node::stroke_path grew its buffer by doubling, copying the
path into ever larger buffers for a compound path of many anchors. The
renderer's geometry cache was swept only once it held more than 1,024
entries, so while an object was dragged (a new node, and layer, in
every frame) the old copies stayed alive with all their members.

Now:
- a compound path is drawn from the path the renderer keeps for it in
  its geometry cache, as a plain path already was, and is assembled
  only when the node changes;
- Node::stroke_path sizes a compound path's buffer up front from its
  members' segment counts (the same elements, in the same order);
- unused geometry entries are dropped after a few frames however few
  entries there are.

Tests:
- crates/render/src/tests/memory.rs: the second frame draws the kept
  path and the same pixels as the first and as a new renderer; after a
  five-frame move the renderer no longer holds the compound path drawn
  before it. The test fails without the renderer change.
- crates/doc/src/node/tests.rs: a compound path's path is its members'
  paths in order (open, closed, empty and single-anchor members).

Not timed; vectorcraft-cli perf was not rerun.
2026-11-03 16:03:40 +07:00
Ahmed Gomaa f0e72fb11a Selection: a click on a large compound path is culled by its control points
Every click and hover measured each path and compound path along its
curves to cull it (Node::reach_bounds_with), and a compound path was
then assembled whole to test its outline and fill. For a compound path
of thousands of members that took milliseconds per click.

Hit testing now culls paths and compound paths by the box of their
control points (which holds the curves), grown by their strokes' reach,
so the box is never smaller than the reach box it replaces. A compound
path's outline and fill are tested against only the members whose
control box, grown by the tolerance, holds the point: a member outside
that box is farther than the tolerance and winds zero times round the
point. Painted strokes still follow the whole compound path (alignment,
dashes, width profiles) and are measured along all of it, as before.

Tests (crates/doc/src/hit/tests.rs):
- a 2,000-member compound path hits exactly as the whole-path test did,
  at random points, on and next to anchors and on the edges of the
  members' boxes, for both fill rules, in Outline view and with Object
  Selection by Path Only;
- wide strokes painting past the control points are still hit, for a
  path and a compound path;
- the cull box holds the reach box for paths and compound paths.

Measured in a debug test build (one run, machine not idle): a click on
a 20,000-member compound path went from about 18 ms to about 1 ms.
vectorcraft-cli perf was not rerun.
2026-11-03 16:03:40 +07:00
dotCooCoo 84db6a54a0 Type: discard queued font wheel turns after text selection changes 2026-11-03 16:03:40 +07:00
dotCooCoo 89f3d79eec Type: clarify stable font wheel ordering 2026-11-03 16:03:40 +07:00
dotCooCoo 2a95625b99 Type: step font families with the mouse wheel
Apply wheel steps over the closed family fields in Character, Properties and Control, preserving event order and one undo step per effective notch. Document the supported controls and the application choices. Fixes #5253.
2026-11-03 16:03:40 +07:00
dotCooCoo 2b29a680f3 Objects on Path: the Space widget spaces the attached objects along the path
With one Objects on Path group of two or more objects selected, the
Selection and Objects on Path tools show a square Space widget beyond the
last object, ahead along the path. Dragging it moves the last object
along the path, around its bends, as far as the pointer moves along it,
and the objects between follow evenly while the first one stays. With
Alt (Option on macOS) the objects spread from both ends toward or away
from the center of an open path, or of the first anchor of a closed one.
The distance between the objects shows next to the pointer in the
document's units; the drag is one undo step, and Escape cancels it.

- object.objectsOnPath.options takes spacing (points, or "auto", the
  default even spread) and start (points from the first anchor). A
  spacing the path has no room for is drawn smaller and kept, so a
  longer path brings it back. Older files read as Auto.
- Moving the group, Pivot, Rotate, path edits, copies and saving keep
  the Space. Scaling, rotating or shearing the group keeps the first
  and last objects where the transform takes them on the new path, live
  shapes included; a value that cannot be kept that way scales with the
  path's length.
- The Rotate All widget follows the first object when Space moves it.

Behavior: https://helpx.adobe.com/illustrator/desktop/manage-objects/arrange-objects/rearrange-and-edit-objects-on-a-path.html
and https://helpx.adobe.com/illustrator/using/objects-on-path.html.
2026-11-03 16:03:40 +07:00
dotCooCoo 2b6cbfda5d Update SVG, type, recoloring, and symbol feature records 2026-11-03 16:03:40 +07:00
dotCooCoo 012ac29d15 Window: Tile with one document open leaves the documents under their tabs
Squashed from #5256 onto main.
2026-11-03 16:03:40 +07:00
dotCooCoo 4b683c3a98 Window: with Open Documents As Tabs cleared, new documents open in windows
Preferences > User Interface > Open Documents As Tabs was stored but did
nothing. With the box cleared, each document opened or created afterwards
opens in a floating window of its own, at the next cascade place, as
Window > Arrange > Float in Window floats it. Documents already open, and
documents open when the app starts, keep their tabs; checking the box
again leaves floating documents in their windows.

The engine records the preference on each document as it opens
(DocState::opened_as_tab), and the UI finds new documents by uid, so a
command batch that closes and opens documents, or changes the preference
between opening them, places each one as the preference was when it
opened.
2026-11-03 16:03:39 +07:00
dotCooCoo ca8aba6d6a Window: drag a document tab out to float it, and a window back to dock it
A document tab dragged more than 24 pt above or below the tab strip
floats its document in a window under the pointer and makes it the
current document (window.arrange.floatInWindow takes index and at for
this). A shorter drag, or one along the strip, leaves the tabs as they
are. A document window dragged by its title bar onto the tab strip goes
back under the tabs; the strip shows an outline while a window is over
it. A desktop document window is an OS window, so it has the document's
tab at its top: dragging that tab moves the window, and dropping it on
the main window's tab strip docks it (window.arrange.consolidateAllWindows
takes index for one document).

A document floated again opens where it is asked to, not where its last
window was.
2026-11-03 16:03:39 +07:00
dotCooCoo 2c0ef0f24e Window: Float in Window, Float All in Windows and Cascade float documents
Window > Arrange > Float in Window (window.arrange.floatInWindow) moves
the current document out of the tab strip into a floating window of its
own, and Float All in Windows (window.arrange.floatAllInWindows), a new
item, does so for every tabbed document. Cascade (window.arrange.cascade)
floats every document and stacks the windows from the upper left of the
document area to its lower right, 30 pt apart, in tab order. On the
desktop each window is an OS window; on the web and on Wayland it is a
window inside the app's window, as floating panels are. While the
control channel is attached, the windows also open inside the app's
window, so ui.click, ui.drag and ui.screenshot reach them.

The current document's window holds the canvas. The other windows, and
the main window while the current document floats, draw their documents
as Tile's panes do, and a press in one makes its document the current
one. A document's OS window that takes the keyboard focus makes its
document the current one, and keys typed there run the main window's
shortcuts. Closing a window closes its document, asking to save unsaved
changes. Consolidate All Windows brings floating documents back under
the tabs, and Tile brings them back into its grid.

Cascade is enabled with two or more documents, Float in Window while the
current document is tabbed, Float All in Windows while any document is
tabbed, and Consolidate All Windows while documents are tiled or
floating. ui.inspect reports the floating documents.
2026-11-03 16:03:39 +07:00
dotCooCoo 84e344c475 Character Styles: Style Options sets character color and OpenType features
Character Style Options and New Character Style get a Character Color
section and an OpenType Features section.

Character Color sets the fill and stroke (None or a document swatch;
a global swatch or a tint of one stays linked, with a Tint from 0% to
100%), the stroke Weight, and Overprint Fill and Overprint Stroke. A
gradient or pattern paint the style already has stays until another
paint is chosen.

OpenType Features sets Figure, Position, Standard and Discretionary
Ligatures, Contextual, Stylistic and Titling Alternates, Swash,
Ordinals, Fractions and Stylistic Sets 1 to 20. A changed control
replaces only its own tags in the style's feature list, so other tags
stay, and Default Figure and Default Position are stored as their
features turned off, distinct from unset.

Empty controls stay unset, and each section's Reset Panel clears only
its own attributes.

charStyle.new, charStyle.edit and charStyle.setAttrs check a changed
fill, stroke, stroke weight or feature list: tints from 0 to 1, links
to global swatches of the document (the color follows the swatch),
weights from 0 to 4000000, and known feature tags, at most 256. Values
the style or the text it is made from already has are kept.
charStyle.duplicate keeps the copied style's values in the same way, so
a style with a language tag that is not in the list can be duplicated.

Editing a global swatch now also updates the fill and stroke stored in
character styles, so their text no longer shows as overriding the style
and text styled later takes the new color. swatch.unused counts a swatch
a character style links to as used.
2026-11-03 16:03:39 +07:00
dotCooCoo a230ef854b Docs: a dropped tool press cancels the drag as Escape does
The progress line said a dropped press keeps nothing it began. A Curvature
press that adds a point and a press on another text object keep what they
did on press, as with Escape during the drag, so the line now says the drag
is canceled as Escape cancels it.
2026-11-03 16:03:39 +07:00
dotCooCoo 641ac7e301 Canvas: a dropped press puts back the tool's options and keeps the path being drawn
A dropped press (a long touch, a canceled touch, a second finger) now
goes to the tool through Tool::drop_press, which takes Escape as during
a drag by default. The Pen, Smart Pen and Curvature tools override it
so the path being drawn goes on: they forget the press, and a Curvature
point the press dragged goes back where it was.

The release that follows runs only the tool's Cancel and Notify actions,
so a Selection marquee selects nothing and a Shift-drag Artboard marquee
toggles nothing. The engine puts back the persistent options the tool
had at the press (the Polygon tool's sides changed with the arrow keys),
and stores none of them.
2026-11-03 16:03:38 +07:00
dotCooCoo 2d6cf9020b Canvas: a dropped press cancels the tool's drag instead of ending it
A long touch, a canceled touch or a second finger drops the tool press in
progress. The tool used to get a plain mouse-up, which it cannot tell from a
release: the options the drag changed (the Polygon tool's sides set with the
arrow keys) were stored, and a shape tool pressed and held still opened its
size dialog.

Session::drop_tool_press undoes the press's interaction, sends the tool
Escape as during a drag, and then a release that returns it to rest without
storing the tool's options. What the tool asks of the UI along the way is
dropped.
2026-11-03 16:03:38 +07:00
dotCooCoo 58e6ce9f02 Type: a text.setStyle stroke gives unstroked characters 1 pt
A stroke color given without strokeWidth left characters at weight 0, so
nothing was drawn. As paint.setStroke does, a painted stroke now gives a
run with no weight 1 pt, for the characters and for the label styles a
graph keeps; an explicit strokeWidth still sets the weight.
2026-11-03 16:03:38 +07:00
dotCooCoo b1dc20b811 Type: text.setStyle sets the text's stroke as well as its fill
text.setStyle takes stroke (a color or "none") and strokeWidth (the character
stroke's weight in document points, as stroke.set gives it), with keepModel
for both colors. They apply to all the text or to the start..end range, and
to graph label styles, in the same undo step as the command's other keys.
A stroke key was ignored before.
2026-11-03 16:03:38 +07:00
dotCooCoo 6228446e9e Fix #4559: shortcuts can use the ISO key next to left Shift
Squashed from #5276 onto main.
2026-11-03 16:03:38 +07:00
Brandon Thomas 065a646799 Merge pull request #5280 from dotCooCoo/feat/symbol-nine-slice-guides-on-canvas
Symbols: 9-slice guides are shown and dragged on the canvas while editing a symbol
2026-11-03 00:19:44 -05:00
Brandon Thomas 2ef386c924 Merge pull request #5249 from dotCooCoo/feat/recolor-wheel-display
Recolor Artwork: the Edit tab shows the colors on a smooth wheel, a segmented wheel or as color bars
2026-11-03 00:19:40 -05:00
Brandon Thomas d232a29591 Merge pull request #5237 from dotCooCoo/feat/global-edit-shift-exclude
Global Edit: a Shift-click on a highlighted match leaves it out of the edit
2026-11-03 00:19:36 -05:00
Brandon Thomas b1faef0081 Merge pull request #5271 from dotCooCoo/fix/projective-scale-invariant-checks
Geometry: a projective map's horizon and invertibility checks do not depend on its scale
2026-11-03 00:19:01 -05:00
Brandon Thomas c6131cf798 Merge pull request #5243 from dotCooCoo/fix/svg-round-trip-edge-ellipse
SVG: an exported ellipse imports as the four-anchor ellipse it was written from
2026-11-03 00:18:50 -05:00
Brandon Thomas 57e0e55bba Merge pull request #5244 from dotCooCoo/feat/select-same-text-fill-stroke
Select: Same › Text Fill & Stroke Color selects type whose fill and stroke both match
2026-11-03 00:18:46 -05:00
Brandon Thomas a47ebfc3ce Merge pull request #5245 from dotCooCoo/fix/inline-graphic-manual-kerning
Type: an inline graphic takes its character's manual kerning
2026-11-03 00:18:42 -05:00