Commit Graph
342 Commits
Author SHA1 Message Date
BFlat 78131ae11c Merge pull request #7419 from dotCooCoo/fix/type-dialogs-story-wide
Type: Justification, OpenType, text styles and Convert to Text change every frame of a selected story
2026-11-15 00:42:04 +07:00
BFlat 63129de08a Merge pull request #7595 from dotCooCoo/fix/image-scaling-alpha
Images: scaled-down images keep their color beside clear pixels
2026-11-15 00:41:27 +07:00
BFlat 2ebf037bc5 Merge pull request #7360 from dotCooCoo/feat/learn-progress-rings
Learn: steps get check boxes, and skill rings fill as tutorials are finished
2026-11-14 21:55:49 +07:00
BFlat 8d1aa857d5 Merge pull request #7276 from dotCooCoo/fix/issue-6784
Contextual Task Bar: Smooth opens the Smooth slider with Direct Selection
2026-11-14 20:38:54 +07:00
dotCooCoo 786dcc5581 Images: scaled-down images keep their color beside clear pixels
The image crate's filtered resize filters each channel on its own, which
is correct only for premultiplied pixels, and its thumbnail averages each
channel on its own too. Placed images, linked-image previews, MCP
captures and previews, metafile bitmaps, PDF downsampling and library
thumbnails passed straight RGBA to them, so the color under clear pixels
(usually black) bled into the opaque pixels beside them and darkened
cut-out edges.

vectorcraft_doc::resample scales such images with each pixel's color
weighted by its alpha: filtered resampling premultiplies the pixels in
place and divides them back after, and averaging takes the area-weighted
mean of the pixels each new one covers. Opaque and alpha-free images are
scaled as before. PDF export also multiplies the inks of a CMYK image
with alpha by that alpha before resampling them, and divides them by the
resampled alpha after.
2026-11-14 05:07:39 -08:00
BFlat a47d7eec91 Merge pull request #7478 from dotCooCoo/fix/export-selection-pdf-options
Export Selection: the picked format's options dialog follows the save panel
2026-11-14 19:38:30 +07:00
dotCooCoo f5eda0e5d9 Merge main into fix/issue-6784 2026-11-14 02:11:12 -08:00
dotCooCoo b67a9320bb Merge main into feat/learn-progress-rings 2026-11-14 01:49:40 -08:00
dotCooCoo acb5b3293f Merge main into fix/type-dialogs-story-wide 2026-11-14 01:47:35 -08:00
BFlat 9ce826bc24 Merge pull request #7358 from dotCooCoo/feat/actions-button-mode
Actions: Button Mode shows actions as colored buttons that play on a click
2026-11-14 13:44:09 +07:00
BFlat 18266da1e1 Merge pull request #7328 from dotCooCoo/fix/save-unused-option-notes
Save, Export for Screens: warnings name an option the file doesn't read
2026-11-14 13:42:55 +07:00
dotCooCoo b39bfbed4f Export Selection: the picked format's options dialog follows the save panel
document.exportSelection run with no params or {} (a shortcut, or an
automation call) wrote the picked file straight away with each format's
defaults: a PDF used the default preset, so Save PDF's options, such as
writing long pages in points, could not be chosen. It now takes Export
As's route after the save panel: Save PDF without its Artboards
section, SVG Options without its artboards, the raster options, EPS
Options, DXF Options, Text Export Options with Selection Only on, or an
exporter plug-in's parameters. OK writes the selection alone, cropped
to it, with the chosen options. While a dialog is open the call returns
null, and OK returns what file.exportAs returns, without format or
bounds.
With a path or any option it still writes straight away.

- file.exportAs takes exportSelection: true and then writes the
  document that document.exportSelection writes
  (fileio::selection_doc), without artboard choices. The options
  dialogs and the replace-file questions pass it on.
- Nothing selected stops before the save panel.
- SVG Options opened by Export Selection leaves the remembered Use
  Artboards as it was.
- Exports through file.exportAs (Export As and the options dialogs)
  apply Appearance of Black's rich black, as document.export does.

