Commit Graph
4412 Commits
Author SHA1 Message Date
dotCooCoo 9c120c735e Keyboard Shortcuts: commands a key cannot run without a value are not listed
Edit > Keyboard Shortcuts listed commands whose params are all optional
but that do nothing or fail when a key runs them with none, such as
Transparency (transparency.set) and Opacity Mask Options
(transparency.setOpacityMask). These are now left out while they have
no shortcut, along with Align and Distribute, Delete Swatch, Move
Swatch, Spot Options, Adjust Color Balance, the library and data set
loaders, stroke.set, layer.setProps and menu queries that no menu item
runs. A key saved for one of them before keeps it listed so it can be
cleared.

A shortcut for a command whose menu bar items all give it the same
params now runs what a click on that item runs, so Clean Up..., Print
Ink Fixes... and Find and Replace... open their dialogs.
2026-11-02 14:32:55 +07:00
dotCooCoo 82806d1441 Fonts: Find Font and Replace Missing Fonts reach the type in symbols
Exports warn about type in a symbol's art that is set in a missing
font and point to Find Font, but Find Font and Replace Missing Fonts
only looked at the type on the layers.

- text.fonts lists the fonts of the type in the document's symbols too;
  with selectionOnly, of the symbols the selected instances show.
- select.font (Find) also selects the instances of the symbols whose
  art uses the font in type that is not hidden or locked.
- text.replaceFont changes that type in the symbols in scope, so every
  instance follows. Type hidden or locked in a symbol's art, and the
  type of symbols that only a selected hidden or locked instance shows,
  keeps its font and is counted in skipped.
- addon.cleanup.replaceFonts replaces missing fonts in symbols' type.

While a symbol is edited, its type is taken from the editing layer
only, so it is counted and changed once.
2026-11-02 14:32:55 +07:00
dotCooCoo 0895eccfe1 Type: right-to-left manual kerning moves a rotated character along the line
Right-to-left manual kerning was added to the glyph's offset, which
Character Rotation turns, so a rotated character with kerning moved
across the line (up at 90 degrees) instead of away from the next
character in reading order. The shift is now applied to the pen
position along the baseline, outside the rotation, and the rotation
turns the glyph about that moved pen position.
2026-11-02 14:32:54 +07:00
dotCooCoo 8346f052e9 Type: manual kerning in right-to-left text spaces the pair it is set on
A manual kerning value on a character in right-to-left text changed the
space between it and the character before it in reading order, under
both Auto and Optical kerning. The shaped glyphs of a right-to-left
cluster now also move right by the value, so the space its advance
gains is at its left, between it and the next character in reading
order. Left-to-right text and tracking are unchanged.

Optical kerning no longer takes the left glyph's manual value off the
advance it measures, since right to left the value is in that glyph's
offset as well.
2026-11-02 14:32:54 +07:00
bflatastic 188754f68e Tests: the listed Shadow style writes every Drop Shadow setting 2026-11-02 14:32:54 +07:00
bflatastic 83daab708d .ai import: graphic styles scale with a document drawn on its page 2026-11-02 14:32:54 +07:00
dotCooCoo 405372555d .ai import: the document's graphic styles open in the panel with their objects linked
Squashed from #5155 onto main.
2026-11-02 14:32:53 +07:00
dotCooCoo 0e38796573 .ai import: placed files are found by the folder they keep relative to the document
Squashed from #5176 onto main.
2026-11-02 14:32:53 +07:00
dotCooCoo 56f6128f94 .ai import: a line width of 0 draws as a hairline
Squashed from #5174 onto main.
2026-11-02 14:32:53 +07:00
bflatastic dc363ec356 Tests: Convert to Shape beside Offset Path is a style any object takes 2026-11-02 14:32:53 +07:00
dotCooCoo dbb04905e0 .ai import: Offset Path, Outline Object and Outline Stroke open live
Squashed from #5148 onto main.
2026-11-02 14:32:52 +07:00
dotCooCoo e8cd6c173a Variables: Save Variable Library… writes the variables and data sets as an XML library
Squashed from #5147 onto main.
2026-11-02 14:32:52 +07:00
dotCooCoo 9031906abd Actions: deleting sets moves the selected action with its set
`ui.actionSet.delete` now moves the panel's selected action down with its
set, and clears it when its set is deleted. Before, the stored set and
action indexes stayed as they were, so a set made later at the deleted
set's index, and an action recorded into it, showed as selected, and
Action Options… renamed that action.
2026-11-02 14:32:51 +07:00
dotCooCoo b2c62c398e Actions: the panel menu reads the selected action only in the current set
The panel menu read the stored (set, action) pair without checking that
its set is still the current one, as the panel and Delete Selection do.
After `ui.actionSet.delete` removed a set above it, the pair pointed at
another set's action, and Action Options…, Batch… and Play Current
Selection acted on that action. They are now off until an action of the
current set is selected.
2026-11-02 14:32:51 +07:00
dotCooCoo 0212c2b00e Actions: Action Options and Set Options refuse a field that is not an index
The dialog's fields choose what OK does, as they choose its heading. A
`set` or `action` field that `ui.dialog.set` changed to null or to an
index past the last set or action is now an error: OK renames no set or
action, adds no set, and the dialog stays open. Before, an Action Options
dialog whose `action` was null renamed the set instead.
2026-11-02 14:32:51 +07:00
dotCooCoo 642df312b3 Actions: the panel menu's Action Options… renames the selected action
Action Options… opens the New Set and Set Options dialog, headed Action
Options, with the selected action's name; OK renames the action and keeps
its steps. The new command ui.action.rename {set, action, name} does the
rename and refuses an index past the last set or action or an empty name.

