While Select > Start Global Edit can run, the Control bar shows a Global Edit
Options dropdown after Recolor Artwork. It opens the Properties panel's Global
Edit Options (Match: Appearance, Size; On Artboards; Include Objects On
Canvas; Result(s)), so both set the same options, and it is off while Global
Edit is on, as the Properties dropdown is. The bar leaves it out when no room
is left for it.
Public reference:
https://helpx.adobe.com/illustrator/desktop/manage-objects/edit-objects/edit-similar-objects.html
The dropdown takes room ahead of the inline X/Y/W/H fields, so the ruler-origin
tests that read X/Y from the Control bar draw it 1700 px wide.
Opening a .ai or a PDF read and checked the whole file up to five
times: for the document it carries, for whether it holds the editor's
private data, for the import, for the editor's copy and for its File
Info. Each pass parses the file and walks every object, about 190 ms on
a 15 MB .ai.
- vectorcraft_pdf::open_pdf reads and checks the file once, on the
import's deep-stack thread, and import_opened imports pages from that
reading. document.open takes the carried document, the page count,
the editor's copy and the File Info from it. The editor's copy is read
after the page import and only when the file is not restored from a
carried document; so is the File Info.
- A .ai saved without PDF compatibility opened with pages that name
every page reads its editor's copy from the same reading.
- document.pdfInfo reads the file once for its pages and the thumbnail.
- The Open and Place dialogs read the file once to decide whether to
ask for pages, instead of twice.
A file whose PDF part fails the check still reads its editing data
separately, as before.
A blend's record in the editing data holds its Blend Options spacing.
Word 1 is the spacing: 0 is Smooth Color, 1 is Specified Steps and 2 is
Specified Distance. For Specified Distance, word 2 is the distance in
points as a 32-bit float. The reader took only records whose word 1 is
1, so every Smooth Color and Specified Distance blend came in as its
drawn steps.
A Smooth Color or Specified Distance blend now opens live with that
spacing where VectorCraft lays out as many steps between each pair of
keys as the file draws, in the same places and colors. Otherwise it
keeps its drawn steps with the existing note. The distance is read as
the shortest decimal that reads back as the stored float. The steps are
counted before anything is laid out, and a blend takes from the
import's budget only when its count matches. Specified Steps blends
are read as before, with the steps counted from the drawn ones.
Tests: import::ai::tests::a_blend_keeps_its_spacing,
a_blend_of_three_keys_keeps_its_distance_between_each_pair,
a_blend_whose_spacing_doesnt_lay_out_its_steps_keeps_them,
import::ai::blend::tests::records_say_their_spacing,
a_blend_takes_from_the_budget_only_when_it_is_laid_out,
a_distance_past_the_keys_lays_out_no_steps, and the fuzz case
ai_blend_spacing_never_panics.
A variable font can leave an ssNN feature empty in GSUB or GPOS and
supply its lookups through a FeatureVariations substitution. The
OpenType panel skipped those sets because the default feature has no
lookups. A set is now listed when a substitution in a variation record
replaces its feature with one that has lookups, and its name is read
from the default feature or the substituted one.
Records after one without conditions are ignored, and at most 4096
variation records and 4096 substitutions are read per table.
Follows #5447.
The room estimate for a large PNG read a row at a time counted 32 bytes
a column. The png reader also keeps at least 128 KiB of rows already
read, the 32 KiB deflate window and a growth step in its stream buffer,
and up to four rows for wide images, so a decode could be approved with
less room than reading takes. The estimate now comes from the PNG
header's row length and these buffers, and a PNG is read a row at a
time only while that estimate fits the decode allowance.
Object > Expand with Object on now turns each symbol instance in the
selection, including one in a selected group or in a placed document's
art, into its art, as Break Link to Symbol places it. It goes one level
deep: the instances in that art stay instances. The art keeps the
instance's id and place in the stacking order, and Expand stays one
undo step.
- Instances with effects stay instances, and Expand Appearance bakes
them as before. Instances with an effect on a fill or stroke,
instances in perspective, and those in blends, repeats and Intertwine
groups stay instances.
- The art keeps the instance's opacity mask, as Break Link gives it.
- A hidden or locked instance's art stays hidden or locked.
- A placed document in an instance's art is expanded too.
- When the instances' art would make more than 1,000,000 objects, they
stay instances, the limit Break Link uses.
- The Fill and Stroke options (object.expand.info, and the Expand
dialog) count the fills, strokes and gradients in the art of those
instances, with a dynamic instance's own changes applied. The info
reports under symbolArt which of them only that art holds, and the
dialog enables those options only while Object is on.
While the Type tool edits a frame of threaded text, Select All selects
the text of every frame of the story, highlighted in each frame. The
tool edits the first frame that holds text.
- Typing, Delete and Cut replace the whole story as one undo step
(`text.editRange` takes `clear`, the other frames whose text goes).
- Copy and Cut take the whole story (`text.getRange {id, story: true}`).
- Fills and strokes, `type.step`, `appearance.copyFrom`, the Character,
Paragraph, OpenType and text style panels, the Tabs panel's tab
stops, the font menus and the Justification dialog act on every
frame's text (`text.setRangeStyle {id, story: true}` styles them in
one edit).
- A caret move, a click or a word or paragraph selection ends it.
Select All in unthreaded type is unchanged.
Docs: docs/mcp.md, docs/target-app-parity.md.
Convert to Smooth or Corner on a blend whose spine came from Replace
Spine stored key anchors with the converted spine, so the spine's
points then moved onto the key centers. It now changes only the
spine's handles: the points stay where they are and the keys stay
spread along the spine. Direct Selection's spine conversion and the
other spine edits are unchanged.
Template sets Lock again even when Lock was set in the dialog before it,
so a template layer is always locked. Only a Dim Images set before
Template keeps its value.
Setting Template in the dialog (the checkbox, or ui.dialog.set of template)
also set Lock and Dim Images, replacing a value set in the dialog earlier.
That value was then sent to every selected row, and ui.dialog.set gave
different results depending on the order of its fields. A Lock or Dim Images
set in the dialog now keeps its value when Template changes.
A .ai file whose PDF part has a page for each artboard had its layers
compared with the first page only. Art that the layers drew on a later
artboard and its page didn't, or that a later page drew and the layers
didn't, opened from the layers with no warning, and a text object that a
later page doesn't draw stayed.
When the PDF part has a page for every artboard, each page is now
compared with the layers on its artboard, and the comparison fails when
any page differs by more than it allows. Text objects that a later page
doesn't draw are weighed there and left out, unless their layer doesn't
print. Art that differs on a later page is handled as on the first page:
such files now open from their PDF part with the usual warning, where
they opened from their layers before. A PDF part with pages for some of
the artboards, or with its pages cropped to the art, is still compared
on its first page only. Pages are compared until their comparison
drawings take 8,388,608 pixels (about 67 letter-size pages, or 4 when the
PDF part is only images), and at most 128 pages are compared. The type
share in the import's note is now that of the page whose type differs
most.
The layers are drawn once for the pages of the same size and cut into
each page's part. Each page moves by less than half a pixel to start on
a whole pixel, and the column or row the move takes past its artboard
isn't compared. Each page's drawing and result are kept until the layers
change, for the last two documents weighed. Taking a text object out
draws again only the pages within reach of it (every page when type
wraps).
An artboard, or the page of an EPS's editing data, whose sides are within
half a point of its page's is drawn on an area of the page's size, so
both drawings have the same number of pixels. Before, such a file could
open without its layers when the half point changed the rounded size of
its drawing, even when its layers matched the page.
Docs: docs/mcp.md, docs/target-app-parity.md.
On screen, a placed document is drawn from a bitmap made in the
background, and that bitmap was rendered with the default options. An
image inside the placed file whose pixels cannot be decoded therefore
drew nothing in the bitmap, even though the canvas marks such images
with a crossed box. The bitmap now follows the frame's
mark_undecoded_images setting, the bitmap cache keys on it, and a
bitmap standing in for one still being made has the same setting.
A font that is not installed offered the sets of the face drawn in its place; the menu now offers none. Set names the font supplies are shown as they are, without UI translation.
StylisticSet.name now holds only a name the font supplies. The OpenType panel shows a set without one as `Set {n}` through tl!, so the label is translated, and each UI catalog has a `Set {n}` row.
Capture sweep-piece source attribution before endpoint pinning can move its
midpoint off the original outlines. Keep the existing lookup after pinning
when the original piece has no source.
Add planar coverage and native compound Make/Expand/undo regressions, and
document the existing front-most source-fill rule.
In a threaded frame whose first paragraph continues from the frame
before, the text at the frame's start is not the start of a paragraph,
and the frame draws no list marker for it. Typing "* " or "1. " there
removed the characters and set a list that never showed. typed_list_at
now returns None for that paragraph.
With a group isolated, a selected layer or group that holds the isolated
group is not selectable itself, so the type inside the isolated group was
never reached and the font Same commands returned "select a text object".
The walk now goes through such a layer or group to the type inside the
isolated group that can be selected.
The new test opens the Color Picker in each working RGB profile and reads
the R, G and B fields the dialog draws. It fails when the fields show the
display sRGB values instead.
A save as .ai or .ait (file.saveCopy, file.saveAs, document.save and
file.saveAsTemplate) set range to "all" before the file was written.
The one exception was a legacy .ai of version 7 given a range, which
its encoder checks. Every other save accepted an artboard, artboards or
range that names an artboard the document does not have (artboards: [5]
on a document of three artboards) and wrote every artboard.
document.export refuses the same value.
The save now refuses such a value with the export's error, under the
name of the command that was run, and writes no file. A range that is
not text, such as range: 42, was also replaced by "all". The save now
leaves it for the encoder, which refuses it as an export does. An
artboard the document has, or an empty artboards list, is still saved
with every artboard, and a legacy .ai still writes the artboards of its
range.
Select > Same > Fill Color, Stroke Color, Fill & Stroke, Stroke Weight,
Opacity, Blending Mode, Appearance, Shape, Graphic Style and Appearance
Attribute compared the other objects with the first selected object,
even when select.set had put a hidden or locked object, one on a
template layer or one outside the isolated group first. They now take
the first selected object that the Select commands could select, in
selection order, and keep the compound path and isolation rules for it.
A selection that holds no such object returns "nothing selected".
New Action in the current set of a Shift-selected range kept the whole range
selected. After the new action was deleted, Delete Selection asked about every
set of the range. The set recorded into is now the only selected set, as it is
when Record starts a recording.
Read RGB and HSB numbers in the active working RGB space in the Color panel
and Color Picker. Keep native values through hex and web-safe controls and
cache live components by native color and color settings.
A layer that was selected (for example with select.set) gave no reference to
Select > Same > Font Family, Font Family & Style, Font Family, Style & Size,
Font Size and the text fill and stroke color commands: the layer itself is
not selectable, so the type on it was never reached and the command returned
"select a text object". A selected layer or sublayer now gives the type on it
that can be selected. A hidden, locked or template layer gives none.
Break Link to Symbol dropped the instance's opacity mask. The art now
keeps it, or a group around the art holds it when the symbol's art has
a mask of its own. The objects in the instance's mask art count against
Break Link's limit of 1,000,000 objects.
A `start` or `end` such as -1 or 1.5 was read as absent and changed text
before the range; it is now refused. Characters that already have the value
are left out, so a run that changes nothing returns count 0 and makes no
undo step. docs/mcp.md cites the public formatting-type page.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test moves from an inline module in cmd/textedit.rs to
tests/charstroke.rs and uses that file's helpers. docs/mcp.md says that
text.setRangeStyle gives a range's stroke a 1 pt weight as text.setStyle
does, and that its strokeWidth and strokeOptions lengths are in document
points.
When an effect on a layer or a group draws copies of its art, the editing
data holds the type of each copy inside the drawn look. The reader skipped
that type, so the copies came in without text objects, the page's type for
them was given to other groups by painting order, and the import noted that
a text object may be in another group than it was.
The reader now keeps such type as a text slot without a story, in the
copy's group. The page's type that lies over a copy's other art (at least
half of it in the art's box) goes to that copy's slots by painting order,
before the rest is given out. Of overlapping copies, the one that holds
more of it takes it, and the smaller one on a tie. When the page's type
outside the copies is too little for the other text objects, a copy with
more of the page's text objects than slots leaves the extra ones to them.
A slot that gets no type
is removed and not counted as a text object that couldn't be read.
Type beside a copy's art, and every copy's type in a file past the import's
text-object limits or opened with its type as outlines, goes as before. A
text object with an appearance keeps its own type as before.
The comparison of an image-only page draws at four times the comparison
scale and resizes the result to the comparison size. The two sizes round
differently along the shorter side, so a pixel is not 1/scale points
wide. A box at the far edge of a large page moved by up to 0.625/scale
points and could lie outside the object that holds it, so the import
used the PDF part instead of the layers. The boxes now use the size the
raster was drawn at.
A graph keeps the paint and stroke weight given to a series' marks, but not
the opacity of their fill or stroke row. An opacity set with
`transparency.set {item}` or `appearance.setItem {opacity}` on a column,
bar, line or other series path was lost the next time the graph was drawn
(a data, type or option change).
- `SeriesPaint` gains `fillOpacity` and `strokeOpacity`. A setItem opacity
on the topmost fill or stroke of a series path stores it, in the same
undo step, and the generator puts it on the topmost fill and stroke of
every path directly in that series' group. Graph designs keep their own
opacity. A value read from a file is held to 0..1.
- The Appearance commands that change the opacity of a series path's
topmost fill or stroke (add, remove, duplicate and move a row, Clear
Appearance, Reduce to Basic Appearance, `appearance.transfer` and the
Eyedropper) update the stored opacity. They do not change the stored
paint, which only `paint.setFill` and `paint.setStroke` set.
- An edit that leaves a series path fully opaque stores nothing for a
series the graph keeps nothing for.
With several rows highlighted, Layer Options shows the first row's
settings, and OK sent Show, Lock, Color, Template, Print, Preview and
Dim Images to layer.setProps for every row. Changing one setting gave
every row the first row's values for all of the others as well.
The dialog now records each setting set by one of its controls or by
ui.dialog.set, and for several rows OK sends only those. A setting set
to the value the dialog shows is still sent, so choosing the first row's
color gives every row that color.
When Template changes and Lock and Dim Images are not set in the dialog,
OK does not send them. layer.setProps then locks each row that becomes
a template and dims it to 50%, unless a percentage is set in the dialog,
and unlocks and stops dimming each row that stops being one. When
Template is turned on, the dialog shows that 50%. When Template is set
back to the first row's value, the dialog shows the first row's Lock,
Dim Images and percentage again. A Dim Images percentage set in the
dialog is sent whenever Dim Images is on, also when Template turned it
on.
ui.dialog.set of template now also sets locked and dimImages, as the
Template checkbox does, for one row as well as several. Before, a script
that set template to true and confirmed the dialog left the layer
unlocked and undimmed.
The Dim Images percentage field now has the accessible name "Dim Images
to:", as its checkbox has.
Window › Toolbars › Manage Toolbars… and Manage Toolbars… in the All Tools
drawer's menu open a dialog that lists the toolbars made with New Toolbar.
A name typed for the selected toolbar renames it, + copies the selected
toolbar or, with none selected, makes a new one, and the trash can deletes
it (https://helpx.adobe.com/illustrator/using/tools.html, Manage toolbars).
VectorCraft's own details:
- A rename applies at Enter, when the text box loses focus, or at OK. The
name follows New Toolbar's rules: not empty, at most 200 characters, and
not another toolbar's in any case.
- A copy is called "<name> Copy" (then "<name> Copy 2"), shows a little
below the toolbar it copies and below earlier copies; a new toolbar is
called "Toolbar N".
- Each change applies at once; deleting also removes the groups torn off
the toolbar.
- When the typed name is refused, a click on +, the trash can or another
toolbar is not applied, so the name can be corrected. When the selected
toolbar is deleted elsewhere while the dialog is open, none is selected.
- Renaming or deleting a toolbar closes the All Tools drawer and a group's
flyout open on it; a change of case only leaves them open, and the Tools
panel's flyouts and other toolbars' stay open.
- Each change shows under Window › Toolbars and is kept with the workspace.
New commands: window.toolbar.manage, window.toolbar.rename,
window.toolbar.duplicate and window.toolbar.delete, with catalog rows for
their labels in every language.
Docs: control-protocol.md, gaps.md, target-app-parity.md, ui-parity.md.
Part of #1759
When the layers fail the comparison with the file's own page because some objects draw
differently (an object in another color, or one that only one side draws), the import finds
each top-level object whose bounds hold a patch of such pixels (the smallest one that holds it)
and replaces it with the page's art in its bounds, in the same way as an unread object. It then
compares the layers with the page again. When that comparison passes, the layers stay, and a
warning names the layer or sublayer of each replaced object (`<Layer>` for one without a name)
and how many were replaced on it. Like the warning for unread objects, this warning counts as
a loss, so an export or Save As to the file's own path needs `acknowledgeLoss: true`. A
replaced wrap object keeps its wrap options, and area type is wrapped again around the page's
art. Placed files at their other placement are tried too when the first placement can't be
kept.
The file still comes in as its PDF part, with the same reason, when only edges or type differ,
when a difference lies outside every top-level object, when more than half of the top-level
objects (or more than 64) hold one, when such an object is or holds type or holds a wrap object
inside a group, when the page's type of a text object that stays would be copied into a
replacement, when the page's art can't replace an object for the reasons it can't replace an
unread one, when matching the differences to the objects would take too much work, or when the
second comparison still fails. Trusting the editing data keeps the objects as read.
The task bar offered no Type on a Path item for a selected type on a
path: of the type actions, it showed only Create Outlines. It now also
offers Type on a Path Options, which opens the same dialog as Type ›
Type on a Path › Type on a Path Options, with the selected type's
effect, alignment and spacing filled in. Point and area type keep
their Convert To Area Type and Convert To Point Type buttons.