- Weed Box and Lines counts the outline points a nested clip group hides when
it tests pieces for being inside a region, and counts the work of every clip
group in the selection together, so a selection cannot run far past the
limit.
- Stencil Bridges refuses art when its measuring budget runs out only while an
island is still unjoined, and a refusal for size or detail says so.
A Cutting Tools add-on command (Object › Plug-ins › Cutting Tools › Weed Box
and Lines…, `addon.cutting.weed`) for vinyl cutting: around the selected art
it adds a weed box, a rectangle at a margin outside the art's bounds, and
weeding lines across the box, horizontal, vertical or both, by count or by
spacing. Each line runs from one side of the box to the other and is left out
over the art and within a gap of its outlines, so it stops at the art and the
waste lifts off in pieces. The lines and the box are straight paths stroked
in a chosen color swatch ([Registration] by default) with no fill, in one
group named Weeding on top of the current layer, selected, as one undo step.
While a clip group, or a group inside one, is edited in isolation, the
group goes on top of the container that holds the outermost clip group
around it.
The art is measured by the outlines a cutter cuts: closed paths by their fill
rule (the hole of an even-odd compound path gets lines too), open paths as
lines, type by its glyph outlines, images by their frames, placed files by
the art they show (by their boxes when the file can't be read), symbol
instances by their art, and blends and other live objects by the art they
draw. A clip group, and an object selected inside one, is measured by what
shows inside the region its clipping paths clip to, and a clipping path
selected on its own as its clip group. Art in a hidden group or layer is
left out. The command refuses an empty selection, art with no outlines, bad
params, and art or lines too complex to measure, with a message.
The dialog has Preview; a Spacing above 0 is used instead of the Count.
Docs: docs/mcp.md (Cutting Tools add-on) and docs/target-app-parity.md.
Object › Plug-ins › Cutting Tools › Stencil Bridges… (`addon.cutting.bridges`)
cuts strips of a set width out of the selected art so that a stencil cut
from it holds together: every island (the inside of an O, A or 8, a hole in
a shape) stays joined to the sheet, directly or through another island.
Bridges take the shortest crossings that fit first, then spread around each
island up to the count asked for, at least two widths apart. They run
vertically, horizontally or along the shortest crossing among 12
directions 15° apart.
- The art is measured by the area its outlines enclose, whatever their
paint, with hidden objects left out; type by its glyph outlines, without
converting the type. The result is one compound path with the strips cut
out, painted as the topmost selected shape with outlines, in the place of
the topmost selected object with outlines. Selected objects with no
outlines in the art stay where they are.
- Keep Original (on by default) moves the selected objects that make up the
art to a new hidden layer, Stencil Original; off replaces them.
- Art with no islands, or none a bridge of the width fits, is left as it is
with a message and no undo step. Islands the cut result still encloses
are counted in `unbridged`, with a message. Otherwise the run is one undo
step.
- Curves are followed within a twentieth of the width (0.002 to 0.25 pt).
Art that reaches more than 10000000 pt from the origin or has more than
200000 anchors is refused before it is combined. Art is also refused when
its combined area has more than 4000 outlines, when its outlines need
more than 200000 straight segments, or when placing the outlines or
joining every island takes more work than a fixed budget allows; when
the budget runs out while extra bridges are added, the bridges found so
far are kept.
Tests in vectorcraft-pathops, vectorcraft-engine and vectorcraft-ui-egui,
command_sweep cases, catalog rows in all 27 languages, docs/mcp.md, the
evidence list in docs/target-app-parity.md and the ROADMAP progress log.
Affinity: read native documents with craft-affinity from craft-libs
* Affinity: read native documents with craft-affinity from craft-libs
crates/affinity's reader moved to craft-libs as craft-affinity (#914).
The crate keeps its name and re-exports it, so the engine, the corpus
tests and fuzz targets, and the Affinity corpus CI job are unchanged.
Its integration tests take craft-libs' versions; the one signature that
changes is patchy-shapes-2.af, whose special shapes now have outlines.
* Affinity: pin craft-affinity to craft-libs 228f6d0c (no change to the crate)
A new gradient kind, `diamond`, runs its stops from the center (the
start) out to a square with a corner at the end of the vector; the
aspect stretches the square across the vector into a rhombus. The
Gradient panel's Type row has a Diamond button, the Gradient tool draws
the square with the aspect handle and center ring, and a gradient
fitted to an object covers its box.
- Model and canvas: the level is |x| + |y| in the square's frame; a
square with no area (no vector, an aspect of 0, numbers out of range)
paints the last stop. The canvas draws it as pixels, out to a
stroke's miters, caps and arrowheads. Transforms keep the vector and
take the mapped size across it as the aspect.
- Commands: `paint.setFill`, `paint.editGradient` and
`paint.setGradientGeom` take `kind: "diamond"`; a negative aspect or
a focal point is an error. A conic or diamond gradient that a plug-in
returns with a focal point loses the focal point.
- Gradient tool: dragging the aspect handle of a radial or diamond
gradient whose file gave it a negative aspect now sets a positive
aspect; only a conic's negative aspect mirrors it.
- Export: PDF, SVG, EPS and legacy .ai write four linear gradients, one
for each quarter of the square, clipped to the shape (PDF as axial
shadings). PDF and SVG write an image for translucent stops, a
dithered fill or a flat square, and for the Perceptual method unless
PDF writes the stops as spot color shadings. SVG writes a diamond on
type characters as a radial gradient through the corners, and so
does CSS. A swatch library saved as CSS gets four corner layers, a
value for the `background` property (a circle when the swatch is
turned by an angle that is not a multiple of 90 degrees). The .ai
editing data holds a radial gradient through the corners. The
document exports give a warning.
- SVG export: a stroke drawn as an image, as conic wedges or as diamond
quarters now covers the miters, caps and arrowheads that reach past
its paint box.
- PDF import reads a function-based shading whose color is the same
along each square about the origin of its space as a diamond.
- Object > Expand gives nested squares or a mesh of rings.
Docs: docs/mcp.md, docs/target-app-parity.md.
action.batch read its true/false options with a fallback, so
{"stopOnError": "false"} kept stopping on the first error, and a
number for a string option such as label or datasetFileNaming was
dropped or turned into an empty string. The source check also ran
after the destination folder was made.
includeSubdirs, overrideOpen, overrideSave, overrideExport and
stopOnError now take only true or false, and source, folder,
destination, destinationFolder, datasetFileNaming and label take only
a string. Any other value is an error naming the key, given before the
destination folder is made or a file is opened. A null reads as a key
left out. The params text and docs/mcp.md say so.
row_thumbnails_wait_for_the_end_of_a_drag expected every row's
thumbnail to render in the first pass. The UI thread renders row
thumbnails for at most 8 ms of wall-clock time per pass, so on a busy
machine the first pass rendered only some rows, the next pass rendered
the rest, and the test failed at "and stay".
The thumbnail cache now takes a clock in tests (as the app's
now_override does for idle scheduling). The drag test gives every
render no time, and a new test gives each render 5 ms and checks that
three rows render two in the first pass and one in the next. The 8 ms
budget and the release build are unchanged.
The install approval's OK now also waits for these to be let go of:
- Enter or Space held down while OK was disabled, whose key repeat
clicked OK once it had the keyboard focus.
- A pointer button held while OK was disabled, even after another
button is pressed once OK takes input.
- A pointer button held on the question before, when a new question
takes its place.
The wait also starts over when the window lost the focus since the
frame before, even if it has the focus again by the next frame.
A new built-in add-on, Image Tools (Object › Plug-ins › Image Tools),
adds Remove Background… (`addon.image.removeBackground`). It makes the
background of the selected images transparent by lowering the alpha of
their own pixels, in one undo step, with no service or model. The
background is the most common color along the image's edges, the
average of the image's corners, or colors the user picks. Contiguous
(on by default) clears it only where it reaches in from an edge; off,
it is cleared wherever it is. Tolerance and Softness (0 to 100, 10 by
default) set how near a color must be to be cleared and the band over
which pixels fade out. Match measures that nearness as the RGB
distance or as the largest difference on one channel. It is a
VectorCraft addition.
- The image stays an image: an embedded PNG with alpha, the source's
ICC profile and resolution, and 16 bits or gray when the source is.
A linked image is embedded and keeps its Placement Options.
- When the edges hold at least as many clear pixels as pixels of their
most common color, edge mode clears nothing, so a second run leaves
the subject alone. Corner mode leaves clear corners out of the
average and clears nothing when all four are clear.
- With Match set to Each Channel, a tolerance of t / 255 × 100 clears
the colors within t 8-bit steps on every channel.
- A CMYK image, a linked image that shows its preview, an image that
would need more than the decode allowance (checked from its header)
and a result with no pixel left are refused, and the document stays
as it was. When no pixel changes, no undo step is added. The result
reports `cleared`, the pixels made fully clear.
- Picked colors are hex colors, with or without `#`, or black, white,
red, green or blue.
- The dialog opens with Preview off; with Preview on, the canvas shows
the result, and Cancel puts the image back. While the dialog
previews, the session keeps the images' decoded pixels (at most
128 MiB, 32 MiB in the web app) so each preview step does not decode
them again, and releases them when the dialog closes with OK or
Cancel. A run that is not a preview step keeps nothing.
Docs: docs/mcp.md (Image Tools add-on), docs/target-app-parity.md.
An XML declaration at the start of XML or XMLList text was skipped up to
the next "?>" without being read. It is now checked against XML 1.0's
grammar (https://www.w3.org/TR/xml/#NT-XMLDecl): a version of "1." and
digits, then an optional encoding name and an optional standalone "yes"
or "no", in that order, with optional white space before "?>". Any other
declaration gives "SyntaxError: invalid XML declaration", and a character
XML does not allow gives "invalid character in XML text". White space
before the declaration is still accepted.
The parser now takes fuel for the length of the declaration and the
white space before it, element and attribute names, white space in open
and closing tags, and the text it searched when an attribute value, CDATA
section, comment or processing instruction is not closed, or when "]]>"
or "<" stops a text run or attribute value. A long run in any of these
used the same fuel as a short one.
Grouping for flattening joined every pair of objects whose 1 pt reach
boxes touched, transitively, so a row or grid of opaque objects next to
one see-through object became one group and was flattened with it.
Now a group holds each see-through object and every object its reach
touches. An object without transparency joins only where its reach
touches a member and it lies above that member but below the group's
topmost object, whose place the group takes, so the stacking order
stays the same. In files without transparency with Clip Complex Regions
on, art under a group within one image pixel of a member joins it too,
with the pixel size taken from the image's actual resolution. Objects in
an overlap set that includes one inside a clip group or clipping layer
keep the previous grouping.
The 1 pt antialiasing margin now goes around a group's art once instead
of once per nested group (a stroked path's plain art is a group, so it
had 2 pt).
On 3,000 stroked rectangles, 60 with a drop shadow, the Flattener Preview
counts 180 affected objects where it counted 3,000, and Flatten
Transparency with the Medium preset makes 240 flat regions and 2 images
where it made one image of the whole grid.
A finally block that break or continue leaves no longer keeps the saved
site of the exception it ran for. A Jump now removes the sites at or
above the stack's length, as a return already does, so a collection
after the stack grows back over that slot does not root and count the
old code.
New tests in crates/js/src/host_tests.rs: an error passed on by a
finally block that collects garbage under a 1 MiB heap is reported at
its throw; the saved site keeps direct eval code live through a
collection; a host abort inside a finally block leaves no saved site;
and break, continue and return out of a finally block drop the site.
#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.
Document Setup gets a Color tab with the document color mode (RGB Color
or CMYK Color), a Convert to CMYK or Convert to RGB box for a mode
change (cleared, the colors keep their numbers), and the RGB and CMYK
profiles assigned to the document, with a working-space entry for none.
When the tab changes something, OK runs document.setup, then
edit.assignProfile, then file.documentColorMode in one command.batch,
and the document's changes are one undo step. Assign Profile runs first,
so a mode change converts through the profile picked with it. An
unchanged Color tab adds no color commands, and Cancel, or OK with
nothing changed, records no undo step. A Color tab field with a value of
the wrong kind is an error, and the dialog stays open with nothing
changed. File › Document Color Mode and Edit › Assign Profile… stay
where they are.
Catalogs: "Working RGB (don't tag)" and "Assign Profile" rows in every
complete catalog, and the "`{key}` must be a profile name or null"
message in every complete-message catalog. Docs: docs/mcp.md,
docs/control-protocol.md, docs/target-app-parity.md.