diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index d827d11cf3e..bf7f9b44b98 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -70,6 +70,13 @@ impl LogicalVec2 { block: b.clone(), } } + + pub fn map(&self, f: impl Fn(&T) -> U) -> LogicalVec2 { + LogicalVec2 { + inline: f(&self.inline), + block: f(&self.block), + } + } } impl Add<&'_ LogicalVec2> for &'_ LogicalVec2 @@ -121,10 +128,7 @@ impl LogicalVec2 { impl LogicalVec2 { pub fn auto_is(&self, f: impl Fn() -> Length) -> LogicalVec2 { - 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> for LogicalVec2 { impl From> for LogicalRect { fn from(value: LogicalRect) -> 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> for LogicalRect { impl From> for LogicalRect { fn from(value: LogicalRect) -> 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(), } } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 2f5d12b0e07..b74e802d31d 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -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; 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, + content_size: LogicalVec2, fragments: Vec, } @@ -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> { /// * /// /// 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, }