Retain frame and extent dependencies independently

Keep the original measurement placement separate from the assigned slot.
Validate frame and extent lengths before reusing an answer or drawing, and
represent hint-only records as having no measured answer.

Retain primitive and mask coordinates with their frame/extent reference.
Forwarded children follow a reused wrapper's placement without rerunning
valid draw bodies. Keep the single Widget::draw API.

Restore the eight failing suite cases from the region/placement prototype,
with regressions for mixed coordinate references, a changed inherited
extent, the sizing-stack fraction, and an undrawn share becoming visible.

This remains experimental: nested container updates do substantially more
work than e44dea3 despite restoring the leaf and wrapper reuse guarantees.
Do not merge it as a performance improvement.
This commit is contained in:
iris-ai committed 2026-09-17 14:50:09 -04:00
1 parent 5fcace1bfa
commit efb416bbc3
14 files changed
+548 -166

No files matched your search

+1 -2
View File
@@ -6,8 +6,7 @@ pub struct Masked {
impl Widget for Masked {
fn draw(&mut self, painter: &mut Painter) -> Size {
let own = painter.placement();
painter.set_mask(own);
painter.set_mask(DrawRegion::Extent(UiRegion::FULL));
painter.widget(&self.inner);
// What it occupies is its box, on both axes, for the reason `Scroll`
// reports the same: it clips what is inside to that box, so it can
+6 -4
View File
@@ -15,10 +15,12 @@ impl Widget for Scroll {
// Draw in the whole container only when its scrolling-axis length is
// not already known, then draw it at the scrolled offset.
let whole = UiRegion::FULL;
let answer_len = match painter.known_len(&self.inner, self.axis, whole) {
Some(len) => len,
None => painter.widget(&self.inner).size().axis(self.axis),
};
let own = painter.placement();
let answer_len =
match painter.known_len(&self.inner, self.axis, whole, [Some(own.x), Some(own.y)]) {
Some(len) => len,
None => painter.widget(&self.inner).size().axis(self.axis),
};
let content = answer_len.apply_leftover();
self.container_len = container_len;
self.content_len = content.to_px(container_len);
+1 -1
View File
@@ -37,7 +37,7 @@ impl Widget for Span {
// from the cursor, because a text has to wrap at the width
// actually there.
let room = axis.pair(Some(along(cursor, far)), None);
let len = match painter.known_len(child, axis, region) {
let len = match painter.known_len(child, axis, region, room) {
Some(len) => len,
None => painter.widget_at(child, region, room).len(axis),
};
+1 -2
View File
@@ -89,8 +89,7 @@ impl TextView {
// hair under that line, and the break made in it is not the break a
// cold layout makes there.
let size = Size::from_px(PxVec2::ceil_from_f32(tex.size));
let within = region.within(&painter.placement());
painter.glyphs(tex, within);
painter.glyphs(tex, DrawRegion::Extent(region));
(region, size)
}