Recompose retained frames exactly and preserve text width validity
Keep each widget's original local frame and replay the same composition order on reuse. Remove inverse region remapping, including its fixed-frame fallback that forced otherwise valid subtrees to draw again. Require exact pixel-region equality in the shared generated oracle. Check primitive and mask geometry as well as draw reuse when fixed frames resize. Publish text's retained line-break range, with no upper bound when there are no soft breaks, and cover widening, explicit newlines, and empty text. Compared withefb416b, the depth-8 diagnostic rig performs 7-9% fewer widget evaluations in the affected phases. Uninstrumented release runs use 3.5% fewer instructions for size changes and 5.0% fewer for resize. Repaint and scroll use 0.7% and 0.6% more instructions. Container updates remain substantially more expensive than thee44dea3baseline; this is still an experimental continuation, not a production replacement.
This commit is contained in:
1 parent
efb416bbc3
commit
2ed5503717
7 files changed
+162
-203
No files matched your search
+1
-30
@@ -42,21 +42,6 @@ const OUTER: (f32, f32) = (1920.0, 1200.0);
|
||||
const INNER: (f32, f32) = (640.0, 900.0);
|
||||
const STILL: (f32, f32) = (900.0, 1200.0);
|
||||
|
||||
/// The same box, to two steps of the grid between the two ways of reaching
|
||||
/// it. A move, a repaint, a row of shares and every length in pixels land on
|
||||
/// the same number. What needs the slack is a position: a box centred in a
|
||||
/// fraction of its parent against the same box centred in its own pixels,
|
||||
/// and a box re-expressed as a fraction of a parent that changed length.
|
||||
/// A step is a thousandth of a pixel, where this was a twentieth of one
|
||||
/// before any of it was on a grid.
|
||||
///
|
||||
/// **One step is not enough**, tried 2026-09-17 once a length in pixels
|
||||
/// stopped being composed: it passes the 100-seed oracle and fails the
|
||||
/// 400-seed shrinker on `resize-size`, seeds 384 and 162, by 0.002 px. So
|
||||
/// what is left here is the resize path's own rounding rather than a length
|
||||
/// reached two ways.
|
||||
const AGREE_STEPS: i32 = 2;
|
||||
|
||||
/// A way of changing what a span holds. Each is a shape worth its own case:
|
||||
/// taking a child out of the middle is not the same as emptying a span, and
|
||||
/// adding one is not the same as adding three.
|
||||
@@ -399,20 +384,6 @@ fn describe_widget(id: WidgetId, h: &Harness) -> String {
|
||||
label
|
||||
}
|
||||
|
||||
fn same_region(got: Option<PixelRegion>, want: Option<PixelRegion>) -> bool {
|
||||
match (got, want) {
|
||||
(Some(got), Some(want)) => {
|
||||
let same = |a: Px, b: Px| (a - b).abs() <= Px::STEP.mul_int(AGREE_STEPS);
|
||||
same(got.top_left.x, want.top_left.x)
|
||||
&& same(got.top_left.y, want.top_left.y)
|
||||
&& same(got.bot_right.x, want.bot_right.x)
|
||||
&& same(got.bot_right.y, want.bot_right.y)
|
||||
}
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Runs `case` on the tree `plan` describes, warm and cold, and says where
|
||||
/// the two disagree. `seed` chooses only the values a case picks at random,
|
||||
/// so one plan under one case is one comparison however it was reached.
|
||||
@@ -439,7 +410,7 @@ pub fn diverges(plan: &Plan, case: Case, seed: u64) -> Option<String> {
|
||||
for (i, (&w, &c)) in tree.ids.iter().zip(&cold_tree.ids).enumerate() {
|
||||
let (got, want) = (warm.region(&w), cold.region(&c));
|
||||
drawn += got.is_some() as usize;
|
||||
if same_region(got, want) {
|
||||
if got == want {
|
||||
continue;
|
||||
}
|
||||
// Where two trees disagree is rarely where the cause is, so the
|
||||
|
||||
Reference in new issue
Block a user