Commit Graph
8977 Commits
Author SHA1 Message Date
dotCooCoo 003f709eb2 Docs: give the open's kept-layout timings in CPU cycles on current main 2026-11-08 11:42:46 +07:00
dotCooCoo dbcdbf2466 Open: the first frame uses the layouts the open made for type objects
Opening a document laid out every type object for its bounds and
baselines and threw the layouts away, and the first frame laid the same
objects out again. The open now keeps them, up to 128 MiB, and a frame
takes each one once.

A frame takes a layout only for a text object equal to the one laid out,
and only while the fonts, the system fallback setting and the hyphenation
exceptions are unchanged. When the last frame being drawn ends, the rest
are dropped if a frame took one, and all of them are dropped after eight
frames that take none. A layout with bitmap or color glyphs and a text
object with a gradient are not kept.
2026-11-08 11:42:45 +07:00
dotCooCoo a18364e2b4 Menus: the wasm build has no unused import warning for menu_open
The only callers of `menus::menu_open` are the native palette-window
code in `panel_docking.rs` and its native tests, so on wasm32 the
re-export and the function were unused and `cargo xtask wasm` printed
two warnings for them. Both now carry `#[cfg(not(target_arch = "wasm32"))]`.
The menu bar still records whether a menu is open on every target.
2026-11-08 11:42:45 +07:00
dotCooCoo f4ccca02d0 Docs: the stroke outline reuse line is listed once
The progress doc listed the moved-path stroke outline reuse twice, once
with the timings first measured and once with the timings measured
against current main. The line with the earlier timings is removed.
2026-11-08 11:42:45 +07:00
dotCooCoo e89f917f5e Panels: long swatch, preset and Add Effect popups scroll inside a short window
The gradient swatches menu, the Image Trace button's list of presets, the
Appearance panel's swatch picker and the top level of the Add New Effect
popup (Appearance panel, Properties) had no length limit, so rows past the
bottom of a short window could not be reached. Each now uses menu_scroll.
Items, order and commands do not change, and a list that fits does not
scroll.
2026-11-08 11:42:44 +07:00
dotCooCoo 0b43158fbb Fix #5813: floating panels hide while a tool group's flyout is open
A tool group's flyout and the All Tools drawer draw in the main window,
so a floating panel's OS window covered them. On the desktop, except on
Wayland, floating panels now hide while either one is open, as they do
for a menu or a dialog, and show again when it closes. A flyout or
drawer left set under a hidden toolbar does not draw and does not hide
them.
2026-11-08 11:42:44 +07:00
BFlat e89c036079 Merge pull request #6046 from dotCooCoo/fix/menu-test-font-race
Tests: the Mac menu bar tests do not depend on fonts other tests install
2026-11-08 12:36:55 +08:00
BFlat 6f1b6aa91c Merge pull request #6045 from dotCooCoo/fix/tr-params-row
i18n: the Turkish params and effect errors name their own keys
2026-11-08 12:36:40 +08:00
BFlat d60ec7a808 Merge pull request #6044 from dotCooCoo/fix/paste-many
Paste: skips relinking copies with no renames, global swatches or styles, and finds type in one walk
2026-11-08 12:36:24 +08:00
BFlat 36680d1e02 Merge pull request #6038 from dotCooCoo/fix/issue-5582
Panels: floating panels reopen on the monitor where they were left
2026-11-08 12:36:10 +08:00
BFlat 44b0136554 Merge pull request #6037 from dotCooCoo/fix/delete-empty-check-once
Menus: Delete Empty Artboards' enabled check does not walk the document every frame
2026-11-08 12:35:55 +08:00
BFlat 60303fbe93 Merge pull request #6036 from dotCooCoo/fix/issue-5347
Fix #5347: a floating panel's menu scrolls inside its window
2026-11-08 12:35:40 +08:00
BFlat 2347f968d3 Merge pull request #6034 from dotCooCoo/fix/ai-legacy-break-direction
.ai import: legacy overflow breaks keep the direction and paragraph attributes they were read with
2026-11-08 12:35:25 +08:00
BFlat d9d7c00e41 Merge pull request #6033 from dotCooCoo/fix/dimension-expand-stays-plain
Dimension tool: Expand keeps a dimension as plain art after it moves
2026-11-08 12:35:10 +08:00
BFlat ac11373527 Merge pull request #6032 from dotCooCoo/fix/ai-clip-path-keeps-fill
.ai import: a filled clipping path keeps its fill
2026-11-08 12:34:55 +08:00
BFlat 5ca010d7aa Merge pull request #6030 from dotCooCoo/fix/hex-field-paste
Color fields: a pasted hex code replaces the field's digits
2026-11-08 12:34:39 +08:00
BFlat a0fbeb0c06 Merge pull request #6028 from dotCooCoo/feat/actions-insert-stop
Actions: Insert Stop pauses playback and shows a message
2026-11-08 12:34:24 +08:00
BFlat 9a474f5138 Merge pull request #6024 from dotCooCoo/feat/ai-editing-data-variables
.ai save: the editing copy keeps variables, data sets and bindings
2026-11-08 12:34:08 +08:00
BFlat b63c07c1f9 Merge pull request #6006 from dotCooCoo/fix/ai-brush-art-colors
.ai import: spot colors in a kept brush's art become swatches
2026-11-08 12:33:52 +08:00
BFlat 46057d0453 Merge pull request #5996 from dotCooCoo/fix/ai-type-on-path-options
.ai import: type on a path keeps its effect, alignment and flip
2026-11-08 12:33:38 +08:00
BFlat 06dea5922e Merge pull request #5995 from dotCooCoo/fix/simplify-long-paths
Simplify: fitted curves stay within the tolerance of the path, and serpentines simplify faster
2026-11-08 12:33:23 +08:00
BFlat b019f881d9 Merge pull request #5994 from dotCooCoo/fix/artboard-locked-art-journal
Artboards: duplicate, copy, cut, move and rearrange journal whether locked and hidden art goes
2026-11-08 12:33:12 +08:00
BFlat 427a8a44c5 Merge pull request #5975 from dotCooCoo/fix/ai-reopen-keeps-active-artboard
.ai save: a reopened file opens on the artboard active when it was saved
2026-11-08 12:32:56 +08:00
BFlat 1a46511c5d Merge pull request #5890 from dotCooCoo/feat/execute-checks-params
Engine: execute refuses keys a command doesn't name, in every build
2026-11-08 12:32:40 +08:00
dotCooCoo eb99aaabfd Tests: the Mac menu bar tests do not depend on fonts other tests install
Type › Font and the plug-in rows come from process-wide state, and a test
running alongside can add to them. Two tests read the menus more than once
and compared the reads, so a font added in between failed them:
fonts_that_load_read_the_menus_again adds Vertitest Sans, for one.

