Commit Graph
563 Commits
Author SHA1 Message Date
BFlat 941277aa38 Merge pull request #7747 from dotCooCoo/feat/3d-render-wireframe
3D and Materials: Render Settings › Wireframe draws the live 3D effect as its faces' edges
2026-11-15 13:50:13 +07:00
dotCooCoo 814cae044f Clipping: painted type keeps its fill and stroke in a group with geometry effects
A clip group whose clipping path is type with a fill or stroke lost that
paint when a group around it had a geometry effect. Outlining the type
for the effect replaced it with a group of glyph outlines, and a group
paints nothing as a clipping path. Distort effects lost it on the canvas
and in SVG and PDF; Transform effects that only move lost it in SVG and
PDF when other type in the group stayed type.

The type's outlines now clip, its fills become art behind the clipped
art inside the clip, and its strokes become art over it outside the
clip, as the canvas draws an unaffected clip group.
2026-11-14 21:34:17 -08:00
dotCooCoo 27a0dc89d4 3D and Materials: Render Settings › Wireframe draws the live 3D effect as its faces' edges
The 3D and Materials panel gets a Render Settings menu with Wireframe.
Extrude & Bevel, Revolve, Inflate and Rotate take a `render` parameter,
`{mode: "shaded" | "wireframe"}`. In wireframe mode the effect stays
live and draws the edges Expand as Wireframes gives, each once, as
0.5 pt black strokes with round joins, with no shadow or graphics. The
object's own opacity, blending mode and opacity mask apply to the mesh.

Commands that set wireframe mode are checked against the edges it
draws: the shaded surface's paint copies, graphics and shadow limits do
not refuse them. A `render` value that is not an object holding only a
valid `mode`, and `render` on the 3D (Classic) effects, are refused.

Docs: docs/three-d.md, docs/mcp.md, docs/effects-parity.md,
docs/target-app-parity.md.
2026-11-14 21:04:33 -08:00
BFlat 3e68e4117a Merge pull request #7712 from dotCooCoo/feat/rough-pastels-load-texture
Effects: Rough Pastels loads its texture from an image file
2026-11-15 09:47:09 +07:00
bflatastic 3a608ae1e3 Effects: the default SVG filters' test raster gives PixelSpace its size
#7680 added PixelSpace::size and #7658's test helper, merged in an earlier batch, didn't
set it, so vectorcraft-effects' tests don't compile on main.
2026-11-15 08:33:38 +07:00
BFlat 507b3a8961 Merge pull request #7714 from dotCooCoo/fix/solid-check-drawn-bounds-test
3D: a test checks that a filled shape builds about the bounds its solid draws
2026-11-15 08:24:54 +07:00
BFlat 2331fd44fa Merge pull request #7680 from dotCooCoo/feat/radial-blur-center
Effects: Radial Blur turns about a Blur Center set in its dialog
2026-11-15 08:24:28 +07:00
BFlat dc870ecf9c Merge pull request #7686 from dotCooCoo/fix/export-places-symbols-in-masks
Export: symbol instances in opacity masks draw their art's live effects
2026-11-15 08:23:13 +07:00
dotCooCoo 514ee4f81e 3D: test that the check builds a filled shape about its drawn bounds
#7569 changed the Extrude & Bevel and Inflate check so that a filled
shape's solid is built once, about the bounds the effect draws it
about, and stated that a filled shape whose solid builds about those
bounds but not about its profile's own bounds now passes. No test
covered that case.

The new test builds a group of a filled shape of 900 small curves and
a line with a 2000 pt stroke. About the shapes' own bounds, the filled
shape's solid is too complex with a repeated rounded bevel; about the
bounds that take in the stroke, its curves are sampled more coarsely
and it fits. The test asserts the first result, then that the check
passes and the solid draws. It fails when the check builds every
shape's profile about the profiles' bounds again.
2026-11-14 15:47:34 -08:00
dotCooCoo 403023f834 Effects: Rough Pastels loads its texture from an image file
The Rough Pastels dialog has a Load Texture… button, as Glass and
Texturizer have. The image's gray levels become the paper surface,
stored with the effect as `textureImage` and listed as Loaded Texture
in the Texture menu; Scaling, Relief, Light Direction and Invert act on
it as on the built-in surfaces. The dialog's Texture and Light
Direction controls are now menus instead of text fields.

