Put lengths, padding, gaps and alignment on the grid too
`Len` is `Px` beside `Rel` beside `Weight`, so the seam `4e28f10` left in `Span` -- a float length added to a fixed-point cursor -- is gone, and the sum a span compares against its box is exact. `Weight` is its own scale, `Fixed<16>`, because a share of what is left over is not a fraction of anything: a list divides its room by the total of them, so the range has to hold a whole list's worth while the precision only has to tell two weights apart. `Rel::ratio` turns two weights into a share on the finer grid, which is what a span needs and what dividing them on their own grid would round away. `AxisAlign` holds a `Rel` rather than a float, which is what the layout was reading out of it anyway. `Padding` and `Span::gap` hold `Px`, converted where they are built instead of on every frame. `RegionAlign::rel` is gone; its one caller wanted a position, and now builds one. `Fixed` gains `from_num` for a number as it is written in source, `mul_int` for a length repeated a whole number of times, and `ratio`. Checked: fmt, clippy, 101 tests, 100 generated seeds in 86 s, all five shrinker cases at 300 seeds, and all five examples byte-identical at 1920x1200 against `4e28f10`. With the fuzzer comparing for equality rather than within 0.05 px, four of the five cases now pass 100 seeds -- `resize-repaint` joins the other three. `reorder` still fails one seed by one step, so the last of it is in what a box is measured *in*: `px_len` and the window are still floats. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4e28f1047e
commit
bd6de71a55
15 files changed
+199
-158
No files matched your search
@@ -1,8 +1,9 @@
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
use crate::layout_diagnostics::{self as diag, Counter};
|
||||
use crate::{
|
||||
Axis, Holds, Len, Px, RegionAlign, RenderedText, Size, StrongWidget, TextAttrs, TextBuffer,
|
||||
TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, WidgetId, Widgets,
|
||||
Axis, Holds, Len, Px, RegionAlign, Rel, RenderedText, Size, StrongWidget, TextAttrs,
|
||||
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, Weight,
|
||||
WidgetId, Widgets,
|
||||
render::{
|
||||
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveHandle, PrimitiveInst,
|
||||
PrimitiveKind, TexturePrimitive,
|
||||
@@ -484,7 +485,7 @@ pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<Len>; 2]
|
||||
// occupies its reported size inside the box it was offered.
|
||||
widget
|
||||
.and_then(|widget| widget.size_hint(axis))
|
||||
.filter(|len| len.leftover == 0.0)
|
||||
.filter(|len| len.leftover == Weight::ZERO)
|
||||
})
|
||||
})
|
||||
}
|
||||
@@ -509,11 +510,11 @@ pub(crate) fn placed_box(
|
||||
let mut placed = region;
|
||||
for (axis, declared) in AXES.into_iter().zip(declared) {
|
||||
let reported = size.axis(axis);
|
||||
if reported.leftover != 0.0 || declared.is_some() {
|
||||
if reported.leftover != Weight::ZERO || declared.is_some() {
|
||||
continue;
|
||||
}
|
||||
let span = placed.axis_mut(axis);
|
||||
let len = span.len().scale(reported.rel) + UiScalar::px(reported.px);
|
||||
let len = span.len().scale(reported.rel) + UiScalar::from_parts(Rel::ZERO, reported.px);
|
||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||
span.end = span.start + len;
|
||||
}
|
||||
@@ -532,7 +533,7 @@ pub(crate) fn declared_box(
|
||||
for (axis, len) in AXES.into_iter().zip(declared) {
|
||||
let Some(len) = len else { continue };
|
||||
let span = region.axis_mut(axis);
|
||||
let len = UiScalar::new(len.rel, len.px);
|
||||
let len = UiScalar::from_parts(len.rel, len.px);
|
||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||
span.end = span.start + len;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user