every_in_window_item_is_in_the_mac_menu_bar_once now lays out the Mac bar
from the in-window bar it compares it with, so both come from one read.
documents_and_selections_change_state_not_structure changes the document
between its reads, so it runs through undisturbed, which runs it again when
the shortcut, plug-in or font generations change.
2026-11-08 11:22:42 +07:00
dotCooCoo 2af4c12dd3 i18n: the Turkish params and effect errors name their own keys
``params` must be an object` read as "gradyan" and `missing `effect`` read as "isim", the keys of two other rows. Both rows now keep the key in backticks, as the rows next to them do.
2026-11-08 11:22:41 +07:00
dotCooCoo a18fbee3c9 Docs: the paste timing line gives CPU time per paste and undo 2026-11-08 11:22:41 +07:00
dotCooCoo b17a744a9c Panels: floating panels reopen on the monitor where they were left
Squashed from #6038 onto main.
2026-11-08 11:22:40 +07:00
dotCooCoo 2f09d9998e Menus: Delete Empty Artboards' enabled check does not walk the document every frame
The Artboards panel menu asks whether Delete Empty Artboards can run on
every frame while it is open, and each ask measured the document. With
an open path of 200,000 anchors across two artboards, that took 70.4 ms
a frame in a release build.

The answer is now kept per open document with the version of the
document it was measured on, and is measured again when the document
changes. A later frame takes under 0.001 ms. The first frame after an
edit measures once. A change of the selection or the view keeps the
answer.
2026-11-08 11:22:40 +07:00
dotCooCoo 7d8f2a315a Paste: skips relinking when nothing changes and finds pasted type in one walk
A paste relinked every copy to the document's resources even when no
resource had another name or color and the objects linked no graphic
style. It now leaves those copies as they are.

Finding the pasted type looked each id up and compared every text object
with the ones already found. Text commands and the bounds refresh after
a paste now look all ids up in one walk and keep the found ids in a set.
Giving a pasted group new ids builds its map of old to new ids only for
an Objects on Path group, which is the only kind that reads it.

