Commit Graph
562 Commits
Author SHA1 Message Date
dotCooCoo 312d4a3914 Merge main into feat/image-color-mask 2026-11-12 13:30:24 -08:00
BFlat 3434e46240 Merge pull request #6825 from dotCooCoo/feat/custom-arrowheads
Stroke: custom arrowheads from an arrowheads file join the arrowhead menus
2026-11-13 04:25:55 +07:00
dotCooCoo 950494802e Merge main into feat/outline-object-image-alpha
# Conflicts:
#	crates/effects/src/tests.rs
2026-11-12 12:45:45 -08:00
dotCooCoo c31af9898e 3D and Materials: one element limit per effect, pasted graphics keep their symbols, safer handle drags
- The graphics of one 3D effect share one limit on drawn path elements
  across every member and opacity group, so a group effect with many
  members no longer multiplies the limit.
- Copy and paste follow the symbols that mapped graphics name, in object
  and graphic style appearances: a document without the symbol gets it,
  and one whose symbol of the same name is other art gets the copied
  symbol under a free name, which the graphic then names.
- A face's inverse map refuses the points its page map refuses, so a
  handle drag cannot save an offset whose handle is not shown.
- A press on a graphic's handle with Space held, or with the Hand, Zoom
  or Rotate View tool, pans, zooms or turns the view.
- A handle drag ends, keeping its preview, when the selection or the
  document changes while the pointer is down.
2026-11-12 12:42:59 -08:00
BFlat 87485971b0 Merge pull request #6959 from dotCooCoo/fix/item-transform-later-raster-effects
Effects: a fill's or stroke's own Transform effect leaves the effects listed after it unscaled
2026-11-13 03:28:16 +07:00
dotCooCoo bd973548d7 Effects: an object's Transform effect moves its fills' raster effects beside a fill's 3D effect
When only a fill or stroke has an Extrude & Bevel, Inflate, Rotate or Revolve effect, the object's
Transform effects reshape the path, and now the raster effects of every fill and stroke follow them
too, as they do on an object without a 3D effect: a shadow after the fill's 3D effect and another
fill's shadow scale and turn with the art.
2026-11-12 12:21:38 -08:00
dotCooCoo 197d033b4f Merge main into feat/custom-arrowheads 2026-11-12 12:04:01 -08:00
BFlat 86f8a6dcbd Merge pull request #6927 from dotCooCoo/fix/roughen-size-zero
Effects: Roughen at size 0 keeps the outline
2026-11-13 02:46:39 +07:00
dotCooCoo 043e517ef6 Effects: a group's or object's Transform effect moves the raster effects inside it
A Transform effect on a group reshaped its members' paths but left the
raster effects inside it at their own values: a member's Drop Shadow
kept its 10 pt offset under a 200% Transform effect, and with Scale
Strokes & Effects on, it scaled by the mean scale without turning. The
same held for the raster effects of an object's own fills and strokes
under the object's Transform effect.

- A Transform effect that moves the art once now transforms the raster
  effects of a group's members (their own and their fills' and
  strokes'), of nested groups, of the art of the linked opacity masks
  in it and of an object's fills and strokes, after the members' own
  Transform effects: sizes scale by the mean scale and a Drop Shadow's
  offset turns, reflects and scales. A raster effect that a member's
  own Transform effect with copies or random holds back keeps its value
  through that effect and still transforms with the group's. Scale
  Strokes & Effects does not scale them a second time. A group's or
  object's Transform effect that makes copies or moves at random leaves
  them as before.
- The canvas, the redraw region, export, Expand Appearance, Object ›
  Expand and Outline Stroke read the same values.
- The Transform effect's params text and docs/target-app-parity.md
  describe the rule.