Docs: docs/mcp.md, docs/control-protocol.md, docs/target-app-parity.md.
2026-11-13 21:44:06 -08:00
dotCooCoo 15bf65f014 Merge main into fix/issue-6784 2026-11-13 20:54:25 -08:00
dotCooCoo 4819fdbc0a Type: Justification, OpenType, text styles and Convert to Text change every frame of a selected story
With the Selection tool, the Justification dialog, the OpenType panel, a
Character or Paragraph Styles row (Alt-click and Clear Overrides
included) and Type > Bullets and Numbering > Convert to Text now change
every frame of each selected threaded story, locked and hidden frames
included, in one undo step. Before, they changed only the selected
frames.

- The Justification dialog keeps the frames of the stories selected when
  it opened for its preview and OK.
- The OpenType panel's Figure menu shows Mixed and its checkboxes show a
  dash when the characters differ; a click on a dash turns the feature
  on everywhere.
- The style panels highlight a style only when all of the text has it,
  and show "+" when any of it overrides the style.
- Convert to Text takes the same stories as Apply Bullets and Apply
  Numbers.
2026-11-13 19:45:29 -08:00
BFlat 446bf59bc2 Merge pull request #7265 from dotCooCoo/feat/live-paint-cursor-swatch-preview
Live Paint Bucket: Cursor Swatch Preview and arrow keys pick swatches
2026-11-14 09:33:39 +07:00
BFlat c1efdbdaae Merge pull request #7255 from dotCooCoo/fix/folder-prefs-out-of-recorded-steps
Actions: keep folder preferences out of saved sets and confined replies
2026-11-14 08:40:15 +07:00
dotCooCoo 00c0c1d6ea Learn: steps get check boxes, and skill rings fill as tutorials are finished
Each step of a Learn tutorial now has a check box that marks it done
once the tutorial's practice sample is open, and Finish tutorial marks
every step done. A skill's ring fills by the share of its tutorials
finished, its count shows tutorials finished of all, and a finished
tutorial has a check mark in its skill's list. Screen readers get the
count and the finished state as the rows' values.

The progress is saved with the UI preferences and read leniently: an
unknown tutorial, a step a tutorial does not have, a repeated entry or a
value of the wrong kind is skipped without resetting other preferences.
Reset progress under the list of skills clears it. A finished tutorial
can be finished again after a restart without reopening its sample.

- learn.markStep marks or clears one step; learn.resetProgress clears
  the progress; learn.list adds done and total per skill and finished
  and completedSteps per tutorial. Both new commands are in the UI
  command catalogs, and bad params are errors that change nothing.
- New labels and messages have rows in every catalog.
- Docs: docs/mcp.md, docs/target-app-parity.md and docs/ui-parity.md.
2026-11-13 17:26:47 -08:00
dotCooCoo 91f77f1eb8 Actions: Button Mode shows actions as colored buttons that play on a click
The Actions panel menu has a Button Mode item with a check mark. While it
is on, the panel shows every action of every set by name as a button in
its Action Options color, without set names, steps or checkmarks, and a
click on a button plays that action without its excluded steps. Choosing
Button Mode again shows the list.

- ui.action.buttonMode {enabled?} switches the view (left out: the
  other view) and is kept with the UI preferences; it cannot be turned
  on while an action records.
- ui.action.playAt {set, action} plays an action by its place, as the
  buttons do.
- An action without a color is an ordinary button. The bottom bar shows
  only Stop Playing/Recording while an action plays or records, and Play
  Current Selection while one waits at a stop. Menu items for a selected
  action or the current set are off in Button Mode.