A pasted solid paint with no swatch link and a tint other than 1 now
keeps that tint when no relinking runs. Saved art carries a tint of 1 on
such a paint.
2026-11-08 11:22:40 +07:00
dotCooCoo 2432807197 Tests: the short-window submenu helper names its rows with expect 2026-11-08 11:22:39 +07:00
dotCooCoo 37245779aa .ai import: legacy overflow breaks keep the direction and paragraph attributes they were read with
The reader holds an overflow paragraph break (`(\r) TX`) until more type
follows it. When that type came, the break took the state in force then,
not the state where the break was read:

- A story that started with the break took the `TV` direction of the
  characters after it, so `1 TV (\r) TX 0 TV (Body) Tx` opened horizontal
  and gave no warning.
- A break read in the other direction inside a story did not count as a
  direction change.
- The empty paragraph that the break ended took the attributes of the
  paragraph after it, while `(\r) Tx` keeps its own.

The pending break now records `TV` and, when it ends an empty paragraph,
that paragraph's attributes.
2026-11-08 11:22:39 +07:00
dotCooCoo c952b8d298 Fix #5347: a floating panel's menu scrolls inside its window
The main window's menu floor was stored once for the whole egui context,
so a menu in a panel's OS window stopped at the main window's bottom bars
instead of its own edge. The floor is now kept per window, and a window
with no recorded floor uses its bottom edge. A menu list is also never
taller than the window, so the last items of a menu stay reachable in a
100 pt window, below the 120 pt minimum.

The Digits, Stylistic Sets, Save Selection and Move to Group submenus,
the libraries menu, the Color Guide's Limit to Library menu and the Layers
panel's Filter popup now scroll the same way.
2026-11-08 11:22:39 +07:00
dotCooCoo 09aa816394 Docs: dimensions state when the menus dim Expand and when a dimension stays live 2026-11-08 11:22:38 +07:00
dotCooCoo 9e0e8993b9 Dimension tool: state the Expand rule after object.expand's parameter list
The sentence inside the braces made every_description_parses fail. The object.expand and effect.expandAppearance texts now also limit the replaced-art case to a dimension selected with that art.
2026-11-08 11:22:38 +07:00
dotCooCoo bc9ea516f5 Dimension tool: Expand keeps a dimension as plain art after it moves
Object > Expand left a dimension's recipe on its group, so the next move
redrew the live dimension and discarded the expanded art. Expand now ends
the live link of a dimension whose art it changes, in the same undo step.
Moving or scaling the group leaves its art as it is, the art no longer
follows what it measured, and undo gives the live dimension back.

Expand Appearance, Create Outlines and Outline Stroke had the same fault
and now do the same, also when they reach only a part of a dimension. A
dimension whose art a command leaves as it was stays live. A dimension
selected with the art it measures becomes a plain group when Expand,
Expand Appearance or Outline Stroke replaces only that art.
2026-11-08 11:22:38 +07:00
dotCooCoo bbf4834f12 .ai import: a hidden clipping path's fill leaves with it
The fill read apart from a clipping path that was read on %_ lines, and
the copies of its subpaths, are recorded as read on those lines too, so
the copy of a look's art that is removed takes them along. The file
format notes list a compound clipping path whose subpaths paint
differently among the exceptions to a clipping path keeping its fill.
2026-11-08 11:22:37 +07:00
dotCooCoo 589fd863c4 .ai import: a compound path's plain subpath keeps its fill
In a compound clipping path whose subpaths paint differently, the fill
of a subpath that does not clip was read apart with the clipping
subpaths' fills. Only the clipping subpaths' fills are read apart now,
and a subpath that does not clip keeps its fill, as before.
2026-11-08 11:22:37 +07:00
dotCooCoo b33cdfd14f .ai import: a clipping path's fill read apart keeps its own ids
A fill read apart from a clipping path took a copy of the clipping
path's opacity mask whose art kept the original's ids, so the document
held two objects with one id. The copy of the mask's art, and the
subpaths of a fill read apart from a compound clipping path, now get
ids of their own and stay linked to the same swatches.
2026-11-08 11:22:37 +07:00
dotCooCoo 72959e6e80 .ai import: a multi-layer mask's fill paints once
Each layer a multi-layer mask covers gets a copy of the mask's path, so
a fill kept on that path painted in every layer, over the art the mask
covers in the layers before. The mask's fill is read as a path of its
own again, where the mask's path is, and the copies have no fill. A
fill read apart from a compound clipping path is a compound path whose
subpaths do not clip and have ids of their own. A fill read apart, its
subpaths and their points count toward the importer's object limit.

