Commit Graph
6772 Commits
Author SHA1 Message Date
BFlat 7eb87ab657 Merge pull request #4774 from dotCooCoo/fix/clipboard-text-only-macos
Clipboard: TEXT_ONLY is built on Linux only, so clippy passes on macOS
2026-10-31 06:46:54 +07:00
dotCooCoo de72fc3998 Clipboard: TEXT_ONLY is built on Linux only
The constant is used only by the Linux Wayland arms, so on macOS it is
dead code and `cargo clippy -p vectorcraft --all-targets -- -D warnings`
fails with "constant `TEXT_ONLY` is never used". Gate it with
`#[cfg(target_os = "linux")]`, as the `Wayland` variant beside it is.
2026-10-31 06:28:35 +07:00
BFlat 7b95f9c059 Merge pull request #4768 from dotCooCoo/fix/paintbrush-alt-smooth
Paintbrush: Alt held at the press smooths a selected path
2026-10-31 06:27:41 +07:00
BFlat 3f3a9f6550 Merge pull request #4772 from dotCooCoo/fix/escape-cancel-skips-tool
View: Escape that cancels a ruler or Tools move does not reach the tool
2026-10-31 06:27:30 +07:00
BFlat 3d051a70a3 Merge pull request #4770 from dotCooCoo/fix/backtick-mid-drag-preview
Canvas: pressing or releasing backquote mid-drag updates the live preview
2026-10-31 06:27:14 +07:00
BFlat 998b9536a6 Merge pull request #4769 from dotCooCoo/fix/legacy-ai-colorized-pattern-tiles
Legacy .ai: colorized image pattern tiles keep their color
2026-10-31 06:26:58 +07:00
BFlat ee85476ac4 Merge pull request #4771 from storytold/feat/addon-path-effects
Add-ons: Path Precision Tools — live path effects
2026-10-31 06:26:41 +07:00
dotCooCoo 51b6bbdd17 Paintbrush: Alt held at the press smooths a selected path
With a path selected that the Smooth tool can change, Alt held at a
Paintbrush press now switches the drag to the Smooth tool: it smooths the
selected paths under the drag with the Smooth tool's radius and Smooth Tool
Options' Fidelity, and the cursor shows the Smooth tool before the press.
Alt pressed after a stroke begins still closes the path on release. With no
such path selected (nothing, only text or an image, or only a two-point
line), Alt at the press draws the closed stroke as before.

