From e166e005dcdcaac70983c0bf96ce537a512c7d0f Mon Sep 17 00:00:00 2001 From: iris-ai <4+iris-ai@noreply.localhost> Date: Wed, 16 Sep 2026 18:16:18 -0400 Subject: [PATCH] Pin that a length in pixels is that many pixels Asked of the `tabs` render: does a gap come out the same number of pixels wherever it appears? For a length in pixels it does, and structurally rather than by luck -- `Len::within` adds a part's own pixels rather than scaling them, and both ends of a gap carry the same fraction, so the multiply that rounds is the same on each and cancels. The test buries a row of five under three containers that are each a fraction of their parent, so nothing reaches the window without being composed and rounded, and checks every gap and every declared width at five box widths. Swept over 2,100 widths when it was written and exact at every one. For a share it does not, and the second test pins by how much rather than pretending otherwise: one or two steps between children that asked for the same fraction, 0.001 to 0.002 px. A position is the quantity that gets rounded so the row fills exactly and no two children leave a seam, and that is what costs it. Exact composition would shrink the spread, not remove it: five equal lengths cannot fill a row whose step count is not a multiple of five. Checked: fmt, clippy, 83 suite tests, 17 core unit tests. Co-Authored-By: Claude Opus 5 --- tests/cases/layout.rs | 92 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/tests/cases/layout.rs b/tests/cases/layout.rs index 43a683c..d5a579e 100644 --- a/tests/cases/layout.rs +++ b/tests/cases/layout.rs @@ -528,3 +528,95 @@ fn a_stack_child_smaller_than_the_stack_keeps_its_own_alignment() { // that is the default. assert_corners!(h, small, (350, 75), (400, 125)); } +/// Five children of one span, buried under three containers that are each a +/// fraction of their parent so no length reaches the window without being +/// composed and rounded on the way. Returns each child's drawn width and +/// each gap between them, in pixels. +fn row_under_fractions(kid: Option, gap: f32, box_w: f32) -> (Vec, Vec) { + let mut h = Harness::new((box_w, 400.0)); + let mut ids = Vec::new(); + let mut kids: Vec = Vec::new(); + for _ in 0..5 { + let r = rect(Color::RED).add(&mut h.rsc); + if let Some(len) = kid { + h.rsc + .widgets_mut() + .set_size_rule(r.id(), Axis::X, SizeRule::Exact(len)); + } + ids.push(r.id()); + kids.push(r.add_strong(&mut h.rsc)); + } + let span = Span { + children: kids, + dir: Dir::RIGHT, + gap: Px::from_f32(gap), + } + .add(&mut h.rsc); + let a = (span.width(rel(0.9)),).span(Dir::RIGHT).add(&mut h.rsc); + let b = (a.width(rel(0.8)),).span(Dir::RIGHT).add(&mut h.rsc); + h.set_root((b.width(rel(0.7)),).span(Dir::RIGHT)); + let boxes: Vec<_> = ids + .iter() + .map(|id| h.region(id).expect("a child drew nothing")) + .collect(); + ( + boxes.iter().map(|b| b.bot_right.x - b.top_left.x).collect(), + boxes + .windows(2) + .map(|p| p[1].top_left.x - p[0].bot_right.x) + .collect(), + ) +} + +/// **A length given in pixels is that many pixels, wherever it ends up.** A +/// gap and a declared width compose additively -- `Len::within` adds a part's +/// own pixels rather than scaling them, and both ends of a gap carry the same +/// fraction, so the multiply that rounds is the same on each -- which is why +/// nesting the row inside fractions of fractions cannot move them. Swept over +/// 2,100 box widths when this was written and exact at every one; five here, +/// including widths that divide badly by five. +#[test] +fn a_length_in_pixels_is_that_many_pixels_however_it_is_nested() { + for box_w in [300.0, 1000.0, 1001.0, 1003.0, 1920.0] { + let want = Px::from_int(7); + let (_, gaps) = row_under_fractions(None, 7.0, box_w); + assert!( + gaps.iter().all(|g| *g == want), + "box {box_w}: gaps between leftover children are {gaps:?}" + ); + let (widths, gaps) = row_under_fractions(Some(LayoutLen::px(100.0)), 7.0, box_w); + assert!( + gaps.iter().all(|g| *g == want), + "box {box_w}: gaps between fixed children are {gaps:?}" + ); + assert!( + widths.iter().all(|w| *w == Px::from_int(100)), + "box {box_w}: declared widths came out {widths:?}" + ); + } +} + +/// **Children asking for the same share of a row are not the same length**, +/// and this pins by how much rather than claiming they are equal. A position +/// is the quantity that gets rounded, so the row fills exactly and no two +/// children leave a seam; what that costs is a step or two between lengths +/// that were asked for identically. Exact composition would shrink the +/// spread, not remove it: five equal lengths cannot fill a row whose step +/// count is not a multiple of five. +#[test] +fn equal_shares_differ_by_at_most_two_steps_and_fill_the_row() { + for kid in [None, Some(LayoutLen::rel(0.2))] { + for box_w in [300.0, 1000.0, 1001.0, 1003.0, 1920.0] { + let (widths, gaps) = row_under_fractions(kid, 0.0, box_w); + let spread = *widths.iter().max().unwrap() - *widths.iter().min().unwrap(); + assert!( + spread <= Px::from_raw(2), + "box {box_w}, {kid:?}: widths {widths:?} spread {spread:?}" + ); + assert!( + gaps.iter().all(|g| *g == Px::ZERO), + "box {box_w}, {kid:?}: children left seams {gaps:?}" + ); + } + } +}