Docs: docs/file-format-parity.md.
2026-11-08 11:22:36 +07:00
dotCooCoo 6ab82ca71e .ai import: a filled clipping path keeps its fill
The reader took the fill off a clipping path in a file's editing data and
added a copy of the path, holding only that fill, under the art it clips.
A clipping path paints its own fill under the clipped art and its stroke
over it, so the reader now keeps the fill on the clipping path. A filled
clipping path opens as one path instead of two, in a clipping group, a
clipping layer and each level of nested clipping paths. Its note, tags and
gradient stroke (`1 BB`) are on that path as before.

A compound clipping path whose subpaths all paint alike keeps their fill.
When its subpaths paint differently, the fills of the filled subpaths are
still a compound path of their own under the clipped art, so a subpath
the file does not fill stays unfilled. Clipping paths in a compound path
that holds its drawn look still have their fills read as paths of their
own under the art, each with its clipping path's opacity mask.

Docs: docs/file-format-parity.md.
2026-11-08 11:22:36 +07:00
dotCooCoo 97df62547b Tests: the hex paste dialog tests release Enter after each press
A dialog's OK ignores a repeat of Enter, and an egui context keeps a key
down until it is released. The Color Picker, Swatch Options and Define
Grid tests pressed Enter in one context without releasing it, so every
press after the first was a repeat and the dialog stayed open. Each test
now releases Enter after pressing it.
2026-11-08 11:22:35 +07:00
dotCooCoo 0b6a6d44c6 Color fields: a hex paste never goes before a leading #, and a replacing paste drops earlier inserts
With the caret before a # that stays, bare digits are not inserted ahead of it; a full code replaces the text instead. A paste that replaces the field's digits also removes bare-digit pastes kept earlier in the same frame.
2026-11-08 11:22:35 +07:00
dotCooCoo a386b3e955 Color fields: a pasted hex code replaces the field's digits
A click put the caret among the six digits and the text box holds seven
characters, so only the first character of a pasted code went in. The
field then held no new color, and Enter closed the dialog with the old
color. A press on a field drawn before the hex field also dropped what
was typed, while Tab and Enter applied it.

The hex fields of the Color Picker, Swatch Options, Recolor Artwork, the
Color panel, Document Setup, Duotone, Color Themes and Perspective Grid
now share one set of rules:

- A click or keyboard focus selects the digits.
- A code of six digits, with or without #, replaces the digits wherever
  the caret is.
- A code of three digits also replaces them, unless the paste holds only
  those digits and exactly three digits stay. Those digits then edit the
  text in place.
- A paste of only one, two, four or five digits edits the text in place
  when it does not cover all of the text and the result has at most six
  digits.
- Any other paste leaves the field as it was.
- A press elsewhere commits the text in the frame of the press.
- A commit returns the digits without # and writes a three-digit code out
  as six, so Duotone reads a typed # and Perspective Grid, whose parser
  reads six digits only, takes a three-digit code.

Part of #5013
2026-11-08 11:22:35 +07:00
dotCooCoo 7d1f2062e3 Actions: Insert Stop pauses playback and shows a message
Squashed from #6028 onto main.
2026-11-08 11:22:34 +07:00
dotCooCoo fe0f3d919c .ai save: the editing copy keeps variables, data sets and bindings
Squashed from #6024 onto main.
2026-11-08 11:22:34 +07:00
dotCooCoo 57dbbbb41b Docs: .ai brush art spot color limits
The file-format entry states the 20,000-name limit across brush art and per section, the first-definition rule, and that colors past the limit still count toward the color mode.
2026-11-08 11:22:33 +07:00
dotCooCoo 8a34c89d7c .ai import: remove the duplicated editing-copy paragraph 2026-11-08 11:22:33 +07:00
dotCooCoo 77b72da70d .ai import: Stair Step spacing is fitted from its glyphs' origins
Stair Step's glyphs stay upright, so their matrices never show the path
turning and the spacing fit found no turn at all. The fit now takes the
path through each glyph's origin, which lies on the path, and measures
how far it turns over a step from the circle through three origins in a
row.
2026-11-08 11:22:32 +07:00
dotCooCoo d180ad456e .ai import: brush art brings at most 20,000 color names, each once
Each brush art section keeps only the first definition of each color name, and at most 20,000 names. The art of the brushes that come in brings at most 20,000 different color names in all, every section's color operators before any section's gradient stops, so art that no brush uses or that a later section replaces takes no places. Colors left out still count toward the color mode.

A test also checks that a global process color which only a brush's art defines with its color operator stays a process color when a gradient stop names it.
2026-11-08 11:22:32 +07:00