Part of #1629.
2026-11-02 14:32:50 +07:00
dotCooCoo f5da917b37 Actions: the current set is kept after a restart
The Actions panel did not save which set was current, so after a restart
Begin Recording put the new action into the first set (Default Actions)
instead of the set the user had picked. The current set is now saved
with the UI preferences as an index into the saved sets; a value that is
not an index, or is past the last set, leaves no set current.

With no set current, Begin Recording records into the first set as
before, and now makes that set current so the panel shows where the
recording goes.
2026-11-02 14:32:50 +07:00
dotCooCoo 0be7609bf7 Tabs: Above Text checks the place below text against the window's top
The place below the text was taken even when the text was panned above
the canvas, which put the panel above the main window. It is now taken
only when it is at or below the window's top. A docked Tabs panel is
measured at the 360-point height it floats at, not 240, so it is placed
below the text only when it fits there.
2026-11-02 14:32:49 +07:00
dotCooCoo 442430ff12 Tabs: Above Text puts the panel below text near the window's top
With no room above the text, the panel went to the top of the main
window's content and could cover the text. It now goes just below the
text when it fits there in the canvas, and at the window's top only when
it does not.
2026-11-02 14:32:49 +07:00
dotCooCoo 48e2bc6508 Tabs: Above Text keeps the panel's bar inside the window
With text near the top of the window, Position Panel Above Text put the
panel, and its OS window, above the main window's content and could put
the bar above every screen. The panel now goes no higher than the top of
the main window's content.
2026-11-02 14:32:49 +07:00
dotCooCoo d8394d5d87 Fix #4995: Above Text moves a Tabs panel that already floats
Position Panel Above Text moved a floating Tabs panel only in the layout's
in-window rect. On desktop builds a floating panel is an OS window, which
moves only when its desktop rect changes, so the panel stayed where it
was and the layout followed it back on the next frame. A docked panel
floated above the text as expected.

place_floating now also sets the window's desktop rect, from the main
window's content origin, when the panel's window already has one.
2026-11-02 14:32:49 +07:00
dotCooCoo 6be88a24b4 Fix #785: commands refuse an id that isn't an object id instead of using the selection
Commands whose `id` or `ids` the shared check in Session::execute does not
read still parsed them with id_param/ids_param, which drop anything that is
not a non-negative integer, and then acted on the selection or the current
layer. `object.blend.make {"ids": 3}` blended the selection,
`object.envelope.makeWithWarp {"ids": [2, "x"]}` warped the selection,
`graph.setData {"id": "2"}` changed the selected graph and
`layer.newSublayer {"parent": "2"}` added a sublayer to the current layer.

- cmd::named_ids and cmd::named_id read `ids`/`id` as targets does: a value
  that is not an object id, or an unresolved step reference, is an error.
- The symbol and brush, Live Paint, Shape Builder and Image Trace, blend,
  envelope and mesh, perspective, Liquify, Puppet Warp and graph helpers use
  them in place of the lenient readers.
- layer.clippingMask.toggle checks `id`, and layer.newSublayer checks
  `parent`, with checked_id before falling back to the highlighted row or the
  current layer.