2026-11-12 11:35:03 -08:00
dotCooCoo 0691e1acbe Gradients: keep every run of a repeated gradient with many stops
When a repeated or reflected gradient needs more stops than a limit
allows, each run now leaves out the stops that change its colors
least, so every run is still written, instead of writing fewer runs
and padding the rest with the last color. Each run keeps its ends,
sharp steps, swatch-linked stops, tint and CMYK ink changes and spans
shaped by an off-center midpoint, and the colors are compared as the
gradient's method mixes them. This applies to gradients along or across
a stroke, CSS conic gradients, and PDF, EPS and .ai export.

- Outline Stroke's mesh fits the gradient to at most 1,024 stops, and
  splits a stroke into several meshes when one would hold more than
  2^20 points.
- Object > Expand leaves a gradient as it is when the box needs more
  than 256 runs, instead of expanding only the first runs.
- CSS writes the stop positions of repeating gradients with four
  decimals, so the period stays in place across the box.
- A swatch chip of a gradient that repeats gets at least four grid
  cells a run along each side (at most one a point, and 128), so it
  does not show one color when the count matches the chip's cells.
- docs/mcp.md states the stop limits and the PDF import sample budget.
2026-11-12 11:30:44 -08:00
dotCooCoo 5f7d4d3922 3D and Materials: graphics take the opacity mask of a cap in a transparent gradient
Under a colored light a surface in a gradient with transparent stops carries an
opacity mask. A graphic drawn on such a cap now takes that mask, and each such
solid gets a graphic of its own, so a graphic is hidden where its cap is.
2026-11-12 11:27:38 -08:00
dotCooCoo be50e5328b Transform: a bevel stops at the corners of the segments it joins with Use Preview Bounds
A bevel join, and a miter join whose miter limit bevels a corner, end the
stroke at the outer corners of the two segments they join. The visual box
measured such a corner as if the stroke reached half its weight round it:
a 40 x 100 pt triangle with a 20 pt stroke and a miter limit of 2 measured
10 pt above its tip, where the stroke paints about 1.96 pt above it. Use
Preview Bounds, and the alignment and sizing that use it, took that box.

- With bevel and miter joins, closed paths and open paths with round or
  projecting caps are now measured along their segments, as butt-capped
  open paths already were, with the miter tips the limit keeps and the
  caps added. Round joins still reach half the weight round each corner,
  the round caps of dashes, which can end at a corner, reach half the
  weight all round, and the projecting caps of dashes reach the diagonal
  of their square. The visual box of
  such a stroke can be smaller than before and is never larger. A path
  with no width, such as a rectangle sized to 0 pt wide, turns back at
  its ends, where the join bevels, so its box no longer reaches past them.
- object.setBounds with Use Preview Bounds measures an object as drawn
  when a beveled or mitered corner, or a butt cap, is on a segment at a
  slant. Before, a closed path with miter spikes the limit keeps missed
  the size typed when the width and height were out of proportion.
- A click past a bevel or a butt cap, by more than the click tolerance,
  no longer selects the stroke. Strokes with a width profile or with
  dashes that have round or projecting caps, and the ends of curves that
  bend more tightly than half the weight, keep the round reach.
- Paths measured along their segments skip the segments that cannot
  reach past the box measured so far, which starts with the path's own
  bounds.
2026-11-12 11:04:25 -08:00
dotCooCoo d46d8bb1fe Merge main into feat/3d-graphics-planar 2026-11-12 11:00:58 -08:00
dotCooCoo 85b3740cca Effects: a fill's or stroke's own Transform effect leaves the effects listed after it unscaled
Effects apply in the order they are listed, so an effect listed after a
Transform effect applies to the art the Transform effect made, at its
own values, as an object's later effects do after the object's
Transform effect. With Scale Strokes & Effects on, a fill's or stroke's
own Transform effect scaled the effects listed after it in that fill's
or stroke's list by the mean scale: a 300% Transform turned a 5 pt
Offset Path after it into a 15 pt one, and a Drop Shadow after it took
three times its offset. With Transform Patterns or Scale Strokes &
Effects on, an SVG filter after it also had the origin of its user space
moved.

