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 holds::*;
|
||||||
pub use layout_holds::*;
|
pub use layout_holds::*;
|
||||||
pub use painter::{Painter, PrimitiveLike};
|
pub use painter::{Painter, PrimitiveLike};
|
||||||
pub use place::*;
|
pub use place::{PlaceDesc, PlaceDescAxis, RetainedPrimitive};
|
||||||
pub use render_state::*;
|
pub use render_state::*;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
|
|||||||
+32
-20
@@ -8,7 +8,10 @@ use crate::{
|
|||||||
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveInst, PrimitiveKind,
|
GlyphPrimitive, Mask, MaskIdx, MoveIdx, Primitive, PrimitiveInst, PrimitiveKind,
|
||||||
TexturePrimitive,
|
TexturePrimitive,
|
||||||
},
|
},
|
||||||
ui::render_state::{DrawInfo, Placing},
|
ui::{
|
||||||
|
place::{PlaceSpan, RelBase},
|
||||||
|
render_state::{DrawInfo, Placing},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// makes your surfaces look pretty
|
/// 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.
|
/// only moves its child does not pin its drawing to a rel base.
|
||||||
fn resolve_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
|
fn resolve_rel_base(&mut self, mut place: PlaceDesc) -> PlaceDesc {
|
||||||
for axis in Axis::BOTH {
|
for axis in Axis::BOTH {
|
||||||
if let Some(span) = place[axis].narrows_rel_base() {
|
let at = &mut place[axis];
|
||||||
let len = span.len();
|
let (RelBase::WithRegion, PlaceSpan::Within(span)) = (at.rel_base, at.span) else {
|
||||||
let stated = (len != Len::FULL).then(|| len.within_len(self.rel_base(axis)));
|
continue;
|
||||||
place[axis] = place[axis].with_rel_base(stated);
|
};
|
||||||
}
|
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
|
place
|
||||||
}
|
}
|
||||||
@@ -255,7 +262,7 @@ impl<'a> Painter<'a> {
|
|||||||
let place = self.resolve_rel_base(place.into());
|
let place = self.resolve_rel_base(place.into());
|
||||||
let states_rel_base = Axis::BOTH
|
let states_rel_base = Axis::BOTH
|
||||||
.iter()
|
.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()) {
|
if states_rel_base || !self.children.contains(&id.id()) {
|
||||||
return self.widget_at(id, place);
|
return self.widget_at(id, place);
|
||||||
}
|
}
|
||||||
@@ -601,16 +608,20 @@ impl Painter<'_> {
|
|||||||
for axis in Axis::BOTH {
|
for axis in Axis::BOTH {
|
||||||
let declared = declared[axis];
|
let declared = declared[axis];
|
||||||
let holds = holds[axis];
|
let holds = holds[axis];
|
||||||
|
let at = place[axis];
|
||||||
let result = &mut result[axis];
|
let result = &mut result[axis];
|
||||||
// Every read became pixels against the window, so a range on
|
// Every read became pixels against the window, so a range on
|
||||||
// it is already in this widget's terms.
|
// it is already in this widget's terms.
|
||||||
result.window = holds.window;
|
result.window = holds.window;
|
||||||
let at = place[axis];
|
// A length this widget named -- a resolved share, a box a sibling
|
||||||
let reaches = at.stated_rel_base().is_none()
|
// decided, a box it sized outright, which is its own base -- is
|
||||||
&& !at.is_sized()
|
// 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);
|
&& declared.is_none_or(|len| len.rel != Rel::ZERO);
|
||||||
result.rel_base = holds.rel_base.and(reaches.then(|| self.rel_base[axis]));
|
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
|
// 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
|
// own lengths, so what it holds for maps back through that
|
||||||
// part into a range on this widget's box. A length it pinned
|
// 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
|
// part is the whole of the box less pixels, which is the one
|
||||||
// shape that inverts exactly; any other part pins this
|
// shape that inverts exactly; any other part pins this
|
||||||
// widget's own length.
|
// widget's own length.
|
||||||
(Some(span), false) => {
|
(PlaceSpan::Within(span), None) => {
|
||||||
let part_len = span.len();
|
let part_len = span.len();
|
||||||
result.region = holds.region.through(part_len);
|
result.region = holds.region.through(part_len);
|
||||||
result.region_len = holds.region_len.map(|pinned| match part_len.rel {
|
result.region_len = holds.region_len.map(|pinned| match part_len.rel {
|
||||||
@@ -641,7 +652,7 @@ impl Painter<'_> {
|
|||||||
|
|
||||||
impl Widgets {
|
impl Widgets {
|
||||||
/// What a widget's box is where a rule or its own hint says so outright.
|
/// 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 rules = self.size_rules(id);
|
||||||
let widget = self.get_dyn(id);
|
let widget = self.get_dyn(id);
|
||||||
Declared::from_axes(|axis| {
|
Declared::from_axes(|axis| {
|
||||||
@@ -668,7 +679,7 @@ impl LayoutLen {
|
|||||||
/// the rule already gave the region its length, and the rule's length is
|
/// 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
|
/// what the widget reports there. And an axis the parent decided from
|
||||||
/// the answer is the answer already.
|
/// 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
|
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
|
/// 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
|
/// it is placed in sits and however long it is -- the fraction is resolved
|
||||||
/// once, here, against the rel base it was reported of.
|
/// once, here, against the rel base it was reported of.
|
||||||
pub(crate) fn placement(
|
pub(super) fn placement(
|
||||||
self,
|
self,
|
||||||
region: UiRegion,
|
region: UiRegion,
|
||||||
size: Size,
|
size: Size,
|
||||||
@@ -693,7 +704,7 @@ impl PlaceDesc {
|
|||||||
let mut placed = region;
|
let mut placed = region;
|
||||||
for axis in Axis::BOTH {
|
for axis in Axis::BOTH {
|
||||||
let reported = size[axis];
|
let reported = size[axis];
|
||||||
if reported.fills(declared[axis], self[axis].does_fill()) {
|
if reported.fills(declared[axis], self[axis].fills) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
placed[axis] = placed[axis].place(reported.without_leftover(), align[axis]);
|
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
|
/// 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
|
/// is the only one that also places the box: a box the caller decided is
|
||||||
/// what `place` names.
|
/// what `place` names.
|
||||||
pub(crate) fn rel_base_and_region(
|
pub(super) fn rel_base_and_region(
|
||||||
self,
|
self,
|
||||||
own: UiRegion,
|
own: UiRegion,
|
||||||
parent_rel_base: UiVec2,
|
parent_rel_base: UiVec2,
|
||||||
@@ -722,9 +733,10 @@ impl PlaceDesc {
|
|||||||
let mut rel_base = parent_rel_base;
|
let mut rel_base = parent_rel_base;
|
||||||
let mut region = given;
|
let mut region = given;
|
||||||
for axis in Axis::BOTH {
|
for axis in Axis::BOTH {
|
||||||
let base = self[axis]
|
let base = match self[axis].rel_base {
|
||||||
.stated_rel_base()
|
RelBase::Len(len) => len,
|
||||||
.unwrap_or_else(|| parent_rel_base[axis]);
|
RelBase::Inherit | RelBase::WithRegion => parent_rel_base[axis],
|
||||||
|
};
|
||||||
let len = declared[axis]
|
let len = declared[axis]
|
||||||
.map(|len| len.within_len(base))
|
.map(|len| len.within_len(base))
|
||||||
.unwrap_or(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.
|
/// it differently, so it is said here.
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
pub struct PlaceDescAxis {
|
pub struct PlaceDescAxis {
|
||||||
span: PlaceSpan,
|
pub span: PlaceSpan,
|
||||||
fills: bool,
|
pub fills: bool,
|
||||||
rel_base: RelBase,
|
pub rel_base: RelBase,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum PlaceSpan {
|
pub enum PlaceSpan {
|
||||||
Within(UiSpan),
|
Within(UiSpan),
|
||||||
Shifted(UiSpan),
|
Shifted(UiSpan),
|
||||||
Sized(Len),
|
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)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
enum RelBase {
|
pub enum RelBase {
|
||||||
/// The caller's own, unchanged.
|
/// The caller's own, unchanged.
|
||||||
Inherit,
|
Inherit,
|
||||||
/// The caller's own, narrowed the way the region is.
|
/// The caller's own, narrowed the way the region is.
|
||||||
@@ -61,14 +63,8 @@ impl PlaceDescAxis {
|
|||||||
self
|
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.
|
/// 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 {
|
match self.span {
|
||||||
PlaceSpan::Within(span) => span.within(&own),
|
PlaceSpan::Within(span) => span.within(&own),
|
||||||
PlaceSpan::Shifted(mut span) => {
|
PlaceSpan::Shifted(mut span) => {
|
||||||
@@ -78,50 +74,6 @@ impl PlaceDescAxis {
|
|||||||
PlaceSpan::Sized(len) => own.place(len, align),
|
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
|
/// 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.
|
/// 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))
|
UiRegion::new(self.x.of(own.x, align.x), self.y.of(own.y, align.y))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user