effect.apply and effect.setParams read `textureImage` from a file or
take the stored string and refuse anything else, and a plug-in filter
cannot have the host read a file for it.

In the Effect Gallery's Settings, a file dialog that answers later
(the macOS sheet, the Linux dialog) now gives the texture to the values
that asked: the filter being browsed, or the stack row that asked,
found by a number each row now carries. An answer for a removed row, a
filter no longer browsed or a gallery that closed is dropped.

Params text, docs/mcp.md, docs/control-protocol.md, docs/gaps.md and
the evidence line are updated.
2026-11-14 15:45:59 -08:00
BFlat dafd993395 Merge pull request #7658 from dotCooCoo/feat/svg-filter-defaults
Effects: Effect › SVG Filters lists default filters
2026-11-15 06:18:12 +07:00
BFlat a92993daf9 Merge pull request #7582 from dotCooCoo/fix/clip-effects-hit-test
Selection: clicks in a clip group follow the region its clipping path's effects give it
2026-11-15 06:16:57 +07:00
BFlat 6b947b28a3 Merge pull request #7676 from dotCooCoo/fix/clip-group-paint-bakes-clip-effects
Effects: a clip group with its own paint exports the clip its clipping path's effects shape
2026-11-15 06:16:48 +07:00
BFlat 0e78bfa60c Merge pull request #7580 from dotCooCoo/fix/create-outlines-gradient-layout-bounds
Type: Create Outlines keeps a run's gradient across the whole text
2026-11-15 05:30:22 +07:00
BFlat 63e40bca44 Merge pull request #7488 from dotCooCoo/fix/3d-shadow-builds-once
3D: a render with a shadow builds each solid once
2026-11-15 05:29:29 +07:00
dotCooCoo a5868102ae Merge main into feat/radial-blur-center 2026-11-14 13:47:19 -08:00
dotCooCoo 500138365b Export: symbol instances in opacity masks draw their art's live effects
PDF, EPS, print and DXF export place each symbol instance whose art has
live effects as that art, baked. The bake followed only an object's
children, so an instance in the art of an enabled opacity mask stayed an
instance, and the mask was written with the symbol's stored art and
without its effects. A symbol whose art used such a symbol only inside a
mask was not placed either.

The bake now also looks into the art of enabled opacity masks: that art
is baked one level deeper and written back to the mask, and symbols that
use a placed symbol only inside a mask are placed too. Disabled masks
and the masks of objects the export leaves out stay as they are.
2026-11-14 13:46:23 -08:00
dotCooCoo 5831b1d23a Effects: Radial Blur turns about a Blur Center set in its dialog
Effect > Blur > Radial Blur... has a Blur Center box. A press or a drag
in the box sets the point the spin or zoom starts from, the arrow keys
move it 1% (10% with Shift), and Horizontal and Vertical fields take the
same position in percent. Screen readers get the box with both values.

- blur.radial takes centerX and centerY, from 0 to 1 across and down the
  object's bounds (0.5 each by default), so the center moves and scales
  with the object. An effect saved without them draws as before.
- effect.apply and effect.setParams refuse a value outside 0 to 1, or
  one that is not a number; a saved one draws at the nearest edge.
- The raster's margin is measured from the center, and the center stays
  in the object's own bounds when a Rasterize splits the stack.
- Params text, docs/mcp.md, the evidence line in
  docs/target-app-parity.md and a Blur Center row in every catalog.
2026-11-14 13:39:57 -08:00
dotCooCoo 25b451acec Effects: a clip group with its own paint exports the clip its clipping path's effects shape
A clip group with a fill or stroke of its own and no geometry effect is
baked through bake_pieces, which baked the clipping path like any other
member instead of applying the geometry effects in it as the canvas clips
by it. A compound clipping path whose member has a Transform effect with
copies then baked into nested compound paths, and SVG, PDF and the other
exports dropped the moved member and its copies from the clip.

