With Document Swatches as the library, traced fills and strokes take the
library color without a swatch link. Global, spot and tint swatches no
longer link the trace, so editing a swatch later leaves the trace
unchanged, and swatch order no longer decides whether a fill is linked.
Each region still takes the nearest library color, and a tint traces at
the color the tint swatch shows.
The Tabs panel's ruler shows an upper marker at the first line's position
(left indent plus first-line indent) and a lower marker at the left
indent. Dragging the upper marker sets the first-line indent. Dragging the
lower marker sets the left indent and keeps each paragraph's first line
where it was; Ctrl-dragging it (Command on macOS) moves both markers.
Marker drags land on whole points, or on ruler ticks with Snap to Unit or
Shift, and each release is one undo step through text.setFormat. With a
marker selected, the X (or Y) field shows and sets its position.
When the touched paragraphs have different left indents, only the upper
marker is shown, and its position applies to every touched paragraph.
Path Precision Tools gains the Shared Edge Merge Tool, kept out of the
toolbars (All Tools drawer and Object › Plug-ins › Path Precision Tools,
no shortcut), and Keep Shared Points Together:
- Shared Edge Merge Tool (sharedEdge): over two paths touching at two
coincident anchors (tolerance 0 to 3 pt) hovering shows the two
stretches and the merged edge; a click replaces both with it, half way
between them, or following the upper (Shift) or lower (Alt) path. Both
paths stay closed or open, anchors either stretch has inside are
matched on the other, one undo step.
- Making ends: near anchors meet on a click and an anchor one path lacks
is added to match; Shift+Alt asks for this inside a stretch.
- Keep Shared Points Together: an option that makes Slide Anchor Along
Path, Extend Path and Set Anchor take coincident anchors along. Nothing
else in the app changes.
- Shared Edges section in the Anchor Inspector: brush diameter,
coincidence and the option.
- Commands addon.pathtools.mergeEdge and movePointsTogether, params
validated and covered by the command sweep.
- Cursor stand-in, catalog rows in every language, docs and tests.
With the Live Paint Bucket, Alt-click on vector art samples its fill,
stroke and stroke weight into the paint defaults, and on a placed image
it samples the pixel as a solid fill with no stroke. Alt+Shift-click
samples only the color under the pointer, including an intermediate
gradient color or image pixels, into the active fill or stroke. Neither
click paints or changes the selection or selected art, and the next
Bucket click paints with the sampled paint. While Alt is held, the
Bucket shows the Eyedropper cursor and no face or edge highlight.
appearance.copyFrom takes `defaultsOnly: true` to update only the paint
defaults, and paint.sampleColor takes `clearStroke: true` to clear the
stroke default after an image sample into the fill.
A knockout element with one opaque Normal solid fill (a path or
compound, no mask, effects or isolation) is drawn once under
AntiAlias::None, including the internal hard-edge frame of Art
Optimized supersampled exports, instead of being erased and added back
through per-element backdrop layers. Analytical antialiasing keeps the
existing compositor and rounding.
Exact-pixel tests compare against the general knockout path for paths
and compound holes across precision, supersampling, translucent parents
and copied backdrops, and check that the backdrop rasters are skipped;
translucent fills keep their knockout compositing.
# Conflicts:
# docs/roadmap.md
# docs/target-app-parity.md
With a path selected that the Smooth tool can change, Alt held at a
Paintbrush press now switches the drag to the Smooth tool: it smooths the
selected paths under the drag with the Smooth tool's radius and Smooth Tool
Options' Fidelity, and the cursor shows the Smooth tool before the press.
Alt pressed after a stroke begins still closes the path on release. With no
such path selected (nothing, only text or an image, or only a two-point
line), Alt at the press draws the closed stroke as before.
The Paintbrush no longer reads the Pencil's "Alt key toggles to Smooth Tool"
setting: its Alt close and Alt smoothing do not depend on it.
The import read each form's /Group /I and /K from the file in order and
matched them to the transparency groups the interpreter pushed. The
interpreter draws a group that adds nothing (full opacity, Normal, no
mask, neither flag) straight onto its parent without pushing it, so every
group after one took another group's flags. Blend steps written as a
knockout group of falling opacity then painted over each other and drew
as solid dark shapes instead of light rings.
The interpreter already reports the flags right after pushing a group
(set_knockout, set_isolated); the import now uses those and drops the
file-order list. That list was capped at 10,000 entries, past which a page
failed to import; that limit goes with it.
#4757 gives a blend the Xy written after its record. When the blend is a
layer's last object, the layer's own state block (Xy, Xd, 7 () XW, LB)
went to the blend instead, and the layer stayed opaque. The blend's state
is now tentative like a mesh's (#4748): its own 6 () XW confirms it, the
layer's LB gives it to the layer and the blend keeps what it had.
Also records the .ai/EPS audit fixes under G9, the File formats row and M4.
A PDF saved with Illustrator editing data for only some of its artboards
has pages for those artboards, while the editing data keeps them all. The
layers were compared with the first page on the first artboard, so a page
showing a later artboard never matched and the file came in as its PDF
part, without its layers.
With fewer pages than artboards, the first page is now taken to be the
artboard of its size whose art draws most like it (up to 16 weighed), and
the pages' type goes to that artboard and the ones after it. All the
artboards still come in, and the comparison still decides whether the
layers are used.
A gradient mesh with an opacity mask has its own state (`Xy`) after the
mask's dictionary, not right after its `/End X!`. The operators of the
mask's art, on `%_` lines, cleared the flag that says a mesh just ended,
so the state was read as the next object's and each masked mesh in a
run drew with the blend mode of the one before it.
The flag now goes back to what it was when a dictionary opened once it
closes, as `after_object` does.
Path Precision Tools gains two tools, kept out of the toolbars (All Tools
drawer and Object › Plug-ins › Path Precision Tools, no shortcuts):
- Corner Tool (cornerTool): editable corners on any path through the
existing Live Corners. Hover shows an eligible anchor, a click cuts a
corner with the tool's radius and kind, a drag sizes it (Shift: whole
values), a corner's marker selects it and loads its values, resizes it
and removes it at 0 or on a double-click; a corner never grows past
what fits; an Alt-marquee cuts every eligible anchor inside.
- Corners section in the Anchor Inspector: radius, kind, selected count,
Apply to Selected Anchors.
- Slide Anchor Along Path (slideAnchor): a drag runs an anchor along its
curve, the neighbouring segments refitted by the keep-shape kernel;
Shift snaps where the tangent is a multiple of 45° from the constrain
angle.
- Commands addon.pathtools.cornerSet, cornerRemove and slideAnchor, one
undo step each, params validated and covered by the command sweep.
- Cursor stand-ins, catalog rows in every language, docs and tests.
A layer's own state block (Xy, Xd, 7 () XW before LB) can have the
stroke style (J j w M d XR) between its Xy and Xd. Read as the art moving
on, it dropped the layer's opacity, so a layer at 17% drew opaque and the
file came in as its page. The stroke style now keeps the pending layer
state, and the state a mesh before it had; an object's own 6 () XW block
still isn't the layer's.
Holding backquote while dragging with the Selection tool (move, bounding-box
scale or rotate) or the Rotate, Reflect, Scale or Shear tool applies the drag
to the selected objects' pattern fills and strokes and leaves their geometry
in place. The key state at release decides the result: the key may be pressed
after the mouse button goes down, and releasing it before the button comes up
commits an ordinary transform. Objects without pattern paint do not move.
PointerEvent gains a `backquote` flag (false when absent). The desktop canvas
reads it from the held key on every pointer event, and `ui.pointer` and the
`pointer_gesture` tool accept it per event or as a default for the gesture.
Apply Last Color keeps `,` and also gets `Shift+,` as a default key;
Apply Last Gradient keeps `.` and also gets `Shift+.`. The keymap
catalog takes the extra defaults from a small alias table, the
Keyboard Shortcuts dialog lists every default key of a row, and reset
restores both.
A shifted punctuation chord that the active keymap binds now runs from
its key press, once per press, so a user binding such as `Shift+;`
works and layouts where Shift+Period types another character still run
the bound command. Text editing still types the characters.
The toolbar tips read "Color (, or <)" and "Gradient (. or >)", with
rows in every catalog.
object.lock.unselected is now reached by its key and as a command only:
the Object > Lock > Unselected Artwork menu item is removed, and the
command stays in the registry, the shortcut editor and automation.
In a partly selected clip group or compound path it now locks the
unselected members, the clipping path included, and leaves the container
and the selected members unlocked. It locks unselected guides while Lock
Guides is on. Hidden art and art on a locked layer stay unlocked, and a
selected layer's art counts as selected.
With a selection in isolation mode the command is enabled and locks only
the unselected art inside the isolated group. The other Lock and Hide
items keep their isolation behavior.
Lock and Hide still share one selector. A lock flag on it selects the
clip group, compound path and guide cases above; Hide > Unselected
Artwork keeps its behavior, and a test covers both directions.
Docs: docs/mcp.md, docs/target-app-parity.md.
The reference app locks all deselected artwork on Cmd/Ctrl+Alt+Shift+2.
VectorCraft had no command for it: Object > Lock held Selection, All
Artwork Above and Other Layers.
The new command, object.lock.unselected (Object > Lock > Unselected
Artwork), locks in one undo step the objects that Hide > Unselected
Artwork hides: every object that Select All takes and that is neither
selected nor holds a selected object. It returns the count. Hidden
objects stay unlocked. The selection stays as it is, Unlock All unlocks
the objects again and selects them, and with nothing to lock the
command records no undo step. Both commands now share one function,
which locks or hides the objects that the existing unselected helper
returns.
In isolation mode the menu item is disabled, and the command returns
the error "not available in isolation mode" that Hide > Unselected
Artwork returns there, and changes nothing.
Docs: docs/mcp.md, docs/target-app-parity.md.
Adds the evidence and revision rows that target-app-parity.md and
roadmap.md expect for the .ai/EPS import changes of 2026-10-30 (#4708,
#4664, #4723, #4742, #4658, #4727, #4738, #4744, #4748, #4743). Scores
and estimates unchanged.
An EPS saved for Illustrator 10 keeps its type in the editing data as
legacy text objects (`To` ... `TO`), with no `/AI11Text` slot for the
page's type to go in, so a file whose page had text came in as its page.
Those text objects are now the layers' own: the page's type isn't put
anywhere, and the comparison with the page decides as before. Type the
editing data keeps only as outlines stays outlines, with a note counting
the page's text objects that are.
When Brushes, Color, Layers, Info, Gradient, Stroke, Attributes, Graphic
Styles, Appearance, Align, Transform, Pathfinder, Transparency or
Symbols is in front of an expanded dock group or a floating group, its
function key now hides the whole group instead of closing only that
tab. The next press brings the group back in the same place with every
tab and the panel in front, and Window > a hidden sibling also restores
the group. A background tab still comes to the front on the first
press, and in an icon column the key opens and closes the flyout.
Other panel shortcuts and plain window.panel calls keep their behavior.
The function key shortcuts for Brushes, Color, Layers, Info, Gradient,
Stroke, Attributes, Graphic Styles, Appearance, Align, Transform,
Pathfinder, Transparency and Symbols now run window.panel with
toggle: true, as the Window menu items do. A second press hides an
active panel in the expanded dock, and the next press restores it in
its group. A chord the user assigns to one of these panels toggles the
same way. Plain window.panel calls still only show the panel.
In Full Screen Mode and Full Screen Mode with Menu Bar, an Escape that
leaves a focused text field, cancels a ruler-origin drag or cancels a
floating Tools panel move no longer also returns to Normal Screen Mode;
the next Escape does. Tests cover a dialog, a focused field, a tool that
claims Escape, pattern edit, Global Edit, a tool flyout and the rotation
reset pair in both modes.
In Full Screen Mode and Full Screen Mode with Menu Bar, an unmodified
Escape that nothing earlier in the Escape chain takes (a popup, dialog,
field, drawer, tool gesture, edit mode, flyout or the view rotation
reset) runs view.screenMode with mode 0. Presentation Mode and the F
cycle are unchanged.
In vertical type, Alt+Down/Up (with or without Shift) steps kerning at a
caret or tracking of selected text, Alt+Left/Right steps leading, and
Alt+Shift+Right/Left steps baseline shift; Cmd/Ctrl makes five steps.
Horizontal type keeps its mapping. Selected type objects follow the same
rule when all of them are vertical, and a selection that mixes horizontal
and vertical type takes the horizontal mapping in one undo step.
An Xy right after a gradient mesh's /End X! is the mesh's only when the
mesh's own 6 () XW follows. When the layer's LB follows (directly or
after the layer's Xd and 7 () XW) it is the layer's, as before, and the
mesh keeps the state it had. Also corrects the revision-history row that
still said meshes with handle weights of 0 aren't read.
Highlight Alternate Glyphs compares each glyph with required shaping
alone, which turns liga and calt off. Older Arabic fonts (such as the
legacy Arial of the Microsoft core fonts) put the mandatory lam-alef
ligature in liga instead of rlig, so every lam-alef was highlighted.
A lam + alef cluster (any alef form, marks allowed) is now never an
alternate candidate, whatever feature the font uses.
Adds a test font built in code (lam-alef under liga or rlig) and
host-independent regressions. Also two equivalent one-line repairs
strict Clippy needs on main: a nonminimal_bool in the Path Precision
Tools inspect check and is_none() in a gradient panel test.
Object › Plug-ins › Artwork Cleanup and a hideable Text row in its panel
gain text tools, each one undo step:
- Break Text into Lines / Paragraphs / Words / Glyphs: point type pieces
placed by the glyph of their first character, keeping their styles.
- Combine Point Text: one-line point type merged into as few objects as
it can, every glyph staying where it was (tracking and spaces, checked
against the layout).
- Split Text at Cursor, Remove Line Breaks, Remove Paragraph Breaks,
Set Alignment, Keep Position, Reset Text Transform and Replace
Missing Fonts.
Type on a path from the editing data's text document came in at the
font's advances, while the file's own layout (and its page) closes the
glyphs up round the outside of a curve and opens them up round the
inside, even where the frame keeps no spacing. Round a circle the type
ran on past where the page ends it.
The spacing (Type on a Path Options > Spacing) that reproduces the
layout is now fitted from the layout's glyph positions, advances and
turns, using the text engine's own model, and set on the imported text
object. Corners and straight runs are left out of the fit.
The corner placement of placed files was tried only when the first
placement failed the comparison with the page. A small logo in the wrong
place differs too little to fail, so it stayed there. When the corner
placement draws closer to the page and still matches it, use it.
A .ai whose layers hold placed (linked) PDFs and no text object came in as
its PDF part, saying its layers had no text objects for its page's text.
The PDF part draws each placed file, type and all, where the layers show
its preview, so type that lies inside the placed files (at either of their
placements) is theirs and needs no text object. Type outside them still
does.
In the editing data of a .ai or EPS file, a gradient mesh's own state
(`Xy`) comes right after its `/End X!`, before its `Xd` and `XW`, as a
group's comes after its `U`. The reader took it as the next object's, so
a Multiply shadow mesh came in as Normal and painted opaque white over
the art under it, while the file's page shows the shadow.
An `Xy` read straight after a mesh ends now also applies to that mesh.
An `Xy` after the mesh's `Xd` and `XW` stays the next object's.
Some files write a handle weight of 0 on some gradient mesh corners. The
reader took only weights of 1, so the mesh and the whole file's layers
were unread. A weight of 0 draws as the same cubic edge against the files'
pages; other weights still leave the mesh unread.
bs.tsv: Bosnian (Latin script, Ijekavian) catalog covering every key of
VectorCraft's other catalogs, its wording shared with storytold/craft-i18n
locales/bs/ and the strings craft-i18n lacks translated new. Every bs-*
locale selects it; counts use one/few/other. Locale and plural tests,
localization docs and an attribution entry (AI-assisted, not yet
reviewed by a native speaker).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013Tayw8nmxoLLmKv13jK93z
Effect › Color Effects › Duotone… (addon.color.duotone, also in Object ›
Plug-ins › Color Effects) prints the grey-equivalent tone of each colour
with one to four inks, each with its own tone curve. It is a colour
adjustment like the add-on's others, so it stacks with them and works as
a filter through addon.color.filter.
- One tone of a swatch the document has gives a tint of that swatch,
linked, so a spot tone separates onto its plate; several tones give
the CMYK mix of their tints (the inks overprint, so they multiply).
- Colour adjustments now map paints with their swatch links
(ColorMap::apply_link); the existing adjustments behave as before.
- Skip Objects with Spot Colors leaves spot-linked colours as they are.
- The dialog has a row per tone and the picked tone's curve (the Curves
graph, reused), its points and Reset to Linear / Inverse.
Print Ink Fixes (addon.color.printFixes, Object › Plug-ins › Color
Effects › Print Ink Fixes…) scales CMYK colours over a total ink limit
down to it, removes white overprint and sets black overprint (Overprint
Black's logic) in a CMYK document, as one undo step, and reports what
changed. RGB documents are refused.
The panel opens both under Inks.
Deferred: an opaque undercoat, tones for type only, extra gradient stops
for smoother tints, curve flip and all-100 % buttons.
When a process swatch listed before a global or spot swatch showed the
same color, a traced fill of that color took the process swatch and
stayed unlinked. Of the swatches that trace as one color, the first
linked one now gives the fill, and the first one otherwise.
With the Perspective Selection tool, Ctrl+Alt-drag (Command+Option-drag on
macOS) now copies objects on their perspective plane, as Alt/Option-drag
does. Before, Cmd/Ctrl lent the last selection tool even with Alt held, so
the drag made a flat copy. Cmd/Ctrl alone still lends the last selection
tool, and the cursor follows the same rule.
Follow-ups to the review of #4697 and #4698:
- With textAs: outlines, a .ai saved without PDF compatibility, read
from its editing data alone, has its type outlined too, as an empty
page or a text-only placeholder already did.
- Threaded type read from the editing data holds its story in its first
frame: it now flows through its frames before it is outlined, so each
frame's outlines show the text it holds, and the outlined frames
leave their threads.
- Each outline group keeps its type's opacity, blend mode, isolation,
opacity mask and effects (the same carry-over the flattener uses).
- A gradient-mesh corner (/N) holding anything but numbers is unread,
instead of being read with the numbers after it shifted into its
colour and opacity.
A page cropped to the art is recognised in a UserUnit page's units too,
when the art's box is the page in those units and the artboard isn't the
page in points. Such pages are taken only when every page is the art's
box, and only the first page's type is read: the later pages are copies
whose type was moved by the first page's offset and could fill the
layers' text objects twice.
prune_unseen ran before the retry that moves placed files to their box's
corner, and that retry cloned the pruned layers: text an image covered
only at its first placement was already gone, so the file came in without
it or as its PDF part. Clone the layers before pruning and prune each
placement on its own.
Character attribute 12 of the editing data's text document is the case
(1 Small Caps, 2 All Caps). The reader skipped it, so type set in All Caps
came in as typed, in lower or mixed case where the page draws capitals.
Map it onto CharStyle::all_caps and CharStyle::small_caps.
A successful command.batch now records its last Unite, Intersect or other
Pathfinder step as the operation Repeat Pathfinder runs, so playing an
action from the Actions panel updates it. A batch that fails and rolls back
leaves the previous operation in place. action.batch, which runs an action
over other files or data sets, does not set it.
Every successful Shape Mode or Pathfinder operation now sets the
operation that Repeat Pathfinder runs, including direct
object.pathfinder.* commands, not only the panel's buttons. Trap,
compound-shape edits and live effects leave it unchanged, and a failed
operation keeps the earlier one. The panel menu names the remembered
operation, and Repeat runs it on the current selection with the current
Pathfinder Options.
With too few objects selected, Cmd/Ctrl+4 leaves the art as it is and
shows the panel's selection message in the status bar. Adds the
"no Pathfinder operation applied yet" rows to the Catalan and Turkish
catalogs, and tests for direct and failed operations, Trap, compound
shapes, current options, a one-path selection and the default keys.
A straight Knife cut now starts only when Alt is held at the press.
Alt pressed later in the drag, even before the pointer moves, leaves
the cut freehand. Releasing Alt during a straight cut keeps it
straight.
With Shift+Alt, the cut keeps to 45° steps from the horizontal and
vertical whatever the Constrain Angle. The Pencil's straight line
still steps from the Constrain Angle.
Tests cover Alt after the press, Alt only at the release, a 90° cut,
a 30° Constrain Angle, and the cut boundaries in the engine.
Docs: docs/target-app-parity.md.
The Knife cut along the freehand drag whatever keys were held. The
reference app cuts in a straight line with Alt-drag, and it cuts at 45
or 90 degrees with Shift+Alt-drag.
With Alt held at the press, or pressed before the drag has moved, the
Knife's stroke is the press point and the pointer: the dashed line
shows it while dragging, and the release sends path.knife with those
two points. With Shift held too, the line keeps to 45° steps from the
Constrain Angle, as the Pencil's Shift line does. Shift is read on each
drag event and at the release. The cut stays straight when Alt is let
go, a line taken back to its press point sends no command, and Shift
alone leaves the cut freehand.
Docs: docs/target-app-parity.md.
paint.invert and paint.complement on the Fill proxy, the Edit Colors
commands, the Blend commands and recolor.apply now recolor the color
that colorizes a grayscale or 1-bit image, as one undo step with the
other targets. Before, they left it unchanged. Expand Appearance and
Object > Expand bake color adjustment effects into that color too.
- A colorized image's pixels are not recolored; they stay the gray
coverage of its color. A stroke-only pass reaches the image's stroke
items and leaves its colorize color unchanged.
- A command that would leave a process color on a grayscale image with
an alpha channel fails with the existing message and changes nothing.
Object > Expand undoes its earlier steps when that happens.
- A colorized image counts as a filled object in a blend.
Alt in a spiral drag now rounds the fitted segment count to whole winds
of four segments, counted from the segment count when Alt went down.
Ctrl/Cmd takes precedence when both keys are held, and switching back to
Alt starts from the current count with the held inner end kept. Arrow
keys, Escape, release and a new drag clear the held Alt count.
Tests cover both keys together, a switch mid-drag, Escape, the 2 to 1000
bounds and the committed path's anchor count. docs/mcp.md and
docs/target-app-parity.md describe the rule.
The reference app adds or subtracts winds from a spiral with Alt-drag
and changes its decay rate with Ctrl/Cmd-drag. VectorCraft's Spiral
tool did nothing with either key during a drag.
While a spiral is dragged out, Alt or Ctrl/Cmd keeps the spiral's
inner end at the distance from the center it had when the key went
down, and the outer end follows the pointer. With Alt the number of
segments changes to the nearest whole number that fits, within 2 to
1000, so dragging outward adds segments and dragging inward removes
them. With Ctrl/Cmd the decay changes to fit, within 5 to 99.99
percent, the decays a spiral is drawn with. When both keys are held,
Ctrl/Cmd changes the decay. Up/Down with a key still held move the
held radius to the new segment count. The new values stay when the
key is let go, and as the Spiral tool's segments and decay options
for the next spiral. Both keys also work with a 5 percent decay and
hundreds of segments.
Docs: docs/mcp.md, docs/target-app-parity.md.