2026-11-02 14:32:49 +07:00
Brandon Thomas cfb30d8139 Merge pull request #5214 from dotCooCoo/feat/recolor-global-adjust
Recolor: the Global Adjust sliders change every color at once
2026-11-02 00:34:59 -05:00
Brandon Thomas 6daefef735 Merge pull request #5212 from dotCooCoo/feat/document-info-save-category
Document Info: Save writes the category the panel shows
2026-11-02 00:34:54 -05:00
Brandon Thomas c4a394c536 Merge pull request #5203 from dotCooCoo/fix/empty-text-clip-kept
Artwork Cleanup: Empty Text and Off-Artboard Art leave type that clips art
2026-11-02 00:34:49 -05:00
Brandon Thomas 9269cb7cf3 Merge pull request #5197 from dotCooCoo/fix/cleanup-leaves-hidden-locked-art
Artwork Cleanup: Simplify Anchors and Deep Ungroup leave hidden and locked art alone
2026-11-02 00:34:43 -05:00
Brandon Thomas a51391a7c3 Merge pull request #5195 from dotCooCoo/fix/release-moves
Canvas: a drag ends where its button went up
2026-11-02 00:34:37 -05:00
Brandon Thomas cb700213c6 Merge pull request #5191 from dotCooCoo/fix/issue-2181
Fix #2181: PDF layer forms get real boxes and lose their off-page marks
2026-11-02 00:34:31 -05:00
Brandon Thomas 3d59d874ac Merge pull request #5190 from dotCooCoo/fix/separations-gamut-count-plural
Separations Preview: Gamut Check counts colors in the singular and the plural
2026-11-02 00:34:26 -05:00
bflatastic 645757448f .ai import: the layer-end operator gets its own method 2026-11-02 12:04:26 +07:00
dotCooCoo ccc7e44078 .ai import: multi-layer masks open as a clipping group in each layer
Squashed from #5117 onto main.
2026-11-02 12:04:26 +07:00
bflatastic f6e262c92e .ai import: translate the note for a graph whose records don't end 2026-11-02 12:04:25 +07:00
dotCooCoo 795cbc060d .ai import: graphs open as their drawn art, with a note
A graph in a legacy .ai, or in a current file's editing data, is written
as `%_Gs`, its data and settings on `%_` lines, its drawn art in a group
with a `%_... Go` tag after each object, and `%_GS`. The reader stopped
on the graph operators as ones it doesn't know, so such a file did not
open through its layers.

The reader now leaves the graph's records out with their operands and
reads the drawn art as usual: the bars, lines and labels come in as the
groups, paths and type they are written as. Paint operators on `%_`
lines between `Gt` and `GT` set nothing. One note per file says the
graphs came in as plain art without their data or settings. A graph
that starts inside another, or doesn't end before its layer does, keeps
the art read so far with a second note. Graph operators outside a graph
stay unknown.
2026-11-02 12:04:24 +07:00
dotCooCoo 69e5eecde0 .ai import: artboard display options, raster effects settings and the header's author come in
Squashed from #5102 onto main.
2026-11-02 12:04:24 +07:00
dotCooCoo 13db3cd602 .ai import: anchors are smooth or corners by the case of their segment operators
In editing data and legacy .ai files, a lower-case l, c, v or y makes the
anchor the segment ends on smooth and an upper-case L, C, V or Y makes it a
corner. The reader used to guess each anchor's kind from whether its
handles are in line, so a lower-case l always read as a corner and an
upper-case C with handles in line read as smooth. A closed path's first
anchor takes the case of the segment back to it. Points and handles do not
move. Paths, compound paths, clipping paths, guide paths, area type frames
and type-on-a-path paths all keep the kinds.
2026-11-02 12:04:23 +07:00
bflatastic ae46139b20 Variables: Edit Data Set's rename test undoes the one step it adds 2026-11-02 12:04:22 +07:00
dotCooCoo ab0072a39e Variables: Edit Data Set's Name field renames the data set
Squashed from #5121 onto main.
2026-11-02 12:04:22 +07:00
dotCooCoo 899a4c2bcb Variables: Import Data Sets reads CSV files that are not UTF-8 as Windows-1252
Squashed from #5116 onto main.
2026-11-02 12:04:21 +07:00
dotCooCoo 2b7b12df33 Symbols: the edited symbol takes the text wrap its area type gets after a wrap object moves
Symbol editing copies the editing layer's art into the symbol before Text Wrap, list numbering and threaded re-flow update that layer, so moving a wrap object in the edit left the symbol, its other instances and the saved file with the old wrap. The edit now syncs the symbol again after those passes, and when that changes the symbol, inline graphics of it are refreshed and the threads holding them re-flow.
2026-11-02 12:04:20 +07:00
dotCooCoo 294d13d857 Symbols: an instance in an opacity mask follows an edit of its dynamic symbol
The appearance changes of the instances on the layers now follow the edited objects through the same pass as the instances in other symbols, graph designs, pattern tiles and brushes. That pass also reaches instances used as opacity-mask art, which keep their changes on the same objects when an edit reorders them and drop the change to an object the edit deletes.
2026-11-02 12:04:20 +07:00
dotCooCoo 5c678ed52c Symbols: instances in pattern tiles, graph designs and brushes follow an edit of their dynamic symbol 2026-11-02 12:04:20 +07:00
dotCooCoo 52f6adfa3b Symbols: the instance a symbol is edited from is not drawn in the view while it is edited
Entering symbol editing mode from an instance puts a copy of the symbol's art on the editing layer in the instance's place, and the instance stays in the document. The view drew the instance dimmed under the copy, so art with transparency showed darker, and its edges showed a dimmed fringe.

