Commit Graph
22 Commits
Author SHA1 Message Date
dotCooCoo 3dad9dbbfc Transparency: makeOpacityMask refuses objects in ids that cannot be edited
A layer among the targets already stood only for its art that can be
edited. An object named in ids is now checked the same way: a hidden or
locked object, or one on a locked artboard, is refused with an error
instead of becoming the mask, being masked or getting an empty mask.
2026-11-02 12:04:14 +07:00
dotCooCoo 482c011233 Transparency: a layer's art on a locked artboard or in a hidden or locked parent is not taken for an opacity mask
Make Opacity Mask expands a layer among its targets to the art that can
be edited: an object in a sublayer of a hidden or locked layer, or on a
locked artboard, is neither the mask nor masked, so it stays where it is.
2026-11-01 08:32:54 +07:00
dotCooCoo d0834e6834 Transparency: a layer on top gives its topmost object as the opacity mask
Make Opacity Mask took the topmost target as the mask. When that target was
a layer (a targeted layer above the art, or `ids` ending in a layer id), the
whole layer was removed from the layer tree and became the mask art. A layer
on top now stands for its visible, unlocked art, as a layer below the mask
already does: its topmost object is the mask and the rest of its art is
masked with the art below. A top layer with no such art is refused and the
document is left unchanged.
2026-11-01 08:32:54 +07:00
dotCooCoo 875d3301f5 Transparency: Make Opacity Mask over several layers masks their art
transparency.makeOpacityMask with two or more layers below the mask
object (or a layer and objects of other layers) wrapped the layers
themselves in a new top-level group, so a layer ended up inside a
group. A layer among several masked items now stands for its art: the
masked group takes the layer's visible, unlocked objects, a hidden,
locked or template layer gives none, and the layers stay where they
are. One layer under a mask object, or one layer alone, is masked as
before.
2026-10-31 19:43:15 +07:00
bflatastic d56bbb49ff Gradient Mesh: select several mesh points; move, color and opacity reach them all (#4207, #4208, #4170) 2026-10-30 03:37:43 +07:00
dotCooCoo 3cfdb58b90 Transparency: pattern editing mode and opacity mask editing can't be entered from each other
Squashed from #4458 onto main.
2026-10-29 18:54:45 +07:00
dotCooCoo 7d04096840 Transparency: Make Opacity Mask is off for a targeted layer in isolation mode 2026-10-29 11:20:08 +07:00
dotCooCoo dfe201dec3 Transparency: isolation mode and opacity mask editing can't be entered from each other
Enter Isolation Mode worked while an opacity mask was edited, and Edit
Opacity Mask and View Opacity Mask worked in isolation mode, so each
mode replaced the other's isolated art. In the reference app, isolation
mode can't be entered while a mask is edited, and mask editing can't be
entered in isolation mode.

object.isolate and perspective.editText, which shows type in isolation
mode, are now off while an opacity mask is edited, and a call returns
an error that ends "stop editing the opacity mask first". In isolation
mode transparency.editOpacityMask and transparency.viewOpacityMask are
off, and transparency.makeOpacityMask refuses one target, an object or
a layer, which it would take into mask editing; a call returns an error
that ends "exit isolation mode first". Make Opacity Mask with two
objects still masks one with the other. Pattern editing mode does not
count as isolation mode for these commands.

Object > Perspective > Edit Text, the canvas context menu and the
Transparency panel's menu and Make Mask button follow the commands'
enablement. A click or Alt-click on the mask thumbnail in isolation
mode shows the error and does not edit the mask. While a mask is
edited, the Contextual Task Bar leaves out Isolate, and the Properties
panel's Quick Actions leave out Isolate Group.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-29 11:20:08 +07:00
NetterSilverandClaude Opus 5.5 ec98f498fd Apply Transparency opacity to the clicked gradient mesh point
Fixes #4206

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 10:00:05 +07:00
Dylan M. Taylor 0b821b3c54 Extract engine command and state helpers 2026-10-28 16:44:14 +00:00
dotCooCoo 0520e9da86 Type: threaded frames do not repeat a continued paragraph's first-line indent or list marker
A paragraph split between two threaded frames took its first-line
indent again at the top of the next frame, and a list paragraph drew
its bullet or number there again. Each frame is laid out on its own,
and its first paragraph kept every paragraph attribute there.

A text object now marks a frame whose first paragraph continues from
the frame before (first_para_continues, not saved). The thread re-flow
sets the mark where each frame's share starts inside a paragraph and
measures each share with it, and a restored document reads the marks
from its saved text. Area type and type on a path set the first line of
such a paragraph as a wrapped line: no first-line indent and no bullet
or number. The paragraph after it takes the next number. Release
Selection, Remove Threading, Convert To Point Type and copies of a
frame clear the mark, so the first paragraph there has its indent and
bullet or number again. When Create Outlines, Expand or Expand
Appearance takes frames out of a thread, a frame that stays keeps the
mark only while it is threaded and the frames before it end inside a
paragraph. A frame whose mark changes lays out its first line again,
and when it is still threaded, its thread re-flows. When the outlined
frame is the last one, the text it has no room for is measured as the
frame lays it out: without the first-line indent when it continues a
paragraph, and with its numbers counted on from the frames before it.
The frame before it now takes exactly the text the last frame has no
room for. Duplicates, copies dragged in the Layers panel, the copies
that Release to Layers (Build), Release Opacity Mask and Edit Opacity
Mask make, and Draw Inside's clipping copy then have their cached
bounds computed again, as paste already does for pasted type.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-24 21:43:44 +07:00
dotCooCoo 67a278b053 Commands: ids leave out an object listed with a group that holds it, as the selection does
Commands that read the selection through edit::selected_roots leave
out an object whose group is also selected (edit::roots_of). Fourteen
places that read `ids` kept an object listed together with its group.
Given ids that list an object and a group that holds it, Make Repeat
failed with "no such object", New Symbol failed or stored the object
twice in the symbol, and object.transform moved it twice (20 pt for a
10 pt move).

These places now pass explicit ids through edit::outermost, which
drops an id whose ancestor is also listed, with the filter that
roots_of runs on the selection (now edit::without_inner). Nothing else
is dropped or replaced: unlike roots_of, it keeps layers and
compound-path members. A list without nesting gives the same result as
before. Commands that take both ids and the selection as listed, such
as paint.setFill without item, are unchanged.

Docs: docs/mcp.md, docs/target-app-parity.md.
2026-10-16 06:16:35 +07:00
dotCooCoo 88bd4812e0 Part of #1429: path, Pathfinder and live-object commands add and remove many objects in one pass
Offset Path, Outline Stroke, the Pathfinder panel, Clean Up, Make
Blend, Rasterize and the other commands that #1429's table marks 3,
except Split Into Grid, added, removed or replaced their objects one at
a time, and so did Remove Anchor Points, Redefine Symbol and the
removal of Shaper groups whose source art is gone. Each insertion or
removal moved the later objects of the layer or group. The lookups by
id that followed walked the tree, and every fourth walk rebuilt the
lookup cache. On 25,000 rectangles a release build of vectorcraft-cli
took 29.1 s for Offset Path.

These commands now make their edits with Document::wrap,
Document::insert_beside and Document::remove_many, in one pass over the
children of each layer or group, and Outline Stroke and Expand write
each new object into the place of the object it replaces. A list that
holds an object twice, or an object and another inside it, and that was
edited without an error before, is still edited one object at a time.
The documents, selections and undo steps are the same. On the same
rectangles Offset Path now takes 1.3 s.

Docs: docs/target-app-parity.md.
2026-10-13 05:21:31 +07:00
arhammusheer 5beac4f122 #1244: smaller objects: Node 352 -> 152 bytes, NodeKind 200 -> 80, and a cheaper undo estimate
Rarely set fields move into one optional boxed NodeExtras, and large NodeKind payloads (images,
live shapes, blends, envelopes) are boxed. Every object, and every undo step that copies it,
shrinks: a 50k-path move keeps ~24.5 MB per step instead of ~40 MB. Files stay byte-identical
(Node keeps its flat JSON through a borrowed Serialize and a from-wire Deserialize, no flatten),
and loading is slightly faster. Undo and redo reuse their step's size estimate instead of
walking the document again (8.3 -> 5.6 ms for a 50k-path move).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VmMmc1J8XeNLxhRihWv9cc

# Conflicts:
#	crates/engine/src/cmd/graph.rs
#	crates/svg/src/export.rs
2026-10-12 11:02:32 +07:00
dotCooCoo 8b6bfe6ed7 Transparency: opacity mask options that change nothing record no undo step
Disable, Enable, Unlink and Link Opacity Mask and Opacity Mask Options
(transparency.setOpacityMask) edited the document whenever a target
had an opacity mask, even when every mask already had the flags the
call set. Such a call recorded an undo step, emptied Redo and marked
the document modified.

When every mask a call acts on has those flags already, the call now
returns without editing the document, whether it acts on the
selection, on id or ids, or on the object whose mask is being edited.
The reply is still null, and the journal still records the call. A
call that changes a flag on any of the masks is still one undo step.

One line in the evidence list of docs/target-app-parity.md names the
commands.
2026-10-12 10:02:03 +07:00
bflatasticandClaude Opus 5.5 b768b4a53b M3.69: target circles target layers, groups and objects; drag them to move appearances
Clicking a Layers panel target circle runs `layer.target {id}`: a layer gets its art
selected and becomes the target (`Selection.target`) of the appearance, effect,
transparency and opacity-mask commands, which then edit the layer itself; the
Appearance panel lists it. Dragging a circle onto another runs
`appearance.transfer {source, target, copy?}` (Alt copies), dropping it on the trash
clears it. Filled dots also mark groups and layers with fills of their own, masked
objects get a dashed underline, and while an opacity mask is edited the panel lists
only an `<Opacity Mask>` entry and the tab says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 02:15:41 +07:00
bflatasticandClaude Opus 5.5 039c0cbef7 M3.48: Page Isolated Blending and Page Knockout Group
New Document.page_isolate / page_knockout, set by
transparency.togglePageIsolatedBlending / togglePageKnockoutGroup {value?}
(one undo step each, saved with the document, reported by
transparency.info) and the Transparency panel menu's check items. The page
renders as an isolated group (top-level blend modes no longer blend with
what lies under the page) and/or a knockout group whose elements are the
layers (neutral layers pass their objects through). PDF and SVG wrap the
page content in an isolated group and write page knockout as soft masks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:10:06 +07:00
bflatasticandClaude Opus 5.5 c95098d15a M3.47: opacity and opacity mask can define an object's knockout shape
New Node.knockout_shape (transparency.set / object.setProps knockoutShape,
reported by transparency.info). In a knockout group such an object knocks
out only as much as its opacity and mask let through (a 50% object knocks
out 50%); otherwise its full coverage knocks out. The renderer, PDF and
SVG masks honour it, and the panel's checkbox is now live.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:07:01 +07:00
bflatasticandClaude Opus 5.5 6e0af835c6 M3.46: three-state knockout groups (on, neutral, off) render, export and edit
Knockout Group is now Knockout {Neutral, Off, On} (old files' true loads as
On, false as Neutral). In a knockout group each child erases what the
children below it drew where it paints, then adds itself, so it composites
against the group's backdrop; neutral plain groups pass their children
through to the enclosing knockout group. transparency.set / object.setProps
take knockout "on"|"off"|"neutral"|bool; transparency.info reports the
state. PDF and SVG write knockout groups as nested soft masks with the same
look (PDF warns); the Transparency panel has a tri-state checkbox.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:04:20 +07:00
bflatasticandClaude Opus 5.5 b117566fc2 M3.25: opacity-mask editing and transparency command reach
While a mask is edited, the Transparency panel and its commands act on the
masked object (Release leaves editing first). Mask commands and
transparency.set take ids and work without a selection; Make Opacity Mask
with one object adds an empty mask and enters editing. Opacity is 0..100 in
every command. transparency.info reports the panel's values with null for
mixed ones, shown blank. Saves and exports never include the editing layer
(Document::without_edit_modes; mask_edit is not serialized).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 17:10:21 +07:00
Brandon ThomasandClaude Opus 5.5 4878f1c5dd Rename DrawCraft → VectorCraft: crates (vectorcraft-*), apps, binaries, types, env vars, docs, examples (.vectorcraft); old .drawcraft files and preferences still load. Fix: text bounds exact after opening a file; selection no longer marks a document modified (dirty = content differs from the saved document). Screenshots and renders regenerated.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 14:30:09 -04:00
Brandon ThomasandClaude Opus 5.5 5e15994012 M3: opacity masks — model (linked transform), luminance mask rendering, transparency.* commands, SVG <mask> export/import, PDF luminosity soft masks, Transparency panel controls
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 00:30:38 -04:00