- The effects after such a Transform effect now keep their values, on
  the transformed art and on each copy, on every fill and stroke a
  live-effect plug-in paints the piece with, and when the copies are
  counted against the effect budget.
- With Transform Objects off, the effects before it keep their values
  too.
- The Transform params text, docs/target-app-parity.md and docs/gaps.md
  describe the rule, and drop the note that listed an object's later
  effects keeping their distances as a shortfall.
2026-11-12 10:59:21 -08:00
dotCooCoo c3f7357ec2 3D and Materials: map graphics onto the planar faces of 3D objects
The Materials tab of the 3D and Materials panel lists the document's
graphics (symbols). Add as Single Graphic keeps the selected art as a
new symbol (threeD.addGraphic), and clicking a thumbnail maps it onto
the front of each selected object's 3D effect (threeD.mapGraphic) in
one undo step. The tab lists the mapped graphics with Face, X, Y, Scale
and Rotation and Remove Graphic, and a handle on the artboard drags a
graphic over its face.

The graphics are the new `graphics` parameter of threeD.extrude and
threeD.rotate: drawn on Extrude & Bevel's front and back caps and on
the Plane type, turned, foreshortened, twisted and tapered with the
face, shaded with its light and clipped to it. Symbol renames follow
into the graphics, and Select All Unused counts a symbol a graphic uses.

Docs: docs/mcp.md, docs/three-d.md, docs/effects-parity.md.
2026-11-12 10:31:37 -08:00
dotCooCoo f4e1db029e Merge main into feat/outline-object-image-alpha 2026-11-12 10:12:18 -08:00
dotCooCoo 70a4c44033 Effects: every fill a painted effect returns follows the Transform effect
A painted live effect on a fill can return a piece with several fills,
each a copy of that fill with its effects. A Transform effect after it
moved the piece, but only the first returned fill's raster effects
followed it: with a Drop Shadow before the painted effect and a 200%
Transform effect after it, the first fill's shadow offset became 20 pt
and the second fill's stayed 10 pt. Each returned fill and stroke now
takes the followed values.
2026-11-12 10:08:53 -08:00
dotCooCoo 00e07698b1 Image Tools: a live color adjustment recolors an image whose masked pixels are missing
When the document does not hold a color mask's masked pixels, the image is
drawn from its own pixels. A live color adjustment now recolors those pixels
and drops the mask on the recolored copy, instead of pointing the image at
the missing masked pixels, which drew nothing and left Expand Appearance with
an image whose pixels were not in the document.
2026-11-12 09:59:11 -08:00
dotCooCoo 556123e691 3D and Materials: Expand as Wireframes keeps a layer's path guides and cuts Revolve's art for Revolve
A layer expanded to its edges keeps the paths made into guides inside it, as it keeps its ruler
guides. A clipping group with Revolve and Rotate is cut for Revolve, the effect the canvas draws,
so its fills go in one piece and art with more fills than a 3D effect takes still expands.
2026-11-12 09:47:53 -08:00
bflatastic cfce336215 Dashes fitted to corners take a subpath with no segments
An HP-GL wedge of almost no radius drawn with an adaptive line type
(LT-1;EW0.000001,0,0;) leaves a lone moveto. Fitting the dashes to its
corners indexed the empty segment list and panicked while rendering. Such
a subpath now uses the exact plan, which has no runs to fit.

Found by import_fuzz::random_hpgl_instructions_never_panic.
2026-11-13 00:47:30 +07:00
dotCooCoo fe34c2b818 Merge main into feat/custom-arrowheads 2026-11-12 09:23:20 -08:00
dotCooCoo 87d1f0b3d7 Merge main into fix/transform-effect-scales-raster-effects 2026-11-12 09:23:19 -08:00
dotCooCoo 8d27e53115 Merge main into feat/image-color-mask 2026-11-12 08:56:33 -08:00
dotCooCoo 91e1412d77 Effects: Roughen at size 0 keeps the outline
With Size 0, Roughen moved no point but still replaced each segment
with its Detail's points joined by straight lines (Corner) or by a
smoothed curve through them (Smooth), so a curved path lost its shape.

