layout: make AxisResult, Anchor & AbsoluteAxisSolver use Au (#31395)

* make AxisResult and Anchor use Au

* Avoid some .into()

* review fix

* review update

---------

Co-authored-by: Oriol Brufau <obrufau@igalia.com>
This commit is contained in:
atbrakhi 2024-02-26 23:41:33 +05:30 committed by GitHub
parent a97a04d84c
commit 304ab9b09c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 102 additions and 108 deletions

View file

@ -70,6 +70,13 @@ impl<T: Clone> LogicalVec2<T> {
block: b.clone(),
}
}
pub fn map<U>(&self, f: impl Fn(&T) -> U) -> LogicalVec2<U> {
LogicalVec2 {
inline: f(&self.inline),
block: f(&self.block),
}
}
}
impl<T> Add<&'_ LogicalVec2<T>> for &'_ LogicalVec2<T>
@ -121,10 +128,7 @@ impl<T: Zero> LogicalVec2<T> {
impl LogicalVec2<LengthOrAuto> {
pub fn auto_is(&self, f: impl Fn() -> Length) -> LogicalVec2<Length> {
LogicalVec2 {
inline: self.inline.auto_is(&f),
block: self.block.auto_is(&f),
}
self.map(|t| t.auto_is(&f))
}
}
@ -479,14 +483,8 @@ impl From<LogicalVec2<Au>> for LogicalVec2<CSSPixelLength> {
impl From<LogicalRect<Au>> for LogicalRect<CSSPixelLength> {
fn from(value: LogicalRect<Au>) -> Self {
LogicalRect {
start_corner: LogicalVec2 {
inline: value.start_corner.inline.into(),
block: value.start_corner.block.into(),
},
size: LogicalVec2 {
inline: value.size.inline.into(),
block: value.size.block.into(),
},
start_corner: value.start_corner.into(),
size: value.size.into(),
}
}
}
@ -494,14 +492,8 @@ impl From<LogicalRect<Au>> for LogicalRect<CSSPixelLength> {
impl From<LogicalRect<CSSPixelLength>> for LogicalRect<Au> {
fn from(value: LogicalRect<CSSPixelLength>) -> Self {
LogicalRect {
start_corner: LogicalVec2 {
inline: value.start_corner.inline.into(),
block: value.start_corner.block.into(),
},
size: LogicalVec2 {
inline: value.size.inline.into(),
block: value.size.block.into(),
},
start_corner: value.start_corner.into(),
size: value.size.into(),
}
}
}

View file

@ -502,19 +502,19 @@ impl HoistedAbsolutelyPositionedBox {
let shared_fragment = self.fragment.borrow();
let inline_axis_solver = AbsoluteAxisSolver {
containing_size: cbis.into(),
padding_border_sum: pbm.padding_border_sums.inline.into(),
computed_margin_start: pbm.margin.inline_start,
computed_margin_end: pbm.margin.inline_end,
containing_size: cbis,
padding_border_sum: pbm.padding_border_sums.inline,
computed_margin_start: pbm.margin.inline_start.map(|t| t.into()),
computed_margin_end: pbm.margin.inline_end.map(|t| t.into()),
avoid_negative_margin_start: true,
box_offsets: &shared_fragment.box_offsets.inline,
};
let block_axis_solver = AbsoluteAxisSolver {
containing_size: cbbs.into(),
padding_border_sum: pbm.padding_border_sums.block.into(),
computed_margin_start: pbm.margin.block_start,
computed_margin_end: pbm.margin.block_end,
containing_size: cbbs,
padding_border_sum: pbm.padding_border_sums.block,
computed_margin_start: pbm.margin.block_start.map(|t| t.into()),
computed_margin_end: pbm.margin.block_end.map(|t| t.into()),
avoid_negative_margin_start: false,
box_offsets: &shared_fragment.box_offsets.block,
};
@ -523,23 +523,25 @@ impl HoistedAbsolutelyPositionedBox {
block: block_axis_solver.is_overconstrained_for_size(computed_size.block),
};
let mut inline_axis = inline_axis_solver.solve_for_size(computed_size.inline);
let mut block_axis = block_axis_solver.solve_for_size(computed_size.block);
let mut inline_axis =
inline_axis_solver.solve_for_size(computed_size.inline.map(|t| t.into()));
let mut block_axis =
block_axis_solver.solve_for_size(computed_size.block.map(|t| t.into()));
let mut positioning_context =
PositioningContext::new_for_style(absolutely_positioned_box.context.style()).unwrap();
let mut new_fragment = {
let content_size;
let content_size: LogicalVec2<Au>;
let fragments;
match &mut absolutely_positioned_box.context {
IndependentFormattingContext::Replaced(replaced) => {
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-replaced-height
let style = &replaced.style;
content_size = computed_size.auto_is(|| unreachable!());
content_size = computed_size.auto_is(|| unreachable!()).into();
fragments = replaced
.contents
.make_fragments(style, content_size.clone().into());
.make_fragments(style, content_size.clone());
},
IndependentFormattingContext::NonReplaced(non_replaced) => {
// https://drafts.csswg.org/css2/#min-max-widths
@ -547,10 +549,11 @@ impl HoistedAbsolutelyPositionedBox {
let min_size = non_replaced
.style
.content_min_box_size(&containing_block.into(), &pbm)
.auto_is(Length::zero);
.map(|t| t.map(Au::from).auto_is(Au::zero));
let max_size = non_replaced
.style
.content_max_box_size(&containing_block.into(), &pbm);
.content_max_box_size(&containing_block.into(), &pbm)
.map(|t| t.map(Au::from));
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width
// https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height
@ -560,14 +563,11 @@ impl HoistedAbsolutelyPositionedBox {
Anchor::End(end) => end,
};
let margin_sum = inline_axis.margin_start + inline_axis.margin_end;
let available_size = cbis -
anchor.into() -
pbm.padding_border_sums.inline -
margin_sum.into();
let available_size =
cbis - anchor - pbm.padding_border_sums.inline - margin_sum;
non_replaced
.inline_content_sizes(layout_context)
.shrink_to_fit(available_size)
.into()
});
// If the tentative used inline size is greater than max-inline-size,
@ -577,8 +577,8 @@ impl HoistedAbsolutelyPositionedBox {
// https://drafts.csswg.org/css2/#min-max-widths (step 2)
if let Some(max) = max_size.inline {
if inline_size > max {
inline_axis = inline_axis_solver
.solve_for_size(LengthOrAuto::LengthPercentage(max));
inline_axis =
inline_axis_solver.solve_for_size(AuOrAuto::LengthPercentage(max));
inline_size = inline_axis.size.auto_is(|| unreachable!());
}
}
@ -590,12 +590,12 @@ impl HoistedAbsolutelyPositionedBox {
// https://drafts.csswg.org/css2/#min-max-widths (step 3)
if inline_size < min_size.inline {
inline_axis = inline_axis_solver
.solve_for_size(LengthOrAuto::LengthPercentage(min_size.inline));
.solve_for_size(AuOrAuto::LengthPercentage(min_size.inline));
inline_size = inline_axis.size.auto_is(|| unreachable!());
}
struct Result {
content_size: LogicalVec2<CSSPixelLength>,
content_size: LogicalVec2<Au>,
fragments: Vec<Fragment>,
}
@ -604,7 +604,7 @@ impl HoistedAbsolutelyPositionedBox {
// percentages may be resolved incorrectly.
let mut try_layout = |size| {
let containing_block_for_children = ContainingBlock {
inline_size: inline_size.into(),
inline_size,
block_size: size,
style: &non_replaced.style,
};
@ -630,13 +630,13 @@ impl HoistedAbsolutelyPositionedBox {
Result {
content_size: LogicalVec2 {
inline: inline_size,
block: block_size.into(),
block: block_size,
},
fragments: independent_layout.fragments,
}
};
let mut result = try_layout(block_axis.size.map(|t| t.into()));
let mut result = try_layout(block_axis.size);
// If the tentative used block size is greater than max-block-size,
// recalculate the block size and margins with max-block-size as the
@ -645,9 +645,9 @@ impl HoistedAbsolutelyPositionedBox {
// https://drafts.csswg.org/css2/#min-max-heights (step 2)
if let Some(max) = max_size.block {
if result.content_size.block > max {
block_axis = block_axis_solver
.solve_for_size(LengthOrAuto::LengthPercentage(max));
result = try_layout(AuOrAuto::LengthPercentage(max.into()));
block_axis =
block_axis_solver.solve_for_size(AuOrAuto::LengthPercentage(max));
result = try_layout(AuOrAuto::LengthPercentage(max));
}
}
@ -658,8 +658,8 @@ impl HoistedAbsolutelyPositionedBox {
// https://drafts.csswg.org/css2/#min-max-heights (step 3)
if result.content_size.block < min_size.block {
block_axis = block_axis_solver
.solve_for_size(LengthOrAuto::LengthPercentage(min_size.block));
result = try_layout(AuOrAuto::LengthPercentage(min_size.block.into()));
.solve_for_size(AuOrAuto::LengthPercentage(min_size.block));
result = try_layout(AuOrAuto::LengthPercentage(min_size.block));
}
content_size = result.content_size;
@ -676,22 +676,16 @@ impl HoistedAbsolutelyPositionedBox {
let pb = &pbm.padding + &pbm.border;
let inline_start = match inline_axis.anchor {
Anchor::Start(start) => start + pb.inline_start.into() + margin.inline_start,
Anchor::End(end) => Length::from(
cbis - end.into() -
pb.inline_end -
margin.inline_end.into() -
content_size.inline.into(),
),
Anchor::Start(start) => start + pb.inline_start + margin.inline_start,
Anchor::End(end) => {
cbis - end - pb.inline_end - margin.inline_end - content_size.inline
},
};
let block_start = match block_axis.anchor {
Anchor::Start(start) => start + pb.block_start.into() + margin.block_start,
Anchor::End(end) => Length::from(
cbbs - end.into() -
pb.block_end -
margin.block_end.into() -
content_size.block.into(),
),
Anchor::Start(start) => start + pb.block_start + margin.block_start,
Anchor::End(end) => {
cbbs - end - pb.block_end - margin.block_end - content_size.block
},
};
let content_rect = LogicalRect {
@ -709,10 +703,10 @@ impl HoistedAbsolutelyPositionedBox {
absolutely_positioned_box.context.base_fragment_info(),
absolutely_positioned_box.context.style().clone(),
fragments,
content_rect,
content_rect.into(),
pbm.padding.into(),
pbm.border.into(),
margin,
margin.into(),
None, /* clearance */
// We do not set the baseline offset, because absolutely positioned
// elements are not inflow.
@ -740,22 +734,22 @@ impl HoistedAbsolutelyPositionedBox {
}
enum Anchor {
Start(Length),
End(Length),
Start(Au),
End(Au),
}
struct AxisResult {
anchor: Anchor,
size: LengthOrAuto,
margin_start: Length,
margin_end: Length,
size: AuOrAuto,
margin_start: Au,
margin_end: Au,
}
struct AbsoluteAxisSolver<'a> {
containing_size: Length,
padding_border_sum: Length,
computed_margin_start: LengthOrAuto,
computed_margin_end: LengthOrAuto,
containing_size: Au,
padding_border_sum: Au,
computed_margin_start: AuOrAuto,
computed_margin_end: AuOrAuto,
avoid_negative_margin_start: bool,
box_offsets: &'a AbsoluteBoxOffsets,
}
@ -772,78 +766,86 @@ impl<'a> AbsoluteAxisSolver<'a> {
/// * <https://drafts.csswg.org/css2/visudet.html#abs-replaced-height>
///
/// In the replaced case, `size` is never `Auto`.
fn solve_for_size(&self, computed_size: LengthOrAuto) -> AxisResult {
fn solve_for_size(&self, computed_size: AuOrAuto) -> AxisResult {
match self.box_offsets {
AbsoluteBoxOffsets::StaticStart { start } => AxisResult {
anchor: Anchor::Start(*start),
anchor: Anchor::Start((*start).into()),
size: computed_size,
margin_start: self.computed_margin_start.auto_is(Length::zero),
margin_end: self.computed_margin_end.auto_is(Length::zero),
margin_start: self.computed_margin_start.auto_is(Au::zero),
margin_end: self.computed_margin_end.auto_is(Au::zero),
},
AbsoluteBoxOffsets::Start { start } => AxisResult {
anchor: Anchor::Start(start.percentage_relative_to(self.containing_size)),
anchor: Anchor::Start(
start
.percentage_relative_to(self.containing_size.into())
.into(),
),
size: computed_size,
margin_start: self.computed_margin_start.auto_is(Length::zero),
margin_end: self.computed_margin_end.auto_is(Length::zero),
margin_start: self.computed_margin_start.auto_is(Au::zero),
margin_end: self.computed_margin_end.auto_is(Au::zero),
},
AbsoluteBoxOffsets::End { end } => AxisResult {
anchor: Anchor::End(end.percentage_relative_to(self.containing_size)),
anchor: Anchor::End(
end.percentage_relative_to(self.containing_size.into())
.into(),
),
size: computed_size,
margin_start: self.computed_margin_start.auto_is(Length::zero),
margin_end: self.computed_margin_end.auto_is(Length::zero),
margin_start: self.computed_margin_start.auto_is(Au::zero),
margin_end: self.computed_margin_end.auto_is(Au::zero),
},
AbsoluteBoxOffsets::Both { start, end } => {
let start = start.percentage_relative_to(self.containing_size);
let end = end.percentage_relative_to(self.containing_size);
let start = start.percentage_relative_to(self.containing_size.into());
let end = end.percentage_relative_to(self.containing_size.into());
let margin_start;
let margin_end;
let used_size;
if let LengthOrAuto::LengthPercentage(s) = computed_size {
if let AuOrAuto::LengthPercentage(s) = computed_size {
used_size = s;
let margins = self.containing_size - start - end - self.padding_border_sum - s;
let margins = self.containing_size -
start.into() -
end.into() -
self.padding_border_sum -
s;
match (self.computed_margin_start, self.computed_margin_end) {
(LengthOrAuto::Auto, LengthOrAuto::Auto) => {
if self.avoid_negative_margin_start && margins < Length::zero() {
margin_start = Length::zero();
(AuOrAuto::Auto, AuOrAuto::Auto) => {
if self.avoid_negative_margin_start && margins < Au::zero() {
margin_start = Au::zero();
margin_end = margins;
} else {
margin_start = margins / 2.;
margin_end = margins / 2.;
margin_start = margins / 2;
margin_end = margins - margin_start;
}
},
(LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => {
(AuOrAuto::Auto, AuOrAuto::LengthPercentage(end)) => {
margin_start = margins - end;
margin_end = end;
},
(LengthOrAuto::LengthPercentage(start), LengthOrAuto::Auto) => {
(AuOrAuto::LengthPercentage(start), AuOrAuto::Auto) => {
margin_start = start;
margin_end = margins - start;
},
(
LengthOrAuto::LengthPercentage(start),
LengthOrAuto::LengthPercentage(end),
) => {
(AuOrAuto::LengthPercentage(start), AuOrAuto::LengthPercentage(end)) => {
margin_start = start;
margin_end = end;
},
}
} else {
margin_start = self.computed_margin_start.auto_is(Length::zero);
margin_end = self.computed_margin_end.auto_is(Length::zero);
margin_start = self.computed_margin_start.auto_is(Au::zero);
margin_end = self.computed_margin_end.auto_is(Au::zero);
// This may be negative, but the caller will later effectively
// clamp it to min-inline-size or min-block-size.
used_size = self.containing_size -
start -
end -
start.into() -
end.into() -
self.padding_border_sum -
margin_start -
margin_end;
};
AxisResult {
anchor: Anchor::Start(start),
size: LengthOrAuto::LengthPercentage(used_size),
anchor: Anchor::Start(start.into()),
size: AuOrAuto::LengthPercentage(used_size),
margin_start,
margin_end,
}