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.
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.
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.
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.
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.
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.
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
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.
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.
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.
- 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.
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.
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.
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.
- 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.
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.
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.
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.
A Warp effect on an image, or on a group that holds one, bent the image's
frame but drew the pixels unbent, cut by the bent frame. The image now
bends with the frame as a raster mesh warp, as an envelope bends it: after
the last effect in the list, the image is cut into 10 x 10 cells of two
triangles, each a clipped piece of the image under its own affine map,
through every Warp it took and the Transform moves between them. Effects
after a Warp reshape only the frame, and a placed gradient on a group
that holds the image follows the group's bounds as the pieces draw them.
The image itself is unchanged, so editing or removing the warp redraws
it. The images stay unbent when their pieces would make the art pass 2
million objects, and an image stays unbent when its clipping frame keeps
its shape because the warp would pass the effects' anchor budget.
- SVG export writes the image once and draws the pieces with <use> when a
group holds pieces of one image clipped by triangles. PDF, EPS, .ai and
PNG exports write the bent pieces.
- Envelopes: a grayscale image's fill color now colorizes the pieces an
envelope cuts. Before, the pieces drew the gray image.
- Geometry effects: an image under any geometry effect keeps its fill
color and its smoothing setting. Before, it drew the gray image,
smoothed.
Docs: Warp params text, docs/mcp.md, docs/target-app-parity.md.
With colored lights a surface can be one clipped composite of its facets. The comment above the plain check now states that every surface of such a solid, masked ones included, draws whole in member order.
The 3D and Materials row of docs/target-app-parity.md names Revolve
(Classic) with its options and surfaces among what ships, and its
evidence names the tests that cover it.
With Extrude & Bevel, Extrude & Bevel (Classic) or Inflate on a group
or an object with fills and strokes, a solid whose gradient has
transparent stops carries an opacity mask, and it was drawn as one
whole surface in the order of the members. It could cover a solid in
front of it or hide behind one it is in front of. Its faces now take
their places in the one back-to-front order of every solid's faces, in
runs that each carry the solid's opacity mask. A run splits only where
a face drawn after it overlaps the next face.
With Revolve (Classic) on a group, a member whose gradient has
transparent stops drew its whole surface in the members' order, so it
could cover a member in front of it or hide behind one it is in front
of. Its faces now take their places in the one back-to-front order of
every member's faces, in runs as a member with transparency of its own
does, and each run carries the member's opacity mask.
Effect › 3D and Materials › 3D (Classic) › Rotate (Classic)… turns every
fill and stroke as one flat plane, as Rotate does, and shades it with the
classic No Shading or Diffuse surface.
- `effect.apply` with `threeD.classicRotate`: the Position rotation and
Perspective, `surface` (`none` or `diffuse`), the classic lights,
Ambient Light, Blend Steps and Shading Color. It has no highlight, no
Draw Hidden Faces and no shadow.
- The dialog shows Position on the Rotation tab and the surface and
lights on the Lighting tab, with no Object tab.
- Groups and layers turn about one shared center, and the effect also
goes on a fill or stroke, as Rotate's does.
- `effect.lightingPreset` refuses it, as it refuses the other classic
3D effects.
- Unknown parameters, numbers out of range, bad flags, a surface other
than No Shading or Diffuse and bad shading colors are refused with an
error.
Effect › 3D and Materials › 3D (Classic) › Revolve (Classic)… sweeps the
profile round a vertical axis, as Revolve does, and draws every face with
the Wireframe, No Shading, Diffuse and Plastic surfaces of Extrude & Bevel
(Classic).
- `effect.apply` with `threeD.classicRevolve`: Angle (0 to 360), Cap,
Offset (0 to 1000 pt) from the left or right edge of the profile's
bounds, the Position rotation and Perspective, and the classic lights,
Ambient Light, highlight, Blend Steps and Shading Color.
- Groups and layers revolve about one shared axis, and the effect also
goes on a fill or stroke, as Revolve's does.
- `effect.lightingPreset` refuses it, as it refuses Extrude & Bevel
(Classic).
- Revolve faces carry their view-space normal, and
`three_d::revolve_facets` hands them to the classic surface code.
- Unknown parameters, numbers out of range and bad flags, edges,
surfaces and colors are refused with an error.
The Stroke panel menu's Edit Arrowheads… (stroke.arrowheads.edit) opens
Arrowheads.vectorcraft next to the preferences, creating it with one
example head when it is missing. Each symbol in the file is one head,
listed by name after the built-in heads in both arrowhead menus: it
points right, its registration point is the tip, and its height is drawn
as wide as the built-in heads. The file is read at startup and again
each time VectorCraft saves it; stroke.arrowheads.reload and
stroke.arrowheads.list read and list it.
Arrowhead gets a Custom variant, appended after the built-in names, that
carries the head's name and outline, so a document that uses one draws,
saves, reopens and exports it without the arrowheads file. stroke.set
takes {"custom": name} or the {"Custom": {name, path}} form that
document.inspect reports.
Part of #5421.
Window > 3D and Materials > Quick Actions > Expand as Wireframes, and the
command effect.expandAsWireframes, replace each selected object that has a
visible 3D effect (Extrude & Bevel, Extrude & Bevel (Classic), Revolve,
Inflate or Rotate) with a group of paths: the edges of the faces the effect
draws for the object as it is turned and projected now.
- Each edge appears once. Edges that meet end to end form one path, closed
where it comes back to its start, and curved edges stay curves. Geometry
effects after the 3D effect reshape the edges as they reshape the drawn
surface.
- The paths have a 0.5 pt black stroke with round joins and no fill. The
group keeps the object's id, name, transparency, attributes, slice and
text wrap, and is selected. A layer stays a layer holding the edges.
- It is one undo step. Nothing selected, no visible 3D effect, a solid that
can't be built or is drawn as its source art, or more than 1,000,000 edges
in one object is an error, and the document does not change.
Docs: docs/mcp.md, docs/three-d.md, docs/effects-parity.md,
docs/target-app-parity.md.
Fixes#6354
Each of the fifteen Warp styles now bends the bounds as one Bézier patch.
The style sets the patch's control points from the bend and the size of
the bounds, the horizontal distortion scales each column of control
points about its middle, and the vertical distortion scales each row.
The Warp effects and warp envelopes share the map (`WarpNet`). Content
with no width or no height takes the middle of the patch along that
side.
A warp carries the map it draws with as `version`. New warps, the
built-in graphic styles' Warps and warps opened from .ai files get 1.
Warps in .vectorcraft documents saved before the version existed read
as 0 and keep the earlier map, so those documents keep their look.
Edits keep a warp's version, and Warp Options editing several objects
keeps each one's own. effect.apply, effect.setParams and the warp
envelope commands take `version` 0 or 1 (`1.0` counts as 1) and refuse
any other value. An .ai file holds a warp's settings and not its
version, so a version 0 warp saved to .ai opens again with version 1.
The .ai writer compares a style's settings without the version, so
saved warps still export as editable effects.
Docs: docs/mcp.md (Envelopes), docs/effects-parity.md (Warp),
docs/target-app-parity.md.
#6716 added the member index to each solid part after #6754's shadow
code was written against the five-field tuple, so main stopped compiling
once both landed. The Inflate, Extrude and shadow-drawing loops now
destructure all six fields.