Commit Graph

1397 Commits

Author SHA1 Message Date
Dennis Kobert
ca0f288f43 Trim comment narration and stale marker references 2026-09-10 01:12:22 +00:00
Dennis Kobert
394c6aad32 Carry appearance columns through the list attribute group glue 2026-09-10 01:12:22 +00:00
Dennis Kobert
ff074b2a1c Retire the Vector stroke field into the appearance coverage
Stroke parameters live only on the appearance's stroke coverage now.
Vector loses its stroke field, transform normalization, and concat
stroke adoption; solidify, morph, combine, and the recolor read the
coverage instead, with morph gaining the cover-paired appearance lerp.
The stroke-inclusive bounds take the stroke as a parameter, the plain
vector bounds ignore include_stroke, the editor's metadata channel
carries one resolved appearance snapshot per layer, and the data
panel's Vector table drops its stroke properties tab for a handles tab.
Legacy vector payloads parse their stroke solely to validate the shape.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-10 00:37:10 +00:00
Dennis Kobert
d278fd666d Delete the legacy fill and stroke paint markers
The appearance column is now the only paint channel. The Fill and
Stroke attribute markers, their name constants, the LanePaint push with
its two-hop reach, and the interior paint placement all go away; nodes
emit and readers cascade the appearance alone. PaintReach shrinks to
the cascade's own-wins arbitration, the legacy conversion converts the
group content inside appearance paint cells, and transform baking lands
on those cells too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-10 00:01:29 +00:00
Dennis Kobert
f726e712bc Retire the stroke paint order input into fill and stroke node order
The Stroke node no longer takes a paint order value: stroke-below is now
the Stroke node sitting upstream of the Fill node, and the editor's
paint order control rewires the two nodes through set_stroke_paint_order.
Documents with the retired input migrate to the nine-input shape, their
stored order replayed as that topology rewrite. The Stroke struct drops
its paint_order field; renderers read stroke_below from the resolved
appearance alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 22:44:18 +00:00
Dennis Kobert
46e0a4f2f5 Read every paint through the cascaded appearance
The renderer, metadata collection, hit testing, and clip-path reduction
all resolve a lane's paint as its own declared appearance or the
nearest ancestor's through the cascade, taking the first fill and
stroke coverages in one walk: the coverage's stroke parameters replace
the element-resident stroke, the paint cells' interior lists feed the
paint renderers, and the paint order reads off the coverage row order,
which the stroke nodes now place from their paint order input. The
paint overlay and its transmute dissolve into an inherited-appearance
parameter on the vector-level bodies, with the Render trait untouched.
Mask clones paint through a single black-fill appearance, and every
row-building node stamps the appearance beside the legacy markers it
still writes, so renders stay identical until the markers go.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 22:18:50 +00:00
Dennis Kobert
1fff59f380 Composite a paint's own opacity into its rendered color
A paint row's opacity and fill-opacity attributes now fade the color it
contributes, and a color stack collapses to the one composited color
the SVG fast path emits: each pass mixes by its blend mode and then
composites source-over in straight alpha, with the alpha-only modes
moving only the backdrop's coverage. Gradient paints fade every emitted
stop the same way, on the SVG stop order and the vello ramp alike, and
a masker drops the fill half so it cannot reach the content clipped to
it. The blend-mode formula application lands beside the BlendMode enum,
with an overlay channel formula pinned as hard light with swapped
operands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 21:35:21 +00:00
Dennis Kobert
26de6912f7 Fix the fill transform toggle's name with a HasTransform newtype
The fill's gradient placement input splits from one optional transform
into the has-transform toggle and a plain transform, so the toggle's
input name is fixed in the document format ahead of the transform
toggle's own arrival. An unset placement keeps the toggle's false
default and derives from the content's bounds at evaluation, which is
also the unbaked placeholder the deferred gradient bake probes for.
Documents saved with the optional form migrate by decomposing it, a
wired transform source keeping its connection marked explicit, and the
legacy fill migration now lands on the split shape directly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 21:23:24 +00:00
Dennis Kobert
5f0c02e240 Stamp the appearance from the fill and stroke nodes
Both nodes append their coverage to the content's appearance following
the painter's algorithm: the most downstream paint node paints on top,
and a repainted cover is replaced in place keeping its position in the
paint order. The coverage's paint is the canonical paint list carried
as one graphic cell, the input lane's own envelope dropped; a stroke
coverage records its authoring space by composing the item transform
with the translation cleared, so an otherwise-identity capture elides.
The legacy fill and stroke writes continue beside the appearance until
the readers move over, keeping renders unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 21:04:49 +00:00
Dennis Kobert
5e30501560 Cascade the appearance through the paint reach and both flatten paths
The appearance cascade rides PaintReach beside the legacy paint push,
with the opposite arbitration: a lane's own declared appearance wins
wholesale and an undeclared lane inherits the nearest ancestor's, at
any depth, crossing the group boundaries the paint push resets at. A
fresh render entry starts bare, which is what clears the cascade for a
pattern's own content. Both flatten paths push a parent's declared
appearance into undeclared children without composing, pinned against
each other by a shared test. The appearance and paint markers move to
hand-written impls whose stored form is the bare value the appearance
writers use, collapsing an absent and an empty cell to the same
undeclared read at every seam.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 20:52:02 +00:00
Dennis Kobert
334d48c7fb Retarget the list field promote onto the coverage container
The appearance promote carries the two-level sharing law the paint list
promote established: a group-free appearance moves its parked header
into the persistent region (once, however many lanes share it), a
paint-held group denies the move and clones through the Cow dispatch
that shares persistent interiors pointer for pointer, and stroke
parameter columns on a coverage deny nothing. Four regression tests pin
the move and share behavior, mirroring the paint promote suite.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 20:19:18 +00:00
Dennis Kobert
76a6bae528 Add the appearance model's types, markers, and deep field glue
Cover, Coverage, and Appearance mirror the upstream appearance model on
the record substrate with a 'static interior: the paint column stores
Graphic<'static>, and the appearance marker's value is Option<&Appearance>,
exactly as the Fill paint marker's is today. Stroke parameters ride the
coverage item as attributes elided at their defaults, with typed markers
whose defaults are pinned to Stroke::default() by test. The deep field
glue carries paint-held groups across the owned, resident, and
persistent seams as the paint list glue does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 20:14:40 +00:00
Dennis Kobert
e10d56c261 Box the largest message and update payloads 2026-09-09 15:39:37 +00:00
Dennis Kobert
6910a12f71 Drop redundant conversions, assertions and struct updates 2026-09-09 15:39:17 +00:00
Dennis Kobert
f726014c93 Elide the arena lifetimes that the signatures do not need 2026-09-09 15:39:12 +00:00
Dennis Kobert
a06039c6c8 Explain why the selective color and spline loops index by range 2026-09-09 15:39:12 +00:00
Dennis Kobert
0a4288eca6 Read a named attribute at each value type it can hold
One read node per value type, mirroring master's read family. A name
means one value type, so there is no coercion between them: master's
number read silently widened integers, and these refuse instead, which
is the same rule the write side already enforces.

