The SVG writer always wrote the document's title in <title>
(crates/svg/src/export.rs), so every file of Export As with Use
Artboards, Export for Screens or an `artboard`/`range` export was titled
after the document ("Icons"), whatever its artboard was called. The
writer's `artboard` option can't tell those apart from Save: Save writes
the first artboard too, standing for the whole document.
ExportOptions has a new `artboard_title` (set by the caller, as
`artboard` is, not deserialized): the file is that one artboard, exported
on its own, and its <title> is the artboard's name (XML-escaped as
before), or the document's title when the artboard has no name. The
engine's SVG encoder (fileio/svg.rs) sets it exactly when the export
names its artboards, which is also when a file holds only that
artboard's art (#550): Export As per artboard, document.export /
serialize with `artboard` or `range`, MCP export, and Export for Screens'
artboards, assets, layers and selections (each written as an artboard
named after it). Save and Save As keep the document's title. Export for
Screens' Full Document draws the art bounds as one artboard, which is now
named after the document, so its SVG keeps the document's title too.
docs/file-format-parity.md's SVG row says so.
Tests: title_control_chars::an_artboard_exported_alone_is_titled_after_it
(crates/svg: two named artboards, the second named with markup;
exporting either alone gives its escaped name, the default and an
artboard without artboard_title give the document's title, an unnamed
artboard falls back to it) and
tests_svgenc::an_svg_of_one_artboard_is_titled_after_it (the engine:
`artboard` 0 and 1, useArtboards range all, Save's SVG, Export for
Screens per artboard, an asset and Full Document). Both fail without the
change (the title was "Icons") and pass with it.
Review follow-up (CodeRabbit): step_value clamped once after all of a
frame's steps, so at the lower bound a step down then a step up in the
same frame left the field at the bound. Each step is now clamped as it is
applied. The Stroke panel test steps down and up in one frame at each
bound and expects one step above it; it fails without the change.
Wheel notches and the arrow keys over a focused number field step the
value its text shows (widgets::step_value), and nothing there knew the
field's bounds: the Stroke panel's Weight went on to -3 pt and its Limit
to 0 x in the field, while the panel only clamped what it applied (the
spinner's min, Limit's clamp to 1..500), so the next step went on from
the out-of-range text. A label scrub (scrub::field) had the same gap.
step_value and scrub::field now take the field's bounds and stop at
them, so the field shows where they stopped and the value applied is
the same. The fields that have bounds pass them:
- spin_field / spin_field_auto / spin_plain: their `min` (the spinner
and a typed value already stopped there);
- range_field: its range; it now also takes a value that may be blank
(None), as mixed_field does;
- opt_field (dash and gap lengths): 0;
- the Revolve dialog's values: their range.
Fields that clamped only what they applied now say their range with
range_field instead: the Stroke panel's Limit (1..500), the Transparency
and Properties opacity (0..100), the Transform panel's polygon sides,
and the dialogs' bounded counts, percentages and lengths (Blend Options,
Envelope, Flattener, Liquify, Freehand, Live Paint, Path ops, Perspective
Grid, PNG ppi, Print, Save for Web, Shape Builder, Slices, Swatch
Options, Symbol options, Justification, Dimension, PDF page, the effect
dialogs' number rows). docs/ui-parity.md's number-field row says so.
Test: panels::stroke::tests::the_wheel_stops_weight_at_zero_and_limit_at_one
(the Stroke panel in a headless frame; focus Weight at 1 pt and turn the
wheel down four notches: the field shows 0 pt and the stroke is 0 pt;
the same with Limit at 2 x: 1 x and a limit of 1). It fails without the
change (the field showed -3 pt) and passes with it; the other numeric
field, scrub and dialog tests still pass.
The MCP drawing tools ran the creating command (path.create, shape.*)
and only then paint.setFill, paint.setStroke, stroke.set,
object.setProps and effect.apply, each as a command of its own.
check_draw_options checked dash, cap, join, opacity, name and effects up
front, but not the paints: a fill or stroke the engine can't read
(stroke: "currentColor"), or a swatch the document lacks, failed after
the object was made, so the call returned an error and left the path,
its undo step and its SVG node behind. Each styling command was also an
undo step of its own.
The tools now send the creating command and the styling commands as one
command.batch (crates/mcp/src/tools.rs, draw): the engine rolls the
whole batch back when a step fails, so a refused paint leaves no object,
no undo step and nothing in the SVG, and a good call is one undo step
named as the creating command names its own (Pen, Rectangle, …). The
styling steps act on the new object, which the creating command selects,
with item: null (its whole appearance), as the ids did before. The
reply gives the failed step's own error, without the batch's prefix.
docs/mcp.md says so.
Test: tests_drawopts::a_bad_paint_draws_nothing (invalid fill, stroke,
a missing swatch and a non-numeric strokeWidth on draw_path and
draw_shape: error, node count, undo history and SVG export unchanged;
a good call adds one undo step named Pen / Rectangle). It fails without
the change (draw_path with stroke "currentColor" drew a path) and passes
with it; the other draw option and command_batch tests still pass.
An export through the desktop save panel kept any typed extension
that names a known format, whatever format it wrote. Export As with
PNG chosen and card.svg typed wrote PNG data to card.svg, and Save as
PDF, Save for Office Documents, Text Export Options, Export Library
and the other writes that go through pick_path did the same.
document.exportSelection with a format suggested and added .png
whatever the format.
Such an extension is now replaced with the written format's, as Save
As has done since #3372: card.svg is written as card.png. An extension
of the written format stays as typed in any letter case (photo.JPEG
for JPEG), Export As SVG (and file.exportAs, file.export.svg) keeps
art.svgz and writes it compressed, and document.exportSelection
without a format still writes the format the typed extension names.
With a format, it suggests and adds that format's extension.
Docs: docs/target-app-parity.md.
File › Package… read every linked file and font and wrote the package
on the UI thread, so the window stopped responding until the package
was written. For a document that links 50 images of 21 MB each, OK
with Background Export off, which does the same work, takes a median
of 2.25 s in a release build on Windows.
With Enable Background Export on (Preferences › File Handling), OK now
takes the options, the report's Document Info text and a snapshot of
the document, and closes the dialog. The thread that writes background
saves and exports then collects the links and fonts and writes the
package. The same OK takes 0.001 s, and the package holds the same
bytes. A save of unsaved changes that Package starts is written first.
With the preference off, on the web and over MCP and scripts, the
package is made at once with the same reply as before.
Docs: docs/target-app-parity.md.
With the Artboard tool, Paste and Paste in Place select the pasted
artboards, Cut gives the tool the artboard before the first cut one
(the new first artboard when artboard 1 is cut), and tool.setOption
sets its selected or active artboard. The active artboard, the view's,
stayed where it was, so the navigator showed another artboard than the
tool and the Artboards panel. document.activate and File › Revert
started the tool on artboard 1, while choosing a document's tab starts
it on that document's active artboard.
After a command that changes the artboards the Artboard tool has
selected, the app now makes the tool's active artboard the active one,
as a click with the tool does. After a command that chooses another
document, and after Revert, the tool starts on the document's active
artboard.
Docs: docs/mcp.md, docs/target-app-parity.md.
The Layers list scrolls in its own scroll area, which kept egui's floating
scroll bar when #3093 gave the panel bodies a bar in a column of their own.
Hovering the list showed the bar over the right edge of the rows, over the
target circles and the selection squares the user clicks to select a layer.
The list now uses the menus' slim solid bar (list_scroll_style) in its own
column, and the rows end beside it. The list knows its total height before
it lays the rows out, so the bar is shown exactly when the rows overflow
(decided up front): the rows never shift sideways a frame after the bar
appears.
Test: dock::tests::the_layers_scroll_bar_covers_no_row (40 layers in a
1440x600 window: no row's accessibility rect intersects the bar). It fails
without the change and passes with it. The Layers tests that pin row
positions across frames still pass. Checked live: the bar sits beside the
rows.
With the pointer resting over art while the view moves (trackpad or wheel
scrolling, pinch zoom, a Hand/space pan), the document point under the
pointer changes every frame, and the canvas hit-tested the art there on
each one, up to three times: Object Highlighting (canvas.rs
hover_highlight -> selection_hit_at) and the Selection tool's cursor
(select.rs cursor: hit_test, and with Snap to Point the nearest-anchor
search). Over a detailed engraving in a clip group (the reporter's
PhotoCraft icon: one path of tens of thousands of segments) each of those
costs roughly 3-6 ms, so every frame of the move took 12-15 ms of UI time;
off the art they return at once.
- canvas.rs: the canvas notes when its view (rect, zoom, centre,
rotation) last changed. Until it has been still for HOVER_STILL_SECS
(0.15 s) it draws no hover highlight and keeps the cursor the tool last
gave for the same tool and modifier keys instead of asking again; it
asks for a repaint then, so both come back without the pointer moving.
Pointer moves still reach the tool as before.
- test: a_moving_view_leaves_the_art_under_the_pointer_unhighlighted_until_it_stops
(wheel frames draw no hover outline and keep the cursor; once still,
the outline returns and the cursor follows the art). It fails on main
at the first wheel frame.
Measured on an Apple M4 (release build, 1440x900 window, the PhotoCraft
app icon SVG fitted at 138%, Selection tool, Smart Guides and Snap to
Point on), median UI frame time over 60 wheel-pan frames with the pointer
resting:
before: over the art 12.3-15.0 ms, off the art 1.0 ms
after: over the art 0.4-1.0 ms, off the art 0.6 ms
The render readout is the art's own raster time on the render worker,
which this change doesn't touch.
The panels' scroll areas used egui's default floating scroll bar, which
is drawn over the right edge of the content: in a window too short for
the Properties panel it covered the Image Trace button's dropdown arrow
and the W/H constrain link, and in a dock column too tall for the window
it covered the panels' menu buttons and right-hand controls. Menus
(#2086, list_scroll_style) and the toolbar and dock icon column (#808,
strip_scroll) had already been given bars that keep clear of their
items; the panel bodies hadn't.
- widgets: panel_scroll shows a panel's scroll area with the menus' slim
solid bar (list_scroll_style), in a column of its own at the right
edge; scroll areas inside the body keep their own style.
- dock.rs: the docked Properties panel and Properties in a flyout,
floating group or shared dock group use it.
- floating.rs: a dock column too tall for the window uses it.
- panel_docking.rs: a panel's body in the shared dock uses it, laid out
as wide as the scroll area leaves beside the bar; the shared dock's
icon column scrolls with strip_scroll, as the dock's icon column does.
- test: the_properties_scroll_bar_covers_no_control (a 1440x600 frame of
the dock with an image selected: no control's rect meets the
Properties scroll bar). It fails on main with "Tracing Presets" (the
Image Trace arrow) and "Constrain Width and Height Proportions" under
the bar.
Verified live at 1440x600 with an image selected: before, the hovered
bar sat over the Image Trace arrow and the right ends of the Quick
Action buttons, and a dock column's bar over the Swatches panel menu;
after, both bars sit in their own 8 pt column and nothing is covered.
With the Artboard tool the arrow keys did nothing to the artboards: the
tool claimed only Escape, Delete and Backspace (tools/src/xform/artboard.rs
claims_key), so the arrows fell through to object.nudge in
ui-egui/src/shortcuts.rs, which moved the selected art on its own (or
nothing, with no art selected) and left the artboard where it was.
- artboard.rs: the tool claims the arrow keys and turns each press into
one artboard.move of the selected artboards that aren't locked, by the
keyboard increment (Preferences > General > Keyboard Increment, read
from the tool context as Touch Type does), Shift ten times as far as
object.nudge does, with moveArt from the tool's Move/Copy Artwork with
Artboard option, as a drag sends it. One undo step per press; nothing
during a drag or with only locked artboards selected.
- tests: arrow_keys_nudge_the_selected_artboards (tools: claims, step,
Shift, moveArt, several boards, locked, mid-drag) and
artboard_tool_arrow_keys_move_the_selected_artboards_with_their_art
(engine: the artboards and the art on them move, one step per press).
Verified live over --control: a 400x300 artboard with a selected 40 pt
square, Artboard tool, ArrowRight: before, the artboard stayed at x 0 and
the square moved to x 51 ("Move"); after, the artboard goes to x 1 and the
square with it ("Move Artboard"); Shift+Down moves both 10 pt; with
Move Artwork off only the artboard moves; increment 5 moves 5 pt.
The drag case in the report: a drag already moves the art, but only the
art that lies wholly inside the artboard and is unlocked and visible
(doc/src/lib.rs art_on_artboard; locked and hidden art only with
Move Locked and Hidden Artwork with Artboard). Art overlapping the
artboard's edge stays behind by design, which may be what the reporter
saw when dragging.
## Summary
When the Paragraph and Properties panels act on multiple paragraphs with different hyphenation settings, the Hyphenate checkbox is off, matching Illustrator mixed-value behaviour alongside mixed indents, alignment and composer. Toggling still applies through `text.setFormat` to every paragraph in scope.
## Tests
- `paragraph_mixed_hyphenate_checks_off` in `vectorcraft-ui-egui` paragraph panel tests.
Part of gap G4
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
Adobe help documents Area Type and Type on a Path as starting from a click on the path or shape border, not inside a filled interior. Restore outline-only hit testing for those tools (no fill-interior hits that would steal point-type clicks). Strokeless filled paths still accept clicks on the outline.
## Tests
- area_and_path_tools_hit_path_outline_not_fill_interior
Part of storytold/vectorcraft#3505 (review feedback on PR #3534)
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
Area Type and Type on a Path locate the path under the click with the same hit rules as the other tools, so a filled shape with no stroke can be clicked in its interior. Illustrator accepts those clicks for area type and for type on a path (the start follows the click on the path). VectorCraft had forced outline-only hit testing here, so interior clicks missed and the tools fell back to ordinary point or area text with placeholder copy.
## Tests
- type_on_path_and_area_type_hit_filled_paths_without_a_stroke in vectorcraft-tools
Closesstorytold/vectorcraft#3505
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
The fill/stroke chip popover no longer closes while the pointer is down, a panel paint drag is active, or the opening click is still on the chip anchor, so dragging fill onto stroke (or the reverse) inside the popover can finish. Color Picker proxies are not added; the reference app edits only the colour the picker was opened for.
## Tests
- panels::tests::dropping_a_proxy_paint_on_the_other_proxy_applies_it (unchanged)
Closesstorytold/vectorcraft#3440
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
Illustrator lets you drag the fill colour onto the stroke (or the other way) in the Color Picker and in the fill/stroke chip popover. VectorCraft now shows the Fill/Stroke proxy pair in the Color Picker (except for artboard background edits) and applies paint.setFill or paint.setStroke when a proxy paint is dropped on either square; clicking a square switches which side the picker edits. The fill/stroke chip popover stays open while the pointer is down, while a panel paint drag is active, or when the opening click is on the chip anchor, so drags between the proxies can finish.
## Tests
- color_picker_proxy_drag_applies_fill_to_stroke (headless egui)
- existing dropping_a_proxy_paint_on_the_other_proxy_applies_it unchanged
Closesstorytold/vectorcraft#3440
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
Replace length/angle with Length X/Y, reference point, Type, Base Along, Slope and Fill Arc; extend geom and shape.arc params.
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
A click on the artboard with the Arc tool (no drag) opens an Arc options
dialog at the pointer, matching Illustrator. Length, angle, and Closed
follow the same form as Line Segment; OK runs shape.arc and remembers
Closed via tool.setOption.
## Tests
- dialogs::tests::arc_click_opens_options_and_ok_draws
- Existing draw2::family::tests::click_opens_dialog_and_arc_shift (tools)
Part of gap G11
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
Exporting a CMYK document to PDF/X-1a or PDF/X-3 flattens transparency
first. Where the flattener has no single colour (an image with see-through
pixels over a flat fill, gradients, masks, raster effects) it renders the
area into an image, and that image was always an RGB PNG. The PDF writer
then separated it back to CMYK, so CMYK art behind the image came back with
other inks: a C100 M6 Y41 K3 panel printed C75 M14 Y35 K5 under a
transparent logo, with a hard edge against the rest of the panel, and K
moved into C, M and Y.
For files without transparency the flattener's images are opaque and
clipped to their regions anyway, so in a CMYK document it now draws them
as ink amounts over the paper (Renderer::render_region_inks) and stores a
CMYK TIFF, which the PDF writer keeps as DeviceCMYK samples. An area too
large for a CMYK image falls back to the PNG it made before. In-app
Flatten Transparency and other flattening, whose images keep alpha, are
unchanged.
Test: tests_pdfx::pdfx_1a_flattening_keeps_the_inks_behind_an_image_in_a_cmyk_document
exports a CMYK panel under a half see-through PNG to PDF/X-1a, opens the
file again and checks the inks behind the see-through half.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
## Summary
When the Paragraph panel menu acts on multiple paragraphs with different composers (single-line vs every-line), neither composer item is checked, matching Illustrator mixed-value behaviour and the panel's other mixed fields (indents, alignment).
## Tests
- `paragraph_mixed_composer_checks_neither_menu_item` in `vectorcraft-ui-egui` paragraph panel tests.
Part of gap G4
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
ui.libraryPanel.locate decided whether a panel's library was missing
through missing_file, which answers only for a persistent panel. A
command that turns Persistent off leaves the panel open on its missing
library until the next drawn frame closes it, and while the window is
hidden the app draws no frame between control requests. Locate
Library… on that panel answered "isn't missing its library" and read
no file.
The check now asks whether the panel's library can be found, the
lookup the tab label and the per-frame tidy use. A panel whose library
is there is still refused, persistent or not.
window.swatchLibrary and window.graphicStyleLibrary had the same
check: given the library id of such a panel, they answered "no
library". They now bring the open panel forward and answer its file's
name with count 0; the panel still closes at the next tidy.
Docs: docs/mcp.md (ui.libraryPanel.locate, window.swatchLibrary).
## Summary
Package status notes are parenthetical fragments joined with spaces; templates without {note} are used when there are no missing links or skipped fonts, so folder paths are not followed by stray spaces or double gaps.
## Tests
- package_status_without_notes_has_no_extra_spaces
- package_status_message_templates_parse extended
Closesstorytold/vectorcraft#3494
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
Package completion status and the show-folder prompt use i18n templates with
literal text between {folder} and {note}, so @msg rows parse and translate in
every locale (Illustrator-style localized status feedback).
## Tests
package_status_message_templates_parse; dialogs::tests_package; complete_languages_translate_every_message.
Closesstorytold/vectorcraft#3494
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
Swatch library panels title imported and User Defined .acb color books from the file name (without the extension), matching Illustrator. Host temporary import paths still fall back to the book title when copying into the user library folder (#2996).
## Tests
- `color_book_tab_titles_use_the_file_name` covers user-folder scan, load by path, and copyToUser keeping the source file name.
- Existing `copying_a_color_book_from_a_temporary_path_uses_its_title` unchanged.
Closesstorytold/vectorcraft#3395
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
document.open with a path that is already open in another tab now activates
that document instead of reading the file again and opening a second window,
matching Illustrator Home › Recent Files when the file is already open.
The result includes activated: true; unsaved edits and the active tab are kept.
## Tests
open_same_path_activates_existing_document in cmd::fileio::tests.
Closesstorytold/vectorcraft#3455
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
The panels and dialogs draw in their own egui families (`ui`,
`ui-semibold`, `mono`), and egui panics drawing text in a family no
font is bound to. Only `theme::install_fonts` binds them, and only
`VectorcraftApp::logic` calls it, on its first frame. An embedder that
draws the panels or dialogs itself (`dialogs::show`, a panel's `ui`)
on its own context, without `logic`, panics on the first semibold
title it draws, an effect dialog's for one. Calling `install_fonts`
avoids that, but it embeds the interface's five faces (about 2 MB)
whatever the embedder wants: today such an embedder keeps them out of
its binary only by never calling it, so that the linker drops them.
vectorcraft-ui-egui gets an `interface-fonts` feature, on by default,
that embeds those faces. Without it `install_fonts` binds the same
three families to egui's built-in fonts, so an embedder can always
call it. Those lack some symbols the panels show (→ ▾ ● ✓), which the
docs say. With the feature, `install_fonts` installs exactly what it
did before: the same font data and the same family stacks.
`tests/install_fonts.rs` draws an effect dialog on a context only
`install_fonts` prepared, and checks the face at the head of each
family in both configurations. `cargo xtask ci`'s `no-bundled-fonts`
step runs it without default features and lints the crate that way.
Without the `install_fonts` call, or without the semibold binding,
both tests fail with egui's "FontFamily::Name(\"ui-semibold\") is not
bound to any fonts". The two lib tests about the interface faces are
adjusted: the graphics-loss test checks a family install_fonts binds,
and the catalogs' glyph coverage test needs `interface-fonts`.
docs/development.md says when an embedder calls `install_fonts`, and
that it replaces the context's font definitions.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Review feedback on #3498: dimmed neighbours share one opacity composite
before the centre tile and one after, preserving overlap paint order
without per-copy compositing.
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
## Summary
In pattern editing mode, preview copies were drawn in row-major order and the
centre tile was always composited on top, so Pattern Options Overlap had no
visible effect when negative spacing made tiles overlap (as in Illustrator).
Preview copies now paint in the same order as tiled pattern fills.
## Tests
- vectorcraft-doc: preview_paint_order_respects_overlap
Closesstorytold/vectorcraft#3480
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>
Add the 13 Japanese rows the Keyboard Shortcuts dialog (File > Keyboard
Shortcuts...) and the Print dialog's overprint note were missing, so they no
longer fall back to English. Wording follows the catalog's existing terms
(初期設定, 競合, ショートカット).
Drafted with AI assistance; native-speaker review welcome.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K5NRZNWfaSLBWVzV8hivyS
Exercise Selection-tool busy state before takeover and verify it is idle after tab activation, drop, Escape and outside release. Session::set_active already reconstructs the tool via reset_tool_for_doc_switch, so the reported missing-Up busy state does not reproduce and no additional synthetic release is needed.
Narrow documentation to the internal clipboard asserted by the regressions and correct the stationary-pointer sentence. All 10 cargo xtask ci gates pass.
With the Artboard tool, a Ctrl/Cmd double-click on the name of an
artboard that was not selected added it with the first click and took
it out again with the second, so the name field renamed that artboard
alone. The panel menu's Rename opened the field on the active artboard
even when it was not selected. Paste with the Artboard tool leaves it
outside the selection: it selects the pasted artboards and keeps the
active one. Rename then renamed the active artboard alone.
The second click of a Ctrl/Cmd double-click now leaves the row's
artboard selected, and the field renames the selection with it. A
Ctrl/Cmd double-click on a selected row works as before. When the
active artboard is selected, Rename opens the field on its row;
otherwise Rename opens the field on the first selected row.
Docs: docs/target-app-parity.md.
path.create read closed only when it drew from anchors. Given path
data, {"d": "M0 0 L10 0 L10 10", "closed": "true"} drew the path and
recorded an undo step, while the same closed with anchors fails with
"`closed` must be true or false". shape.rectangularGrid and
shape.polarGrid read rows, columns, concentric and radial given as text
as the count left out, so {"rows": "3"} drew the default 5 horizontal
dividers instead of 3.
path.create now checks closed before it reads d or anchors, and the
grid commands refuse such a count with "`rows` must be a number, not
"3"". Neither command changes the document or its undo history then.
With d, a closed of true, false or null still leaves the path as its
path data draws it.
Docs: docs/mcp.md, docs/target-app-parity.md.
Add the three Turkish catalog entries requested by the maintainer on #3479. Preserve upstream catalog additions and place existing tab-drag entries beside stable menu labels to avoid append conflicts. Update feature progress notes for all 24 catalogs.
Simplify an equivalent Effect Gallery selection predicate required by the Rust 1.95 clippy gate. Full cargo xtask ci passed all 10 checks, including tab-drag regressions and wasm.
## Summary
Linux file portals grey out files that do not match the open dialog's default
filter. Other Library… and Locate Library… used File › Open filters, whose
first entry is All readable files and omits swatch-library extensions such as
.ase. Add library_open_filters with the library formats first (matching
Illustrator's Swatch Libraries › Other Library…) and use it from swatch and
graphic style library pickers.
## Tests
- engine: library_open_filters_list_library_formats_first
- ui-egui: other_swatch_library_asks_off_the_ui_thread asserts Swatch libraries
is the default filter and includes ase
Closesstorytold/vectorcraft#3465
Co-authored-by: nrq6993-a11y <nrq6993-a11y@users.noreply.github.com>