The renderer now leaves that instance out of the screen view while the editing layer is isolated, with its masks and effects, and in Outline view inside a clip group. Exports and thumbnails draw it as before.
2026-11-02 12:04:19 +07:00
dotCooCoo 87dea538ae Symbols: instances inside other symbols' art follow an edit of their dynamic symbol
Editing a dynamic symbol moved each placed instance's appearance changes with the objects they
name, but an instance stored in the art of another symbol kept its changes at the old paths, so
placing that symbol showed a change on the wrong object. Those instances, opacity masks included,
now follow the edit too and keep only the changes to objects the art still has.
2026-11-02 12:04:19 +07:00
dotCooCoo 0af8096364 Symbols: a refused switch to another symbol keeps the current edit, and isolation stays on the editing layer
symbol.edit checks the new placement before it ends the symbol being edited, so a call with an out-of-range x or y fails and leaves the current edit open. While a symbol is edited, object.isolate refuses art outside the editing layer, and object.exitIsolation goes back to the editing layer only from a group inside it; from any other isolation it leaves symbol editing mode.
2026-11-02 12:04:18 +07:00
dotCooCoo 7c1d73d818 Symbols: test the Symbols panel, panel menu and Control bar entries to symbol editing mode
Headless tests cover a double-click on a symbol in Thumbnail View and List View, the panel
menu's Edit Symbol with and without a selected instance, the Control bar's Edit Symbol button,
and the Control bar's Exit Symbol Editing Mode and Exit Isolation Mode buttons inside the
symbol's art. The panel's module comment now says a double-click opens the symbol in symbol
editing mode, and docs/mcp.md lists symbol.edit's ids parameter.
2026-11-02 12:04:18 +07:00
dotCooCoo 10235563ae Character Style Options: the dialog test sets Vertical Scale and checks it on the style and its text 2026-11-02 12:04:17 +07:00
dotCooCoo 94a6917c68 Character Styles: Advanced Character Formats takes scales and baseline shift up to the document limit
Horizontal Scale and Vertical Scale accept any number above 0 and at most 4000000 %, and Baseline Shift accepts -4000000 to 4000000 pt, the limits the document model keeps a character style in. Character Rotation is stored from -180 to 180 degrees, as text.setFormat stores it. A scale outside its limit shows the new message "{label} must be a number above 0 and at most {max}", translated in every catalog that has Basic Character Formats.
2026-11-02 12:04:17 +07:00
dotCooCoo 7a527fce64 Character Styles: New Character Style keeps a language tag the selected text holds
charStyle.new now validates attrs against the target text's attributes, so a
language tag that is not in the list but that the selected run already holds
(a native file can store any tag) is kept. Any other unlisted tag is still an
error.
2026-11-02 12:04:16 +07:00
dotCooCoo 6e7945773e Character Styles: Style Options sets Advanced Character Formats
Character Style Options and New Character Style get an Advanced
Character Formats section with Horizontal Scale, Vertical Scale,
Baseline Shift, Character Rotation and Language. Empty fields stay
unset, an explicit 100%, 0 degrees or English: USA stays distinct from
unset, and Reset Panel on the section clears only these five. Scales
take 1% to 10000% and baseline shift -1296 pt to 1296 pt, as
text.setRangeStyle does; rotation is stored from -180 to 180 degrees.
Language sets the language the characters are shaped in; hyphenation
and spelling do not change.

A field still as it opened keeps its stored value without the range
check, so a style captured from a scaled type object can be renamed.
The same applies to Basic's Size and Leading minimum.

charStyle.edit keeps a language tag that is not in the list when the
style already has it, so a style read from a file with such a tag can
be edited.
2026-11-02 12:04:16 +07:00
dotCooCoo 3cb252198a OpenType: the panel's Position menu sets superscript, subscript, numerator or denominator glyphs
The OpenType panel gets a Position menu after Figure, with Default
Position, Superscript, Subscript, Numerator and Denominator. `numr` and
`dnom` join the extra features (the existing bits keep their indices),
so they round-trip through the stored tags and reach the shaper.

text.setStyle and text.setRangeStyle take `featureChanges`, which turns
features on or off on top of each character's own features in one
command and keeps every tag the list does not name. The Figure menu,
the Position menu and the checkboxes send it, so on a selection whose
characters have different features each character keeps its other
features. Reset OpenType Features still sends `features`.

Catalog rows for Position:, Default Position, Numerator and
Denominator; one line each in docs/type-parity.md and
docs/target-app-parity.md.
2026-11-02 12:04:15 +07:00