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
+38
-44
@@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use crate::{UiNum, util::impl_op};
|
||||
use crate::{Px, Rel, UiNum, Weight, util::impl_op};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct Size {
|
||||
@@ -7,11 +7,14 @@ pub struct Size {
|
||||
pub y: Len,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
/// What a widget asks for along one axis: pixels, a fraction of the box it
|
||||
/// is given, and a share of whatever is left over once everything fixed has
|
||||
/// been taken. The three add up rather than choosing between one another.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Len {
|
||||
pub px: f32,
|
||||
pub rel: f32,
|
||||
pub leftover: f32,
|
||||
pub px: Px,
|
||||
pub rel: Rel,
|
||||
pub leftover: Weight,
|
||||
}
|
||||
|
||||
impl<N: UiNum> From<N> for Len {
|
||||
@@ -97,41 +100,44 @@ impl Size {
|
||||
|
||||
impl Len {
|
||||
pub const ZERO: Self = Self {
|
||||
px: 0.0,
|
||||
rel: 0.0,
|
||||
leftover: 0.0,
|
||||
px: Px::ZERO,
|
||||
rel: Rel::ZERO,
|
||||
leftover: Weight::ZERO,
|
||||
};
|
||||
|
||||
pub const LEFTOVER: Self = Self {
|
||||
px: 0.0,
|
||||
rel: 0.0,
|
||||
leftover: 1.0,
|
||||
px: Px::ZERO,
|
||||
rel: Rel::ZERO,
|
||||
leftover: Weight::ONE,
|
||||
};
|
||||
|
||||
/// The whole of what is left over counts as the whole box, which is what
|
||||
/// a length means to something that is not dividing a box between
|
||||
/// siblings -- a scroll asking how long its content is.
|
||||
pub fn apply_leftover(&self) -> UiScalar {
|
||||
let share = if self.leftover > 0.0 { 1.0 } else { 0.0 };
|
||||
UiScalar::new(self.rel + share, self.px)
|
||||
let share = match self.leftover > Weight::ZERO {
|
||||
true => Rel::ONE,
|
||||
false => Rel::ZERO,
|
||||
};
|
||||
UiScalar::from_parts(self.rel.add(share), self.px)
|
||||
}
|
||||
|
||||
pub fn px(px: impl UiNum) -> Self {
|
||||
Self {
|
||||
px: px.to_f32(),
|
||||
rel: 0.0,
|
||||
leftover: 0.0,
|
||||
px: Px::from_num(px),
|
||||
..Self::ZERO
|
||||
}
|
||||
}
|
||||
pub fn rel(rel: impl UiNum) -> Self {
|
||||
Self {
|
||||
px: 0.0,
|
||||
rel: rel.to_f32(),
|
||||
leftover: 0.0,
|
||||
rel: Rel::from_num(rel),
|
||||
..Self::ZERO
|
||||
}
|
||||
}
|
||||
pub fn leftover(ratio: impl UiNum) -> Self {
|
||||
Self {
|
||||
px: 0.0,
|
||||
rel: 0.0,
|
||||
leftover: ratio.to_f32(),
|
||||
leftover: Weight::from_num(ratio),
|
||||
..Self::ZERO
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,33 +146,21 @@ pub mod len_fns {
|
||||
use super::*;
|
||||
|
||||
pub fn px(px: impl UiNum) -> Len {
|
||||
Len {
|
||||
px: px.to_f32(),
|
||||
rel: 0.0,
|
||||
leftover: 0.0,
|
||||
}
|
||||
Len::px(px)
|
||||
}
|
||||
pub fn rel(rel: impl UiNum) -> Len {
|
||||
Len {
|
||||
px: 0.0,
|
||||
rel: rel.to_f32(),
|
||||
leftover: 0.0,
|
||||
}
|
||||
Len::rel(rel)
|
||||
}
|
||||
pub fn leftover(ratio: impl UiNum) -> Len {
|
||||
Len {
|
||||
px: 0.0,
|
||||
rel: 0.0,
|
||||
leftover: ratio.to_f32(),
|
||||
}
|
||||
Len::leftover(ratio)
|
||||
}
|
||||
}
|
||||
|
||||
impl_op!(Len Add add; px rel leftover);
|
||||
impl_op!(Len Sub sub; px rel leftover);
|
||||
impl_op!(same Len Add add; px rel leftover);
|
||||
impl_op!(same Len Sub sub; px rel leftover);
|
||||
|
||||
impl_op!(Size Add add; x y);
|
||||
impl_op!(Size Sub sub; x y);
|
||||
impl_op!(same Size Add add; x y);
|
||||
impl_op!(same Size Sub sub; x y);
|
||||
|
||||
impl Default for Len {
|
||||
fn default() -> Self {
|
||||
@@ -182,13 +176,13 @@ impl std::fmt::Display for Size {
|
||||
|
||||
impl std::fmt::Display for Len {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if self.px != 0.0 {
|
||||
if self.px != Px::ZERO {
|
||||
write!(f, "{} px;", self.px)?;
|
||||
}
|
||||
if self.rel != 0.0 {
|
||||
if self.rel != Rel::ZERO {
|
||||
write!(f, "{} rel;", self.rel)?;
|
||||
}
|
||||
if self.leftover != 0.0 {
|
||||
if self.leftover != Weight::ZERO {
|
||||
write!(f, "{} leftover;", self.leftover)?;
|
||||
}
|
||||
Ok(())
|
||||
|
||||
Reference in new issue
Block a user