Sharpen the declared-length defect, and what a negative share does

Only rel doubles: apply_rest turns rest into the whole box and px
coincides. Aligned and Scroll honour a hint the same way Span does, so
all three double it. Also corrects the note about a fractional hairline,
which fails because a fraction is a fraction of its own box rather than
through any rounding, and records that a span whose shares run out walks
its children backwards instead of overflowing forward.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-15 12:44:55 -04:00
1 parent e6b9cb29b7
commit 324f0f02ef
1 file changed
+21 -10
+21 -10
View File
@@ -26,12 +26,15 @@ reference renders and the resize render are byte-identical across all of
it, and the hundred-seed sweep passes. `/home/bob/repos/ai-app-2` is on it, and the hundred-seed sweep passes. `/home/bob/repos/ai-app-2` is on
`rustify`, worktree clean. `rustify`, worktree clean.
**A declared fraction is applied twice, and it is the one thing to fix before **A declared `rel` length is applied twice, and it is the one thing to fix
#18 lands.** `.width(rel(0.5))` in a 400-wide span puts the `SetSize` at 0..200 before #18 lands.** `.width(rel(0.5))` in a 400-wide span puts the `SetSize` at
and its child at 0..100: the span sizes the box from the hint, and `c596bf1` 0..200 and its child at 0..100: the span sizes the box from the hint, and
then measures the child in the declared length again *inside* that box. A `c596bf1` then measures the child in the declared length again *inside* that
declared pixel length is unaffected -- 200 px of a box already 200 px wide is box. `px` is unaffected, since 200 px of a box already 200 px wide is the whole
the whole box -- so only `rel` and `rest` double. It shows in the `text` box, and `rest` is unaffected because `Len::apply_rest` turns any rest into
`rel(1.0)`, which is the whole box too. Only `rel` doubles, and it doubles
under every placer that honours a hint -- `Span`, `Aligned` and `Scroll` all
call `known_len` -- while a `Pad` or the root, which do not, are correct. It shows in the `text`
example, whose "same words in half the width" panel is 474 px where example, whose "same words in half the width" panel is 474 px where
`upstream/main` draws 948, and that is 111,923 pixels of difference, so **the `upstream/main` draws 948, and that is 111,923 pixels of difference, so **the
claim above that the five reference renders are byte-identical is wrong for claim above that the five reference renders are byte-identical is wrong for
@@ -130,13 +133,21 @@ Invariants, not history. Everything in `core/src/ui` rests on them.
2026-09-15 by `tests/layout.rs`, which composes sixteen hairlines under four 2026-09-15 by `tests/layout.rs`, which composes sixteen hairlines under four
levels of span and padding on `rest(3)/rest(7)/rest(5)` weights and applies levels of span and padding on `rest(3)/rest(7)/rest(5)` weights and applies
the shader's own snapping at four output sizes. **A span short of room takes the shader's own snapping at four output sizes. **A span short of room takes
it from its shares and never from a fixed length**: the shares reach zero and it from its shares and never from a fixed length**, though a share that has
run out does not stop at zero: three 60 px children in a 100 px box overflow
forward to 0..60, 60..120 and 120..180, which is what the owner intends,
but putting a `rest` share between each pair gives the shares -40 px and
walks the children *backwards* to 0..60, 20..80 and 40..100. Clamping a
share at zero is the fix, and is not in yet: the shares reach zero and
then go past it, so the fixed parts start overlapping each other -- at 400 then go past it, so the fixed parts start overlapping each other -- at 400
wide three marks sit at 132, 265 and 399, at 3 wide at 0, 1 and 2, and at 1 wide three marks sit at 132, 265 and 399, at 3 wide at 0, 1 and 2, and at 1
wide two of them land on the same pixel. Overlapping is what hides a wide two of them land on the same pixel. Overlapping is what hides a
separator in an over-constrained tree; collapsing one never happens. The same separator in an over-constrained tree; collapsing one never happens. The same line
line written as `rel(1.0 / 1920.0)` instead is zero pixels wide even at 1920, written as `rel(1.0 / 1920.0)` fails the test, but not through rounding: a
which is the mutation that shows the tests have teeth. fraction is a fraction of *that widget's box*, so at the root of a 1920-wide
output it is exactly one pixel and two spans down, where the box is half the
output, it is half a pixel and floors to nothing. That is what `rel` means
rather than a defect, and it is the reason a hairline is written in `px`.
- **The walk stops where a length did not change.** A part of a box with no - **The walk stops where a length did not change.** A part of a box with no
relative extent on an axis is a fixed length held as offsets from that box's relative extent on an axis is a fixed length held as offsets from that box's
start, and composing anything into it leaves no relative extent either -- so a start, and composing anything into it leaves no relative extent either -- so a