The Paintbrush no longer reads the Pencil's "Alt key toggles to Smooth Tool"
setting: its Alt close and Alt smoothing do not depend on it.
2026-10-31 06:11:00 +07:00
dotCooCoo a072cf16be View: Escape that cancels a ruler or Tools move does not reach the tool
An Escape that cancels a ruler-origin drag or a floating Tools panel move
now stops there: the active tool does not receive it, so a tool's own
Escape action (for example Intertwine returning to the Selection tool)
waits for the next press. The ruler-origin test also covers the drawer
and Global Edit.
2026-10-31 06:10:57 +07:00
dotCooCoo 501ae57fef Canvas: pressing or releasing ` mid-drag updates the live preview
A Selection or transform drag held still now gets another drag event when
the backquote key goes down or up, as it already did for Shift, Alt,
Cmd/Ctrl and Space, so the preview switches between a pattern-only and an
ordinary transform without waiting for the next pointer move.
2026-10-31 06:10:53 +07:00
dotCooCoo 7584b6335e Legacy .ai: colorized image pattern tiles keep their color
Saving a legacy .ai with transparent images flattened expands pattern
fills whose tile image is see-through or has opacity or a blending mode,
so the tile images flatten with the art under them. A pattern whose tile
is an opaque grayscale image with a colorize paint was not expanded, so
the writer drew the source gray pixels over white. A colorize paint now
counts too.
2026-10-31 06:10:51 +07:00
bflatastic e13c4bc9d0 Add-ons: Path Precision Tools — live path effects 2026-10-31 06:10:47 +07:00
BFlat 72f4159570 Merge pull request #4767 from storytold/feat/flatpak-version-pins-access
fix(flatpak): allow reading launcher version pins
2026-10-31 06:09:38 +07:00
BFlat a557617340 Merge pull request #4765 from dotCooCoo/fix/pdf-colorize-mask-failure
PDF export: leave out an object whose opacity mask lost an image
2026-10-31 06:09:22 +07:00
BFlat a497f3991c Merge pull request #4764 from dotCooCoo/fix/pdf-colorize-cache-reject
PDF export: cache colorized images that can't be exported
2026-10-31 06:09:07 +07:00
BFlat b45658a87b Merge pull request #4766 from mockydevs/fix/testkit-temp-dir-private-setup
Testkit: the temp_dir test pre-makes a private directory, as temp_dir does
2026-10-31 06:08:51 +07:00
Dylan M. Taylor 4d61f4b2f6 fix(flatpak): allow reading launcher version pins 2026-10-31 05:42:54 +07:00
Dylan M. Taylor a61c912f82 fix(flatpak): allow reading launcher version pins 2026-10-31 05:42:54 +07:00
dotCooCoo fa89546397 PDF export: leave out an object whose opacity mask lost an image
An unclipped opacity mask is drawn on a white backdrop. When an image in
the mask art could not be written (a colorized image whose color channel
is over the size limit, an image that can't be decoded, or one placed
beyond the coordinates a file holds), the backdrop stayed white and the
masked object showed in full where the image should hide it.

The exporter now records an image left out while it writes mask art,
and leaves the masked object out instead of applying the incomplete
mask, with a warning. A failure in a nested mask makes the outer mask
incomplete too.
2026-10-31 05:42:51 +07:00
dotCooCoo 7d706ffa26 PDF: colorized images that can't be exported are cached as missing
colorized_image returned before its cache insertion when the image was
missing, left out or undecodable, or when its color channel was larger
than MAX_RASTER_ALLOC. Every placement of such an image then decoded it
and computed its coverage again. Both cases now cache None for the key,
as load_image does.
2026-10-31 05:42:41 +07:00
Don Omondi 20f7f8be1e Testkit: the temp_dir test pre-makes a private directory, as temp_dir does
a_temp_dir_starts_empty_in_a_process_and_stays_for_later_calls
pre-created the "earlier process" directory with create_dir_all, which
under a usual umask gives others access, so temp_dir refused it as not
private and the test failed on every Unix run (main's CI included).
The test now makes it with mode 0o700; temp_dir and the assertions are
unchanged.
2026-10-31 05:42:38 +07:00
BFlat 2ced6b67e4 Merge pull request #4763 from mockydevs/fix/pdf-knockout-groups
PDF import: take a group's knockout and isolate flags from the interpreter
2026-10-31 05:41:37 +07:00
Don Omondi b0cc17343e fix(pdf-import): take a group's knockout and isolate flags from the interpreter
The import read each form's /Group /I and /K from the file in order and
matched them to the transparency groups the interpreter pushed. The
interpreter draws a group that adds nothing (full opacity, Normal, no
mask, neither flag) straight onto its parent without pushing it, so every
group after one took another group's flags. Blend steps written as a
knockout group of falling opacity then painted over each other and drew
as solid dark shapes instead of light rings.

The interpreter already reports the flags right after pushing a group
(set_knockout, set_isolated); the import now uses those and drops the
file-order list. That list was capped at 10,000 entries, past which a page
failed to import; that limit goes with it.
2026-10-31 05:27:13 +07:00
BFlat aee88d4bdf Merge pull request #4760 from mockydevs/fix/eps-blend-layer-state
.ai/EPS import: a layer's state after its last blend stays the layer's
2026-10-31 05:26:38 +07:00
Don Omondi d4745fe046 fix(eps): a layer's state after its last blend stays the layer's
#4757 gives a blend the Xy written after its record. When the blend is a
layer's last object, the layer's own state block (Xy, Xd, 7 () XW, LB)
went to the blend instead, and the layer stayed opaque. The blend's state
is now tentative like a mesh's (#4748): its own 6 () XW confirms it, the
layer's LB gives it to the layer and the blend keeps what it had.

Also records the .ai/EPS audit fixes under G9, the File formats row and M4.
2026-10-31 05:11:04 +07:00
BFlat 60bccc60c4 Merge pull request #4759 from mockydevs/fix/ai-layers-vs-page
.ai import: compare a PDF of some artboards on the artboard its page shows
2026-10-31 05:09:48 +07:00
Don Omondi aa6a960062 fix(ai-import): compare a PDF of some artboards on the artboard its page shows
A PDF saved with Illustrator editing data for only some of its artboards
has pages for those artboards, while the editing data keeps them all. The
layers were compared with the first page on the first artboard, so a page
showing a later artboard never matched and the file came in as its PDF
part, without its layers.

With fewer pages than artboards, the first page is now taken to be the
artboard of its size whose art draws most like it (up to 16 weighed), and
the pages' type goes to that artboard and the ones after it. All the
artboards still come in, and the comparison still decides whether the
layers are used.
2026-10-31 04:55:14 +07:00
BFlat f1b7bd8aa7 Merge pull request #4757 from mockydevs/fix/eps-blend-state
.ai/EPS import: a blend takes the transparency written after its record
2026-10-31 04:54:39 +07:00
Don Omondi c4d2480132 .ai/EPS import: a blend takes the transparency written after its record
Squashed from #4757 onto main.
2026-10-31 04:39:05 +07:00
BFlat 1347e006ed Merge pull request #4756 from mockydevs/fix/eps-masked-mesh-state
.ai/EPS import: a masked gradient mesh takes the transparency after its mask
2026-10-31 04:38:31 +07:00
BFlat c60bdc8b81 Merge pull request #4758 from storytold/feat/addon-corner-tool
Add-ons: Path Precision Tools — Corner Tool and Slide Anchor
2026-10-31 04:38:11 +07:00
Don Omondi a1fc3cfdb1 fix(eps): a masked gradient mesh takes the transparency after its mask
A gradient mesh with an opacity mask has its own state (`Xy`) after the
mask's dictionary, not right after its `/End X!`. The operators of the
mask's art, on `%_` lines, cleared the flag that says a mesh just ended,
so the state was read as the next object's and each masked mesh in a
run drew with the blend mode of the one before it.

The flag now goes back to what it was when a dictionary opened once it
closes, as `after_object` does.
2026-10-31 04:21:56 +07:00
bflatastic c9dc4fa857 Add-ons: Path Precision Tools — Corner Tool and Slide Anchor
Path Precision Tools gains two tools, kept out of the toolbars (All Tools
drawer and Object › Plug-ins › Path Precision Tools, no shortcuts):

- Corner Tool (cornerTool): editable corners on any path through the
  existing Live Corners. Hover shows an eligible anchor, a click cuts a
  corner with the tool's radius and kind, a drag sizes it (Shift: whole
  values), a corner's marker selects it and loads its values, resizes it
  and removes it at 0 or on a double-click; a corner never grows past
  what fits; an Alt-marquee cuts every eligible anchor inside.
- Corners section in the Anchor Inspector: radius, kind, selected count,
  Apply to Selected Anchors.
- Slide Anchor Along Path (slideAnchor): a drag runs an anchor along its
  curve, the neighbouring segments refitted by the keep-shape kernel;
  Shift snaps where the tangent is a multiple of 45° from the constrain
  angle.
- Commands addon.pathtools.cornerSet, cornerRemove and slideAnchor, one
  undo step each, params validated and covered by the command sweep.
- Cursor stand-ins, catalog rows in every language, docs and tests.
2026-10-31 04:21:26 +07:00
BFlat 0494f505d9 Merge pull request #4755 from mockydevs/fix/eps-group-opacity-after-look
EPS import: keep a layer's opacity when its state block has the stroke style
2026-10-31 04:21:09 +07:00
Don Omondi ff1f721013 fix(eps-import): keep a layer's opacity when its state block has the stroke style
A layer's own state block (Xy, Xd, 7 () XW before LB) can have the
stroke style (J j w M d XR) between its Xy and Xd. Read as the art moving
on, it dropped the layer's opacity, so a layer at 17% drew opaque and the
file came in as its page. The stroke style now keeps the pending layer
state, and the state a mesh before it had; an object's own 6 () XW block
still isn't the layer's.
2026-10-31 04:02:35 +07:00
BFlat 2f4119d8d7 Merge pull request #4754 from dotCooCoo/feat/transform-pattern-backquote-drag
Transform tools: backquote drag transforms only the pattern
2026-10-31 04:02:01 +07:00
BFlat 6913d9e181 Merge pull request #4750 from dotCooCoo/feat/paint-mode-angle-bracket-keys
Shortcuts: Shift+Comma and Shift+Period also apply the last color and gradient
2026-10-31 04:01:44 +07:00
BFlat 81f119d48a Merge pull request #4753 from dotCooCoo/feat/lock-unselected-objects-key
Object: Cmd/Ctrl+Alt+Shift+2 locks every unselected object
2026-10-31 04:01:26 +07:00
BFlat 70a86c6c38 Merge pull request #4751 from mockydevs/docs/ai-import-audit-records
docs: record the .ai/EPS import fixes from a user's file audit
2026-10-31 04:01:09 +07:00
BFlat 6dbe386eb6 Merge pull request #4752 from mockydevs/fix/eps10-type
EPS import: read layers whose type is in the legacy format beside a page with text
2026-10-31 04:00:53 +07:00
dotCooCoo 6a034c77c3 Transform tools: backquote drag transforms only the pattern
Holding backquote while dragging with the Selection tool (move, bounding-box
scale or rotate) or the Rotate, Reflect, Scale or Shear tool applies the drag
to the selected objects' pattern fills and strokes and leaves their geometry
in place. The key state at release decides the result: the key may be pressed
after the mouse button goes down, and releasing it before the button comes up
commits an ordinary transform. Objects without pattern paint do not move.

PointerEvent gains a `backquote` flag (false when absent). The desktop canvas
reads it from the held key on every pointer event, and `ui.pointer` and the
`pointer_gesture` tool accept it per event or as a default for the gesture.
2026-10-31 03:34:55 +07:00
dotCooCoo 5f9b524d1a Shortcuts: Shift+Comma and Shift+Period run their bindings where Shift types another character
On layouts such as German, Shift+Period types `:` and Shift+Comma types
`;`, so the key event carries the Colon or Semicolon key and the
`Shift+.` and `Shift+,` bindings did not run. A shifted press at the
Comma or Period key position now runs the chord bound to that position
when no binding exists for the typed character; a binding the keymap
has for the typed character, such as a user's `Shift+;`, still wins.
Each press runs one command.

The tests send the key events these layouts produce, and the text
editing test checks after each press that fill and stroke stay as they
were.
2026-10-31 03:34:52 +07:00
dotCooCoo 26ac7799e7 Shortcuts: Shift+Comma and Shift+Period also apply the last color and gradient
Apply Last Color keeps `,` and also gets `Shift+,` as a default key;
Apply Last Gradient keeps `.` and also gets `Shift+.`. The keymap
catalog takes the extra defaults from a small alias table, the
Keyboard Shortcuts dialog lists every default key of a row, and reset
restores both.

A shifted punctuation chord that the active keymap binds now runs from
its key press, once per press, so a user binding such as `Shift+;`
works and layouts where Shift+Period types another character still run
the bound command. Text editing still types the characters.

The toolbar tips read "Color (, or <)" and "Gradient (. or >)", with
rows in every catalog.
2026-10-31 03:34:51 +07:00
dotCooCoo fc7ef3102f Object: Cmd/Ctrl+Alt+Shift+2 locks inside clip groups and isolation, with no menu item
object.lock.unselected is now reached by its key and as a command only:
the Object > Lock > Unselected Artwork menu item is removed, and the
command stays in the registry, the shortcut editor and automation.

In a partly selected clip group or compound path it now locks the
unselected members, the clipping path included, and leaves the container
and the selected members unlocked. It locks unselected guides while Lock
Guides is on. Hidden art and art on a locked layer stay unlocked, and a
selected layer's art counts as selected.

With a selection in isolation mode the command is enabled and locks only
the unselected art inside the isolated group. The other Lock and Hide
items keep their isolation behavior.

Lock and Hide still share one selector. A lock flag on it selects the
clip group, compound path and guide cases above; Hide > Unselected
Artwork keeps its behavior, and a test covers both directions.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-31 03:34:47 +07:00
dotCooCoo a372d39a31 Object: Cmd/Ctrl+Alt+Shift+2 locks every unselected object
The reference app locks all deselected artwork on Cmd/Ctrl+Alt+Shift+2.
VectorCraft had no command for it: Object > Lock held Selection, All
Artwork Above and Other Layers.

The new command, object.lock.unselected (Object > Lock > Unselected
Artwork), locks in one undo step the objects that Hide > Unselected
Artwork hides: every object that Select All takes and that is neither
selected nor holds a selected object. It returns the count. Hidden
objects stay unlocked. The selection stays as it is, Unlock All unlocks
the objects again and selects them, and with nothing to lock the
command records no undo step. Both commands now share one function,
which locks or hides the objects that the existing unselected helper
returns.

In isolation mode the menu item is disabled, and the command returns
the error "not available in isolation mode" that Hide > Unselected
Artwork returns there, and changes nothing.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-31 03:34:47 +07:00
Don Omondi 7591e35345 docs: record the .ai/EPS import fixes from a user's file audit
Adds the evidence and revision rows that target-app-parity.md and
roadmap.md expect for the .ai/EPS import changes of 2026-10-30 (#4708,
#4664, #4723, #4742, #4658, #4727, #4738, #4744, #4748, #4743). Scores
and estimates unchanged.
2026-10-31 03:34:43 +07:00
Don Omondi bfe509bb38 fix(eps-import): read layers whose type is in the legacy format beside a page with text
An EPS saved for Illustrator 10 keeps its type in the editing data as
legacy text objects (`To` ... `TO`), with no `/AI11Text` slot for the
page's type to go in, so a file whose page had text came in as its page.
Those text objects are now the layers' own: the page's type isn't put
anywhere, and the comparison with the page decides as before. Type the
editing data keeps only as outlines stays outlines, with a note counting
the page's text objects that are.
2026-10-31 03:34:40 +07:00
BFlat 9de15d6599 Merge pull request #4749 from dotCooCoo/feat/panel-fkey-toggles-panel
Panels: a second press of a panel's function key hides its group
2026-10-31 03:33:29 +07:00
BFlat c27e4b51ee Merge pull request #4745 from dotCooCoo/feat/escape-leaves-full-screen
View: Escape in either Full Screen Mode returns to Normal Screen Mode
2026-10-31 03:33:13 +07:00
BFlat f004980e2e Merge pull request #4747 from dotCooCoo/feat/vertical-type-arrow-steps
Type: Alt+arrow spacing steps turn with vertical type
2026-10-31 03:32:56 +07:00