Each takes any record wire through the opaque reading input and serves
the name's own default where the attribute is absent, so the value
carries the declared type either way.

The gradient enums join the value-type rows now that a family exists to
read them at.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 12:36:00 +00:00
Dennis Kobert
5baeb8fd46 Accept any record wire on an input read only for its attributes
An element generic declared on a reading input, absent from the output
and from every other input, has nowhere to go and nothing to be: the
node reads its declared attributes and never the element. That is an
attr-to-element map, so it accepts any upstream record wire.

The blessing is inferred rather than marked, since the signature already
says it. The two substrate pieces were both in place: the element rides
as the byte-carried token, so the registry takes one generic row instead
of a row per element type, and the reads resolve against the input's own
layout as they always have. Only the passthrough rule stood in the way,
in the three places that enforced it.

A generic the output carries, or one on an input with no reads, is
unchanged and still owes an implementations list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 12:15:40 +00:00
Dennis Kobert
f04d439b33 Name the attribute read for the type it reads
The read is a number read, not a read of whatever the name holds: our
model has no coercion, so a name written at another value type is a graph
error rather than a conversion. The name says so.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 11:35:38 +00:00
Dennis Kobert
6e22d6a412 Serve a declared name's census default on an absent read
An absent read of a name the census declares now serves that name's own
default rather than its value type's, which is the rule for a declared
name. The census stages it exactly as it fills any absent field, as the
declared default's bytes, so the read reuses the census's own mechanism
instead of a second one; the compiler takes them when the name folds and
`set_layout` installs them beside the offset.