At Size 0 each segment is now split at the Detail spacing into pieces
of equal length on the segment itself, with `pathtools::insert_at`: a
straight segment gets corner points without handles, and a curve gets
smooth points whose handles follow it. The path keeps its outline with
Smooth or Corner points alike. The params text of `distort.roughen`
describes size 0.

`insert_at` now counts the anchors added before each returned mark in
one pass. It counted them again for every split segment, which took
quadratic time on a path with many split segments. Its results are
unchanged.

Existing documents with a Roughen of Size 0 on a curved path, or with
Smooth points, draw differently.

This is VectorCraft's own rule. What Roughen does is described in
https://helpx.adobe.com/illustrator/desktop/manage-objects/reshape-transform-objects/distort-and-transform-effects-in-illustrator.html
2026-11-12 08:55:07 -08:00
BFlat cc6509827d Merge pull request #6878 from dotCooCoo/fix/opacity-mask-follows-reshape
Opacity masks: linked masks follow group effects, the Free Transform distort and envelopes
2026-11-12 23:10:24 +07:00
BFlat 3df161a972 Merge pull request #6903 from dotCooCoo/feat/gradient-repeat
Gradients: repeat or reflect a gradient's stops a set number of times
2026-11-12 23:10:02 +07:00
dotCooCoo e54519d6bd Merge main into feat/image-color-mask 2026-11-12 07:51:12 -08:00
dotCooCoo 5a8cb30259 3D and Materials: Expand as Wireframes reshapes edges by the effects after the 3D effect drawn
With two 3D effects on an object, the geometry effects after the first one
reshaped the edges, even when the second one (Revolve, which is drawn first)
built the faces. A geometry effect between the two then moved the profile and
the edges both. The edges now take only the effects after the 3D effect that
built them.
2026-11-12 07:44:35 -08:00
dotCooCoo 55a80ca480 3D and Materials: Expand as Wireframes looks up swatches for plug-ins after a fill's 3D effect
A live-effect plug-in after a fill's or stroke's 3D effect (Extrude & Bevel,
Inflate, Rotate or Revolve) that links its pieces to a swatch or pattern was
run without the document, so its result was refused and the edges kept the
shape before it. The document now goes to those effects, as it does for the
effects after an object's 3D effect.
2026-11-12 07:31:39 -08:00
dotCooCoo 63a36fec51 Image Tools: geometry effects keep a color mask
An image with a geometry effect (Transform, for example) is drawn from a
copy of the image, and that copy now keeps the image's color mask. The
canvas and outputs show the masked pixels, and Expand Appearance keeps
the mask on the image it makes.

Test: a_transform_effect_keeps_the_mask.
2026-11-12 07:26:48 -08:00
dotCooCoo 2911958414 Image Tools: live color adjustments and envelope warps keep a color mask
- A live color adjustment recolors a masked image's masked pixels, on the
  canvas and in outputs that apply the adjustment, so the colors the mask
  hides stay hidden. Before, the adjustment recolored the image's own
  pixels and the hidden colors showed again.
- An envelope warp gives each piece of a masked image the image's color
  mask, so the warped image shows its masked pixels.

Tests: a_live_color_adjustment_keeps_the_hidden_colors_hidden and
an_envelope_warp_draws_the_masked_pixels.
2026-11-12 07:09:30 -08:00
BFlat 558fec9f96 Merge pull request #6838 from dotCooCoo/fix/3d-transparent-gradient-member-order
3D: a solid in a transparent gradient keeps the shared face order
2026-11-12 22:00:51 +07:00
dotCooCoo b4fbcc5672 Opacity masks: a strokes-only Transform effect scales a member's mask
With Transform Objects off, a group's Transform effect scales the
strokes and moves the patterns of a member's linked mask as it does
the member's, instead of leaving the mask as it was.
2026-11-12 06:58:57 -08:00
dotCooCoo 5036099b51 Effects: a copying Transform effect after 3D holds raster effects back; pixel filter sizes follow
- A Transform effect that makes copies or moves at random, listed after
  an Extrude or Revolve effect, now keeps the raster effects before the
  3D effect at their own values, as it does without the 3D effect.
  Before, the 3D art kept a Drop Shadow scaled by a Transform effect
  between them.
