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

View file

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