Docs: docs/mcp.md, docs/ui-parity.md, docs/target-app-parity.md.
2026-11-13 17:26:31 -08:00
dotCooCoo 45be5112e9 Merge main into fix/save-unused-option-notes 2026-11-13 16:56:43 -08:00
BFlat 92d9604726 Merge pull request #7264 from dotCooCoo/fix/confined-svg-export-script-paths
MCP: SVG export by a confined caller refuses script links outside its read roots
2026-11-14 07:34:26 +07:00
dotCooCoo d30831bd5a Merge main into feat/live-paint-cursor-swatch-preview 2026-11-13 15:54:47 -08:00
dotCooCoo 6fb49b9c4b Merge main into fix/issue-6784 2026-11-13 15:40:31 -08:00
dotCooCoo 3429bbc76a Save, Export for Screens: warnings name an option the file doesn't read
The save commands' warnings now follow an export's .ai rules: a legacy
.ai file (aiVersion "7") reads only its own options, and the other .ai
and .ait files don't read outlineText, hiddenObjects, transparentImages
or preserveEditing. They name any option given beside the path that the
file doesn't read, not only compress, version, preview and precision,
and any such key in options. The bytes a save writes don't change.

The Save Options dialog sends a .ai save only the options the chosen
version reads, so a save from the dialog gets none of these warnings.
When the document's own file is already a .ai, the .ai options that a
save doesn't give and its file doesn't read keep their remembered
values, so the dialog still shows them; the save doesn't write them, and
a retry in another folder doesn't send them.

Export for Screens and Export Assets already accepted a key in a format
row or in a format's settings that only another format takes. Their
warnings now name it as given (formats[0].quality, settings.png.quality).
A key in a format's settings is named only when no row of that format,
as the export writes it, reads it. The options of an exportPreset, and
for assets.export the settings the document keeps, get no warning.

