Ruler guides were a list kept beside the layers. Each guide is now an
object of its layer or sublayer, always directly in it and above the
layer's art. These behave as on main:
- Guides draw on screen only. Exports (SVG, PDF, PNG, PSD), Fit All,
Select All, the art bounds, clicks and marquees, and a layer's
Pathfinder and Transform effects leave them out. The Layers panel
lists them as guide rows of their layer, the highest guide.list
index first.
- Deleting a layer deletes its guides, and merging layers keeps their
guides in the merged layer.
- The guide commands number guides as guide.list does, in the order
they were made.
New: each guide takes an id from the document's object ids. An object
command given a guide's id fails with an error, and node.move cannot
put a guide into a group or out of its layers. A guide made while an
opacity mask, a symbol or a pattern is edited moves to the top
visible, unlocked layer when editing ends.
File format: native files still save the guides in the document's
guides list, in every file version, so older builds read them. Each
entry may now also carry the guide's id, name, locked and hidden
flags; older builds ignore those fields. Opening a file puts each
saved guide on its layer (on the top visible, unlocked layer when the
file names none or a layer it does not have), and each saved guide
counts against the object limit for opening a file. A ruler guide node
that a file holds below a layer's art moves up to the layer's guides,
and one anywhere else (in a group or another object, beside the
layers, or in a symbol) is removed. Ruler guides read from an .ai file
become guide objects on the layer they were on, numbered in the order
the file lists them.
The test for new XML with a one-item list now starts from an item that
has a parent, an attribute and a child. It checks that the copy has no
parent and that changing the copy's attribute and child leaves the
original unchanged, so a copy that drops or shares the children fails.
Outside Windows, `\\host\s\x.txt`, `\\?\C:\x.txt` and `\\.\pipe\x` are
relative file names in the script's folder, so `exists`, `open` and
`getFiles` look them up. The test now expects no lookups for them on
Windows only, and on macOS and Linux checks `//host/s/x.txt`, an absolute
path outside the folder, alone. The returned values are the same on every
platform.
Adds step-security/harden-runner (audit, pinned to v2.22.4 like
craft-common-actions) as the first step of each job that did not have it,
so every workflow in the org's public repos reports its egress to
StepSecurity. Audit, not block: block-mode allow lists come from each
job's observed traffic.
new XML(list) now returns a deep copy of the list's single item, as
ECMA-357 section 13.4.2 specifies for an XMLList argument; before, it
returned the item itself, so changes to the new value changed the list.
insertChildAfter and insertChildBefore take one unit of fuel for each
child they compare with the reference, as childIndex does.
The test for the missing xpath method now checks the XML and XMLList
prototypes; reading .xpath on a value selects child elements and
returned an empty list in every case.
`color_name` clamps each component before rounding, but `clamp` keeps a
-0.0, so a color with a -0.0 component was named "R=-0 G=128 B=-0" (and
"K=-0", "Gray K=-0" in CMYK and Gray). Adding 0.0 after rounding turns
it into 0, as the Lab branch already does.
The params docs now state the direction (and the zero) of each angle or
rotation a command takes; behaviour is unchanged. Shape creation, text.create,
the grids, add-on shapes, saved views, Liquify, Puppet Warp pins, Mirror and
Radial Repeat and Vector Halftone turn clockwise; text character rotation,
gradients, the eraser tip and print screen angles turn counter-clockwise.
view.saved.new's rotation note changes its schema, so the API level goes to 3.
A test walks every command's params doc and fails when a param named like an
angle or rotation doesn't say clockwise or counter-clockwise.
Check Script read names with Rust's alphabetic and alphanumeric tests, so it
split names at U+2118, U+203F, U+00B7 and the zero width non-joiner and joiner,
and took U+00B2 and U+2E2F into names. It now uses the Unicode 16.0 ID_Start
and ID_Continue rule that vectorcraft-js uses, with `$` and `_`
(https://www.unicode.org/reports/tr31/,
https://tc39.es/ecma262/#sec-names-and-keywords).
A `\uXXXX` escape is part of a name only when it stands for a character the
name may hold where it is: `\u0030abc` no longer becomes `0abc`, and malformed
escapes end the name.
The engine's lexer comparison test now checks that both crates take the same
characters into names, written out and as escapes.
A closed subpath that refits to a single curve has one anchor, which is
not a subpath, so Simplify dropped it: a small circle inside a compound
path was lost and the result ended hundreds of points from the original,
and a small closed path on its own came out empty. Such a subpath is now
refitted in two parts, cut at the point farthest from its start, or in
three when two parts would still enclose no area (two lines that retrace
each other with Convert to Straight Lines). A closed subpath of a single
segment stays as it is.
addNamespace and setNamespace now add a declaration's bytes to the heap total when the element
gains a new prefix, and QName.prototype.toString adds the bytes of the string it returns. Before,
both only checked for room, so a loop of distinct prefixes could grow an element past the heap
limit until a collection recounted it.
A centred or right-aligned line of tracked type was measured with the
tracking after its last character, so it sat half that tracking
(centred) or the whole tracking (right-aligned) left of where the page
of users' .ai files draws it. That page aligns a line as wide as its
characters without that tracking.
Shaping now records the tracking each glyph's advance holds
(SGlyph::tracking), and a line that isn't justified leaves its last
character's out of the width it is aligned by. The last character is
the last one the line draws before a paragraph's end, a forced line
break or the spaces a wrap leaves; spaces or a tab typed before a
paragraph's end or a forced line break keep the letter's tracking, as
the page does. Forced line breaks and wraps aren't in the files: they
follow the rule so that turning a wrap into a paragraph or a forced line
break keeps the line in place. Hyphenated lines, lines whose last
character hangs, vertical and right-to-left lines and type on a path
keep it. The tracking stays in the glyph's advance, so the caret,
selections, line breaking and Fit Headline are unchanged.
LineInfo::trailing gives the amount. Right-aligned area type sets the
text after its last tab the same way.
What aligns by line widths follows. Convert To Area Type makes its
frame end where the lines are aligned, with room for the tracking, so
tracked type converted either way stays in place. Affinity import lines
up differently aligned paragraphs of artistic text by the aligned
widths. SVG import moves a centred or right-aligned letter-spaced line
back by its share of the last letter spacing, so it stays where a reader
draws it and SVG export, which anchors lines at the end of their
advances, reads back unchanged.
Centred and right-aligned tracked type lays out differently than before
in every document.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Clearing Preferences > Plug-ins & Scratch Disks > Additional Plug-ins Folder
left the folder recorded as the one last loaded. Setting the same folder
again then matched that record, and nothing in it was installed, so a
plug-in removed in the meantime stayed removed. Clearing the preference now
forgets the folder when it is the one last loaded.
- A list copy holds each new copy as a root while the list is charged
for it, so a collection at that point no longer frees the copy. Before,
`x.setChildren(<c/> + <d/>)` near the heap limit could leave one child
twice or end with an internal error.
- An assignment to a path such as `x.a.b = v` or `x.a.b[0] = v` removes
the elements it added for the path when a later step stops at a limit
or throws.
- Comparing XML values counts the attribute tables and the work stack
against the heap limit.
Add `cargo xtask ui-commands` (and `--check` in ci) so the headless
catalogue cannot drift from desktop UI_COMMANDS, and fix params-doc
escaping that printed literal backslashes.