Commit Graph
8080 Commits
Author SHA1 Message Date
dotCooCoo f4469e16d6 Control bar: the Global Edit Options dropdown shows while Start Global Edit can run
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.
2026-11-04 15:41:15 +07:00
dotCooCoo a176ffae46 PDF/.ai import: the file is read and checked once when it opens
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.
2026-11-04 15:41:11 +07:00
dotCooCoo a8c6d078e5 .ai import: blends keep their Specified Distance and Smooth Color spacing
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.
2026-11-04 15:41:08 +07:00
dotCooCoo 663c3264ca Type: list stylistic sets whose lookups come from FeatureVariations
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.
2026-11-04 15:41:05 +07:00
dotCooCoo 9c191793e2 Images: a PNG read a row at a time counts all of the reader's buffers
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.
2026-11-04 15:41:03 +07:00
BFlat a207c7b816 Merge pull request #5543 from dotCooCoo/feat/expand-selected-symbol-instances
Expand: selected symbol instances become their art, as Break Link places it
2026-11-04 15:34:10 +07:00
BFlat eaa7ebb0a5 Merge pull request #5511 from dotCooCoo/fix/same-symbol-reference
Select: Same Symbol Instance takes its reference from an object that can be selected
2026-11-04 15:33:55 +07:00
BFlat 1e992980d8 Merge pull request #5542 from dotCooCoo/feat/select-all-threaded-story
Type: Select All in a threaded frame selects the whole story
2026-11-04 15:33:39 +07:00
BFlat d4469e9920 Merge pull request #5538 from dotCooCoo/fix/convert-replaced-spine-handles-only
Blends: Convert on a replaced spine changes only its handles
2026-11-04 15:33:24 +07:00
dotCooCoo 146d30502a Expand: selected symbol instances become their art, as Break Link places it
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.
2026-11-04 15:14:02 +07:00
dotCooCoo a79ab62712 Select: Same Symbol Instance takes its reference from an object that can be selected
Squashed from #5511 onto main.
2026-11-04 15:13:32 +07:00
dotCooCoo 92640179e5 Type: Select All in a threaded frame selects the whole story
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.
2026-11-04 15:13:20 +07:00
dotCooCoo 40318753db Blends: Convert on a replaced spine changes only its handles
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.
2026-11-04 15:13:18 +07:00
BFlat 6bde3c59a5 Merge pull request #5516 from dotCooCoo/fix/layer-options-template-keeps-set-lock-dim
Layers: Layer Options keeps a Dim Images that was set before Template changes
2026-11-04 15:05:59 +07:00
BFlat c06be0349c Merge pull request #5533 from dotCooCoo/fix/ai-layers-checked-on-every-page
.ai import: the layers are compared with every page of a multi-artboard file
2026-11-04 15:05:43 +07:00
BFlat d0c703328f Merge pull request #5535 from dotCooCoo/fix/placed-document-undecoded-marks
Render: placed-document bitmaps draw undecoded-image marks when the view does
2026-11-04 15:05:27 +07:00
BFlat 30c33c5048 Merge pull request #5536 from dotCooCoo/fix/perceptual-spot-stop-limit-docs
Docs: Perceptual spot gradients with more than 4,096 curve stops export as images
2026-11-04 15:05:12 +07:00
dotCooCoo 4aa8a8b0c8 Layers: Template always locks the layer in Layer Options
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.
2026-11-04 14:56:41 +07:00
dotCooCoo 2ac1fa4cce Layers: Layer Options keeps a Lock or Dim Images that was set before Template changes
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.
2026-11-04 14:56:41 +07:00
dotCooCoo e5834f7686 .ai import: the layers are compared with every page of a multi-artboard file
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.
2026-11-04 14:56:38 +07:00
dotCooCoo f15a16f2c1 Render: placed-document bitmaps draw undecoded-image marks when the view does
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.
2026-11-04 14:56:36 +07:00
dotCooCoo b9d3881872 Docs: state the stop limit for Perceptual spot gradient shadings
PDF export writes a Perceptual spot gradient as a Separation or DeviceN shading only when its expanded curve has at most 4,096 stops (MAX_INK_TINTS in crates/color/src/gradient.rs). Longer curves are written as images, with the process-color warning.
2026-11-04 14:56:35 +07:00
BFlat d977fd9181 Merge pull request #5447 from dotCooCoo/feat/ot-stylistic-sets
Add font-aware OpenType stylistic sets menu
2026-11-04 14:31:00 +07:00
BFlat d702bdfc23 Merge pull request #5527 from dotCooCoo/fix/parity-doc-wording
Docs: name glows with shadows in the pan raster entry, and mark VectorCraft's own values
2026-11-04 14:30:44 +07:00
BFlat afce54206a Merge pull request #5524 from dotCooCoo/fix/live-paint-face-attribution
Live Paint: preserve face colors at shared curved boundaries
2026-11-04 14:30:29 +07:00
BFlat e2a551226f Merge pull request #5523 from dotCooCoo/fix/continued-paragraph-typed-list
Type: typing a list's start in a continued paragraph starts no list
2026-11-04 14:30:14 +07:00
dotCooCoo 3bd1514acb Type: offer stylistic sets only for an installed font, by their own names
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.
2026-11-04 14:09:34 +07:00
dotCooCoo 4fa4862613 Type: translate the numbered stylistic set label
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.
2026-11-04 14:08:30 +07:00
dotCooCoo 1858da4106 Type: use selected font version for stylistic sets 2026-11-04 14:08:30 +07:00
dotCooCoo b72c822f1d Add font-aware OpenType stylistic sets menu 2026-11-04 14:08:30 +07:00
dotCooCoo d46079b872 Docs: name glows with shadows in the pan raster entry, and mark VectorCraft's own values
The panning entry says a Drop Shadow or Outer Glow raster holds the
shadow or glow of group members outside the view. The Blob Brush
Fidelity entry keeps its citation on the option and states that the
slider and field range and the 1.5 pt default are VectorCraft's own
values. The Escape in Selection tool drags entry is stated as
VectorCraft's own behavior.
2026-11-04 14:08:26 +07:00
dotCooCoo f7bebdeaf0 Live Paint: preserve face colors at shared curved boundaries
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.
2026-11-04 14:08:23 +07:00
dotCooCoo ccf4252a73 Type: typing a list's start in a continued paragraph starts no list
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.
2026-11-04 14:08:20 +07:00
BFlat e492106a51 Merge pull request #5422 from dotCooCoo/feat/action-exclude-step
Actions: exclude recorded steps from playback
2026-11-04 14:01:43 +07:00
BFlat 5602f0a2eb Merge pull request #5522 from dotCooCoo/fix/same-font-isolated-group-on-layer
Select: the font Same commands look through a selected group that holds the isolated group
2026-11-04 14:01:31 +07:00
BFlat e44b76a9c2 Merge pull request #5521 from dotCooCoo/fix/picker-rgb-fields-test
Tests: the Color Picker's R, G and B fields show the working RGB values
2026-11-04 14:01:15 +07:00
dotCooCoo 251cc964a5 Actions: exclude recorded steps from playback
Squashed from #5422 onto main.
2026-11-04 13:42:33 +07:00
dotCooCoo a9a2c4dee8 Select: the font Same commands look through a selected group that holds the isolated group
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.
2026-11-04 13:42:03 +07:00
dotCooCoo 8733f3c65d Tests: the Color Picker's R, G and B fields show the working RGB values
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.
2026-11-04 13:42:00 +07:00
BFlat 695c967a33 Merge pull request #5517 from dotCooCoo/fix/ai-save-missing-artboard
.ai save: an artboard the document does not have is refused, as an export refuses it
2026-11-04 13:36:27 +07:00
BFlat e20eba502e Merge pull request #5515 from dotCooCoo/fix/ai-look-copies-type-docs
Docs: cite where a group's or layer's effect comes from in the .ai look copies entry
2026-11-04 13:36:13 +07:00
dotCooCoo d18499613c .ai save: an artboard the document does not have is refused, as an export refuses it
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.
2026-11-04 13:16:24 +07:00
dotCooCoo a35f3a0fee Docs: cite where a group's or layer's effect comes from in the .ai look copies entry
The evidence entry for type in copies that a layer's or group's drawn look
draws now cites the help page that describes effects on a group or a layer,
and says that matching the page's type with a copy is VectorCraft's own rule.
2026-11-04 13:16:20 +07:00
BFlat eed006d808 Merge pull request #5510 from dotCooCoo/fix/same-reference-skips-unreachable
Select: Same commands take their reference from an object that can be selected
2026-11-04 13:09:25 +07:00
BFlat c2e4117c8c Merge pull request #5512 from dotCooCoo/fix/new-action-clears-set-range
Actions: New Action leaves its set as the only selected set
2026-11-04 13:09:10 +07:00
BFlat e553135ce9 Merge pull request #5513 from dotCooCoo/fix/mcp-docs-vertical-and-action-duplicate
MCP docs: vertical text uses vert alternates, and duplicate defaults to the current set
2026-11-04 13:08:55 +07:00
dotCooCoo 6cbfb83c65 Select: Same commands take their reference from an object that can be selected
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".
2026-11-04 12:50:38 +07:00
dotCooCoo 6a8e381dfa Actions: New Action leaves its set as the only selected set
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.
2026-11-04 12:50:35 +07:00
dotCooCoo d9cfaf9041 MCP docs: vertical text uses vert alternates, and duplicate defaults to the current set
add_text's vertical option turns on the OpenType vert feature, so the docs no
longer say it leaves glyph orientation unchanged. ui.actionSet.duplicate uses
the current set when set is omitted, with or without action.
2026-11-04 12:50:33 +07:00
BFlat 0ccf9d4fdd Merge pull request #5507 from dotCooCoo/fix/color-panel-working-components
Color controls: preserve working RGB components in numeric edits
2026-11-04 12:46:26 +07:00