Give a length with no share in it its own type again

`UiScalar` was `Len` without the `leftover` weight, which is the separation
canonical `main` already had as `Len` beside `LayoutLen` and this branch
collapsed. It is needed back for the queued clamp: a cap may not contain a
share, because a cap has to read the report a rule otherwise makes moot, and
a share puts the container's division into the same equation -- two
self-consistent assignments, which is the multiple-fixed-point failure
generated seed 13 punished for orthogonal sizing. `min(report, cap)` is not
a `LayoutLen` either: it is a sum of parts, and the smaller of two of them
is not one.

So `UiScalar` is `Len`, what was `Len` is `LayoutLen`, and the two say in
their docs which is which: a `Len` is pixels plus a fraction of a box -- a
position being the length from the box's start, which is why a span is two
of them -- and a `LayoutLen` is a `Len` plus a claim only a container
dividing its room can answer. `From<Len> for LayoutLen` is the one-way step
between them.

Names only; the shader's `UiScalar` is renamed with them. Checked: fmt,
clippy, 105 tests, and `tabs`, `minimal`, `view`, `text` and `random`
byte-identical at 1920x1200.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-16 13:40:15 -04:00
1 parent 4f5e27cba9
commit a8898aaa54
27 files changed
+218 -202

No files matched your search

+5 -5
View File
@@ -27,7 +27,7 @@ fn a_span_ruled_across_itself_does_not_measure_its_children_there() {
let span = (child,).span(Dir::RIGHT).height(rel(1.0)).add(&mut h.rsc);
h.set_root(span);
assert_eq!(h.render.active[&span.id()].size.y, Len::rel(1.0));
assert_eq!(h.render.active[&span.id()].size.y, LayoutLen::rel(1.0));
}
#[test]
@@ -38,7 +38,7 @@ fn a_span_reports_its_tallest_fixed_child() {
let span = (short, tall).span(Dir::RIGHT).add(&mut h.rsc);
h.set_root(span);
assert_eq!(h.render.active[&span.id()].size.y, Len::px(70.0));
assert_eq!(h.render.active[&span.id()].size.y, LayoutLen::px(70.0));
}
#[test]
@@ -331,7 +331,7 @@ fn drawn_edges(h: &Harness, id: WidgetId, axis: Axis) -> (f32, f32) {
let region = h.render.moves.resolve(active.parent_move, active.region);
let dim = h.size().axis(axis);
let snap = |v: f32| (v + Px::STEP.to_f32() * 0.5).floor();
let edge = |s: UiScalar| snap(s.rel.to_f32() * dim) + snap(s.px.to_f32());
let edge = |s: Len| snap(s.rel.to_f32() * dim) + snap(s.px.to_f32());
let span = region.axis(axis);
(edge(span.start), edge(span.end))
}
@@ -343,7 +343,7 @@ fn hairline(h: &mut Harness, marks: &mut Vec<WidgetId>) -> StrongWidget {
}
fn share(h: &mut Harness, inner: StrongWidget, ratio: f32) -> StrongWidget {
h.set_len(&inner, Axis::X, Len::leftover(ratio));
h.set_len(&inner, Axis::X, LayoutLen::leftover(ratio));
inner
}
@@ -454,7 +454,7 @@ fn only_a_pure_leftover_child_disappears_when_nothing_is_left() {
let mut h = Harness::new((100, 20));
let fixed = rect(Color::RED).width(100).add(&mut h.rsc);
let mixed = rect(Color::BLUE)
.width(Len::px(20) + Len::LEFTOVER)
.width(LayoutLen::px(20) + LayoutLen::LEFTOVER)
.add(&mut h.rsc);
h.set_root((fixed, mixed).span(Dir::RIGHT));