Update Links, and opening a document with Update Links: Automatically,
now read a modified file again for the images and placed documents in
symbols, graph designs, patterns and opacity masks that show the same
content as the objects read in the layers. By default Update Links also
reads the files that only that art shows. Each nested object takes the
file's place as its own Placement Options say, including the clip, and
its link takes the new path, size, modification time and hash.
Saving a document also refreshes the placed copies of it inside symbols,
graph designs, patterns and opacity masks of the other open documents,
not only those in the layers.
Relink, Embed and Unembed still change only the objects they are given.
A save wrote the path relative to the document only for linked images and
placed documents in the layers. Links inside symbols, graph designs,
patterns and opacity masks kept only their absolute path, so after the
document and its files moved to another folder together, those files were
not found.
- The save sets the relative path of every link the document holds.
- On open, a link inside that art whose file was found away from its path
takes the new path, as a link in the layers does, so the next save
writes the right relative path.
- Document::update_links_where changes only the links it picks and copies
only the nodes on the way to them.
Docs: docs/mcp.md (Linked images), docs/target-app-parity.md.
With Fade Region Outside Artboard on, the canvas now draws the fade over the
art as well as the pasteboard: one mesh of black at 40% opacity covers the
canvas outside the artboards, so the pasteboard and any art on it show each
channel at 60% of its value, and art inside an artboard is unchanged. It
replaces the darker pasteboard fill.
Artboard Options sets the Global checkboxes' preferences only after
artboard.setProps or artboard.new succeeds. When the artboard command
refuses a value, the preferences stay as they were and the dialog stays
open. A Global value that is not true or false is refused before anything
changes.
Docs: docs/mcp.md, docs/target-app-parity.md.
Artboard Options gets a Global group with Fade Region Outside Artboard and
Update While Dragging. Both are application preferences
(fadeRegionOutsideArtboard, artboardUpdateWhileDragging), on by default and
also listed under Preferences > General > Artboard Options.
While the Artboard tool is active, the canvas draws the pasteboard with each
color channel at 60% of its value. With Update While Dragging off, the
pasteboard draws as usual while the tool moves or resizes an artboard and
darker again when the drag ends. Exports and print do not change.
Docs: docs/mcp.md, docs/target-app-parity.md.
Recent Colors now keeps up to 30 solid colors instead of 10, newest
first and each once; applying a 31st drops the oldest. The Session
holds the list, so it stays the same when another document is opened
or made active, and it lasts for the session.
The Color and Swatches panels wrap the chips onto further rows when
the panel is too narrow for one row, so every color can be clicked.
A list that fits one row draws as before.
Docs: paint.recent params text, docs/mcp.md, docs/target-app-parity.md.
Reset Bounding Box set the angle to 0 on the selected objects only. A
rotation changes the box angle of the selected objects and of every
object inside them, so the members of a rotated group kept their angle:
after rotating two rectangles 20 degrees, grouping them, rotating the
group 10 degrees and resetting, Ungroup brought back a box at 30
degrees, and a second reset reported 2 objects to change.
The command now also squares every object inside the selected ones: the
children of groups, compound paths, clip groups, blends, envelopes,
repeats and intertwines, and the art of linked opacity masks. The art of
an unlinked mask does not turn with the object, so it keeps its angle.
Ungroup, Release Clipping Mask, Release Compound Path, Blend Expand,
Release Envelope, Release Repeat, Release Intertwine and Release Opacity
Mask then bring back boxes square to the page. The whole reset stays one
undo step.
Two results change. `changed` counts every object reset, the objects
inside included, so the steps above return 3 where they returned 1. A
group whose own box is square but whose members are turned used to
return 0 with no undo step; it now squares the members in one step.
Docs: params text, docs/mcp.md, docs/target-app-parity.md.
The Preferences dialog has a Search Preferences field above the category
list. It has the keyboard focus when the dialog opens, and Cmd/Ctrl+F
focuses it again. While it has text, the list shows every setting whose
label, section or category contains it (ignoring case, in the interface
language or in English), or "No settings found". Choosing a setting shows
its category, scrolls to its row and highlights it. Escape in the field
with text clears it; Escape in the empty field closes the dialog.
The dialog's `__search` field holds the text, so `ui.dialog.set` drives
the search too.
A short move with View > Snap to Pixel on returned to where it began and
showed a "last location" label, skipping the pixel step. Snap to Last
Location is now off while Snap to Pixel is on, for the Selection tool and
for paths Direct Selection moves by an anchor, so the move lands on whole
pixels as it does with the option off.
Preferences > Smart Guides gets Snap to Last Location (`snapToLastLocation`,
off by default). With it and Smart Guides on, a selection moved by dragging
with the Selection, Group Selection or Direct Selection tool, Shift too, goes
back to where the move began while the move is within Snapping Tolerance,
labeled "last location". An Alt copy is not pulled back onto its original.
Source: https://helpx.adobe.com/illustrator/desktop/measure-and-align/grids-and-guides/smart-guides-options.html
The distance, the label and the copy rule are VectorCraft's own.
The Symbols panel menu's Reset Transformation and the Control bar's Reset
(shown while symbol instances are selected) give the selected instances
their symbol's own scale again, without rotation, shear or reflection, as
one undo step (symbol.instance.resetTransform). Each instance keeps the
center of its art's bounding box in place. Instances in perspective and
instances already at their symbol's scale are left as they are, no undo
step is added when nothing changes, and both controls are enabled only
while a selected instance would change.
Docs: docs/mcp.md, docs/target-app-parity.md.
The History panel gets a New Document from State button at its bottom,
which runs the new edit.newDocumentFromState command. The command makes
a new document holding the art of a History panel row ({index?}, the
current state when omitted) and makes it the active document. An index
that names no state is an error and changes nothing.
The new document takes the next Untitled-N name, is marked unsaved, has
nothing selected, no steps to undo or redo and no modified date, and
leaves symbol, opacity-mask and pattern editing; the art drawn in a
pattern's tile is stored in the pattern, as Done stores it. Its links point at the files the
source finds, including files found in the source's folder away from the
links' paths. Those files are looked for only within the folders the
asking caller may read; for a caller without limits, within the folders
the caller that opened the source may read. The source
document, its steps and its saved state stay as they are; typing or a
drag in progress is first kept as a step, as Undo keeps it. While an IME
composes, the command waits, as Undo does.
Docs: docs/mcp.md, docs/target-app-parity.md.
The Appearance commands do not store a stroke paint or weight for a series
that draws a Filled Lines band, but they do store a stroke opacity set on the
band, and the band's 0.25 pt black outline takes it when the graph is drawn
again. docs/mcp.md now says so, and a test covers it.
paint.setFill, paint.setStroke, paint.none, Apply Fill to Stroke and Apply
Stroke to Fill stored a series' paint on the graph. appearance.setItem, the
Eyedropper, appearance.transfer, Clear Appearance, Reduce to Basic Appearance
and the add, remove, move and duplicate row commands stored no paint or weight.
An Eyedropper pick of a blue fill at 40% onto a red column drew red at 40%
after the next redraw.
These commands and Show All Hidden Attributes now store the paint and weight
of the topmost visible fill and stroke of a path directly in a series group,
in the same undo step. A color, weight or opacity that a command writes to that
row replaces the stored value even when the mark's own value does not change. A
row that has no paint before and after the command does not change the stored
paint. These commands store no stroke for a series that draws Filled Lines
bands, and a band no longer takes its color from an empty stored stroke.
The stored opacity also comes from the topmost visible row: hiding a top row
stores the row under it, and an opacity set on a hidden top row is not stored.
Follows #5501.
Edit > Keyboard Shortcuts gains Export Text..., which saves the set shown
in the dialog, as edited so far, as a UTF-8 text file the user names in a
save dialog with a .txt filter. shortcuts.exportText {path?} does the same
for the current set over MCP and the control channel.
The file holds a "Keyboard Shortcuts" line and the set's name, then a
Tools and a Menu Commands section with the rows the dialog lists, in its
order and named as it shows them: the name, a tab and the shortcuts as the
dialog shows them on the current platform. A row with no shortcut ends
after the tab. A path that is not a string, or a file that cannot be
written, returns an error and nothing is written.
Docs: docs/mcp.md, docs/target-app-parity.md.
Choosing a PDF/X standard without a PDF/X preset writes a file with no bleed
(BleedBox = TrimBox) even when Document Setup sets one, and the export gave no
warning about it. The export now warns when a PDF/X file has no bleed on a side
where the document's bleed has one. The warning comes ahead of the flattening
note, because the status bar shows only the first warning. The code adds a
warning and does not change what is written.
These cases do not warn: the PDF/X presets, Use document bleed settings, a
nonzero bleed on every side the document sets, a document with no bleed, files
that aren't PDF/X files, and Export for Screens rows whose artboards Include
Bleed grows.
The warning has a row in every catalog. The Summary's warning and error rows in
the Save PDF and Print dialogs now go through the catalog, so they show its
translations.
Object > Expand left a dimension's recipe on its group, so the next move
redrew the live dimension and discarded the expanded art. Expand now ends
the live link of a dimension whose art it changes, in the same undo step.
Moving or scaling the group leaves its art as it is, the art no longer
follows what it measured, and undo gives the live dimension back.
Expand Appearance, Create Outlines and Outline Stroke had the same fault
and now do the same, also when they reach only a part of a dimension. A
dimension whose art a command leaves as it was stays live. A dimension
selected with the art it measures becomes a plain group when Expand,
Expand Appearance or Outline Stroke replaces only that art.
The curve fitter split a piece over the tolerance at its worst point and
accepted any piece at depth 41 whatever its error. A worst point near the
end of a piece peels off a few points, so a long path refitted nearly all
of its points at every level. A serpentine of 200,000 anchors kept pieces
with a fitted error of up to about 1,598 pt at a tolerance of 1 pt.
Simplify also took at most 256 samples per segment, so the lines between
the samples on a long arc could be farther from it than the tolerance.
- `fit_rec` moves a split that is near an end of its piece to two fifths
of the piece from that end, so the depth is logarithmic, and it keeps no
piece over the tolerance. A piece of 32 points or more is first fitted
to about 16 of them, and it is split when that fit is over the tolerance.
- A curve is also rejected when it is over the tolerance from the lines
between the points it fits, with samples close enough that it stays
within 1% of the tolerance of the chord between them. A pair of points
that would need more than 1,024 samples counts as too far.
- `join_pieces` joins neighboring pieces when one curve fits them, up to
33 pieces per curve.
- `sample_steps` takes enough samples of a curved segment to keep it within
0.5% of the tolerance of the lines between them. A segment that would
need more than 65,536 samples stays as it is, and so does a segment
after a run's first 16,777,216 samples or 2,097,152 result segments. With
Convert to Straight Lines such a segment becomes evenly spaced lines, up
to 65,536. A fit holds at most 1,048,576 samples, so a longer run is
fitted in parts.
- Simplify fits at 98% of the tolerance, since turning a nearly straight
curve into a line moves it by up to 1.5%.
- Above slider level 0, Object > Path > Smooth fits a whole closed path
with no corner along one direction across its start, when no segment
stays as it is and the path is fitted as one part. A direct-selected
section does not get this. The start can still have a kink: a first or
last fitted curve that is nearly straight becomes a line, which leaves
along its chord, and a refit with more anchors than the path is
discarded, so the path stays as it is.
A closed subpath that refits to one curve is still dropped, as on main, so
it can end up farther than the tolerance from the result. docs/mcp.md
states this.
The anchors of every simplified path can differ from before, and so can
the results of the Pencil, Blob Brush and Smooth, which use the same fit.
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.
Extrude & Bevel (Classic) has no lighting presets; its lights are set in
its own options. effect.lightingPreset now refuses a target whose effect
at the index is Extrude & Bevel (Classic) with an error that names it,
before any object changes. Before, every preset failed on it with an
unknown-parameter error for lightColor. The params text and docs/mcp.md
state the rule.
plugin.run and plug-in commands read `ids` strictly: a value that is not
a list, or an entry that is not a non-negative integer, is an error
naming `ids` ("ids must be an array of non-negative integer object
ids"). Left out or null, `ids` is still the selection.
A new test shows that a plug-in command that runs out of its
instruction budget leaves the document and the undo history unchanged,
and that the error names the plug-in and the command.
docs/plugins.md and docs/mcp.md name MCP's `command_list` and
`list_commands` as the listings that show plug-in commands, and the
params text, docs and progress line describe the `ids` rule.
A filter or live effect may declare up to 32 `commands` in its manifest,
each `{id, label, params?}`. While the plug-in is installed each one is the
command `plugin.<id>.<command>`: listed by `command.list` and in the
plug-in's `plugin.list` entry, run through `run`, MCP and `command.batch`
with its parameters checked before the plug-in runs, and recorded in
actions. A run goes through `vc_run` on the selection with
`_context.mode` "command" and `_context.command`, under the plug-in's
permissions, as one undo step named after the command. A failing run
leaves the document as it was, and its error starts with the plug-in's
name and the command's label. Removing or replacing the plug-in removes
its commands.
In the app, a plug-in with commands is a submenu named after it under
Object › Plug-ins (Effect › Plug-ins for a live effect), holding its own
item and then its commands; a `menu` key in a manifest is ignored. A
command with parameters opens a dialog for them from its menu item or a
shortcut. Edit › Keyboard Shortcuts lists the commands for the user to
give a shortcut; a manifest cannot set one. Labels and names are shown
with control and bidirectional characters escaped, and a malformed entry
is refused by name when the module is installed.
Docs: docs/plugins.md, docs/mcp.md, docs/target-app-parity.md.
A manifest may list `permissions` (doc.read, doc.write, state,
effect.render, export.write) and an `api` level. doc.read, doc.write
and state follow the capability model proposed in
storytold/photocraft#662; the other names are VectorCraft's own. An
unknown, reserved, duplicate or wrong-kind name is refused by name. A
manifest without the key gets the permissions its kind implies and
installs as before.
- Install Plug-in... and File > Open show the name, id, version, file
SHA-256 and each permission in plain words, with control and
bidirectional characters escaped and each string cut to 64
characters. OK installs the module only if it still has the SHA-256
shown; Cancel installs nothing. The heavy-budget prompt and the
status line show the escaped name too, and OK keeps the `replace` it
was given.
- `plugin.install` needs `grant` listing every permission, and
`plugin.inspect` reports `needsApproval`. `hash` pins the module:
one with another SHA-256 is refused. The grant is kept with the
module's hash in the store's `grants.json`, and only that store's
grants count while it is attached; the same set does not ask again,
more permissions do, and `plugin.remove` forgets it.
- The Additional Plug-ins Folder and `plugin.reload` install only
plug-ins the attached store has granted and report the others as
needing approval. At startup the store skips an ungranted plug-in.
- A filter run without doc.read is given no objects; without state it
neither reads nor writes `documentData`; without doc.write an output
that changes the document is refused and the document is unchanged.
Docs: docs/plugins.md, docs/mcp.md, docs/target-app-parity.md.
Effect > 3D and Materials > 3D (Classic) > Extrude & Bevel (Classic)... applies
`threeD.classicExtrude`, a live effect built on the Extrude & Bevel solid. It
takes Extrude Depth, Cap, a bevel with Height and Bevel Extent In or Out, the
Position presets, rotation and Perspective, and draws the faces with the
Wireframe, No Shading, Diffuse or Plastic surface: one to ten lights, Ambient
Light, Highlight Intensity and Size, Blend Steps, a Black, Custom or no Shading
Color, and Draw Hidden Faces. Invalid parameters are refused with an error.
A new standalone crate, vectorcraft-apischema, describes a command's
parameters: type (number with range and unit, integer, boolean, string,
enum, id, id list, color, point, object, array), whether each is
required, the default of an omitted value, whether null counts as
omitted, the API levels it was added and deprecated at, and the lenient,
cost and writes fields. It validates a params object and names the
parameter of the first problem, writes the params text, writes the
schema in the shape of a JSON Schema 2020-12 object schema, and hashes a
set of schemas.
CommandSpec gains an optional schema (both builders: the cmd! macro and
the text style specs). Session::execute checks the params of a command
that has one before anything else, refusing a value of the wrong type,
out of range or not in its list, a missing parameter or an unknown key
with an error naming the parameter, and fills in defaults; the journal
keeps the params as given. engine.commands lists each schema.
The six commands in cmd/views.rs have schemas, and their params text is
the text the schema writes. schemas::API_VERSION is 1, and a test fails
when a schema changes without a new row in SCHEMA_HASHES.
Docs: docs/mcp.md (Parameter schemas), docs/target-app-parity.md.
A .ai or EPS whose editing data defines symbols but has no layers came
in as its PDF part or page without symbols, and Other Library in the
Symbols panel listed none. Such a file, and a file read as its PDF part
or page because its layers can't be used, now gets the symbols its
editing data defines before its first layer, as a file read from its
layers does: File > Open shows them in the Symbols panel in the order
of the symbol list, and Other Library lists them in a library panel.
- Each symbol keeps its registration point. A symbol that holds an
instance of a symbol the file doesn't define is left out, and an
object linked to a listed graphic style keeps the link.
- The symbols' art takes ids of the document, the art of opacity masks
in it included, and the images it shows come with it. Instances
drawn too deep are removed with the usual note.
- The global and spot colors the art is linked to come in as swatches.
A color whose name another swatch has takes that swatch's place when
it is a default swatch of a file without a palette; otherwise it
comes in under a free variant of the name ("Ink 2"), which the art
then names.
- Symbol art keeps the editing data's units, as in a file read from its
layers, so in a file in larger units its linked graphic styles are
drawn at the scaled size and the symbol art is not.
- The art of the patterns a palette or brush brings into a file read as
its PDF part or page now also takes new ids for its opacity masks.
Part of #3349
An object opacity or blend mode set on a path directly in a graph series, and
the blend mode of its topmost visible fill or stroke, were lost when the graph
was drawn again. The graph now stores them per series next to the row opacity
it already stores, and puts them on every path directly in the series when it
draws the series again.
- transparency.set and object.setProps store the object's opacity and blend
mode. A value the mark already has still replaces the value another mark of
the series stored.
- appearance.clear, appearance.transfer, appearance.copyFrom with Transparency
picked up, graphicStyle.apply without add and graphicStyle.redefine store
the object's opacity and blend mode they leave on the mark.
- The other Appearance and style commands store them when they change them
on a mark.
- Every command that stores the opacity of the topmost visible fill or stroke
also stores its blend mode. A Filled Lines band's outline takes the stored
stroke opacity and blend mode and keeps its black 0.25 pt stroke.
- An opacity and blend mode are stored as a pair from the edited mark:
setting only the opacity of one mark also stores that mark's blend mode.
- A graph design's copy in a series keeps its own values.
Docs: docs/mcp.md, docs/target-app-parity.md.
Applying a graphic style, Redefine Graphic Style, Default Fill and Stroke
and Swap Fill and Stroke on a path in a graph series changed the path
but not the paint the graph stores for the series. When the graph was
drawn again, the series went back to its earlier paint.
These commands now store the mark's topmost visible fill and stroke on
the graph, in the same undo step as the command:
- graphicStyle.apply stores the paint, weight and opacity of both kinds
of row. With `add` it stores only the kinds of row that are visible
in the style.
- graphicStyle.redefine stores the paint, weight and opacity of the
marks still linked to the style.
- paint.default stores the white fill and the 1 pt black stroke, both
opaque.
- paint.swap stores the swapped paints and the stroke weight and keeps
the stored opacity. It swaps the topmost rows even when they are
hidden, and a hidden row it swaps is not stored.
The rule for each kind of mark is the one docs/mcp.md gives for the
Appearance commands. docs/mcp.md also says what the graph does not
store from a graphic style and that a series group given to a graphic
style command is not stored. The params text, docs/mcp.md and the
Graphs line in docs/target-app-parity.md list the commands.
paint.setFill, paint.setStroke, paint.none, Apply Fill to Stroke and Apply
Stroke to Fill stored a series' paint on the graph. appearance.setItem, the
Eyedropper, appearance.transfer, Clear Appearance, Reduce to Basic Appearance
and the add, remove, move and duplicate row commands stored no paint or weight.
An Eyedropper pick of a blue fill at 40% onto a red column drew red at 40%
after the next redraw.
These commands and Show All Hidden Attributes now store the paint and weight
of the topmost visible fill and stroke of a path directly in a series group,
in the same undo step. A color, weight or opacity that a command writes to that
row replaces the stored value even when the mark's own value does not change. A
row that has no paint before and after the command does not change the stored
paint. These commands store no stroke for a series that draws Filled Lines
bands, and a band no longer takes its color from an empty stored stroke.
The stored opacity also comes from the topmost visible row: hiding a top row
stores the row under it, and an opacity set on a hidden top row is not stored.
Follows #5501.
The earlier paragraph said document.export takes any key when its description names none. The export commands refuse an unknown option key, so the paragraph now lists them as an exception and keeps document.save as the example that takes any key.
document.export, document.exportSelection, document.serialize, app.export
and file.export took {noSuchOption: true} and wrote the file with no
warning. They now refuse a key that no format lists in document.formats,
and name the nearest key when one is close. document.exportPdf,
document.pdfSettings and pdf.preset.save refuse a key PDF doesn't take,
document.exportEps one EPS doesn't take and document.exportDxf one DXF
doesn't take. Each refuses an unknown key inside an option object it takes,
such as marks.useDocumentBleed, and names its path.
A key that only another format reads, such as {format: pdf, quality: 80},
is still ignored: docs/mcp.md says one object can carry several formats'
options. The check runs for callers (the control channel, MCP, the CLI).
A journal or a recorded action isn't checked, and a saved PDF preset with
a key that is no longer read still loads.
document.formats now also lists PDF's thumbnails, fastWebView and
viewAfterSaving.
edit.copy and edit.cut chose the artboard route by the tool chosen, which
the journal does not record. A replay in a new session acted on the objects
selected there, or stopped with "nothing selected" when there were none.
With the Artboard tool chosen, both now record selectedArtboards and art in
the journal entry. A given selectedArtboards runs the artboard route with
any tool and needs only a document. A recorded action leaves both values
out, so it follows the tool chosen when it plays. Cut and Copy of objects
record nothing new.
After Select All in threaded text, the panels read the frames from the
list saved at Select All. A frame that had left the thread still took
Paragraph, Tabs, Justification and Text Styles changes, a frame added
later did not, and when the first saved frame had left, Character,
OpenType and font changes went to that frame alone.
text_story now reads the frames of the edited frame's thread from the
document. Locked and hidden frames stay in the story.
prefs.set did not check the folder given as recoveryFolder or pluginsFolder,
beyond the automation roots check, so a control or MCP caller could save a
folder that does not exist, a file, or a folder the app cannot use. Only the
Preferences dialog checked the folder itself.
The dialog's folder checks move to the engine, and prefs.set runs them after the
automation roots check. A folder that fails returns the same error the dialog
shows, and no preference changes. An empty value, an omitted value and a folder
the preference already holds are not checked. The Wasm build skips the check, as
the dialog did. The dialog's OK now gets the check from prefs.set, and Choose…
calls the moved check directly.
With the Artboard tool, the canvas context menu lists the entries of the
public Use the artboard context menu page in its order, in place of the
entries for objects and the view. Lock Artboards and Unlock Artboards are
two submenus. An entry that cannot run is left out, and Undo and Redo stay
dimmed. A right-click on an artboard that is not selected selects it alone
first, and the menu measures the art for Delete Empty Artboards and Fit to
Artwork Bounds once, at the right-click.
Cut, Copy, Duplicate Artboards, Rename, Delete Artboards, Lock Selected,
Unlock Selected, Fit to Artwork Bounds, Switch Orientation and Export act on
the artboards the tool has selected, else the active one. docs/mcp.md lists
what the other entries act on.
- artboard.rename renames in one undo step and numbers several names. The
menu's Rename opens a dialog that runs it, and the Artboards panel's name
field runs it too.
- artboard.switchOrientation swaps width and height and keeps the top-left
corner, skipping square and locked artboards.
- artboard.selectAll chooses the tool and selects every artboard.
- edit.paste takes artboardsAt, and the menu's Paste centers copied
artboards on the right-click's point.
- The menu's Cut and Copy run artboard.cut and artboard.copy. In the desktop
app those commands publish to the system clipboard, and the menu shows the
Cut and Copy shortcuts for them.
- artboard.fitToArt and the panel's name field record no undo step when
nothing changes.
artboard.duplicate, copy, cut, rename and switchOrientation take their
artboards from the tool's selection when a call names none. Each now records
them in the journal as selectedArtboards, which a replay reads and a recorded
action leaves out. The copy commands also record art. switchOrientation
records scaleArt, and it takes patterns and lockedAndHidden and records what
its artboard.setProps step resolved for them.
While the Artboard tool is in use, a command chosen from any menu or the
command palette moves the tool's selection as the Artboards panel does:
artboard.new makes the new artboard active, artboard.duplicate selects the
copies, and artboard.delete and artboard.deleteEmpty make a remaining
artboard active.
save_file's note for a key in `options` that the written format doesn't
read named every .ai file a PDF-compatible .ai, also when the save wrote
a version 7 file (`aiVersion: "7"`) or one without PDF content
(`pdfCompatible: false`).
The save itself now writes that note, beside its note on a top-level
`compress`, `version`, `preview` or `precision`, and names the file it
writes, including when it reuses the options the document was last saved
with. save_file returns the save's reply unchanged, and
`run_command document.save` and the other save commands give the same
notes.
Encryption keeps the /ID already in the trailer and draws one from the
seed only when there is none. A PDF 1.3 export draws no random bytes, so
it repeats with SOURCE_DATE_EPOCH set, while PDF 1.4 and later differ
between runs. Their random bytes are in the encryption dictionary and,
at PDF 1.6 and later, in the AES initialization vectors.
When a frame threaded in before the edited frame takes all of the story's
text, the edited frame is left with no text while the story stays
selected. The other frames' text is now highlighted, Delete and Backspace
replace the story, an Alt+arrow step changes the tracking of every frame,
and Copy and Cut take the story. A story whose frames hold no text has
nothing to copy, and Delete in it records no undo step.
With a whole story selected, the highlight and typing read the frames saved
at Select All, while a pick, a fill and the other story-wide edits read the
document's thread. A frame added by text.thread.add took a pick without being
highlighted, and typing left its text in place.
Both now read the thread through Document::story_of. A frame threaded in
during the selection is highlighted and takes the edit, and a frame that
leaves the thread is not highlighted and keeps its text.
appearance.copyFrom and a fill or stroke change on a story selected by
Select All no longer skip locked frames, hidden frames and frames on a
locked artboard. They apply to every frame of the story, as the Character
panel's story edits do. appearance.copyFrom still leaves out a frame that
is its source.
With a threaded story selected by Select All, switching to the Eyedropper kept
only the edited frame's selection, so a pick styled one frame. The selection now
carries the story's frames, a pick or Shift-click applies to the text of every
frame as one undo step, and switching back to a Type tool restores the story
selection. A selection inside one frame and unthreaded type behave as before.
A pick and a fill or stroke change on a selected story leave locked and hidden
frames and frames on a locked artboard as they are. appearance.copyFrom leaves
out a frame that is its source.
Typing over a selected story no longer removes the text of a frame whose thread
was removed after Select All.