bake_pieces now applies with_clip_effects_applied to the clipping path
first, as the plain clip group route already does. Clipping type keeps
its own handling.
2026-11-14 13:34:22 -08:00
BFlat 88dd37d2d9 Merge pull request #7527 from dotCooCoo/fix/3d-masked-cap-graphic-once
3D: a gradient fill with transparent stops and its stroke draw their graphic once
2026-11-15 04:22:18 +07:00
dotCooCoo cf8b88b0ea Merge main into fix/clip-effects-hit-test 2026-11-14 12:59:50 -08:00
dotCooCoo bf0950c0ef Merge main into fix/3d-shadow-builds-once 2026-11-14 12:30:56 -08:00
dotCooCoo 98fbda2eb1 Merge main into fix/create-outlines-gradient-layout-bounds 2026-11-14 12:28:14 -08:00
BFlat 6970c4efec Merge pull request #7609 from dotCooCoo/fix/transform-copies-raster-effects
Effects: each copy of a Transform effect draws the raster effects listed before it
2026-11-15 03:21:43 +07:00
BFlat 2986979149 Merge pull request #7432 from dotCooCoo/fix/wireframe-transform-measures-shadow
3D: Expand as Wireframes measures later effects with the cast shadow
2026-11-15 03:21:13 +07:00
BFlat ab913e84ad Merge pull request #7628 from dotCooCoo/fix/clipping-members-drawn-budget
Effects: a clipping path's members count toward the member limit of a group's effects
2026-11-15 03:20:21 +07:00
dotCooCoo b7678494a2 Merge main into fix/clip-effects-hit-test 2026-11-14 12:18:53 -08:00
dotCooCoo fb8afd7919 Merge main into feat/svg-filter-defaults 2026-11-14 12:12:02 -08:00
dotCooCoo 0b1e1e99a1 Effects: Effect › SVG Filters lists default filters
Effect › SVG Filters and Apply SVG Filter list 14 default filters in
every document, before the document's own. The set, the names and the
values are VectorCraft's own, written with SVG 1.1 filter primitives
(crates/effects/src/svg_filter/defaults.rs).

A document holds none of the defaults until one is applied or edited
there. svgFilter.apply with a default's name copies it into the document
in the same undo step, and svgFilter.define with replace naming a default
adds the edited copy under that name. The copy is listed in the default's
place. svgFilter.delete refuses a default the document holds no copy of,
and deleting the copy lists the default again.

svgFilter.list also returns the defaults. svgFilter.apply takes index and
item to put the filter in the place of an applied SVG filter, which the
dialog's OK uses when it is opened for an applied effect; an index that
is not an applied SVG filter, null included, is an error.
2026-11-14 11:19:22 -08:00
dotCooCoo 66f989c27b Effects: the member limit's doc comment says a compound path with fill or stroke effects becomes a group of pieces 2026-11-14 10:09:26 -08:00
dotCooCoo 7e390fe079 Merge main into fix/3d-masked-cap-graphic-once 2026-11-14 09:55:12 -08:00
dotCooCoo a3ba3eeb38 Merge main into fix/3d-shadow-builds-once 2026-11-14 09:52:39 -08:00
BFlat e76f8d2c88 Merge pull request #7501 from dotCooCoo/fix/export-bakes-symbol-art-effects
Export: live effects in symbol art apply in PDF, EPS, print and DXF
2026-11-15 00:41:46 +07:00
BFlat d0b37826c0 Merge pull request #7338 from dotCooCoo/fix/colored-light-seams
3D: colored-light facets close their shared edges over an underlay
2026-11-15 00:40:19 +07:00
dotCooCoo 40d0b31cbe Effects: the clipping path doc comment says what the member limit leaves of a compound path
When the member limit is reached among the paths of a compound clipping
path that has geometry effects of its own, the compound path still
becomes one path of its reshaped geometry. The paths that were not
visited go into that geometry as they are, and their own effects are
not applied. The doc comment of with_clip_effects_applied_while said
that they keep their effects, which holds for the members of a group or
layer only.

New test a_compound_clipping_path_takes_its_own_effect_at_the_member_limit
covers the compound path.
2026-11-14 08:54:44 -08:00
dotCooCoo e001227ce1 Selection: effects on a hidden member of a clipping group leave clicks alone
A clipping path that is a group clips by its visible members only. A
geometry effect on a hidden member made clicks inside the clip group
count the group's type by its glyph outlines, where they count it by its
frame when nothing has an effect.