A name the census does not declare keeps the value type's default, which
is that case's own rule. One name carries one value type, checked when
the name folds, so the row's value type and width agree with the read's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 11:13:41 +00:00
Dennis Kobert
5eb80721dd Resolve a named read's offset when the graph compiles
The fold already holds the name and the read input's finished layout, so
the offset falls out there rather than at construction: `RecordLayout`
carries the resolved numbers and `set_layout` copies them into the read
slots. Constructors are untouched, and census-marker reads keep their
current installation.

A read meets the value type the name was written at, so a disagreement
between a read here and a write upstream is the same graph error as two
writes disagreeing; the one-name-one-type check now spans reads and
writes together. An absent attribute stays absent and the read serves
the forced default rather than reporting it.

`read_attribute` is the catalog's get half, typed and never `Option` at
the kernel boundary, with the name declared exactly as the write side
declares it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 10:50:08 +00:00
Dennis Kobert
fc94487d0b Keep the name placeholder out of the kernel entirely
A name input declares where a placeholder's name is wired and nothing
more. The name is spent resolving the layout when the graph compiles, so
the kernel neither declares it nor is passed it; the return type's
`Named<X, V>` is the only tie between the write slot and the folded name.

The wire is untouched: the input keeps its declared position and crosses
as constant text, so a document's input order is unchanged. The
placeholder stays a concrete token, so it adds no generic for the node
to carry and none to go unconstrained.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 10:20:22 +00:00
Dennis Kobert
37c0d0852d Carry the new layout fields through the hand-built fixtures
The record fixtures spell their metas and resolved layouts out in full,
so the name-from-input fields reach them as empty. `named_value!`'s
example moves to `ignore`: its `for T` arm implements a core-types trait
on the value type, which only core-types itself may do.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 09:43:52 +00:00
Dennis Kobert
9b92edc0e9 Write an attribute under a name the graph supplies
`Named<X>` in parameter position declares where a placeholder's name is
wired, and the macro gives that input constant text; `Attr<Named<X, V>>`
in the return writes under it. The kernel is handed the bare placeholder,
since the name is spent resolving the layout and a folded offset is all
the write needs, so the hot path matches a marker node's exactly.

A name-generic write names its value type through the wired generic,
which only an implementations row resolves, so those nodes emit their
layout meta per row rather than sharing one across rows.

