Commit Graph
7448 Commits
Author SHA1 Message Date
ham9zah a141372cd9 Type tool icons: one family, the same T with a frame, wave, arrow or dotted box; the vertical Area and Path tools get their own 2026-11-02 14:36:09 +07:00
ham9zah 6fd542822d Type on a path made with the Type tool shows its brackets at once and flips across its path 2026-11-02 14:36:09 +07:00
ham9zah 93b310c069 Type cursors: the I-beam with a frame or curve badge for area type and type on a path 2026-11-02 14:36:09 +07:00
ham9zah afd9ec036c Type tool: a click on a path's outline makes area type or type on a path, with cursors that say which 2026-11-02 14:36:08 +07:00
Taha-Mahmoodi 1b5d11ef4b Units: Preferences › East Asian Type reads, with Q and Ha units (#394)
Squashed from #4845 onto main.
2026-11-02 14:36:08 +07:00
Don Omondi 15a5e64134 #4919: Create Swatch Legend becomes an add-on under Object › Plug-ins › Color Effects with a dialog
addon.color.swatchLegend replaces swatch.legend. The dialog sets columns, chip size, gap, the values shown
and whether to use only the swatches selected in the Swatches panel, with a preview; duplicate value
kinds are refused. The Swatches panel menu item is removed. Catalog rows in all 26 languages.
2026-11-02 14:36:08 +07:00
Don Omondi 236a3c264d Swatch legend: no unreachable! in the test
The workspace lints ban it; the test panics with a message instead.
2026-11-02 14:36:07 +07:00
Don Omondi aa71acc29f Swatch legend: linked chips, labels that fit, exact Gray
Each chip's fill links to its swatch as paint.setFill {swatch} does, so
editing a global or spot swatch recolours the legend. Labels are area
type the size of the chip that shrinks text to fit. Gray values use the
app's own Gray conversion, and fractional column counts are refused.
2026-11-02 14:36:07 +07:00
Don Omondi c823e7f5b2 Fix #4919: Create Swatch Legend
swatch.legend draws a grid of chips, one per colour swatch (the given
ones, else every one), each filled with and linked to its swatch and
labelled with its name and colour values (HEX, RGB, CMYK, Lab or
Grayscale; by default its own model; spot swatches marked), black on
light chips and white on dark ones, as one selected group in one undo
step. The Swatches panel menu's Create Swatch Legend draws the selected
colour swatches, else every one.
2026-11-02 14:36:07 +07:00
el-j 601ab957e6 perf(canvas): zero-copy texture upload and progressive worker frame acceptance (#4615)
Squashed from #4961 onto main.
2026-11-02 14:36:07 +07:00
Wadah Badawi 66e22f4ba1 M2.1: recurse into groups and compound paths for path.average 2026-11-02 14:36:07 +07:00
NetterSilverandClaude Sonnet 5.5 88d8a7839e fix: validate parse_date calendar dates with chrono
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 14:36:06 +07:00
NetterSilverandClaude Haiku 5.5 83ed70acce Validate hyphen placement and days in month in parse_date
Found while testing crates/engine/src/cmd/fileio/naming.rs:103

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 14:36:06 +07:00
dotCooCoo 2fafe25c27 Asset Export: Import Preset and Export Preset read and write preset files
Squashed from #5032 onto main.
2026-11-02 14:33:29 +07:00
bflatastic 57a76f4f8d Paste: translate the two paste messages into Catalan 2026-11-02 14:33:02 +07:00
dotCooCoo b1c98821d6 Clipboard: a bitmap pasted from another app is decoded off the UI thread
Squashed from #4277 onto main.
2026-11-02 14:33:02 +07:00
dotCooCoo e8e09af782 Brushes: Calligraphic and Scatter values follow pen tilt, bearing and rotation
Squashed from #5031 onto main.
2026-11-02 14:33:02 +07:00
dotCooCoo 6d369d013c Toolbars: New Toolbar makes a named toolbar filled from the All Tools drawer
Squashed from #5038 onto main.
2026-11-02 14:33:01 +07:00
dotCooCoo adc3e75be4 Window: Arrange > Tile shows every open document side by side
Window > Arrange > Tile (window.arrange.tile) splits the document area
into one pane per open document, edge to edge, in a grid with as many
columns as the square root of the number of documents, rounded up. Each
document is fitted to its pane, and fitted again when its pane changes
size (a document opened or closed, the window resized) unless it was
zoomed or scrolled since. The current document's pane is the canvas;
the other panes draw their documents with their artboards, guides,
selected objects and Pixel Preview, and a press in one makes its
document the current one, as a click on its tab does. Window > Arrange >
Consolidate All Windows (window.arrange.consolidateAllWindows) goes back
to one document under its tab. It works the same on the desktop and the
web, and the arrangement is not saved.

Tile is enabled with two or more open documents, and Consolidate All
Windows while documents are tiled. ui.inspect reports tiled and the
panes.
2026-11-02 14:33:00 +07:00
bflatastic d5edca7452 Type: the East Asian character settings get their own method 2026-11-02 14:32:59 +07:00
dotCooCoo e13cf73ae0 Type: Tate-chu-yoko Settings move a block up, down, left or right
Squashed from #5206 onto main.
2026-11-02 14:32:59 +07:00
dotCooCoo f69f7976b7 .ai import: legacy files without layers open through the format reader
Squashed from #5209 onto main.
2026-11-02 14:32:58 +07:00
dotCooCoo ec0a98a77b Selection: a drag with Real-time Drawing off shows the bounds of a selection too big to outline
With Real-time Drawing and Editing off, a drag drew one outline per selected
object with no limit, so a selection with hundreds of thousands of points
built the overlay mesh that the canvas's 100,000-point limit keeps it from
drawing at rest (#525, #2460). Past the same number of points the drag now
draws the moved selection's bounds, as the canvas does for the selection at
rest.
2026-11-02 14:32:58 +07:00
dotCooCoo c4dfe6bfc2 Selection: with Real-time Drawing off, the bounding box moves with a move drag
With Preferences › Performance › Real-time Drawing and Editing off, a
Selection tool move drag leaves the object in place until release, and
the bounding box was hidden for the whole drag. The box, with its
handles, now follows the pointer during the drag (Session::deferred_move
gives the offset the document has not taken yet). Scale and rotate
drags, and drags with Real-time Drawing on, hide the box as before.

Docs: docs/target-app-parity.md.
2026-11-02 14:32:58 +07:00
dotCooCoo 5685cc256c Tabs: Above Text keeps the ruler at the zoom when the panel comes out wider
Position Panel Above Text sizes the Tabs panel so its ruler spans the
text at the canvas zoom. A floating panel is at least 220 pt wide, so
for narrow text at a low zoom the panel comes out wider than asked, and
the ruler stretched the text's width across the whole panel. Its marks
then no longer sat over the text.

After Above Text, while the same text in the same document is selected
and the panel floats no wider than the narrowest panel, the ruler now
draws the text at its screen scale and runs on past the text's width.
Any other ruler fits the span to its width as before.
2026-11-02 14:32:58 +07:00
dotCooCoo 79c5218f8a Fix #5161: Shape Builder merges across a line under a merged shape's edge
Where a line lies under the outline of a closed path in front of it (such as
a shape an earlier merge made, which takes the place of the art in front of
the lines), the planar map gave that stretch only to the closed path, so the
line had no piece there. A merge or an erase across it left the line whole,
and the next map split the new shape along it into two regions.

- pathops: each planar edge records every input it lies on, and
  BuilderArrangement::lines_under holds the lines' pieces under a closed
  outline in front of them. lines, edges and Live Paint are unchanged.
- tools: BuilderMap adds those pieces to its lines, so a merge or an erase
  removes the stretch between the regions it takes, as it does elsewhere.
  An Alt-click where a line lies under an edge hits the one in front.
2026-11-02 14:32:57 +07:00
bflatastic 8913ba2440 Tests: the placed-files fuzz fixture goes in after the noted path 2026-11-02 14:32:57 +07:00
bflatastic 71d706fdcc .ai import: a placed file's tick operator gets its own method 2026-11-02 14:32:56 +07:00
dotCooCoo 01bc69cc80 .ai import: placed EPS files in the version 7 form are read
Squashed from #5187 onto main.
2026-11-02 14:32:56 +07:00
dotCooCoo 2a41c74690 .ai import: a group still open at the end of the art is an error
A group (`u`), clipping group (`q`) or compound path (`*u`) opened after
the last layer and never closed was accepted, and the art inside it was
dropped without a message. The reader now stops with "it ends inside a
group or compound path", as it already does for data that ends inside a
layer. Pattern and symbol definitions, which are read inside a group of
their own, are not affected.
2026-11-02 14:32:56 +07:00
dotCooCoo b9f4ea29f7 Actions: Save Actions… and Load Actions… save a set to a file and load it back
Squashed from #5192 onto main.
2026-11-02 14:32:55 +07:00
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 90179904d8 Actions: the saved current set follows its set when windows merge
When two windows save the preferences, the current set's index and the
list of sets can come from different windows. The index now points at
the same set in the merged list, found by its contents or its name, and
no set is current when the merge cannot tell which set it was. Recording
into, renaming or deleting the current set, or deleting a set before it,
does not override a set the other window made current.
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