Give a length with no share in it its own type again
`UiScalar` was `Len` without the `leftover` weight, which is the separation canonical `main` already had as `Len` beside `LayoutLen` and this branch collapsed. It is needed back for the queued clamp: a cap may not contain a share, because a cap has to read the report a rule otherwise makes moot, and a share puts the container's division into the same equation -- two self-consistent assignments, which is the multiple-fixed-point failure generated seed 13 punished for orthogonal sizing. `min(report, cap)` is not a `LayoutLen` either: it is a sum of parts, and the smaller of two of them is not one. So `UiScalar` is `Len`, what was `Len` is `LayoutLen`, and the two say in their docs which is which: a `Len` is pixels plus a fraction of a box -- a position being the length from the box's start, which is why a span is two of them -- and a `LayoutLen` is a `Len` plus a claim only a container dividing its room can answer. `From<Len> for LayoutLen` is the one-way step between them. Names only; the shader's `UiScalar` is renamed with them. Checked: fmt, clippy, 105 tests, and `tabs`, `minimal`, `view`, `text` and `random` byte-identical at 1920x1200. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f5e27cba9
commit
a8898aaa54
27 files changed
+218
-202
No files matched your search
@@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
Holds, LayerId, Len, MaskIdx, MoveIdx, PrimitiveHandle, RegionAlign, Size, TextureHandle,
|
||||
Holds, LayerId, LayoutLen, MaskIdx, MoveIdx, PrimitiveHandle, RegionAlign, Size, TextureHandle,
|
||||
UiRegion, WidgetId,
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ pub struct ActiveData {
|
||||
/// The declared lengths whoever drew this widget resolved into its box.
|
||||
/// A change to one moves a box this widget cannot fix by drawing again,
|
||||
/// and comparing them is what says so.
|
||||
pub declared: [Option<Len>; 2],
|
||||
pub declared: [Option<LayoutLen>; 2],
|
||||
/// The alignment its parent asked it with. A local redraw repeats that
|
||||
/// question, including an override chosen by a container.
|
||||
pub align: RegionAlign,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::{Px, REL_SHIFT, UiScalar, fixed::div_toward, fixed::narrow};
|
||||
use crate::{Len, Px, REL_SHIFT, fixed::div_toward, fixed::narrow};
|
||||
use std::ops::RangeInclusive;
|
||||
|
||||
/// The lengths of a box, in pixels, that one drawing of a widget holds for:
|
||||
@@ -50,7 +50,7 @@ impl Holds {
|
||||
/// the length alone instead gives a point that need not even contain the
|
||||
/// box the part was drawn in, which is a range excluding the drawing it
|
||||
/// was made for.
|
||||
pub const fn through(self, len: UiScalar) -> Self {
|
||||
pub const fn through(self, len: Len) -> Self {
|
||||
let rel = len.rel.raw() as i64;
|
||||
if rel == 0 {
|
||||
return Self::ANY;
|
||||
@@ -98,7 +98,7 @@ mod tests {
|
||||
#[test]
|
||||
fn through_reverses_a_range_for_a_negative_fraction() {
|
||||
// `10 - box / 2` is between 20 and 40 for boxes from -60 to -20.
|
||||
let part = UiScalar::from_parts(Rel::from_f32(-0.5), Px::from_int(10));
|
||||
let part = Len::from_parts(Rel::from_f32(-0.5), Px::from_int(10));
|
||||
let holds = Holds::from(Px::from_int(20)..=Px::from_int(40)).through(part);
|
||||
assert!(holds.contains(Px::from_int(-60)) && holds.contains(Px::from_int(-20)));
|
||||
assert!(!holds.contains(Px::from_int(-61)) && !holds.contains(Px::from_int(-19)));
|
||||
@@ -109,7 +109,7 @@ mod tests {
|
||||
/// box is not a whole number of steps.
|
||||
#[test]
|
||||
fn a_part_maps_back_onto_the_box_it_was_measured_in() {
|
||||
let part = UiScalar::from_parts(Rel::from_f32(1.0 / 3.0), Px::from_int(-146));
|
||||
let part = Len::from_parts(Rel::from_f32(1.0 / 3.0), Px::from_int(-146));
|
||||
for box_len in (440..460).map(Px::from_int) {
|
||||
let holds = Holds::at(part.to_px(box_len)).through(part);
|
||||
assert!(holds.contains(box_len), "{box_len:?} left out by {holds:?}");
|
||||
|
||||
+11
-11
@@ -1,8 +1,8 @@
|
||||
#[cfg(feature = "layout-diagnostics")]
|
||||
use crate::layout_diagnostics::{self as diag, Counter};
|
||||
use crate::{
|
||||
Axis, Holds, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget, TextAttrs,
|
||||
TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiScalar, UiVec2, Weight,
|
||||
Axis, Holds, LayoutLen, Len, Px, PxVec2, RegionAlign, Rel, RenderedText, Size, StrongWidget,
|
||||
TextAttrs, TextBuffer, TextData, TextureHandle, UiRegion, UiRenderState, UiRsc, UiVec2, Weight,
|
||||
WidgetId, Widgets,
|
||||
render::{
|
||||
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveHandle, PrimitiveInst,
|
||||
@@ -109,7 +109,7 @@ impl<'a> Painter<'a> {
|
||||
/// it resolves into its box. Reading them depends on nothing -- the box
|
||||
/// that comes of them is kept on the child, and `redraw` compares it
|
||||
/// there.
|
||||
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<Len>; 2] {
|
||||
fn declared_lens<W: ?Sized>(&self, id: &StrongWidget<W>) -> [Option<LayoutLen>; 2] {
|
||||
declared_lens(self.rsc.widgets(), id.id())
|
||||
}
|
||||
|
||||
@@ -218,7 +218,7 @@ impl<'a> Painter<'a> {
|
||||
|
||||
/// What a child says its length is without being drawn, if it can say.
|
||||
/// Asking counts as reading its size.
|
||||
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<Len> {
|
||||
pub fn size_hint<W: ?Sized>(&mut self, id: &StrongWidget<W>, axis: Axis) -> Option<LayoutLen> {
|
||||
let widgets = self.rsc.widgets();
|
||||
// A rule is the answer where there is one: it wins over whatever the
|
||||
// widget would draw, so it has to win over what the widget says too.
|
||||
@@ -252,7 +252,7 @@ impl<'a> Painter<'a> {
|
||||
child: &StrongWidget<W>,
|
||||
axis: Axis,
|
||||
region: UiRegion,
|
||||
) -> Option<Len> {
|
||||
) -> Option<LayoutLen> {
|
||||
let declared = self.declared_lens(child);
|
||||
let align = self.rsc.widgets().alignment(child.id());
|
||||
let local = declared_box(region, declared, align);
|
||||
@@ -472,7 +472,7 @@ impl<W: ?Sized> DrawResult<'_, '_, W> {
|
||||
self.size
|
||||
}
|
||||
|
||||
pub fn len(self, axis: Axis) -> Len {
|
||||
pub fn len(self, axis: Axis) -> LayoutLen {
|
||||
self.size().axis(axis)
|
||||
}
|
||||
}
|
||||
@@ -505,7 +505,7 @@ impl PrimitiveLike for &TextureHandle {
|
||||
/// What a widget declares a length of its box to be. `leftover` is not one: a
|
||||
/// share of what is left over is only a length to the widget dividing one,
|
||||
/// so it passes up in the size instead.
|
||||
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<Len>; 2] {
|
||||
pub(crate) fn declared_lens(widgets: &Widgets, id: WidgetId) -> [Option<LayoutLen>; 2] {
|
||||
let rules = widgets.size_rules(id);
|
||||
let widget = widgets.get_dyn(id);
|
||||
AXES.map(|axis| {
|
||||
@@ -537,7 +537,7 @@ pub(crate) fn placed_box(
|
||||
region: UiRegion,
|
||||
size: Size,
|
||||
align: RegionAlign,
|
||||
declared: [Option<Len>; 2],
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
) -> UiRegion {
|
||||
let mut placed = region;
|
||||
for (axis, declared) in AXES.into_iter().zip(declared) {
|
||||
@@ -546,7 +546,7 @@ pub(crate) fn placed_box(
|
||||
continue;
|
||||
}
|
||||
let span = placed.axis_mut(axis);
|
||||
let len = span.len().scale(reported.rel) + UiScalar::from_parts(Rel::ZERO, reported.px);
|
||||
let len = span.len().scale(reported.rel) + Len::from_parts(Rel::ZERO, reported.px);
|
||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||
span.end = span.start + len;
|
||||
}
|
||||
@@ -559,13 +559,13 @@ pub(crate) fn placed_box(
|
||||
/// space hands back the same length, so this is the identity for it.
|
||||
pub(crate) fn declared_box(
|
||||
mut region: UiRegion,
|
||||
declared: [Option<Len>; 2],
|
||||
declared: [Option<LayoutLen>; 2],
|
||||
align: RegionAlign,
|
||||
) -> UiRegion {
|
||||
for (axis, len) in AXES.into_iter().zip(declared) {
|
||||
let Some(len) = len else { continue };
|
||||
let span = region.axis_mut(axis);
|
||||
let len = UiScalar::from_parts(len.rel, len.px);
|
||||
let len = Len::from_parts(len.rel, len.px);
|
||||
span.start += (span.len() - len).scale(align.axis(axis).rel());
|
||||
span.end = span.start + len;
|
||||
}
|
||||
|
||||
+11
-17
@@ -2,9 +2,9 @@
|
||||
use crate::layout_diagnostics::{self as diag, Counter, ReuseOutcome, TimerKind};
|
||||
use crate::ui::painter::{declared_box, declared_lens, placed_box};
|
||||
use crate::{
|
||||
ActiveData, Axis, DrawLayers, Holds, IdLike, Len, MaskIdx, MoveIdx, Moves, Painter,
|
||||
PixelRegion, PxVec2, RegionAlign, Rel, Size, StrongWidget, UiRegion, UiRsc, UiScalar, UiSpan,
|
||||
Weight, WidgetId, Widgets,
|
||||
ActiveData, Axis, DrawLayers, Holds, IdLike, LayoutLen, Len, MaskIdx, MoveIdx, Moves, Painter,
|
||||
PixelRegion, PxVec2, RegionAlign, Rel, Size, StrongWidget, UiRegion, UiRsc, UiSpan, Weight,
|
||||
WidgetId, Widgets,
|
||||
util::{HashMap, Vec2},
|
||||
};
|
||||
|
||||
@@ -75,14 +75,8 @@ impl UiRenderState {
|
||||
/// downstream has to know the output's size to resolve a position.
|
||||
fn write_root(&mut self) {
|
||||
let region = UiRegion::new(
|
||||
UiSpan::new(
|
||||
UiScalar::ZERO,
|
||||
UiScalar::from_parts(Rel::ZERO, self.output_size.x),
|
||||
),
|
||||
UiSpan::new(
|
||||
UiScalar::ZERO,
|
||||
UiScalar::from_parts(Rel::ZERO, self.output_size.y),
|
||||
),
|
||||
UiSpan::new(Len::ZERO, Len::from_parts(Rel::ZERO, self.output_size.x)),
|
||||
UiSpan::new(Len::ZERO, Len::from_parts(Rel::ZERO, self.output_size.y)),
|
||||
);
|
||||
match self.root_move == MoveIdx::NONE {
|
||||
true => self.root_move = self.moves.push(MoveIdx::NONE, region),
|
||||
@@ -255,8 +249,8 @@ impl UiRenderState {
|
||||
let reported = answer.0.axis(axis);
|
||||
let placed_len =
|
||||
match reported.leftover != Weight::ZERO || declared[axis as usize].is_some() {
|
||||
true => UiScalar::FULL,
|
||||
false => UiScalar::from_parts(reported.rel, reported.px),
|
||||
true => Len::FULL,
|
||||
false => Len::from_parts(reported.rel, reported.px),
|
||||
};
|
||||
settled.1[axis as usize] =
|
||||
settled.1[axis as usize].and(drawing_holds[axis as usize].through(placed_len));
|
||||
@@ -765,10 +759,10 @@ impl UiRenderState {
|
||||
let size = Size {
|
||||
x: widget
|
||||
.and_then(|w| w.size_hint(Axis::X))
|
||||
.unwrap_or(Len::ZERO),
|
||||
.unwrap_or(LayoutLen::ZERO),
|
||||
y: widget
|
||||
.and_then(|w| w.size_hint(Axis::Y))
|
||||
.unwrap_or(Len::ZERO),
|
||||
.unwrap_or(LayoutLen::ZERO),
|
||||
};
|
||||
self.active.insert(
|
||||
id,
|
||||
@@ -1079,7 +1073,7 @@ impl RegionRemap {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_scalar(self, scalar: UiScalar, from: UiSpan, to: UiSpan) -> UiScalar {
|
||||
fn apply_scalar(self, scalar: Len, from: UiSpan, to: UiSpan) -> Len {
|
||||
let extent = from.end.rel - from.start.rel;
|
||||
// A box that only moved, or that has no relative extent to divide,
|
||||
// carries its parts by moving them, which is exact. Dividing to find
|
||||
@@ -1100,7 +1094,7 @@ impl RegionRemap {
|
||||
let from_px = fraction.lerp(from.start.px, from.end.px);
|
||||
let to_rel = fraction.lerp(to.start.rel, to.end.rel);
|
||||
let to_px = fraction.lerp(to.start.px, to.end.px);
|
||||
UiScalar::from_parts(to_rel, scalar.px - from_px + to_px)
|
||||
Len::from_parts(to_rel, scalar.px - from_px + to_px)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user