Document independent widget bounds and measured layout costs
This commit is contained in:
1 parent
ddaf9b37d6
commit
17423a57b8
3 files changed
+96
-5
No files matched your search
@@ -12,6 +12,57 @@ in flight stands. The sections from "Three names, and the one argument that
|
||||
says them" onwards are the settled design, the findings that outlived the
|
||||
working log, and the measurement method.
|
||||
|
||||
## Bounds on the offered box
|
||||
|
||||
`SizeRule` carries an optional preferred request and independent min/max bounds.
|
||||
The bounds constrain both the box offered to a widget and its reported size.
|
||||
`.min_width`, `.max_width` and their height variants edit that widget's rules
|
||||
and preserve its identity and type; `MaxSize` is removed. Setting `.width` or `.height` preserves the bounds; setting a bound
|
||||
preserves the preferred request and the other bound, in either call order.
|
||||
`Widgets::set_len` makes the same edit at runtime; `set_size_rule` replaces
|
||||
the complete axis. This replaces the rule/widget split recorded in
|
||||
`LAYOUT_LOG.md` (Bryan, 2026-09-20).
|
||||
|
||||
The shared ask resolves declarations and bounds against the incoming rel
|
||||
base, compares the offer, and retains the chosen box length in `Declared`.
|
||||
These are window lengths. Placement aligns a retained length in its destination
|
||||
without resolving it again or comparing the destination against the bound.
|
||||
The comparison's window range and incoming-region dependency invalidate the
|
||||
ask when its inputs change. Ask constraints are combined after the draw, so a
|
||||
widget widening its own `window_holds` cannot erase a bound's crossing.
|
||||
Fractional rules also track their incoming base. Allocated slots use the
|
||||
allocator's base for bounds; applying a 25% cap to its own 25% slot would
|
||||
shrink it twice. Changing an inactive bound also reaches the parent, because
|
||||
it changes which offers the parent can safely reuse.
|
||||
A cap constrains wrapping and scroll viewports, but short intrinsic content
|
||||
can still report less than the cap. Shares remain deferred requests for the
|
||||
parent to allocate; the offered box does not replace their reported weight.
|
||||
|
||||
Measured against `4cb6f68`, medians of five release-process instruction counts:
|
||||
|
||||
| Fixture | Before | After | Change |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| 128 capped rows, 2,000 resizes | 7.387B | 5.779B | -21.77% |
|
||||
| Same, every widget redrawn | 13.864B | 9.755B | -29.64% |
|
||||
| 128 plain rows, every widget redrawn | 10.041B | 10.010B | -0.31% |
|
||||
| 128 fixed-width rows, every widget redrawn | 10.085B | 10.056B | -0.29% |
|
||||
| 40 text rows, 1,000 resizes | 9.460B | 9.472B | +0.13% |
|
||||
|
||||
Plain and fixed-width retained resizes differ by under 0.05%; text repaint,
|
||||
edit and scroll differ by -0.05%, +0.07% and +0.06%. `tests/bounds_cost.rs`
|
||||
asserts the same geometry for the old builders and new attributes, with 513
|
||||
active widgets before and 385 after in the capped fixture. The text runs use
|
||||
`tests/revision_cost.rs`. These include cold setup and do not measure GPU or
|
||||
phone frame times. The unbounded cold dump remains identical at 34,986 boxes;
|
||||
bounded geometry changes intentionally because the offer is now constrained.
|
||||
|
||||
The storage tradeoff is explicit: a `SizeRule` is now 40 bytes rather than 24,
|
||||
so independent preferences and bounds add 32 inline bytes per widget across
|
||||
both axes. Plain, expression-bounded and attribute-bounded fixtures each
|
||||
perform zero allocations over 100 forced-redraw resize frames after warm-up.
|
||||
Bounds introduce no heap allocation; an expression also loses
|
||||
its former extra outer `Arc`. Artifacts are in `/tmp/attribute-bounds/`.
|
||||
|
||||
## Deferred size requests on PR #19
|
||||
|
||||
`Widget::draw` still returns the small, copyable `Size` of two `LayoutLen`s.
|
||||
|
||||
Reference in new issue
Block a user