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

+11 -11
View File
@@ -1,8 +1,8 @@
#[cfg(feature = "layout-diagnostics")]
use crate::layout_diagnostics::{self as diag, Counter};
use crate::{
Axis, Holds, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget, TextAttrs,
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, Weight,
Axis, Holds, LayoutLen, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget,
TextAttrs, TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiVec2, Weight,
WidgetId, Widgets,
render::{
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveHandle, PrimitiveInst,
@@ -109,7 +109,7 @@ impl<'a> Painter<'a> {
/// it resolves into its box. Reading them depends on nothing -- the box
/// that comes of them is kept on the child, and `redraw` compares it
/// there.
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<Len>; 2] {
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<LayoutLen>; 2] {
declared_lens(self.rsc.widgets(), id.id())
}
@@ -218,7 +218,7 @@ impl<'a> Painter<'a> {
/// What a child says its length is without being drawn, if it can say.
/// Asking counts as reading its size.
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<Len> {
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<LayoutLen> {
let widgets = self.rsc.widgets();
// A rule is the answer where there is one: it wins over whatever the
// widget would draw, so it has to win over what the widget says too.
@@ -252,7 +252,7 @@ impl<'a> Painter<'a> {
child: &StrongWidget<W>,
axis: Axis,
region: UiRegion,
) -> Option<Len> {
) -> Option<LayoutLen> {
let declared = self.declared_lens(child);
let align = self.rsc.widgets().alignment(child.id());
let local = declared_box(region, declared, align);
@@ -472,7 +472,7 @@ impl<W: ?Sized> DrawResult<'_, '_, W> {
self.size
}
pub fn len(self, axis: Axis) -> Len {
pub fn len(self, axis: Axis) -> LayoutLen {
self.size().axis(axis)
}
}
@@ -505,7 +505,7 @@ impl PrimitiveLike for &TextureHandle {
/// What a widget declares a length of its box to be. `leftover` is not one: a
/// share of what is left over is only a length to the widget dividing one,
/// so it passes up in the size instead.
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<Len>; 2] {
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<LayoutLen>; 2] {
let rules = widgets.size_rules(id);
let widget = widgets.get_dyn(id);
AXES.map(|axis| {
@@ -537,7 +537,7 @@ pub(crate) fn placed_box(
region: UiRegion,
size: Size,
align: RegionAlign,
declared: [Option<Len>; 2],
declared: [Option<LayoutLen>; 2],
) -> UiRegion {
let mut placed = region;
for (axis, declared) in AXES.into_iter().zip(declared) {
@@ -546,7 +546,7 @@ pub(crate) fn placed_box(
continue;
}
let span = placed.axis_mut(axis);
let len = span.len().scale(reported.rel) + UiScalar::from_parts(Rel::ZERO, reported.px);
let len = span.len().scale(reported.rel) + Len::from_parts(Rel::ZERO, reported.px);
span.start += (span.len() - len).scale(align.axis(axis).rel());
span.end = span.start + len;
}
@@ -559,13 +559,13 @@ pub(crate) fn placed_box(
/// space hands back the same length, so this is the identity for it.
pub(crate) fn declared_box(
mut region: UiRegion,
declared: [Option<Len>; 2],
declared: [Option<LayoutLen>; 2],
align: RegionAlign,
) -> UiRegion {
for (axis, len) in AXES.into_iter().zip(declared) {
let Some(len) = len else { continue };
let span = region.axis_mut(axis);
let len = UiScalar::from_parts(len.rel, len.px);
let len = Len::from_parts(len.rel, len.px);
span.start += (span.len() - len).scale(align.axis(axis).rel());
span.end = span.start + len;
}