* security: linear vector import, stroking and rounding, validation and a cycle check for dev snapshots
Closing a subpath, rounding corners and chaining stroke runs each rescanned the whole
network per step, and Document::validate searched a parent's children per child. They now
update only the current subpath's last segment, rebuild each region loop in one pass, walk
per-vertex adjacency lists, and check edges against a once-built index. A dev snapshot whose
layers contain a cycle under the root is refused instead of reconstructed.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(doc): address review findings for snapshot children and 2-segment rounded loops
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
The hover search now recurses into each child first and looks up its mask only when the child added a candidate, as layers_at in crates/doc/src/geometry.rs does.
Text went onto a path only with the Design panel's Put text on path
button (a text layer and a path selected together) or with text.onPath.
The Text on a path tool, in the Text flyout of the toolbar
(tool.textOnPath), shows the I-beam over a shape's or vector's path, and
a click there puts new, empty text on the path, starting at the click,
and starts typing. The text takes the path layer's place, transform,
box, constraints and effects, and its fills when one of them shows; the
path layer is removed. Ending the edit with nothing typed puts the path
back with no undo step.
The tool measures the distance on the page, so a layer scaled more one
way than the other, or shown smaller, is reached where it shows. Shapes
in front whose outline is away from the click do not hide a path behind
them, and paths that a mask or a clipping frame hides at the click are
skipped, as are locked layers and layers inside instances.
A double-click into a text layer that was just made no longer makes it
count as an existing layer, so leaving it empty records no undo step,
with this tool and with the Text tool.
The status line of docs/file-format-parity.md repeated eight topics,
from SVG/PDF export depth refusal (#208) to "last major". Each topic is
now listed once, and the boards entry closes its parenthesis.
Three parity rows still listed work that has landed on main. The
prototyping Triggers row listed delays on mouse enter, leave, down and
up as missing; they landed on 2026-10-13. Canvas & navigation's
remaining work in target-app-parity listed outline mode's Include
hidden layers and Include object bounds, which View > Outlines has.
The file-format Fonts row said missing fonts give warnings only; the
desktop app lists them in the Missing fonts window, and replacing them
is still missing.
Each file gets its status line and a revision-history row. The
percentages and hours are unchanged.
The Corner smoothing row showed "iOS: 60%" as plain text. The help
page on corner radius and smoothing says to click iOS to set corner
smoothing to 60%. The row now has an iOS button that sets
cornerSmoothing to 0.6 on the selection in one undo step, with the
hover text "Set corner smoothing to 60%".
Polygon and star outlines did not use their corner smoothing: the value
was stored, imported and exported, but `shape_path` drew their corners
as plain circular arcs, and the Design panel showed the Corner
smoothing field only for rectangles and frames. Rounded polygon and
star corners now take smoothing the way rectangle corners do. Each
corner keeps a circular arc over the unsmoothed part of its turn and
eases into both edges, and it starts (1 + smoothing) times the plain
corner's length from the vertex. When a smoothed corner does not fit
in half of its shorter edge, smoothing is reduced first, then the
radius, as for rectangles. The Individual corners button opens the
panel for polygons and stars too, with the Corner smoothing row and no
field per corner.
The Design panel's font family and font style menus offered no way to
bind a string variable; these bindings could be made only by commands
such as variable.bind. Each menu now starts with Apply variable, which
opens the variable picker on string variables for the selected text
layers. A bound family or style shows its variable's chip in place of
the menu. A click on the chip picks another variable, and its detach
button unbinds it. While a text is being edited (a caret or selected
characters), the menus have no Apply variable item and show the plain
dropdown. A pick applies to the selected characters, or to the whole
layer when no characters are selected, as before.
The variable picker opened from a style's field listed every variable of
the field's type, and the Fill and Stroke style picker's Color variables
listed every color variable, whatever their scopes. Both now offer only
variables scoped to the property, as the Design panel's pickers do. A
paint style's colors take variables scoped to a fill or to strokes, an
effect style's fields take effect variables, and a text style's fields
take the variables of their font property. Layout grid fields still take
any number variable. style.bind still binds a variable outside its
scopes, as variable.bind does.
The style editor bound variables to paint colors, shadow colors, blur
radii and grid sizes, but a text style's fields took variables only
through style.bind. The font and font style menus now start with Apply
variable, which opens the picker on string variables, and the size, line
height and letter spacing fields show a variable button on hover for
number variables, as the Design panel's number fields do. A bound field
shows its variable's chip in place of the value, as in the Design
panel. A click on the chip picks another variable, and its detach
button unbinds it.
Found while testing crates/pathops/src/lib.rs:326-333 (stroke_outline_of, StrokeAlign::Inside and Outside arms calling binary(), which uses FillRule::NonZero at :82)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Found while testing crates/doc/src/colors.rs:30 (TextStyle::for_each_color_mut, used by TextData, Style and Document::map_colors / set_color_profile)
Co-authored-by: Claude Haiku 5.5 <noreply@anthropic.com>
* chore: explicit test imports in engine, part 1 (Sonar S2208)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
* fix(security): cap COLR layers, PNG glyph dimensions, and layout cache capacity
---------
Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
A Selection colors row could take a color style but not a color
variable, and a row linked to a style or variable could not be
unlinked from there.
selection.bindColorVariable binds a color variable to every solid fill
and stroke slot a row stands for. It replaces a color style on that
list and any earlier binding of the slot. A text range with fills of
its own takes the variable's value in the layer's modes. Gradients and
slots outside the variable's scopes are refused.
selection.detachColor unlinks the style or variable of a row's slots
and keeps their colors.
In the Design panel, the Styles menu of an unlinked row lists the
document's color variables after its color styles, and a linked row
shows a Detach button in the Styles button's place.
* M6: Dev Mode measurements kept on the canvas, a read-only layers panel
Measurements placed between two layers, along a side or to the layer
around one (devMode.addMeasurement / removeMeasurement / measurements),
stored on the layer they start from (saved, synced, undoable; old files
open without them), drawn in Dev Mode as labelled redlines that follow
the layers and listed, placed and removed in the Inspect tab. In Dev Mode
the layers panel only selects and expands.
* M6: Dev Mode measurements: explicit imports, a measurement row of its own (Sonar)