Take two roundings out of where a box comes from
Traced what was left of the warm-against-cold difference after fixed point. It is not accumulation and not one place: it is the same box reached two ways, and each way rounds where the other does not. `Scroll` was writing a box it had been given back out as its own length in pixels. That is the same box in another form, and centring a part in `rel 1` lands a step from centring it in `px 900`, because halving a difference is not halving each part of it. Content that fills the viewport and has not been scrolled is now handed back as it came, which makes the shrinker's `repaint` and `resize-repaint` cases agree exactly rather than within a step. `Span` placed each child a step from where the last one ended, so the rounding of every share was carried along the row. A position is now the fixed parts before it -- a sum, exact -- plus one rounded share of the room. Measured: two hundred equal shares of a 1000 px row ended at 999.999 and now end at 1000, and `tests/cases/layout.rs` pins it at 2, 3, 7, 64 and 200. What is left is a step per level of nesting between the two ways, which is what the fuzzers now allow: four of the five shrinker cases pass at one step and the fifth is five spans deep. Closing it needs one way of asking where a box is, which is a bigger change than this. Checked: fmt, clippy, 103 tests, all five shrinker cases at 300 seeds, 100 generated seeds, five examples byte-identical at 1920x1200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
9d8415d65f
commit
bdab55824f
6 files changed
+90
-25
No files matched your search
@@ -46,13 +46,23 @@ impl Widget for Scroll {
|
||||
// have placed the whole scroll in a box longer than it.
|
||||
let slack = (self.container_len - self.content_len).max(Px::ZERO);
|
||||
let anchor = slack.mul(align.rel());
|
||||
let offset = UiVec2::from_axis(
|
||||
self.axis,
|
||||
UiScalar::from_parts(Rel::ZERO, anchor - self.amt),
|
||||
UiScalar::ZERO,
|
||||
);
|
||||
let mut region = UiRegion::FULL.offset(offset);
|
||||
region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len);
|
||||
let mut region = UiRegion::FULL;
|
||||
// Content that fills the viewport and has not been scrolled is the
|
||||
// viewport, and is handed back as it came. Writing the same box as
|
||||
// its own length in pixels is the same box in another form, and the
|
||||
// two do not round alike: a part centred in `rel 1` lands a step from
|
||||
// one centred in `px 900`, since halving a difference is not halving
|
||||
// each part of it.
|
||||
let moved = anchor != Px::ZERO || self.amt != Px::ZERO;
|
||||
if moved || self.content_len != self.container_len {
|
||||
let offset = UiVec2::from_axis(
|
||||
self.axis,
|
||||
UiScalar::from_parts(Rel::ZERO, anchor - self.amt),
|
||||
UiScalar::ZERO,
|
||||
);
|
||||
region = region.offset(offset);
|
||||
region.axis_mut(self.axis).end = region.axis(self.axis).start.offset(self.content_len);
|
||||
}
|
||||
painter.widget_aligned(&self.inner, region, RegionAlign::NEAR);
|
||||
// What it occupies is its box, on both axes: it clips its content to
|
||||
// that box, so it can neither take less of one nor honestly ask for
|
||||
|
||||
Reference in new issue
Block a user