- In a fill's or stroke's own effects, such a Transform effect also
  keeps the raster effects before it from following an earlier
  Transform effect with Transform Patterns on, and the Transform
  effects between them.
- Colored Pencil's pencilWidth and Paint Daubs' brushSize are distances
  in document units, so a Transform effect after them and Scale Strokes
  & Effects scale them as they scale Palette Knife's strokeSize. The
  Paint Daubs params text names the unit.
2026-11-12 06:57:26 -08:00
dotCooCoo 891ca3859e Merge main into fix/opacity-mask-follows-reshape 2026-11-12 06:54:42 -08:00
dotCooCoo 91d705e155 Gradients: repeat or reflect a gradient's stops a set number of times
A linear, radial, conic or diamond gradient has a spread: Pad (the
default, as before), Repeat or Reflect, with a count of 1 to 100
(VectorCraft's own limit). Repeat and Reflect run the stops that many
times along the vector (around the turn for a conic) and keep going past
both ends, Reflect running every other run backwards, as SVG's
spreadMethod does.

The Gradient panel has a Spread menu and a Repeats field, and the
Gradient tool marks where the runs meet. paint.setFill and
paint.editGradient take `spread` and `repeats`; bad values are errors.
Presets, swatches, blends, strokes along or across a path, Outline
Stroke and Object › Expand follow the spread; Expand gives each run the
same whole number of objects, and Outline Stroke's mesh keeps the color
on each side of a sharp step between two stops at one offset.

SVG writes and reads spreadMethod: SVG import now reads a repeating or
reflecting gradient as one that repeats or reflects once, instead of
expanding its stops over the shape. CSS writes repeating gradients.
PDF writes a conic's sweep shading over one run. PDF, EPS, legacy .ai
and the .ai editing data write the other kinds with their stops
repeated across the shape: at most 256 runs and 16,384 stops (256 stops
in .ai files), and for a radial or diamond no farther than 65,536 runs
from its center, with a warning past those. PDF import now finds sharp
steps in any axial or radial shading instead of blurring them.

Docs: docs/mcp.md (Spread), docs/target-app-parity.md, docs/gaps.md.
2026-11-12 06:52:38 -08:00
dotCooCoo 94e9839438 Opacity masks: linked masks follow group effects through type, plug-ins and perspective
Type and live objects in the art of a linked opacity mask are outlined
and evaluated before a group's or layer's geometry effects run over it,
so the mask moves and bends with the art it masks. Before, the effects
reached only the paths in a mask's art.

- With Scale Strokes & Effects on, a Transform effect scales the strokes
  of an image's or symbol instance's linked mask as it scales those of a
  path's mask.
- A mask's art takes Transform copies in the form it had before the
  first effect, as the art it masks does.
- A linked mask whose art is one image or symbol instance takes a
  Transform effect's move and copies with the art it masks. Under any
  other geometry effect, which images and symbol instances do not take,
  art whose masks hold one keeps its shape.
- A symbol instance in perspective projects the linked masks in its art
  with that art.
- A live-effect plug-in that paints its pieces leaves art with linked
  masks as it is, since a mask can't take the pieces.

Docs: the docs/target-app-parity.md line moves next to the Transparency
entry and lists the cases where existing documents draw differently.
2026-11-12 06:35:37 -08:00
dotCooCoo 3fdbb461fe Merge main into feat/outline-object-image-alpha 2026-11-12 06:33:36 -08:00
dotCooCoo ccc962300c Effects: Object › Expand, Outline Stroke and 3D keep the raster effects a Transform effect moves
A raster effect listed before a Transform effect follows that Transform
effect on the canvas. Several commands apply and remove the geometry
effects, and they dropped the Transform effect while the raster effect
kept its old values: Object › Expand of a gradient or pattern fill,
Outline Stroke (also Expand's Stroke option and Flatten Transparency's
Convert All Strokes to Outlines) and the 3D effects. For a square with a
Drop Shadow and a 200% Transform effect, the canvas drew a 20 pt offset
and these commands gave a 10 pt one.

- These commands now keep the raster effects at the values the canvas
  uses (without_geometry).
- A fill's or stroke's own Transform effect with Transform Patterns or
  Scale Strokes & Effects on now transforms the raster effects listed
  before it, as one without these options does. Before, Scale Strokes &
  Effects only scaled them, and Transform Patterns left them as they
  were.
- In a fill's or stroke's own effects, a Transform effect that makes
  copies or moves at random keeps the raster effects before it from
  following the Transform effects after it, as in an object's effects.
- The params text and docs/target-app-parity.md say that pixel filters
  keep their angles and light directions.
2026-11-12 06:24:48 -08:00
dotCooCoo 102ad44304 Effects: an image's Outline Object outline follows new pixels under the same key
The canvas kept the art of an image whose own fill or stroke follows the
outline of its pixels for as long as the image object stayed the same. When
the document's pixels for the image changed under the same key (Update Link
replacing a preview with the linked file's pixels), the stroke kept the old
outline while hit testing and Use Preview Bounds used the new one. The
renderer now keys that art by the document's pixels for the image too.

- vectorcraft-effects: `follows_image_pixels` names such images.
- vectorcraft-render: `reads_outside` counts them, and the resources key
  hashes the address of the document's pixels for them; their walk is not
  kept between frames.
- A test places an off-center opaque area in a smaller copy of the pixels
  under a turned and reflected placement.
- Docs: the Outline Object params text names every case that keeps the frame
  and the 50% cutoff as VectorCraft's own; docs/mcp.md's `effect.apply` entry
  for Outline Object, how long an outline is kept and the 16-bit RGBA limit;
  docs/target-app-parity.md's evidence lines.
2026-11-12 06:04:34 -08:00
dotCooCoo ac79ae55ba 3D and Materials: Expand as Wireframes keeps a layer's ruler guides and reshapes each face
- Expanding a layer removed its ruler guides with its members. The guides
  of the layer and of its sublayers now stay on the layer, after the edges.
- Geometry effects after a 3D effect reshaped all the faces as one path, so
  Offset Path merged faces that touch. Each effect now reshapes each face on
  its own, about the bounds of all the faces, within one shared budget of
  anchors, as it reshapes the drawn surface.

Docs: docs/mcp.md.
2026-11-12 05:52:39 -08:00
dotCooCoo 6ccb7c9077 3D and Materials: Expand as Wireframes expands Revolve (Classic) and Rotate (Classic)
effect.expandAsWireframes returned "draws no faces" for an object with
Revolve (Classic). It now takes the faces of Revolve (Classic) with that
effect's own options, and Rotate (Classic) is expanded as Rotate is: every
fill and stroke turned as one plane.

Docs: docs/mcp.md, docs/three-d.md.
2026-11-12 05:36:03 -08:00
dotCooCoo 01ccb1d8ca Merge main into feat/3d-expand-as-wireframes 2026-11-12 05:35:05 -08:00
dotCooCoo b9b1a1e967 Effects: linked opacity masks follow group effects, Free Distort and envelopes
A linked opacity mask moves with the art it masks, and an unlinked one
stays in place. Geometry effects on a group or layer reshaped its
members but left their linked masks where they were, Free Distort left
a linked mask behind, and an envelope bent unlinked masks too.

- Geometry effects on a group or layer run over the art of the linked
  masks of the paths, compound paths and groups inside it, nested and
  inverted masks included. Each Transform copy of a masked path carries
  its own mask, and an image or symbol instance moved by a Transform
  effect carries its linked mask. The effects on an object do not move
  that object's own mask.
- When a mask can't take an effect as the art it masks does (a path in
  either would pass the geometry budget, or the mask would get fewer
  Transform copies), the art and its masks keep their shape under that
  effect. Mask art counts toward the budget.
