Read a slot's ends where they are used, not carry one between children

`start` looked like a third accumulator beside `fixed` and `taken`, carried
across iterations and assigned at three points. It was never independent:
every assignment was `shared(fixed, taken)`, so it was those two read
together. Reading it at each end of a slot instead drops the variable, drops
two of the three calls per child, and leaves the gap added after the last
child deriving nothing -- which was the thing that read as a bug, and is not
one because no end is taken from it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
iris-aiandClaude Opus 5 committed 2026-09-19 22:13:52 -04:00
1 parent 8d2b7a512b
commit 6c84b6f2cb
1 file changed
+8 -11
+8 -11
View File
@@ -83,15 +83,14 @@ impl Widget for Span {
let shrinks = !painter.has_exact_size(!axis);
// What the fixed parts and the gaps before here take, which is a sum
// of lengths and exact, and how much of the leftover weight is
// spoken for. A position is one from the other rather than a step
// from the last child: the share of the room is rounded, and taking
// each from the one before it would carry every rounding along the
// row.
// spoken for. Both ends of a slot are read from those two rather
// than stepped from the last child: the share of the room is
// rounded, and taking each end from the one before it would carry
// every rounding along the row.
let mut fixed = Len::rel_min();
let mut taken = Weight::ZERO;
let mut start = Len::rel_min();
let mut ortho = LayoutLen::ZERO;
let shared = |fixed: Len, taken: Weight| match taken == Weight::ZERO {
let reached = |fixed: Len, taken: Weight| match taken == Weight::ZERO {
true => fixed,
false => fixed + room.scale(Rel::ratio(taken, total.leftover)),
};
@@ -102,15 +101,14 @@ impl Widget for Span {
if len.is_only_leftover() && !shares {
painter.undraw(child);
fixed.px += self.gap;
start = shared(fixed, taken);
continue;
}
let from = start;
let from = reached(fixed, taken);
if len.leftover > Weight::ZERO && shares {
taken += len.leftover;
}
fixed += len.without_leftover();
start = shared(fixed, taken);
let to = reached(fixed, taken);
// Along the row the span says where the child goes, and that slot
// is the child's box outright rather than something to place an
// answer inside again. A share is decided here and nowhere
@@ -118,7 +116,7 @@ impl Widget for Span {
// it, since a text wraps at the width it is actually given. A
// fixed child's slot is its own answer, so a drawing made in the
// room is put there as it is, and one not made yet is made here.
let slot = along(from, start);
let slot = along(from, to);
let mut place = slot.shifted_desc().fills().on_axis(axis);
if len.leftover > Weight::ZERO && shares {
place = place.rel_base(axis, slot.len());
@@ -136,7 +134,6 @@ impl Widget for Span {
}
}
fixed.px += self.gap;
start = shared(fixed, taken);
}
// Carried whole rather than collapsed to one share: a span that sizes