Commit Graph
357 Commits
Author SHA1 Message Date
dotCooCoo fc728b909e Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-08 20:23:21 -08:00
dotCooCoo d56a598c88 Merge main into fix/issue-3526-docs 2026-11-08 18:05:41 -08:00
dotCooCoo 28fbbfb23a Merge main into fix/issue-3526-docs 2026-11-08 17:17:29 -08:00
dotCooCoo be46e95cd9 Merge main into fix/blend-pick-resets-on-history-step 2026-11-08 16:34:32 -08:00
dotCooCoo 98b5892a37 Merge main into fix/blend-pick-resets-on-history-step 2026-11-08 16:06:38 -08:00
dotCooCoo 9a312e8ada Type: type in a composite font is measured in its own document's definition
- A file read for opening is laid out in the composite fonts registered
  then. Opening a document and reverting the front one now measure again
  the type set in a font named like a composite font that an open document
  defines, the font database holds or the session registered earlier. Type
  in other fonts, missing ones included, keeps the bounds it was read with.
- Switching to a document or closing the front one measures again the type
  set in a composite font whose definition changed, and any type without
  bounds.
- A document reverted while in the back measures its type in composite
  fonts when it comes to the front, not in the front document's.
- Text holding an inline graphic whose symbol's type was measured again
  takes the graphic's new size.
- A failed or panicked command puts the font database's composite fonts
  back with the documents.
- Setting a composite font to the definition an export lends keeps it after
  the export ends.
2026-11-08 14:23:43 -08:00
dotCooCoo 87cd34bbd1 Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-08 14:21:52 -08:00
dotCooCoo c94269ff72 Type: Composite Fonts… sets each class of character in a font of its own
Squashed from #6244 onto main.
2026-11-09 03:08:23 +07:00
dotCooCoo d5fc96327e Merge main into fix/shape-builder-merge-off-ui-thread
# Conflicts:
#	crates/engine/src/lib.rs
#	crates/engine/src/session/documents.rs
2026-11-08 11:33:51 -08:00
dotCooCoo fd3482c272 Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-08 11:28:00 -08:00
Sven Lafebre 748ac5cf6e Pen: keep a lent pick across tool resets; a gesture that picks nothing keeps the Pen's anchor (#6123)
The remembered selection is now tied to the document it was made in, by its
uid, instead of being cleared on every tool reset: another view of the same
document, or closing an inactive tab, kept the anchors picked but made Copy
take the whole path.

A lent gesture that leaves the selection as it found it (a Cmd+Shift marquee
over nothing) is no longer recorded as a pick, so the Pen's last anchor stays
its own and Copy takes the whole path.