Clicks now ask `effects::reshaped_clip_outline`, which gives a region
only when an object the clipping path clips by has a geometry effect.
`clip_outline` uses the same function.
2026-11-14 08:29:00 -08:00
dotCooCoo c3341be03c Effects: the member limit's doc comment covers clipping paths walked twice
A group or layer in a clipping path that has geometry effects of its
own is walked once for its members' effects and once for its own, and
its members count toward the member limit each time. The doc comment
of members_as_drawn now states this.
2026-11-14 08:28:31 -08:00
dotCooCoo be44f10b6a Effects: a clipping path's members count toward the member limit of a group's effects
When a group's geometry effects evaluate the members of the group, a
clip group's clipping path takes the geometry effects in it first. A
clipping path that is a group, layer or compound path had each of its
members reshaped at every depth without counting them, so a large
clipping path was reshaped past the SYMBOL_ART_MAX_NODES members that
members_as_drawn documents.

Each member of a clipping path now counts as one visited member. Once
the limit is reached, that member and the members after it keep their
effects, as the other members past the limit do. The canvas, the
export bake and clipping type are unchanged: they do not count members.
2026-11-14 08:21:58 -08:00
dotCooCoo 62604c38bd Merge main into fix/wireframe-transform-measures-shadow 2026-11-14 08:01:42 -08:00
dotCooCoo 69ec28dc4c Merge main into fix/3d-shadow-builds-once 2026-11-14 07:28:03 -08:00
BFlat 45d98a5f82 Merge pull request #7443 from dotCooCoo/fix/wireframe-outline-stroke-width
3D: Expand as Wireframes outlines each face's own stroke under a later Outline Stroke
2026-11-14 21:55:03 +07:00
BFlat 8657b38b35 Merge pull request #7590 from dotCooCoo/perf/group-sublayer-guides-one-pass
Effects: a layer's effects gather its sublayers' ruler guides in one pass
2026-11-14 21:51:54 +07:00
BFlat d1aa073c42 Merge pull request #7585 from dotCooCoo/fix/clipping-type-fill-effects
Export: clipping type with geometry effects clips where the canvas does
2026-11-14 21:50:33 +07:00
dotCooCoo 4f7a10c002 Merge main into fix/3d-shadow-builds-once 2026-11-14 06:02:41 -08:00
dotCooCoo 80854eb4b8 Merge main into fix/export-bakes-symbol-art-effects 2026-11-14 06:00:09 -08:00
BFlat 035d22b3e2 Merge pull request #7476 from dotCooCoo/fix/svg-clip-path-effects
Effects: a clipping path's geometry effects shape the clip on the canvas
2026-11-14 20:38:37 +07:00
BFlat 4bcb0026da Merge pull request #7569 from dotCooCoo/perf/3d-validation-builds-once
3D: effect validation builds each Extrude and Inflate solid once
2026-11-14 20:38:09 +07:00
dotCooCoo f00ddcbaa9 Effects: each copy of a Transform effect draws the raster effects listed before it
A path's Drop Shadow, glow, blur, Feather or pixel filter listed before a
Transform effect that makes copies was drawn once under all the copies, at
the object's own distances. Each copy now carries those raster effects,
scaled by the copy's mean scale, with a Drop Shadow's offset turned,
reflected and scaled with the copy. Raster effects listed after the
Transform effect still paint once around all the copies. Copies that stop
at the effect budget keep their effects, and a Transform effect without
copies draws as before.

The canvas, the object's bounds, export, baking and Expand Appearance use
the same art. Type, images, symbol instances, groups, a fill's or stroke's
own copying Transform effect, and paths with Rasterize or an SVG filter
before the copying effect keep one set of raster effects.
2026-11-14 05:32:43 -08:00
dotCooCoo 190e4be825 Merge main into fix/3d-masked-cap-graphic-once 2026-11-14 04:59:36 -08:00
dotCooCoo c482037570 Merge main into fix/3d-shadow-builds-once 2026-11-14 04:57:13 -08:00