Match a place's own cases instead of asking it five questions
`PlaceSpan` and `RelBase` were private to `place.rs`, so `painter.rs` reached them through six `pub(crate)` accessors -- `stated_rel_base`, `narrows_rel_base`, `within_span`, `is_sized`, `does_fill`, `with_rel_base` -- and `in_parent` re-derived a three-case enum from five yes/no answers. The two enums are `pub` now and `ui/mod.rs` re-exports `place` by name rather than by glob, the way it already did for `painter`, so nothing new leaves the crate and there is no visibility qualifier to get right. All six accessors are deleted: `in_parent` matches `(at.span, declared)`, `resolve_rel_base` matches `(rel_base, span)` and assigns, and the other three read the field. `!at.is_sized()` was dead. `PlaceSpan::Sized` is built in exactly one place, `Len::as_desc`, which sets `RelBase::Len(self)` in the same literal, so `stated_rel_base().is_none()` already excluded it. Deleting `with_rel_base` removes the only writer that could have separated the two, so a named length now carries its own base by construction rather than by habit -- which is what the comment on `RelBase` says. The four `pub(crate)` methods left in `painter.rs` are inherent methods on types the crate does export, so hiding the path is not available to them; they are `pub(super)`, which is the module tree that calls them. fmt, workspace clippy under `-D warnings` with and without `layout-diagnostics`, and the workspace tests under both are clean. The cold dump over 400 depth-5 trees is byte-identical: 34,492 boxes.
This commit is contained in:
1 parent
7e2b4cd9db
commit
1ebd4d3a05
3 files changed
+43
-79
No files matched your search
+1
-1
@@ -20,7 +20,7 @@ pub use active::*;
|
||||
pub use holds::*;
|
||||
pub use layout_holds::*;
|
||||
pub use painter::{Painter, PrimitiveLike};
|
||||
pub use place::*;
|
||||
pub use place::{PlaceDesc, PlaceDescAxis, RetainedPrimitive};
|
||||
pub use render_state::*;
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
+32
-20
@@ -8,7 +8,10 @@ use crate::{
|
||||
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveInst, PrimitiveKind,
|
||||
TexturePrimitive,
|
||||
},
|
||||
ui::render_state::{DrawInfo, Placing},
|
||||
ui::{
|
||||
place::{PlaceSpan, RelBase},
|
||||
render_state::{DrawInfo, Placing},
|
||||
},
|
||||
};
|
||||
|
||||
/// makes your surfaces look pretty
|
||||
@@ -156,11 +159,15 @@ impl<'a> Painter<'a> {
|
||||
/// only moves its child does not pin its drawing to a rel base.
|
||||
fn resolve_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
|
||||
for axis in Axis::BOTH {
|
||||
if let Some(span) = place[axis].narrows_rel_base() {
|
||||
let len = span.len();
|
||||
let stated = (len != Len::FULL).then(|| len.within_len(self.rel_base(axis)));
|
||||
place[axis] = place[axis].with_rel_base(stated);
|
||||
}
|
||||
let at = &mut place[axis];
|
||||
let (RelBase::WithRegion, PlaceSpan::Within(span)) = (at.rel_base, at.span) else {
|
||||
continue;
|
||||
};
|
||||
let len = span.len();
|
||||
at.rel_base = match len == Len::FULL {
|
||||
true => RelBase::Inherit,
|
||||
false => RelBase::Len(len.within_len(self.rel_base(axis))),
|
||||
};
|
||||
}
|
||||
place
|
||||
}
|
||||
@@ -255,7 +262,7 @@ impl<'a> Painter<'a> {
|
||||
let place = self.resolve_rel_base(place.into());
|
||||
let states_rel_base = Axis::BOTH
|
||||
.iter()
|
||||
.any(|&axis| place[axis].stated_rel_base().is_some());
|
||||
.any(|&axis| matches!(place[axis].rel_base, RelBase::Len(_)));
|
||||
if states_rel_base || !self.children.contains(&id.id()) {
|
||||
return self.widget_at(id, place);
|
||||
}
|
||||
@@ -601,16 +608,20 @@ impl Painter<'_> {
|
||||
for axis in Axis::BOTH {
|
||||
let declared = declared[axis];
|
||||
let holds = holds[axis];
|
||||
let at = place[axis];
|
||||
let result = &mut result[axis];
|
||||
// Every read became pixels against the window, so a range on
|
||||
// it is already in this widget's terms.
|
||||
result.window = holds.window;
|
||||
let at = place[axis];
|
||||
let reaches = at.stated_rel_base().is_none()
|
||||
&& !at.is_sized()
|
||||
// A length this widget named -- a resolved share, a box a sibling
|
||||
// decided, a box it sized outright, which is its own base -- is
|
||||
// not a length of this widget's rel base, so a pin on it stops
|
||||
// here. So does a declaration in pixels: no length of either base
|
||||
// is in it to see.
|
||||
let reaches = !matches!(at.rel_base, RelBase::Len(_))
|
||||
&& declared.is_none_or(|len| len.rel != Rel::ZERO);
|
||||
result.rel_base = holds.rel_base.and(reaches.then(|| self.rel_base[axis]));
|
||||
match (at.within_span(), declared.is_some()) {
|
||||
match (at.span, declared) {
|
||||
// Its box is a part of this widget's own box, in that box's
|
||||
// own lengths, so what it holds for maps back through that
|
||||
// part into a range on this widget's box. A length it pinned
|
||||
@@ -618,7 +629,7 @@ impl Painter<'_> {
|
||||
// part is the whole of the box less pixels, which is the one
|
||||
// shape that inverts exactly; any other part pins this
|
||||
// widget's own length.
|
||||
(Some(span), false) => {
|
||||
(PlaceSpan::Within(span), None) => {
|
||||
let part_len = span.len();
|
||||
result.region = holds.region.through(part_len);
|
||||
result.region_len = holds.region_len.map(|pinned| match part_len.rel {
|
||||
@@ -641,7 +652,7 @@ impl Painter<'_> {
|
||||
|
||||
impl Widgets {
|
||||
/// What a widget's box is where a rule or its own hint says so outright.
|
||||
pub(crate) fn declared_lens(&self, id: WidgetId) -> Declared {
|
||||
pub(super) fn declared_lens(&self, id: WidgetId) -> Declared {
|
||||
let rules = self.size_rules(id);
|
||||
let widget = self.get_dyn(id);
|
||||
Declared::from_axes(|axis| {
|
||||
@@ -668,7 +679,7 @@ impl LayoutLen {
|
||||
/// the rule already gave the region its length, and the rule's length is
|
||||
/// what the widget reports there. And an axis the parent decided from
|
||||
/// the answer is the answer already.
|
||||
pub(crate) fn fills(self, declared: Option<Len>, decided: bool) -> bool {
|
||||
pub(super) fn fills(self, declared: Option<Len>, decided: bool) -> bool {
|
||||
self.leftover != Weight::ZERO || declared.is_some() || decided
|
||||
}
|
||||
}
|
||||
@@ -683,7 +694,7 @@ impl PlaceDesc {
|
||||
/// part. That is what makes a fraction the same fraction wherever the part
|
||||
/// it is placed in sits and however long it is -- the fraction is resolved
|
||||
/// once, here, against the rel base it was reported of.
|
||||
pub(crate) fn placement(
|
||||
pub(super) fn placement(
|
||||
self,
|
||||
region: UiRegion,
|
||||
size: Size,
|
||||
@@ -693,7 +704,7 @@ impl PlaceDesc {
|
||||
let mut placed = region;
|
||||
for axis in Axis::BOTH {
|
||||
let reported = size[axis];
|
||||
if reported.fills(declared[axis], self[axis].does_fill()) {
|
||||
if reported.fills(declared[axis], self[axis].fills) {
|
||||
continue;
|
||||
}
|
||||
placed[axis] = placed[axis].place(reported.without_leftover(), align[axis]);
|
||||
@@ -711,7 +722,7 @@ impl PlaceDesc {
|
||||
/// name. The child's declaration is a fraction of whichever reached it, and
|
||||
/// is the only one that also places the box: a box the caller decided is
|
||||
/// what `place` names.
|
||||
pub(crate) fn rel_base_and_region(
|
||||
pub(super) fn rel_base_and_region(
|
||||
self,
|
||||
own: UiRegion,
|
||||
parent_rel_base: UiVec2,
|
||||
@@ -722,9 +733,10 @@ impl PlaceDesc {
|
||||
let mut rel_base = parent_rel_base;
|
||||
let mut region = given;
|
||||
for axis in Axis::BOTH {
|
||||
let base = self[axis]
|
||||
.stated_rel_base()
|
||||
.unwrap_or_else(|| parent_rel_base[axis]);
|
||||
let base = match self[axis].rel_base {
|
||||
RelBase::Len(len) => len,
|
||||
RelBase::Inherit | RelBase::WithRegion => parent_rel_base[axis],
|
||||
};
|
||||
let len = declared[axis]
|
||||
.map(|len| len.within_len(base))
|
||||
.unwrap_or(base);
|
||||
|
||||
+10
-58
@@ -11,21 +11,23 @@ use crate::{Axis, AxisAlign, Len, PrimitiveHandle, RegionAlign, UiRegion, UiSpan
|
||||
/// it differently, so it is said here.
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
pub struct PlaceDescAxis {
|
||||
span: PlaceSpan,
|
||||
fills: bool,
|
||||
rel_base: RelBase,
|
||||
pub span: PlaceSpan,
|
||||
pub fills: bool,
|
||||
pub rel_base: RelBase,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum PlaceSpan {
|
||||
pub enum PlaceSpan {
|
||||
Within(UiSpan),
|
||||
Shifted(UiSpan),
|
||||
Sized(Len),
|
||||
}
|
||||
|
||||
/// What a child's fractions are of, where the caller has not named a length.
|
||||
/// What a child's fractions are of. [`PlaceSpan::Sized`] is a length the
|
||||
/// caller named, which is always its own base, so nothing here constructs one
|
||||
/// beside anything but [`Self::Len`].
|
||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||
enum RelBase {
|
||||
pub enum RelBase {
|
||||
/// The caller's own, unchanged.
|
||||
Inherit,
|
||||
/// The caller's own, narrowed the way the region is.
|
||||
@@ -61,14 +63,8 @@ impl PlaceDescAxis {
|
||||
self
|
||||
}
|
||||
|
||||
/// Whether the region is the placement outright, rather than a box the
|
||||
/// answer is placed inside.
|
||||
pub(crate) const fn does_fill(self) -> bool {
|
||||
self.fills
|
||||
}
|
||||
|
||||
/// Where it lands in the coordinates `own` is in.
|
||||
pub(crate) fn of(self, own: UiSpan, align: AxisAlign) -> UiSpan {
|
||||
pub fn of(self, own: UiSpan, align: AxisAlign) -> UiSpan {
|
||||
match self.span {
|
||||
PlaceSpan::Within(span) => span.within(&own),
|
||||
PlaceSpan::Shifted(mut span) => {
|
||||
@@ -78,50 +74,6 @@ impl PlaceDescAxis {
|
||||
PlaceSpan::Sized(len) => own.place(len, align),
|
||||
}
|
||||
}
|
||||
|
||||
/// The child's rel base, where this says one outright. `None` forwards
|
||||
/// the caller's own, and [`RelBase::WithRegion`] is resolved by whoever
|
||||
/// can read that rel base, so it does not reach here.
|
||||
pub(crate) const fn stated_rel_base(self) -> Option<Len> {
|
||||
match self.rel_base {
|
||||
RelBase::Len(len) => Some(len),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The length this narrows the caller's rel base by, where it does.
|
||||
/// `None` leaves that rel base alone, and reading it is then a
|
||||
/// dependency the caller does not take.
|
||||
pub(crate) const fn narrows_rel_base(self) -> Option<UiSpan> {
|
||||
match (self.rel_base, self.span) {
|
||||
(RelBase::WithRegion, PlaceSpan::Within(span)) => Some(span),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// The span it composes into the caller's box, where that is what it
|
||||
/// does: the one case whose validity maps back through the part.
|
||||
pub(crate) const fn within_span(self) -> Option<UiSpan> {
|
||||
match self.span {
|
||||
PlaceSpan::Within(span) => Some(span),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether the caller decided this length rather than a place along its
|
||||
/// own box, which is what stops its length reaching the child at all.
|
||||
pub(crate) const fn is_sized(self) -> bool {
|
||||
matches!(self.span, PlaceSpan::Sized(_))
|
||||
}
|
||||
|
||||
/// The same, with its rel base stated outright.
|
||||
pub(crate) const fn with_rel_base(mut self, len: Option<Len>) -> Self {
|
||||
self.rel_base = match len {
|
||||
Some(len) => RelBase::Len(len),
|
||||
None => RelBase::Inherit,
|
||||
};
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a child is asked, on both axes. A [`UiRegion`] converts into the
|
||||
@@ -172,7 +124,7 @@ impl PlaceDesc {
|
||||
}
|
||||
|
||||
/// The box each axis names, in the coordinates `own` is in.
|
||||
pub(crate) fn of(self, own: UiRegion, align: RegionAlign) -> UiRegion {
|
||||
pub fn of(self, own: UiRegion, align: RegionAlign) -> UiRegion {
|
||||
UiRegion::new(self.x.of(own.x, align.x), self.y.of(own.y, align.y))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user