Also records #6123 in target-app-parity.md.
2026-11-09 02:03:05 +07:00
Sven Lafebre 91a0ba4231 Pen: Copy and Cut take the anchors a Cmd-lent Direct Selection picked (#6123)
With the Pen or Curvature tool, Copy and Cut ignore the anchor selection,
so that the last anchor the Pen leaves selected doesn't make Copy take just
that anchor (#2122). Anchors picked with the Direct Selection that Cmd/Ctrl
lends those tools were ignored too, and the whole path was copied.

The session now remembers the selection the lent tool leaves when it gives
the tool back. While that is still the selection, Copy and Cut take the
picked anchors and segments, as with Direct Selection chosen.
2026-11-09 02:03:05 +07:00
VladimirCeric e3817d6b50 Typographer's Quotes: a lone typed ” opens like a straight quote
Squashed from #5459 onto main.
2026-11-09 02:03:00 +07:00
dotCooCoo 434c032f9e Symbols: Direct Selection sets the solid fill and stroke of one object in a dynamic instance
Squashed from #5962 onto main.
2026-11-09 00:26:11 +07:00
dotCooCoo 74863fa778 Engine: execute refuses keys a command doesn't name, in every build
Session::execute ran check_params only in the engine's own tests, so a
direct execute in a release build ran a misspelled key with the
command's default. It now checks every call, the commands a command runs
included, as MCP and the control port already did. A command.batch or
an action.batch is checked before its first step runs, and each step is
checked again as it runs, so an effect.setParams step is checked
against the effects the steps before it added.

Saved steps play through Session::replay, which takes keys a command no
longer reads, so an action recorded by an older version still plays and
Session::replay still plays an older journal. The Actions panel's Play
(Accelerated, Step by Step and Pause For, its function keys and
ui.action.play) and the Batch dialog use it.

Docs: the cmd/params.rs module doc, the Parameter keys section of
docs/mcp.md and a line in docs/target-app-parity.md describe both
paths.
2026-11-08 11:22:28 +07:00
dotCooCoo f0f19077df Document Color Mode: convert reusable paints and restore them with Undo
Squashed from #4517 onto main.
2026-11-04 16:55:43 +07:00
dotCooCoo a0a4633c26 Restore Type editing after a dropped press 2026-11-04 10:25:57 +07:00
dotCooCoo e01823c2eb Gradient: a dropped or canceled point drag keeps the point selected
A drag that takes a selected freeform gradient point out of the object previews its removal,
which deselects it. A dropped press now selects again the point that was selected once the
tool took the press, and Escape reselects a point dragged out and back inside the object.
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
Dylan M. Taylor 2fec613353 Place: the place cursor reads its files within the roots it was loaded in
An agent confined to automation roots could load the place cursor, with
file.place.queue or tool.setOption, and the files were placed later, by
a click of the person at the keyboard, outside any roots. tool.setOption
checked a queued path but not files given inline, whose linked files (an
SVG's referenced images) were then read with the keyboard user's
unrestricted access.

The session now keeps the automation roots in force when the cursor's
queue is loaded, and both the engine's own placement and the desktop
app's background placement read the queued file within them. A queue
loaded outside any roots places as before.
2026-11-03 15:56:55 +07:00
dotCooCoo b1c98821d6 Clipboard: a bitmap pasted from another app is decoded off the UI thread
Squashed from #4277 onto main.
2026-11-02 14:33:02 +07:00
dotCooCoo 05ac9ce040 Merge main into fix/shape-builder-merge-off-ui-thread 2026-11-01 22:20:23 -08:00
dotCooCoo a4a3f8c13e Fix #3526: the bounding box follows a resize drag
With View > Show Bounding Box on, a resize by a bounding-box handle
keeps the box and its handles drawn at the bounds the drag gives. A
move, a rotation and a corner-radius drag still hide the box until the
release (#712).

With Real-time Drawing off the document stays at the drag's snapshot,
so the box is measured from the drag's pending preview, through the
same cache as the deferred outlines.
2026-10-31 18:51:34 -07:00
dotCooCoo dfd07552c8 Cursors: Caps Lock gives the drawing tools the crosshair
While Caps Lock is on, the tools whose pointer General > Use Precise
Cursors changes show the crosshair, and the saved preference does not
change. The desktop app reads the lock state on macOS, Windows and
Linux X11 and passes each change to the new view.capsLock command. A
change to view.capsLock or usePreciseCursors through app.run refreshes
the canvas pointer. The view.preciseCursors command is labeled Use
Precise Cursors, so command search finds it by the preference's name.
2026-11-01 01:59:54 +07:00
VoiceLessQ 1411a821c1 Fix #3098: Image Trace traces off the UI thread, with progress and Cancel
Tracing a photo or a large image ran inside imageTrace.make on the UI
thread, so the window froze for as long as the trace took, with nothing
to say it was working.

A trace the user asks for (Object > Image Trace > Make and Make and
Expand, the task bar's Image Trace, the Image Trace panel's Trace and
presets) now runs on a thread of its own, as heavy plug-in filters do.
The status bar says so, and after 0.4 s a progress window shows how
many of the image's colors are traced, with Cancel and Continue in
Background (imageTrace.cancelRuns, imageTrace.hideRuns).

The result goes back to the command it was prepared for
(cmd::TraceRun, Traced::hand_in), which takes it only for the same
object, image and settings, so the edit is one undo step as before. A
newer trace of the same object replaces one still running, and a trace
whose image or settings changed meanwhile changes nothing. The control
channel, MCP, scripts and the web trace at once, as before.

The tracer reports its stages and color layers to a callback and stops
when it says so (trace_watched).
2026-10-29 22:39:34 +07:00
dotCooCoo 4e59c3f0be Merge main into fix/shape-builder-merge-off-ui-thread 2026-10-29 07:58:05 -07:00
dotCooCoo 9703b86074 Merge commit 'refs/check/v4447-main' into fix/blend-pick-resets-on-history-step
# Conflicts:
#	crates/tools/src/meshblend.rs
2026-10-29 06:31:24 -07:00
bflatastic bbbc711b6a Fix #4382: the Eyedropper's Alt-click puts what it picked up on the object clicked when nothing is selected
With nothing selected, a click with the Eyedropper picks up an object's attributes and an Alt/Option-click on another object applies them, as the reference app's Eyedropper does. Alt-click only copied from a selected object, and with nothing selected it failed. The session now keeps a copy of what appearance.copyFrom picked up last, and a reversed copy with nothing selected applies it.
2026-10-29 19:57:59 +07:00
dotCooCoo c9853094d4 Image Trace: Manage Presets saves, renames and deletes custom tracing presets
Squashed from #4071 onto main.
2026-10-29 19:21:32 +07:00
dotCooCoo cf5ed86729 Merge main into fix/shape-builder-merge-off-ui-thread 2026-10-29 03:59:34 -07:00
dotCooCoo efd7f3e97a Blend: a pending pick starts over when the document's history changes
The Blend tool kept its first pick, its clicked anchor and the blend it
was adding to through edits made outside the tool. Picking A, recoloring
other art and clicking B made a blend of A and B; undoing A's creation
left the next click doing nothing.

History::step names the current step by the serial numbers of the newest
undo step and the next redo step. The session keeps the active document's
uid and step from the tool's last pointer event and calls the new
Tool::history_moved at the next pointer event, or before drawing
overlays, when they differ. The tool's own edits are recorded after its
actions; a selection tool lent by Cmd is not told. BlendTool clears its
pick and chain there, as Escape does. A selection change keeps them.
2026-10-29 03:38:35 -07:00
bflatastic efc1501ac9 Path: Object › Path › Smooth smooths the selected paths with a slider and Auto-Smooth (#4115) 2026-10-29 13:51:51 +07:00
dotCooCoo 93677c26ec Shape Builder: a large selection merges on another thread
A Shape Builder click or drag over a selection of more than 128
segments merged on the UI thread, so the app stopped drawing and
answering until the merge was done. The tool now computes such a
merge on another thread from the map it built for the hover.
Meanwhile the canvas keeps drawing, the touched regions stay
highlighted and the pointer is the busy pointer. When the merge is
done, the tool runs shapeBuilder.merge with the gesture's params as
one undo step, and the command takes the computed shapes when it
would compute the same ones. The web build merges in the command, as
before.

A press while the map is still being built no longer waits for it on
the UI thread: the tool records the gesture and makes it once the map
is there.

Clicks, drags and the Shape Builder's arrow keys made during the
merge, and commands, menu items, the app's own dialogs, saves and tool
or document switches, run after it on the merged art; engine queries
that only read run at once. A change to the selected paths made
outside a command drops the merge. The headless host and ui.pointer
reply once the merge is applied.

The Shape Builder and the Live Paint Bucket keep their map of the
selection over a new revision of the document when the selected paths
and their outlines are unchanged, instead of building it again.
2026-10-27 17:26:38 -07:00
aiongg ef991b9c8a refactor(engine): move lib.rs items to {command_sets,doc_state,error,history,interaction,prefs,sanity,session,session/documents,session/edit,session/execute,session/undo}.rs 2026-10-26 22:01:25 +00:00
aiongg f1d427762b style: cargo fmt on files moved without formatting 2026-10-26 19:32:10 +00:00
aiongg 83eec43b18 refactor(engine): move tests_*.rs to tests/<topic>.rs 2026-10-26 18:26:56 +00:00
dotCooCoo 389dce727d Undo: a canceled undo scope drops the journal entries it cut from open undo groups
When an undo scope that joined an open undo group was canceled, the
journal was cut back to where the scope began, but the group still
listed the cut entries' numbers. The next command took one of those
numbers, so a later cancel of the group also removed that command's
entry, even when it ran in another document, and a replay of the
journal no longer matched the documents. end_undo_scope now removes
the cut numbers from every open undo group's journal entries and batch
steps.
2026-10-26 16:58:49 +07:00
Taha-Mahmoodi cfd085f34a Fix #3426: the Pathfinder panel's Pathfinder Options… sets Precision, Remove Redundant Points and Divide and Outline Will Remove Unpainted Artwork
Squashed from #4141 onto main.
2026-10-26 15:28:51 +07:00
Taha-Mahmoodi 0a241a7fdd Brushes: Window › Brush Libraries opens brush libraries whose brushes click or drag into the document's Brushes
Squashed from #4020 onto main.
2026-10-26 15:17:30 +07:00
Taha-Mahmoodi 502b204d74 Transform panel: the menu's Transform Object Only, Pattern Only, Both and Use Registration Point for Symbol act
Squashed from #4146 onto main.
2026-10-26 10:04:25 +07:00
dotCooCoo ad75ea5d06 Type: Highlight Substituted Fonts moves to Preferences › Type and applies to every document
Highlight Substituted Fonts is now a preference in Preferences › Type,
next to Highlight Alternate Glyphs, on by default and saved with the
other preferences (`prefs.set highlightSubstitutedFonts`). The canvas
reads it through `RenderOptions::highlight_substituted_fonts` for every
open document; a document's own setup no longer decides it. File ›
Document Setup no longer shows the checkbox and keeps Highlight
Substituted Glyphs.

A file saved with Document Setup's Highlight Substituted Fonts off now
shows the pink highlight when it opens, while the preference is on.
The file still opens with the stored value, and saving it again keeps
that value.

`document.setup` no longer reports `highlightSubstitutedFonts`. It
ignores the key and adds a `warnings` entry that names `prefs.set` to
its reply, so an older reply passed back still applies its other keys.

The raster cache of type under a raster effect now also redraws when
Highlight Alternate Glyphs changes.
2026-10-26 09:09:47 +07:00
dotCooCoo 056274f5d6 Undo: canceling an undo group keeps a batch's steps in other documents
A command.batch that edited a document with an undo group and then a
document without one was dropped from the journal as a whole when the
group was canceled, so a replay lost the second document's edit, which
the session kept. Each batch step is now noted in the undo groups it
belongs to, by the same rule as a top-level command, and a cancel takes
only those steps out of the batch's journal entry. A step that changed
the active document becomes that change. Undo groups that stay open
follow the entry and step numbers that a cancel changes.
2026-10-26 09:09:45 +07:00
Brandon Thomas dda90f0f4f Merge pull request #4060 from dotCooCoo/feat/unknown-command-suggestion
Commands: an unknown command id is answered with the nearest command id
2026-10-25 10:37:54 -04:00
aiongg 8bf090b253 Shortcuts: use the shared craft-keymap crate for the catalogue, overrides, dispatch and .kys import (#3119)
* Shortcuts: the keymap, overrides and dispatch come from craft-keymap

The editor's catalogue (commands, UI commands, panels, tools; one tool
group per tool; show/hide commands marked as toggles) builds a
craft-keymap Keymap. UiState::shortcut_overrides is a craft_keymap
Overrides stored through keymap::stored, which writes the same map of
entry key -> one string as before, with panel: keys and VectorCraft's
spellings, so earlier versions read the file; a value that is not text
drops that entry instead of every preference.

Key presses run through craft_keymap's Dispatcher with accept filters:
keys that type text go to the one-key text path, and while the Type
tool edits only command-key chords run. Held keys repeat. Conflicts
and assignment use the crate's conflicts and set_bindings. Extra Shift
no longer falls back to the chord without it.

* Shortcuts: .kys import matches and applies through craft-keymap

The review proposes targets with craft_keymap's namematch, and Apply
hands the ready rows to craft_keymap::plan as one set, each row's
target passed as the remembered answer for its entry. The later row
takes a chord, and commands outside the set lose the chords the set
gives. Rows with one name in one block keep their own targets.
The engine's own namematch module is removed.

* Shortcuts: Cmd+, beside other hits, web Mac platform, cached dialog view

- Pin craft-keymap at 362eb59f.
- Cmd+, opens Settings on a Mac after the frame's other shortcuts run, with the
  Mac read from egui's OS; drop settings_chord, which dispatch no longer used.
- The web build follows the browser's OS, so Ctrl stays Ctrl on a Mac.
- The Keyboard Shortcuts dialog keeps its keymap, row texts and conflict count
  between frames while the working set is unchanged.
- Every default shortcut text becomes its entry's binding (test).
- craft-keymap counts as a UI crate for the layer check.
- Translate "too many changed shortcuts"; the parse error reuses the existing
  "can't parse shortcut `{c}`" message.

* Shortcuts: the chords the operating system takes can't be assigned

The keymap reserves craft_keymap::reserved::system for its platform:
window switching and closing, and the virtual consoles off the Mac.
The Keyboard Shortcuts dialog and shortcuts.set refuse them with
"<chord> is reserved by the system", and a saved override on one keeps
the entry's default. No default shortcut uses a reserved chord.

* Shortcuts: craft-keymap at craft-libs 2eca9b3a

craft-keymap comes from storytold/craft-libs (craft-libs #164 and #186), at the rev craft-pdf
already uses. The web build keeps the browser's full platform, so Windows browsers get Windows'
reserved chords, and each platform caches its own default keymap.
2026-10-24 15:01:26 -04:00
dotCooCoo 6e6fbbac1d Commands: an unknown command id is answered with the nearest command id
A misspelled parameter key got a did-you-mean suggestion, but a
misspelled command id only got "unknown command `select.al`", through
the CLI, MCP and the control channel alike. Session::execute now names
the nearest command id, using the same matching as parameter keys
(ignoring case), and action.batch does the same for an unknown step. An
id with no near match keeps the plain error.

The matching skips candidates whose length differs by more than the
allowed number of edits, so a very long unknown command id or parameter
key is answered at once instead of being measured against every command
id or accepted key.

The new message has a row in every catalog, and docs/mcp.md's
Parameter keys section shows it.
2026-10-24 11:20:27 -07:00
dotCooCoo 6cd57cfa1b Undo groups: an open undo group also groups the edits in a document opened or created before its end
A document opened or created between edit.undoGroup.begin and
edit.undoGroup.end opens an undo group of its own with the begun
group's name, so an atomic command_batch that starts with file.new or
document.open is one undo step in the new document. The group opens
after the command that opens the document: when that command also
edits it (a command.batch), those edits stay the command's own undo
step, and a canceled group keeps them, so the journal still replays.
Both commands also run with no document open, and a command.batch that
fails rolls back a begun group. Switching to a document that was
already open does not open a group in it.
2026-10-24 20:10:04 +07:00
dotCooCoo bc041e15ef Type: the Numbered List button numbers paragraphs 1, 2, 3
Squashed from #3960 onto main.
2026-10-24 19:02:08 +07:00
dotCooCoo 8ce6177c62 Arrange: a layer id given to Send to Back and the other selection commands is refused
Squashed from #3951 onto main.
2026-10-24 18:16:24 +07:00
Taha-Mahmoodi 97f84723ef Fix #3965: an unresolved step reference given as id is refused under the command's name; effect.apply keeps its effect-naming id 2026-10-24 17:57:21 +07:00
Taha-Mahmoodi c40113b755 Fix #3965: a malformed or unknown id is refused under the command's name, never replaced by the selection 2026-10-24 17:57:20 +07:00