From 324f0f02ef6173b1a90a785bf211446f6909f8a7 Mon Sep 17 00:00:00 2001 From: iris-ai <4+iris-ai@noreply.localhost> Date: Tue, 15 Sep 2026 12:44:55 -0400 Subject: [PATCH] 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 --- docs/HANDOFF.md | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/docs/HANDOFF.md b/docs/HANDOFF.md index 7f4d5a8..2348f01 100644 --- a/docs/HANDOFF.md +++ b/docs/HANDOFF.md @@ -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 `rustify`, worktree clean. -**A declared fraction is applied twice, and it is the one thing to fix before -#18 lands.** `.width(rel(0.5))` in a 400-wide span puts the `SetSize` at 0..200 -and its child at 0..100: the span sizes the box from the hint, and `c596bf1` -then measures the child in the declared length again *inside* that box. A -declared pixel length is unaffected -- 200 px of a box already 200 px wide is -the whole box -- so only `rel` and `rest` double. It shows in the `text` +**A declared `rel` length is applied twice, and it is the one thing to fix +before #18 lands.** `.width(rel(0.5))` in a 400-wide span puts the `SetSize` at +0..200 and its child at 0..100: the span sizes the box from the hint, and +`c596bf1` then measures the child in the declared length again *inside* that +box. `px` is unaffected, since 200 px of a box already 200 px wide is the whole +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 `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 @@ -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 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 - 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 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 - separator in an over-constrained tree; collapsing one never happens. The same - line written as `rel(1.0 / 1920.0)` instead is zero pixels wide even at 1920, - which is the mutation that shows the tests have teeth. + separator in an over-constrained tree; collapsing one never happens. The same line + written as `rel(1.0 / 1920.0)` fails the test, but not through rounding: a + 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 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