- Free Distort (`object.distort`) warps a linked mask with its object;
  the params text says so.
- An envelope bends only a linked mask.

Docs: a line in docs/target-app-parity.md.
2026-11-12 05:12:05 -08:00
dotCooCoo 6129853555 Effects: a Transform effect transforms the raster effects listed before it
Effects apply in the order they are listed, so a Drop Shadow, glow, blur,
Feather or pixel filter listed before a Transform effect paints art that
the Transform effect then transforms. VectorCraft drew such an
effect at its own distances around the transformed art: a square scaled
to 200% kept a 10 pt shadow offset. Now the effect follows the Transform
effects after it, with Scale Strokes & Effects on or off: its sizes scale
by the mean scale, and a Drop Shadow's offset turns, reflects and scales
with the art. Effects listed after the Transform effect keep their values,
and Transform Objects off changes nothing.

- raster_effects reads each raster effect through the Transform effects
  after it, so the canvas, export and the redraw region use the followed
  values.
- Where the geometry effects are applied and removed (Expand Appearance,
  baking for export, evaluated groups), the raster effects that remain
  carry the same transformation, hidden ones included.
- A Transform effect that makes copies or moves at random leaves the
  raster effects before it as they are. Rasterize and SVG filters keep
  their options.

Docs: the Transform effect's params text, docs/target-app-parity.md.
2026-11-12 05:07:12 -08:00
dotCooCoo 5e80810605 Merge main into feat/custom-arrowheads 2026-11-12 05:00:21 -08:00
dotCooCoo 67ebbf0b53 Merge main into feat/warp-images 2026-11-12 04:59:37 -08:00
dotCooCoo 1d41b403e1 Effects: Outline Object on an image's fill or stroke follows its opaque pixels
An image's own fill or stroke with Outline Object now follows the outline of
the image's pixels that are at least 50% opaque, traced from the alpha and
fitted with curves, instead of the image's frame. An image without
transparency, one whose pixels can't be read, one of more than 64 megapixels
or whose decoded pixels take more than 256 MB, and one whose outline would
need more than 100,000 anchor points keep the frame. An image with no pixel
at least half opaque gives nothing to paint. Images of more than 4 megapixels
are traced from their alpha averaged down to 4 megapixels, and an averaged
pixel that covers a pixel at least half opaque stays at least half opaque, so
thin opaque lines stay in the outline. Each outline is traced once for its
pixels, kept for the next redraw while those pixels are loaded, and dropped
after them; a second thread that needs the same outline waits for the trace.

- vectorcraft-trace: `decode_alpha` reads an image's alpha, and
  `opaque_outline` traces it as Black and White mode at threshold 128.
- vectorcraft-effects: the reshaped image art uses it for rows whose first
  effect is Outline Object; Convert to Shape rows keep the frame.
- Docs: docs/mcp.md, the Outline Object params text and an evidence line in
  docs/target-app-parity.md. docs/mcp.md also says that Use Preview Bounds
  takes in the shapes an image's fills and strokes paint.
2026-11-12 04:58:03 -08:00
BFlat aa990cf58e Merge pull request #6817 from dotCooCoo/feat/revolve-classic
3D (Classic): Revolve (Classic) sweeps a profile with Angle, Cap and Offset and the classic surfaces
2026-11-12 18:18:59 +07:00
dotCooCoo d32425d378 Merge main into fix/3d-transparent-gradient-member-order 2026-11-12 02:28:08 -08:00