`write_attribute` is the catalog's set half, restoring the identifier
master's documents carry with its input positions. Its name input is a
constant, so those documents resolve without migration, and the reset
marker that stood in for the missing node retires with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 09:26:17 +00:00
Dennis Kobert
348e9022a6 Fold attribute names out of their constant inputs when the graph compiles
`compute_layouts` resolves every name-from-input write against the text
its name input carries, so a folded meta is indistinguishable from a
marker node's and the layout holds a `&'static str` from there on. That
leaves nowhere for a name to be computed, which is the whole of the
rule: a name input that is not a constant is refused right here, per
node, with the path the editor pins its diagnostic to.

One name carries one value type, checked across the census and the
names a node folds together, so no graph can declare one field at two
widths. `compute_layouts` returns those refusals rather than panicking.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 08:51:05 +00:00
Dennis Kobert
0001cdf04d Carry a name-generic attribute's value type as its own row
An attribute's name and its value type separate: `AttrValue` declares
everything `Attribute` does except the name and its name-specific
default, and `Named<X, V>` pairs one with a name the graph supplies.
The value type stays concrete in the signature while the name varies
per instance, so a computed name has nowhere to come from.

`LayoutMeta` gains the name-from-input variant the fold consumes: a
`FieldWrite` template with every facet minted from the concrete type
and only the name left as a placeholder, plus the input position the
name's constant sits at. `fold_name` resolves one, preferring the
census row's descriptor where the name is declared so a known name
keeps its census default. `RecordLayout` carries the folded names so
`set_layout` can resolve offsets without a marker's `NAME`.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-09-09 08:41:53 +00:00
Dennis Kobert
c2845def11 Take rasterize's data input on the materialized leveled form 2026-09-08 20:19:18 +00:00
Dennis Kobert
b8bd9499fc Pin the async source materialized input shape 2026-09-08 20:19:18 +00:00
Dennis Kobert
e92ced1e4a Cross an async source's materialized input as an owned snapshot 2026-09-08 20:19:18 +00:00
Dennis Kobert
e322d8957d Lift the run to owned legacy list bridge into core-types 2026-09-08 20:19:12 +00:00
Dennis Kobert
296185b7fc Register a record-io source whose generic sits on an implementations secondary 2026-09-08 15:23:33 +00:00
Dennis Kobert
b321c094d2 Keep the new assert messages inside the format width 2026-09-08 13:29:09 +00:00
Dennis Kobert
d4768d606f Justify the unsafe sites in the arena, record and graphic glue 2026-09-08 13:23:52 +00:00
Dennis Kobert
148008c695 Refuse a wasm threads build where the Send and Sync impls assume one thread 2026-09-08 13:15:18 +00:00
Dennis Kobert
2b5845464c Rederive the shared source pointer through an unwinding set_layout 2026-09-08 13:15:13 +00:00
Dennis Kobert
5e388cb38f Assert the deep element glue is registered before the executor evaluates 2026-09-08 13:15:06 +00:00
Dennis Kobert
49daf2895e Make Attribute an unsafe trait stating its re-park and glue coupling 2026-09-08 13:14:59 +00:00
Dennis Kobert
682d3dafbd Bound attribute value types Send and Sync 2026-09-08 13:14:59 +00:00
Dennis Kobert
ad03b5b0bf Check a census row against the field before its writer runs 2026-09-08 13:14:33 +00:00
Dennis Kobert
324925aedb Debit the retained hint before the drop glue that may panic 2026-09-08 13:14:18 +00:00
Dennis Kobert
e78a987e3e Bind a park forwarding to the destination arena generation 2026-09-08 13:14:12 +00:00
Dennis Kobert
2c8fa44eb4 Mint arena handles only over bytes the bump reserved 2026-09-08 13:14:12 +00:00
Dennis Kobert
6b22316077 Re-park a cross-arena adopt's payloads into the target arena 2026-09-08 13:11:04 +00:00
Dennis Kobert
e0848abc59 Scan item attribute values for groups the ownership gates miss 2026-09-08 12:22:04 +00:00
Dennis Kobert
f237a5ee50 Claim the carrier's frame before the lazy cursor snapshot 2026-09-08 12:22:04 +00:00
Dennis Kobert
df99ab3a72 Guard attribute writes against an uninstalled layout offset 2026-09-07 16:12:01 +00:00
Dennis Kobert
0fc4424a09 State the disjointness a plan's copies require 2026-09-07 16:11:56 +00:00
Dennis Kobert
e9a3199456 State what contains the laundered arena borrow in the flatten test 2026-09-07 16:11:32 +00:00
Dennis Kobert
ef8312806d Serve the probe record the forwarding test finishes 2026-09-07 16:11:32 +00:00
Dennis Kobert
548cbfbf4e Check the claim's layout when replaying an owned record 2026-09-07 16:11:32 +00:00