Docs: params text of document.save, document.exportForScreens and
assets.export; docs/mcp.md; docs/target-app-parity.md.
2026-11-13 15:34:25 -08:00
BFlat efba8bfd89 Merge pull request #7295 from dotCooCoo/fix/negative-wrap-offset
Text Wrap: a negative Offset lets text run into the wrap object
2026-11-14 06:26:39 +07:00
dotCooCoo aa18c36039 UI commands: catalog row for Save Actions with folder preferences
crates/mcp/src/ui_catalog.rs now carries the ui.actionSet.save params
text from crates/ui-egui/src/menus/ui_commands.rs, so `cargo xtask
ui-commands --check` passes.
2026-11-13 15:11:53 -08:00
dotCooCoo 38127af144 UI commands: catalog row for Export As with confined script links
crates/mcp/src/ui_catalog.rs now carries the file.exportAs params text
from crates/ui-egui/src/menus/ui_commands.rs, so `cargo xtask
ui-commands --check` passes.
2026-11-13 15:11:52 -08:00
BFlat 517b725be5 Merge pull request #7089 from dotCooCoo/fix/smooth-fidelity-screen-pixels
Smooth: Fidelity is in screen pixels, so a drag smooths as much at any zoom
2026-11-14 05:42:42 +07:00
dotCooCoo 395dd5b294 Text Wrap: a negative Offset lets text run into the wrap object
The help page says a wrap object's Offset may be positive or negative
(https://help.adobe.com/archive/en_US/illustrator/cs4/illustrator_cs4_help.pdf#page=307).
Text Wrap Options, the commands, the MCP tool and .ai import already
kept a negative value, but layout set it to 0.

- Layout keeps the signed offset, within -1000 to 1000 pt like the
  commands and .ai import (a value that is not a number counts as 0).
- Around a wrap object, a negative offset shrinks the object by that
  distance from each edge, holes included, so lines beside, above and
  below it run that far into it. A shape narrower than twice the
  distance no longer moves text aside. A line may get less room than
  the exact shrunk shape leaves, for example where several edges come
  close to one piece of the band, or where a band holds more than 64
  anchor heights. It never gets less room than an offset of 0 leaves.
- With Invert Wrap, a negative offset keeps the text that far inside
  the object.
- Zero and positive offsets up to 1000 pt lay out as before. A larger
  positive offset lays out as 1000 pt.
- The params text of object.textWrap.make and object.textWrap.options
  and the MCP text_wrap offset description give the range and what a
  negative value does.

Docs: docs/target-app-parity.md.
2026-11-13 13:19:43 -08:00
dotCooCoo 4ea2f2e9c6 Merge main into fix/smooth-fidelity-screen-pixels 2026-11-13 13:03:29 -08:00
dotCooCoo 8703859c66 Contextual Task Bar: Smooth opens the Smooth slider with Direct Selection
With a path selected whole by the Direct Selection tool, the bar's
"Smooth" button converted every anchor point to smooth at once. It was
the anchor convert, labeled like the path Smooth that the overview lists
beside Simplify as adjusting the path's curvature, and the bar had no
button for Object › Path › Smooth….

- A path selected whole with Direct Selection now offers Smooth after
  Simplify. It runs object.path.smooth the way the menu item does, so
  it opens the Smooth slider and changes nothing until it is confirmed.
- The two anchor convert buttons, with a whole path or with anchors
  selected, show their icons alone, named by the Control bar's tool
  tips "Convert Selected Anchor Points to Corner" and "to Smooth".

The keyboard shortcut part of #6784 is fixed on main by #6810.

Docs: docs/mcp.md, docs/target-app-parity.md, the ui.smoothAuto params.

Fixes #6784
2026-11-13 12:32:03 -08:00
dotCooCoo dd3438cb7f Live Paint Bucket: Cursor Swatch Preview and arrow keys pick swatches
Live Paint Bucket Options gets a Cursor Swatch Preview checkbox (on at
first, saved with the other options). With the Bucket selected, Left and
Right set the active fill, or the stroke when the Stroke proxy is in
front, to the color swatch before or after it in the Swatches panel,
wrapping around at the ends, with the preview on or off. The selected art
keeps its paint. The preview shows the active paint above the pointer
between the swatches before and after it; a color that is no swatch shows
alone until Right picks the first swatch or Left the last, and a paint
that is not a solid color shows no chip. The chips hide during a fill
drag and while Alt samples with the eyedropper. The fill and the stroke
each remember the swatch picked for them, so swatches of the same color
are each reached in turn.

The Bucket and the Shape Builder now take the arrows for swatches only
without Shift, Alt or Cmd/Ctrl, judged by the modifiers held when the key
went down, so modified arrows keep their shortcuts
(Tool::claims_key_with, Session::tool_claims_key_with).

Docs: docs/mcp.md, docs/target-app-parity.md, tool.options params text.
2026-11-13 12:09:16 -08:00
dotCooCoo fdedfb0e59 Merge main into feat/warichu 2026-11-13 11:59:22 -08:00
BFlat a105e14aef Merge pull request #7220 from dotCooCoo/feat/image-indexed-color
Edit Colors: convert embedded images to indexed color
2026-11-14 02:40:36 +07:00
BFlat e718e975b6 Merge pull request #7104 from dotCooCoo/feat/actions-record-into-selected
Actions: Begin Recording adds steps to the selected action, and a drag moves a step
2026-11-14 01:54:47 +07:00
BFlat ca8e49e9e2 Merge pull request #7158 from dotCooCoo/fix/export-unused-option-warning
Export: warnings name an option the chosen format doesn't read
2026-11-14 01:54:29 +07:00
dotCooCoo 1b935b6d0a Merge main into fix/smooth-fidelity-screen-pixels 2026-11-13 10:13:12 -08:00
BFlat 2814e3e53d Merge pull request #7192 from dotCooCoo/feat/context-menu-smooth
Context menu: Smooth… on a selected path opens the Smooth slider
2026-11-14 00:51:29 +07:00
BFlat 211c673ee2 Merge pull request #7186 from dotCooCoo/fix/mcp-window-capture-private-temp
MCP: an old app's window capture goes through a private temporary folder
2026-11-14 00:50:17 +07:00
BFlat 858d52c2f3 Merge pull request #7185 from dotCooCoo/fix/mcp-integration-test-temp-folders
Tests: the vectorcraft-mcp integration tests remove their temp folders
2026-11-14 00:49:12 +07:00
dotCooCoo 81d19f1718 Edit Colors: convert embedded images to indexed color
Edit > Edit Colors > Convert to Indexed Color... (edit.colors.toIndexed)
stores the embedded images in the selection as indexed-color PNGs: a
palette of at most 256 RGB colors, each pixel the index of one. The
dialog previews live and OK is one undo step.

- The palette is chosen as for a PNG-8 export (selective, perceptual,
  adaptive, web, gray, black and white), as evenly spaced levels of red,
  green and blue (uniform), or from the document's swatches. Dithering
  is diffusion, pattern, noise or none, with an amount.
- Pixels under half opacity become one transparent entry; the others
  become opaque in their own color. Linked images, colorized images and
  color glyph images keep their pixels.
- An image that is already an indexed PNG and would show the same pixels
  is left as it is, and no undo step is recorded when no image changes.
- An image of more than 134,217,728 pixels (33,554,432 in the web app)
  is refused, read from its header before decoding.
- With Select All, locked and hidden objects that hold an image that is
  not an indexed PNG yet are counted in notChanged, without converting
  them.
- The quantizer gains quantize_to, which maps pixels to a given palette.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 09:49:00 -08:00
dotCooCoo 6462060928 Merge main into fix/export-unused-option-warning 2026-11-13 09:15:25 -08:00
BFlat 60fd4bd644 Merge pull request #7090 from dotCooCoo/feat/pixel-snapping-options
View: Pixel Snapping Options choose whether Snap to Pixel snaps drawing, moving and scaling
2026-11-13 23:58:35 +07:00
BFlat 2aba3ccaff Merge pull request #7172 from dotCooCoo/fix/mcp-test-temp-folders
Tests: the vectorcraft-mcp tests remove the temp folders they create
2026-11-13 23:44:46 +07:00
dotCooCoo d92e63257b Merge main into fix/smooth-fidelity-screen-pixels 2026-11-13 08:44:25 -08:00
dotCooCoo d1c8ff78de Context menu: Smooth… on a selected path opens the Smooth slider
A right-click on a selection that holds a path (a path, a group of
paths, a compound path, or anchors selected with Direct Selection) lists
Smooth…, after Join and Average… and the anchor entries when those are
listed. It opens the slider that Object › Path › Smooth opens, which
previews the result until OK keeps it as one undo step. With nothing,
only type or a group of type selected, Smooth… is not listed.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-11-13 08:35:40 -08:00
BFlat a2adbf61e6 Merge pull request #7106 from dotCooCoo/feat/custom-toolbar-dock
Toolbars: toolbars made with New Toolbar dock along the window's edges
2026-11-13 23:32:06 +07:00
dotCooCoo 137bc11a2c Merge main into fix/smooth-fidelity-screen-pixels 2026-11-13 08:28:42 -08:00
dotCooCoo c9d85d61db Merge main into feat/actions-record-into-selected 2026-11-13 08:24:12 -08:00
dotCooCoo 940b47234b Tests: the vectorcraft-mcp integration tests remove their temp folders
automation_roots.rs and protocol_props.rs wrote their files into folders
made by vectorcraft_testkit::temp_dir (vectorcraft-testkit-roots-<tag>-<pid>,
mcp-junk, mcp-confined), and nothing removed them after the run.

A shared tests/common module adds TempFolder, which takes the folder from
temp_dir, with its checks against a folder made by another user, and
removes it with everything in it when dropped, also when the test panics,
as the findfiles tests' Tree guard does
(crates/engine/src/cmd/findfiles/tests.rs:49). Each proptest case of
a_confined_server_writes_only_inside_its_root now gets a new folder. A new
test checks that the folder is removed on drop and after a panic.
2026-11-13 08:22:23 -08:00
dotCooCoo e11c21ce98 MCP: an old app's window capture goes through a private temporary folder
An app that does not send the image back wrote the window capture to
vectorcraft-window-<pid>.png directly in the system's temporary folder.
On a shared Unix temporary folder another user could put a link at
that name, and the app would then overwrite the file it points to. A
failed read also left the file behind.

The capture now goes to window.png in a new folder made for it inside
the temporary folder (owner-only on Unix; a name that is taken is
skipped). The folder is removed after the read, also when the app or
the read fails.
2026-11-13 08:19:07 -08:00