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.
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.
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.
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.
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.
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.
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
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.
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.
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.
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.
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.
The MCP unit tests wrote their files into one folder per process under
the temp dir (vectorcraft-mcp-test-<pid>, vectorcraft-mcp-fileio-<pid>,
testkit's mcp-cancel folder) and nothing removed them. The export-as and
links tests removed their folder at the end, so a failing test left it.
Each test that writes files now holds a TempFolder, a folder of its own
that starts empty and is removed with everything in it when the test
ends, also when it panics, as the findfiles tests' Tree guard does
(crates/engine/src/cmd/findfiles/tests.rs:49). A new test checks that a
leftover folder is emptied and that the folder is removed on drop and
after a panic.
`document.export`, `document.serialize` and `document.exportSelection`
accept a key that only another format takes. `{"format": "pdf",
"quality": 80}` wrote the PDF and gave no warning about `quality`.
The reply's `warnings` now name each such key, in the wording of a
save's note: "`quality` was not used: PDF files don't read it".
- The format's own options, the commands' own keys, null values and an
exporter plug-in's format get no note.
- The note names the kind of file written. A legacy `.ai` file
(`aiVersion: "7"`) reads `outlineText`, `hiddenObjects`,
`transparentImages`, the artboard choice and `useArtboards`, and
beside `aiVersion` no other option. The other `.ai` files don't read
those three options or `preserveEditing`, which is always on for
them.
- An export doesn't read `separateArtboards`, or `range` for a
`vectorcraft` or `template` file. A save reads them to write each
artboard to a file of its own.
- In the app, an export that automation asked for (`app.export` with a
path, `file.exportAs` run as a command) gives the same notes in its
reply and in the status bar. A Background Export replies before the
file is written, and that reply has the notes. An export that a
person starts from the File menu gets none.
- Export As gives a template export no `useArtboards` or `range`: a
template doesn't read them.
- `vectorcraft-cli convert` sends `outlineText` only with
`--outline-text`, and `hiddenLayers` only to the formats that read
it. A conversion then warns only about an option the command line
gave.
`document.save` gives its notes as before: it does not apply the `.ai`
rules above.
Docs: docs/mcp.md, docs/control-protocol.md,
docs/target-app-parity.md, the params text of the three commands.
learn.skills {} shows the Learn panel on its Skills tab with the list of
skills, with no skill and no tutorial open, and returns what learn.list
returns. Back to skills after a skill's last tutorial and the Quick skill
guide card on the For you tab now run it, so the control channel and MCP
can reach the same view.
- The command is listed in both UI command catalogs, and its label has a
row in every catalog.
- Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md.
A toolbar made with New Toolbar now docks in a lane along the window's
left or right edge (on the left, right of the Tools panel docked there).
Dropping its title bar on an edge docks it, with the target lit while
the title bar is dragged over it; dragging it out of its lane floats it
under the pointer, and Escape or losing the window's focus during the
drag puts it back. The title bar's context menu has Dock to Left, Dock
to Right and Float Toolbar.
- Toolbars docked at one edge stack from the top, each with an equal
share of the lane's height, and the lane is as wide as its widest
toolbar. A lane too short for its stack wraps it into more columns,
up to half the width beside it; past that the toolbars show only
their title bars, a lone toolbar included, and a column too short
for those scrolls with the mouse wheel.
- With Keep Tools Beside the Canvas on and Tools docked on the left,
the left lane is laid out inside the canvas panel right of Tools, and
the canvas keeps room for one column of it and its 200 points.
- A release in the frame the pointer leaves the lane floats the toolbar
with its corner where the drag put it.
- window.toolbar.dock {name, side?, order?} and window.toolbar.float
{name, x?, y?} do the same from the control protocol; bad params are
errors and change nothing. window.toolbar.list reports floating, side
and order.
- CustomToolbar keeps dock (place in the edge's stack) and dock_right;
both default, so toolbars saved before load floating. Workspaces and
preferences keep the placement; New Toolbar still starts floating, a
copy floats, and deleting a docked toolbar closes up its stack.
- Dock to Left, Dock to Right, Dock Toolbar and Float Toolbar have rows
in every catalog.
Part of #1759
With an action selected, Begin Recording records into it: Stop puts the
recorded commands after the selected step, or after the action's last
step, and the steps after them keep whether they are excluded. With no
action selected it still adds a new Action N.
- ui.action.record takes {set?, action?, after?}; action needs set.
The place stays between the same steps while a step is inserted,
deleted or moved in that action during the recording, and the selected
step and an open Record Stop dialog follow their step when Stop adds
the recorded steps before them.
- New ui.action.moveStep {set, action, step, toSet?, toAction?, before}
moves a step within its action or into another action, also an empty
one or one in another set. The step keeps its params and exclusion,
the selected step and an open Record Stop dialog follow their step,
and a move past 10,000 steps or 8 MiB is an error that changes
nothing.
- In the Actions panel a step row drags: a line shows where the step
goes, the release moves it once, and a release off the actions' rows
leaves it where it was. The list scrolls near its edges.
Help page: https://helpx.adobe.com/illustrator/desktop/automate-visualize-data/automate-actions/add-commands-to-actions.html
Docs: docs/mcp.md, docs/target-app-parity.md.
Control bar > Snapping > Pixel Snapping Options... opens a dialog with
three checkboxes: Snap to Pixel While Drawing, While Moving and While
Scaling. OK sets them; Cancel leaves them as they were. While View >
Snap to Pixel is off, the dialog notes that the options take effect once
it is on.
- view.snapToPixel.options {drawing?, moving?, scaling?} reads and sets
them. They are kept in the preferences as the pixelSnap group, all on
by default, so turning Snap to Pixel on behaves as before. An unknown
key or a value that is not a boolean is refused and changes nothing.
The command has a parameter schema, which raises the API level to 4.
- Drawing covers points the drawing tools place, the Knife's straight
cut, the Measure tool and the rulers' origin. Moving covers Selection
and Direct Selection moves, ruler guides, artboard moves and the
Rotate, Reflect and Shear tools' drags. Scaling covers bounding-box,
Free Transform, artboard and slice handles and the Scale tool's drag.
An edit whose option is off snaps as it does with Snap to Pixel off.
- Align New Objects to Pixel Grid and the objects' pixel-aligned
property do not depend on these options.
Docs: docs/mcp.md, docs/target-app-parity.md.
The Smooth tool, and an Alt smoothing drag with the Pencil, Paintbrush or
Blob Brush, now send path.smoothRegion their Fidelity divided by the zoom,
as the Pencil and the Paintbrush do since #5748. Smooth Tool Options shows
Fidelity in px. A saved Fidelity keeps its number, so it smooths as before
at 100% zoom.
path.smoothRegion now refits at tolerances from 0.05 px at the highest zoom
to 100 px at the lowest (0.000078125 to about 3195 pt) instead of clamping
to 0.05 to 100 pt, so the setting keeps scaling across the whole zoom range.