Record rel_base and the container API, and sweep LAYOUT.md

`frame` is gone from the layout vocabulary in `docs/LAYOUT.md` too, since
leaving the design document in the old words defeats the rename; the
rendered-frame sense of the word is untouched. The `local == UiRegion::FULL`
item is dropped from the handoff: that comment was #18's and is not on the
review branch.
This commit is contained in:
iris-ai committed 2026-09-19 16:35:02 -04:00
1 parent 90400f50ac
commit 93a6830fcd
3 files changed
+70 -60

No files matched your search

+40 -24
View File
@@ -6,11 +6,11 @@ in `docs/LAYOUT_LOG.md`.
## The Iris layout repair is submitted
**Iris PR #19** (`layout/one-ask`) replaces closed #18. The tip is `5642f20`:
**Iris PR #19** (`layout/one-ask`) replaces closed #18. The tip is `aeb60e5`:
`add6774` fixes collapsed-share placement, retained mask ownership and a
redraw-on-reparent defect, `84dad21` removes repeated work in the test
harness, and `5642f20` is the naming sweep below. The core design remains
sound; round-to-nearest is still unchanged.
harness, and `5642f20` and `aeb60e5` are the vocabulary and API work below.
The core design remains sound; round-to-nearest is still unchanged.
Two checkouts share one Git storage. `/home/bob/repos/iris` is the active
`layout/one-ask` worktree; `ai-app-2/iris` stays on `main` at the app's
@@ -20,24 +20,42 @@ Each round was checked with format, workspace clippy under `-D warnings`, the
workspace tests with and without `layout-diagnostics`, the release fast
oracle, and the three prescribed seed scans — 400 at depth 5, 1,000 at depth
6, 2,000 at depth 4. The cold dump covers 34,488 boxes: the fixes moved 650 of
them, all from the collapsed-share correction, and the naming sweep moved
none.
them, all from the collapsed-share correction, and nothing since has moved
one.
## The naming sweep is done
## The vocabulary and the container API are settled
`5642f20` finished the rename decided on 2026-09-17, which `frame`'s return as
a length had left half-applied. The box a parent asks a widget in is the
**region**, and where its drawing ends up is its **placement**:
`5642f20` finished the rename decided on 2026-09-17, which `frame`'s return
as a length had left half-applied, and `aeb60e5` finished the word `frame`
itself. Three names, and only two of them are boxes:
- `Painter::extent``region`, and its `extent_len()``region_len()`.
- `ActiveData::{part, extent}``{region, placement}`, and with them
`DrawInfo::part` and `Placing::extent`.
- `LayoutHolds::{extent, extent_len}``{region, region_len}`, and
`Counter::OutsideExtent``OutsideRegion`.
- `placed_extent` `placement`, `frame_and_extent``frame_and_region`,
`part_of``region_of`.
- `Painter`'s `window_own`, `extent_own`, `frame_own_len` and `extent_len`
become the one `own: LayoutHolds` they were assembled into.
- **region** -- the box a parent asks a widget in. It draws there, and a text
wraps at it. Was `Painter::extent`, `ActiveData::part`, `DrawInfo::part`,
`Placing::extent`, `LayoutHolds::extent`.
- **placement** -- the box its drawing ends up in, the size it reported,
once it has answered. Equal to the region wherever it fills one. Was
`ActiveData::extent`; `placed_extent` is now `placement`.
- **rel_base** -- not a box: the length a fraction it declares or reports is
a fraction of. Was `frame`, which said the wrong shape.
`Painter::frame_len()` is `Painter::rel_base()`, `LayoutHolds::frame_len`
is `rel_base`, and `frame_and_extent` is `rel_base_and_region`.
`aeb60e5` also cut what a container has to say, since correctness and cost
had been paid for and ergonomics had not:
- `Painter::widget_within(id, region)` takes a box in the widget's own
coordinates and derives the child's rel base from it, so `Pad` and
`Offset` are one call each. `Offset` had been reading `region_len`, which
pinned its drawing to a box length an offset does not depend on.
- `Painter::place_at` takes the rel base, returns the answer, and draws the
child where there is no answer to re-express. `Span`'s second pass is one
call, and its `drawn_across` bookkeeping is gone.
- `Part::All` is a `Part::WHOLE` constant rather than a variant. It was
exactly `Of(UiSpan::FULL)`; measured at 0.07% of instructions retired
against 0.04% run-to-run noise on a 60-seed depth-5 shrink.
Cold layout is byte-identical to `84dad21` across all of it, over 400
depth-5 trees.
## What is next, in order
@@ -50,9 +68,10 @@ a length had left half-applied. The box a parent asks a widget in is the
`32f6ad8` has 45 commits not reachable from the review branch; shared UI
ownership, richer masks, Android support, and app-side performance work
must survive the integration. The app then absorbs the branch's
vocabulary, all of it already upstream: `rest` `leftover`, `SizeRule`
beside widgets, alignment properties, the removal of `OrthoSize`, and the
region/placement names above.
vocabulary and container API, all of it already upstream: `rest`
`leftover`, `SizeRule` beside widgets, alignment properties, the removal
of `OrthoSize`, the region/placement/rel_base names above, and
`widget_within`/`place_at`.
3. **Round-to-nearest**, CPU and shader together as one verified change.
Bryan approved it on 2026-09-17 and neither half has landed; the
derivation, the form to use and what to re-check are in `docs/LAYOUT.md`
@@ -67,9 +86,6 @@ a length had left half-applied. The box a parent asks a widget in is the
children and nothing states what a widget may assume about one.
- `Fixed::div` by zero answers `MIN`/`MAX` while `ratio` answers `ZERO`; both
are caller bugs under `debug_assert`, but the fallbacks differ.
- The comment on the `local == UiRegion::FULL` shortcut in `widget_at` says
composing through `FULL` "is not quite the identity in f32"; on the grid it
is exact and the shortcut is performance only.
- `docs/LAYOUT.md` §4, §5 and the density section name `Painter::place`,
`Painter::region()`, `SetSize`, `desired_width`, `apply_rest`, `Len::dp`,
`Aligned` and `MaxSize`, none of which exist. Do not restore