Font Details, Linked Images and Embedded Images, and the Objects counts
Compound Paths, Text Objects, Placed Documents, Symbol Instances, Gradient
Meshes, Blends, Envelopes, Intertwine Groups, Opacity Masks and Objects
with Effects had no catalog rows, so the panel and its category menu
showed them in English in every other language. Each complete catalog
now has them, and the Document rows Pattern Swatches (de, it, ja, ko,
pl, uk, vi, zh-hant) and Path Length (bg, el) are added where missing.
The catalog test now checks every category title, every Objects count
label and Document's fixed row labels. document.info and the saved
report keep the English labels.
The Live Paint Bucket drew the crosshair in place of its own cursor. It
now shows what a click paints: a filled paint bucket over a face it
fills (of a Live Paint group, or a region of the selected paths), a
brush over an edge it paints, and an empty bucket where it paints
nothing. The cursor follows Paint Fills, Paint Strokes and Shift, and
shows with Highlight off too. Alt still shows the Eyedropper, and Use
Precise Cursors shows the crosshair.
With a Live Paint group and ordinary paths selected, a region of the
paths outside the group is now highlighted, as a click there fills it.
The help page: https://helpx.adobe.com/illustrator/desktop/paint-and-fill/learn-painting-basics/paint-with-the-live-paint-bucket-tool.html
paint.setFill, paint.setStroke, paint.none, Apply Fill to Stroke, Apply
Stroke to Fill and a library gradient or pattern applied with library.use
stored the topmost fill or stroke row of a graph series mark on the graph
even when that row was hidden, and stored a stroke set on a Filled Lines
band. When the graph was drawn again, every mark of the series took a
paint that the edited mark never showed, and a band took the stroke color
as its fill.
These commands now follow the rules of the Appearance commands:
- The graph stores the paint only when the row the command wrote is the
topmost visible row of its kind, or when the command changed what the
mark shows. With `item`, that is the named row.
- A series that draws Filled Lines bands stores no stroke paint or
weight; the band keeps its own outline.
- A row without paint before and after the command keeps what the graph
stores, so None on a marker without a stroke no longer removes the
line's stored stroke.
- When one command writes several marks of a series, the frontmost mark
sets what the graph stores, whatever the order of the ids.
- Apply Fill to Stroke and Apply Stroke to Fill on a mark whose row
already has the paint store it, as paint.setFill does.
A document without graph series marks among the edited objects skips the
comparison of paints.
Docs: docs/mcp.md and the params text of the paint commands.
$.line and $.stack counted lines in the run's expanded source. In code
that comes after an #include they gave lines that match no file, and
this included code in a file $.evalFile ran and code a named engine
kept from an earlier run.
Both now map each frame through the run's source maps, as uncaught
errors already were. $.stack writes each frame as name@file:line,
outermost first, with the run's name as the file of a script given as
source. Code that eval or Function compiled keeps the line of the
source they compiled, in [eval]; code whose place a named engine no
longer keeps is at line 0 of [unknown]. The 64-frame limit, [global]
and [anonymous] are unchanged.
Docs: docs/mcp.md, docs/target-app-parity.md.
$.fileName gave the file being run, so a function defined in a file
that #include inserted, in a file $.evalFile ran, or in an earlier run
of a named engine reported the calling file instead of its own.
- vectorcraft_js: HostItem::SiteGetter gives a getter the CallSite
(source tag, line, column) of the code that reads it.
- $.fileName maps that place through the run's source maps, or the
maps a named engine kept, to the file the code is in. It is empty in
code from a script given as source and in kept code whose map was
dropped. Code that eval or Function compiled still gets the file
being run.
Docs: docs/mcp.md, docs/target-app-parity.md.
A blend made with Create Spine set to Never now shows the Appearance
widget with the Selection and Blend tools, so its color Shift can be
dragged on the canvas as on a blend with a spine. The Easing widget
stays hidden, since easing needs a spine.
The widget sits 16 px above the halfway point, by length, of the
straight lines between the key centers that the steps are laid out
along, and a drag follows those lines' direction there. The lines are
not drawn. `blend_layout_line` exposes that line; `blend_spine` still
returns `None` for such a blend.
The eye and lock on a guide's row in the Layers panel hide or lock that
guide alone, in one undo step, and a drag down either column takes guide
rows along with the other rows it passes. A hidden guide is not drawn and
does not snap, and its row is dimmed; a locked guide is drawn and snaps
but can't be selected, moved or deleted. Both can be changed while the
guide's layer is hidden or locked, and the guide shows or can be edited
only when its layer allows it as well. The state is kept through save
and reopen.
- layer.setProps takes ruler guide node ids; every other command still
refuses them.
- guide.list rows carry the guide's node id and its own hidden and
locked state.
- Alt-click and Ctrl/Cmd+Alt-click on a guide row's eye or lock act on
the other layers, as on any row in that layer.
- Object > Lock > Selection and Object > Hide > Selection lock or hide the
selected ruler guides with the selected art, in one undo step, outside
isolation mode. Unlock All and Show All, document scope, also unlock or
show guides locked or hidden on their own and select them as guides.
- Guide rows dropped on the Layers panel's trash delete their guides
(guide.remove {indexes}). A click on a guide row clears the highlighted
rows, so Delete deletes the guide; with no row highlighted the trash
deletes the selected guides.
- guide.remove and guide.setLayer refuse index together with indexes and
an indexes value that is not a list, and count a repeated index once.
guide.select, guide.remove and guide.setLayer refuse an indexes list of
more than 10,000 entries; guide.setLayer cut such a list short before.
- Moving, deleting or moving to another layer a guide that is hidden or
locked on its own fails with "the guide is hidden or locked"; a guide
on a hidden or locked layer still fails with "the guide is on a hidden
or locked layer".
Docs: docs/mcp.md, docs/target-app-parity.md, docs/ui-parity.md.
The sweep filtered by transparency kept every open box in one tree, so
a box without transparency met every open box without transparency it
overlapped, though such pairs never join. Both sweeps closed an open
box early only when a later box held it, so in a nest of boxes that
share their left and top edges and get smaller to the right and
bottom, each box met every earlier box around it. One see-through
object inside 512 nested opaque objects took 130,817 meets in the
unfiltered sweep and 131,328 in the filtered one.
The filtered sweep now keeps open see-through boxes and open opaque
boxes in separate trees. An opaque box looks only in the see-through
tree; a see-through box looks in both.
In both sweeps, a box inside an open box it met, ending no further
right, is not opened when that box joins everything it overlaps (any
box without the filter, a see-through box with it). Whatever later
overlaps the inner box overlaps the outer one.
The nest above now takes 512 meets in each sweep, and a nest of 512
boxes alone takes 511 in the unfiltered sweep where it took 130,816.
The groups are unchanged.
A Fit to Artwork Bounds step of `command.batch` that names neither
`index` nor `indices` now fits the artboards the Artboard tool has
selected when the step runs (two or more), as the command does when the
app runs it on its own. Before, the step took the batch's `artboard` as
its `index`, so an action played from the Actions panel fitted only the
active artboard while several were selected.
- A step's own `index` or `indices` is kept, and the batch no longer adds
an unused `index` to a step that names `indices`.
- The batch's journal entry records the `indices` the step took, so a
replay fits the same artboards. An action leaves them out and fits the
artboards selected when it plays.
Docs: command.batch params text, docs/mcp.md, docs/target-app-parity.md.
- With art, the bar is 10 pt tall and the Edit tab leaves out the gaps
above the wheel and above the sliders. The dialog is as tall on the
Edit tab as on the Assign tab, and all of it but the color chips fits
a 1024 by 576 screen.
- recolor.weigh counts a use for the first row that is not excluded
when an excluded row lists the same color first.
A paragraph format given to the empty paragraph after a frame's last
paragraph break was lost when the story flowed again: the paragraph is
shared with the next frame's first paragraph, and the next frame's old
style replaced it, in that frame and in the frames after it.
- The thread reflow also notes which frames' last paragraph changed
style, and story_paras_restyled keeps that style against the next
frame's unedited first paragraph, across unedited empty frames too.
When the same edit formats the next frame's first paragraph, that
format applies, as before.
- story_paras keeps its behavior for its other callers.
- Tests cover area type and type on a path on either side, a next frame
holding text, three frames, undo and redo, a format that changes
nothing, and numbered list counts.
plugin.install wrote the module and its grant to the Plug-ins folder,
attached the plug-in's settings and cache and turned a disabled plug-in
on before the registry's last approval check. When another session
revoked the grant, or recorded one for other bytes, after the command
recorded its own grant and before that check, the install was refused
but left the new module and grant in the folder for the next launch.
A plug-in another session installed under the same id between the
command's checks and the install took no part in the decision, so the
install replaced it without `replace: true`.
- registry::install_checked records the grant (or forgets it) and
installs the plug-in as one step, after a caller check that sees the
plug-in installed under the id and its grant; a refusal changes
nothing.
- plugin.install commits through it before any store write, refusing
with the existing messages when another plug-in now needs `replace`
or the grant its approval came from changed. The store writes, the
put-back on a failed write and the disabled-list update now run after
the commit; their logic is unchanged.
- The grant call-site audit also counts registry::install_checked.
Docs: docs/plugins.md, docs/target-app-parity.md.
A stroke weight set with stroke.set or stroke.weightUp/weightDown, a
gradient made, placed or edited with paint.editGradient,
paint.setGradientGeom or the freeform gradient edits, and colors changed
by paint.invert, paint.complement, the Edit Colors recolor and Blend
commands, recolor.apply, addon.color.filter,
addon.color.applyNearestSwatch or the ink limit of
addon.color.printFixes changed a series mark but not the paint the graph
stores, so the mark went back to the old paint when the graph was drawn
again.
appearance::edit_items now stores what its edit changes on the topmost
visible fill and stroke of series marks, as the Appearance commands do,
and the recolor pass does the same for the series marks it reaches,
including those inside a series group or a graph it is given. When one
command changes several marks of a series, the frontmost one sets the
stored paint. A gradient is stored with its placement.
These commands do not store the colors they give a graph's axes and
labels. docs/mcp.md, the params text and the Graphs line in
docs/target-app-parity.md say what is stored.
The Materials tab and threeD.mapGraphic now map graphics onto
Revolve's swept side, unrolled flat: x runs around the axis (the
angle times the profile's distance from the axis at that point) and
y along the profile. A graphic keeps its size at every distance from
the axis, so it reaches farther around where the profile comes nearer
the axis. Each face of the side draws the part that falls on it: a
graphic narrows toward the silhouette, follows the profile along its
length, is shaded with the surface (several lights included) and is
hidden where the side faces away. A part that runs past the end of
the profile reaches the curved rim and stops there. The middle of the
side faces the viewer with the axis on either edge. On a compound
profile or a group the graphics go on the longest contour.
- three-d: with Revolve::map_surface set, side faces carry a
SurfaceCell (corners on the page and on the unrolled side, whether
the outside faces the viewer) and a closed profile off the axis
takes an anchor where its side is cut; without it the faces are as
before. revolve_surface_size gives the side's size for a new
graphic's fit.
- effects: Revolve takes `graphics` (front only); surface_parts cuts
and maps them per face; curves are cut into straight pieces one at
a time, and commands refuse graphics past the point limits;
switching between Extrude, Plane and Revolve keeps the front's
graphics.
- The Materials tab hides Face for Revolve; params text, docs/mcp.md,
docs/three-d.md and the progress docs describe the change.
- i18n: the complete-message catalogs translate the three new
refusals in place of the planar-faces refusal they replace, and ja,
es, zh-hans and zh-hant translate the Materials tab's label.
- recolor.weigh drops another row's entry for a color that moved, so
recolor.apply recolors it with the row it moved to and the shares
describe the recolor. A color that the first color of another row
with a new color also lists stays where it is.
- Linked swatch colors are grouped through a map, so a row with many
unlinked colors no longer compares each one with every group.
- The Prominent Colors bar reads the shares again when a row gains or
loses a new color, since that changes which row takes a shared color.
A whole pick from a source with no fill row, or no stroke row, removes
that row from the target. When the target is a graph series mark whose
row had paint, the pick now replaces the row opacity and blend mode the
graph keeps for that kind of row in the series. A row that had no paint
before the pick still leaves the kept values as they are, and a pick of
some attributes from such a source is unchanged.
Part of #2224.
A Smooth tool drag only refitted the anchors in its reach within
Fidelity, so a wobble wider than Fidelity stayed, and a second drag over
the same place changed nothing. Repeated refits also drifted away from
the path, and a drag over a whole closed path left a corner at its first
anchor.
- path.smoothRegion now smooths the stretch in reach along its length
with a Gaussian whose spread is a third of the reach, then refits it
within Fidelity. The run's outer end points and handles stay fixed.
- Each refit stays within twice the distance the smoothing moved the
path (at least a tenth of Fidelity), so repeated drags do not drift
(SimplifyOptions::smooth_moved_only).
- A whole closed path is smoothed across its start as a loop, so a
bump at the first anchor is smoothed like any other and no corner is
left. Object > Path > Smooth smooths a closed path across its start
the same way.
When a painted live effect on a fill or stroke returned several fills or
strokes, the next effect in that stack ran only on the first of them and
the others took its geometry. A later live-effect plug-in, and a later
geometry effect on strokes, now runs once on each of them in paint order,
given the piece's fills and strokes and its own `_context.item`. Each
run's pieces replace only that fill or stroke; a run that fails, is
refused, is deferred or would pass the effects' budget leaves only its own
fill or stroke as it was. Fills and strokes that keep the same path stay
on one path, and a deferred run is listed at the source fill's or
stroke's place.
The results that are kept share the effects' budget, and each run's
result is kept or left out whole. They are first placed with all the
room the art leaves, and placed again with room kept for the piece's path
when a fill or stroke left on that path finds no room. A result on the
path before it costs nothing and is taken whatever room is left; a
built-in effect that finds no room is built again with all the room the
art leaves, and that result is taken only when it is on the path before
it. A plug-in result is held only while it is placed: one that does not
fit, or that moves onto the path before it, is let go at once, so the
results held at one time stay within the budget however many fills and
strokes the piece has. A result kept in the first placing is reused in
the second without running the plug-in again. A painted piece's share of
the budget is counted once at each later effect.
A group's or layer's geometry effects now run after its members' own:
the geometry effects of each visible path and compound path in it and
of their fills and strokes, and a nested group's geometry and
Pathfinder effects, are applied first, at any depth, and the group's
effects reshape the result. A symbol instance's geometry effects run
after those of its symbol's members in the same way. Before, the group
reshaped the members' outlines and their own effects ran afterwards:
a 100 pt square with its own 10 pt Offset Path in a group with a 50%
Transform drew 70 pt wide, and it now draws 60 pt wide. Existing
documents with such groups draw differently.
The canvas, export (including groups that keep their type), Expand
Appearance and the art that Pathfinder operations and compound shapes
take from such a group use the same order. The reply of
effect.expandAppearance names such a group and no longer names the
members whose effects the group's art already holds.
The renderer now drops the art it keeps for a group when a plug-in is
installed or removed and a member of the group has a plug-in effect.
Docs: docs/target-app-parity.md. Not yet: the own geometry effects of
images, symbol instances, paths with a linked opacity mask or a 3D
effect, and nested groups with a 3D effect in a group still run after
the group's.
With Real-time Drawing off, a command that ends a drag first (Undo, Redo,
Clear History, a plug-in command and the others) applies the drag's
deferred preview, but dropped the warning that preview gave, which
releasing the drag shows in the status bar.
- The applied preview's warning is now kept while a top-level command or
the tool's actions run. A command's result carries it as
`previewWarning`, and as `warning` when the command has no warning of
its own, so the status bar shows it.
- Typing kept as its own step when a tool's drag begins, or when Cmd
lends the Selection tool, shows the warning in the status bar.
- The Cmd-lend path no longer ignores an error from keeping the typing.
Docs: docs/mcp.md (undo/redo row), docs/target-app-parity.md.
The Pencil and the Paintbrush send their Fidelity in points at the
current zoom, but path.freehand read at most 100 pt. At 3.13% zoom a
20 px Fidelity (639 pt) was fitted at 100 pt, the same as 3.13 px on
screen, so a stroke drawn zoomed out kept far more anchors than the
same stroke at 100%.
- path.freehand, and brush.freehand, which runs it, take a Fidelity
from MIN_FIT_TOLERANCE to MAX_FIT_TOLERANCE (100 / 0.0313 pt, the
100 px field maximum at the lowest zoom). A value outside that range
is now rejected with an error instead of being read as the nearer
end. The default stays 1.5 pt and path.blob keeps its 100 pt bound.
- The Pencil and the Paintbrush keep the value they send within that
range, so a stroke draws at any zoom.
- An extending stroke still closes the path within four Fidelities of
its other end, at most 400 pt, as before.
It conflicts with open #7089 in crates/tools/src/draw2.rs.
Docs: docs/mcp.md, docs/target-app-parity.md, path.freehand params.
An Eyedropper pick that includes transparency now counts a fill or stroke
row that had paint before the pick and has none after it when it stores
the series' row opacity and blend mode on the graph, as graphic styles
already do. Before, such a pick left the opacity and blend mode another
mark of the series had stored, and the series was drawn with them again
after its data changed. A row that had no paint before the pick still
leaves the stored values as they are.
A top-object envelope gives each piece of a side a share of the content
in proportion to its control polygon's length. When anchors split a
curve without changing its shape, the pieces' polygons don't divide the
side where the curve's own parameter does, so the envelope bent its
contents differently although its outline was the same: Add Anchor
Points on a top object moved the art, and a top object whose .ai mesh
saves each side's curve split into thirds drew its type up to about
half a point off its drawn art, which follows the whole curve's
parameter.
Coons::from_top_object now checks whether a side's pieces, from corner
to corner, are all pieces of one cubic. The pieces' spans of that
curve's parameter come from the handle lengths either side of each
split, the curve from the outer ends and handles, and every piece must
lie within 0.02 pt of the curve's piece over its span (each control
point). Such a side runs along that curve, by its parameter. Any other
side keeps the polygon shares, including a side only partly made of one
curve and a smooth side drawn in many pieces that isn't one curve as a
whole. Corners found from the outline can still move when anchors are
added, as before. Gradient meshes made from a path are unchanged.
Existing top-object envelopes with such sides redraw.
a_split_curve_moves_the_top_object_share_to_its_new_anchor, which
pinned the earlier behaviour, becomes a_split_curve_keeps_the_top_object_patch.
Tests: a_split_curve_keeps_the_top_object_patch,
a_top_object_joins_a_split_curve_saved_with_rounded_coordinates,
a_top_object_keeps_smoothly_joined_curves_apart,
a_top_object_side_partly_of_one_curve_keeps_the_polygon_shares and
a_top_object_side_of_many_arcs_stays_on_them (vectorcraft-doc),
envelope_top_object_keeps_its_look_when_anchors_are_added
(vectorcraft-engine) and
a_top_object_whose_top_is_one_curve_split_in_thirds_opens_live
(vectorcraft-eps).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
A right-click on a character style in the Libraries panel now opens Apply
Character Style, Add to Character Styles, Move to Group, Rename… and
Delete. Apply is enabled only with type selected. Opening the menu applies
nothing, and the paragraph style menu is unchanged.
- library.addToCharacterStyles adds the style to the document's character
styles without applying it, so no type needs to be selected. A document
style with the same name and attributes is reused with no undo step, and
a name taken by other attributes gets a number.
- library.renameItem renames a library item in place and keeps its group.
The name is trimmed and has 1 to 256 characters. Another item of the same
kind with that name is an error, the item's own name writes nothing, and
a rename is not a document undo step.
- library.use and library.addToCharacterStyles compare a library style
with the document's in the form the document stores it in. A whole
number size from a library file no longer adds a numbered copy.
- A character style color linked to a swatch that is not a global or spot
swatch of the document keeps the color it shows without the link.
Before, adding or applying such a style failed with "no swatch".
Help page: https://helpx.adobe.com/illustrator/desktop/design-with-text/fonts-and-scripts/add-and-use-text-and-character-styles-in-libraries.html
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.
path.smoothRegion replaced the anchors of each path it smoothed but left
the selection alone, so anchor and segment refs selected with Direct
Selection still named the old indices: after a smooth that removed
anchors, a ref could point past the end of the path or at another
anchor. The edit now drops those refs for each path it changes, so the
path stays selected whole. Selected paths the drag does not change keep
their anchors, and undo restores the earlier selection.
Simplify, Object > Path > Smooth, the Smooth tool and freehand strokes
turned every refitted curve whose handles lay near its chord into a
straight line. A short curve whose end directions were off the chord
passed that test, and the anchor between it and the next curve became a
corner the path did not have: a Smooth tool drag along a line jagged by
up to 6 pt left corners of 7.7 to 40.6 degrees.
A curve now becomes a line only when the line runs within 0.5 degrees
of the directions the path arrives and leaves along. A nearly straight
piece that would turn more stays a flat curve. Convert to Straight Lines
is unchanged.
The fuzz case counted objects that match the look style C applies, so a
C read with no paint also passed. It now also checks that C's look has
no fill and one red 2 pt stroke.
Symbol and pattern art copied in by a placement takes ids of the
document's own, so the next placement of the same file compared it with
the file's art, found the ids different and added Star 2, Dots 2 and so
on. Definitions are now compared by what their art draws, whatever its
ids. A symbol, pattern or brush whose art uses an image, symbol, pattern,
brush or swatch that comes in under another name is copied under a free
name instead of shared.
With art selected, the Edit tab shows a Prominent Colors bar under the
wheel: a part for each row in its new color, as wide as the row's share
of the art, the largest first. Dragging the edge between two parts moves
width from one to the other; when the drag ends, the rows' current
colors move toward the new widths and the art previews the result. OK
keeps the recolor as one undo step.
- recolor.weigh {map, weights?, ids?} returns each row's share of the
uses of the art's colors and, with weights, the rows with their
current colors moved: one color at a time between rows that have a
new color, while a move brings the shares nearer the weights, the
color nearest in Lab to the row it goes to first. A row keeps its
first color, the tints of one global swatch move together, colors
that stay keep their order, and the command changes nothing. A use
counts for the row recolor.apply recolors it with, and the work is
bounded at 50,000,000 color-by-row comparisons.
- The New Color Group menu beside the link button has Save All Colors
(the new colors in row order) and Save Prominent Colors (the bar's
colors in its order); each saves a color group as its own undo step.
- The dialog's weights field drives the bar from ui.dialog.set. A new
Colors count drops it.
object.mesh.movePoint and object.envelope.setMeshPoint compare a handle
end with point plus handle, the form the caller sends, so a rounding
difference in (p + v) - p no longer turns an unchanged warp into a mesh
envelope with an undo step.