Hold a bound's length where it is decided, and say each thing once
A quality sweep over the deferred request system, which no earlier round has reviewed. `Bound::outside` said which end a length fell outside and left the caller to look that end up through `Bound::at`, which `expect`s an end the value it is given does not promise: only the pairing of the two calls kept `at(Shorter)` off a bound with no floor. It already had the length in hand, so it returns that, and `Outside` and `at` go with the state that could panic. `measured_request` pinned the rel base for any bound at all, so a measured share under a cap in pixels was invalidated by a change to a base its answer cannot depend on. That question is `Bound::has_fraction` now, which is also the one `Placing::ask` and `SizeRule::has_fraction` were each writing out over a bare array. The rest is one name where there were several spellings: `Span::gaps`, `Padding::along`, `Plan::drop_bounds` behind one `IRIS_UNBOUNDED` in both rigs that had grown their own, and `Stack::size_request` resolving its sizing child the way its draw already does. `Span`'s placement loop asked three times whether the row was allocated, twice to decide one child's length; one match answers all three, so the allocated and plain rules are read side by side. The buffers `draw_at` now reuses for their capacity are empty only because every path to it drains them in `remove`; a `debug_assert` says so, since a drawing over primitives left in one would record them twice. Comments: `with_requests` named discovery as the hazard where it is a child drawn mid-row, `Painter::allocate` documented the window it holds for rather than what it does, `minimum_request` had none, and the note saying a span carries its children's weight whole -- which is still what the unallocated path does, and still the surprising part -- had been replaced by one about the other path.
This commit is contained in:
1 parent
0e838e9dd1
commit
4cb6f6882a
12 files changed
+192
-160
No files matched your search
@@ -349,6 +349,14 @@ impl UiRenderState {
|
||||
),
|
||||
None => Default::default(),
|
||||
};
|
||||
// Every one of these is a buffer this widget's last draw filled and
|
||||
// `remove` emptied, kept for its capacity alone. A drawing whose
|
||||
// primitives were still in it would record them twice.
|
||||
debug_assert!(
|
||||
textures.is_empty() && primitives.is_empty() && request_deps.is_empty(),
|
||||
"'{}' ({id:?}) was drawn again over what its last draw left",
|
||||
rsc.widgets().label(id)
|
||||
);
|
||||
let children = std::mem::take(&mut scratch.children);
|
||||
let size_deps = std::mem::take(&mut scratch.size_deps);
|
||||
let under = std::mem::take(&mut scratch.under);
|
||||
@@ -468,11 +476,10 @@ impl UiRenderState {
|
||||
if answer.leftover != Weight::ZERO {
|
||||
continue;
|
||||
}
|
||||
let (outside, kept) =
|
||||
info.bounds[axis].outside(answer.without_leftover(), window[axis]);
|
||||
let (held, kept) = info.bounds[axis].outside(answer.without_leftover(), window[axis]);
|
||||
bounded[axis].window = kept;
|
||||
if let Some(outside) = outside {
|
||||
size[axis] = info.bounds[axis].at(outside).into();
|
||||
if let Some(held) = held {
|
||||
size[axis] = held.into();
|
||||
}
|
||||
}
|
||||
// A widget that clipped its contents to its box drew nothing outside
|
||||
@@ -1031,10 +1038,10 @@ impl UiRenderState {
|
||||
// something below is about to change it -- which is the whole class
|
||||
// of defect where a widget settles inside its parent's draw, clears
|
||||
// its mark there, and tells nobody its answer moved.
|
||||
// A mark made while the walk runs queues itself through `mark`.
|
||||
// What ends the walk is still the set
|
||||
// being spent, not the queue, so a mark that reached it another way
|
||||
// cannot be left for the next frame.
|
||||
// A mark made while the walk runs queues itself through `mark`. What
|
||||
// ends the walk is the marks being spent rather than the queue being
|
||||
// empty, so a mark that reached the queue twice, or that was settled
|
||||
// another way, costs a pop and nothing else.
|
||||
loop {
|
||||
for &id in rsc.widgets().needs_redraw.iter() {
|
||||
if !self.deferred.contains(&id) {
|
||||
|
||||
Reference in new issue
Block a user