From 0e35d70ca87d4f3ecb1ac3c21a28f3fdb0b8ad67 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 31 Mar 2020 17:33:37 +0200 Subject: [PATCH] Introduce a `PaddingBorderMargin` helper --- components/layout_2020/flow/inline.rs | 37 +++++----- components/layout_2020/flow/mod.rs | 97 +++++++++++---------------- components/layout_2020/positioned.rs | 39 +++++------ components/layout_2020/style_ext.rs | 30 ++++++++- 4 files changed, 101 insertions(+), 102 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 6588a6a31378..ef52fba6750a 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -421,13 +421,11 @@ impl InlineBox { ifc: &mut InlineFormattingContextState<'box_tree, '_, '_>, ) -> PartialInlineBoxFragment<'box_tree> { let style = self.style.clone(); - let cbis = ifc.containing_block.inline_size; - let mut padding = style.padding().percentages_relative_to(cbis); - let mut border = style.border_width(); - let mut margin = style - .margin() - .percentages_relative_to(cbis) - .auto_is(Length::zero); + let pbm = style.padding_border_margin(&ifc.containing_block); + let mut padding = pbm.padding; + let mut border = pbm.border; + let mut margin = pbm.margin.auto_is(Length::zero); + if self.first_fragment { ifc.inline_position += padding.inline_start + border.inline_start + margin.inline_start; } else { @@ -530,18 +528,14 @@ fn layout_atomic( ifc: &mut InlineFormattingContextState, atomic: &IndependentFormattingContext, ) { - let cbis = ifc.containing_block.inline_size; - let padding = atomic.style.padding().percentages_relative_to(cbis); - let border = atomic.style.border_width(); - let margin = atomic - .style - .margin() - .percentages_relative_to(cbis) - .auto_is(Length::zero); - let pbm = &(&padding + &border) + &margin; - ifc.inline_position += pbm.inline_start; + let pbm = atomic.style.padding_border_margin(&ifc.containing_block); + let padding = pbm.padding; + let border = pbm.border; + let margin = pbm.margin.auto_is(Length::zero); + let pbm_sums = &(&padding + &border) + &margin; + ifc.inline_position += pbm_sums.inline_start; let mut start_corner = Vec2 { - block: pbm.block_start, + block: pbm_sums.block_start, inline: ifc.inline_position - ifc.current_nesting_level.inline_start, }; if atomic.style.clone_position().is_relative() { @@ -577,9 +571,10 @@ fn layout_atomic( .auto_is(Length::zero); // https://drafts.csswg.org/css2/visudet.html#inlineblock-width + let cbis = ifc.containing_block.inline_size; let tentative_inline_size = box_size.inline.percentage_relative_to(cbis).auto_is(|| { - let available_size = cbis - pbm.inline_sum(); + let available_size = cbis - pbm_sums.inline_sum(); atomic.content_sizes.shrink_to_fit(available_size) }); @@ -641,10 +636,10 @@ fn layout_atomic( }, }; - ifc.inline_position += pbm.inline_end + fragment.content_rect.size.inline; + ifc.inline_position += pbm_sums.inline_end + fragment.content_rect.size.inline; ifc.current_nesting_level .max_block_size_of_fragments_so_far - .max_assign(pbm.block_sum() + fragment.content_rect.size.block); + .max_assign(pbm_sums.block_sum() + fragment.content_rect.size.block); ifc.current_nesting_level .fragments_so_far .push(Fragment::Box(fragment)); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 63e96eaef2ab..bd39a55cc53f 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -14,7 +14,7 @@ use crate::fragments::{CollapsedBlockMargins, CollapsedMargin, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::replaced::ReplacedContent; -use crate::style_ext::ComputedValuesExt; +use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; use crate::ContainingBlock; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; @@ -350,12 +350,7 @@ fn layout_in_flow_non_replaced_block_level( tree_rank: usize, float_context: Option<&mut FloatContext>, ) -> BoxFragment { - let cbis = containing_block.inline_size; - let padding = style.padding().percentages_relative_to(cbis); - let border = style.border_width(); - let margin = style.margin().percentages_relative_to(cbis); - let pb = &padding + &border; - let pb_inline_sum = pb.inline_sum(); + let pbm = style.padding_border_margin(containing_block); let box_size = style.box_size().percentages_relative_to(containing_block); let max_box_size = style @@ -368,22 +363,18 @@ fn layout_in_flow_non_replaced_block_level( // https://drafts.csswg.org/css2/visudet.html#min-max-widths let solve_inline_margins = |inline_size| { - solve_inline_margins_for_in_flow_block_level( - containing_block, - pb_inline_sum, - margin.inline_start, - margin.inline_end, - inline_size, - ) + solve_inline_margins_for_in_flow_block_level(containing_block, &pbm, inline_size) }; let (mut inline_size, mut inline_margins) = if let Some(inline_size) = box_size.inline.non_auto() { (inline_size, solve_inline_margins(inline_size)) } else { - let margin_inline_start = margin.inline_start.auto_is(Length::zero); - let margin_inline_end = margin.inline_end.auto_is(Length::zero); - let margin_inline_sum = margin_inline_start + margin_inline_end; - let inline_size = cbis - pb_inline_sum - margin_inline_sum; + let margin_inline_start = pbm.margin.inline_start.auto_is(Length::zero); + let margin_inline_end = pbm.margin.inline_end.auto_is(Length::zero); + let inline_size = containing_block.inline_size - + pbm.padding_border_sums.inline - + margin_inline_start - + margin_inline_end; (inline_size, (margin_inline_start, margin_inline_end)) }; if let Some(max_inline_size) = max_box_size.inline { @@ -400,8 +391,8 @@ fn layout_in_flow_non_replaced_block_level( let margin = Sides { inline_start: inline_margins.0, inline_end: inline_margins.1, - block_start: margin.block_start.auto_is(Length::zero), - block_end: margin.block_end.auto_is(Length::zero), + block_start: pbm.margin.block_start.auto_is(Length::zero), + block_end: pbm.margin.block_end.auto_is(Length::zero), }; // https://drafts.csswg.org/css2/visudet.html#min-max-heights @@ -427,8 +418,10 @@ fn layout_in_flow_non_replaced_block_level( let mut content_block_size; match block_level_kind { NonReplacedContents::SameFormattingContextBlock(contents) => { - let this_start_margin_can_collapse_with_children = pb.block_start == Length::zero(); - let this_end_margin_can_collapse_with_children = pb.block_end == Length::zero() && + let start_margin_can_collapse_with_children = pbm.padding.block_start == Length::zero() && + pbm.border.block_start == Length::zero(); + let end_margin_can_collapse_with_children = pbm.padding.block_end == Length::zero() && + pbm.border.block_end == Length::zero() && block_size == LengthOrAuto::Auto && min_box_size.block == Length::zero(); @@ -438,13 +431,13 @@ fn layout_in_flow_non_replaced_block_level( &containing_block_for_children, tree_rank, float_context, - CollapsibleWithParentStartMargin(this_start_margin_can_collapse_with_children), + CollapsibleWithParentStartMargin(start_margin_can_collapse_with_children), ); fragments = flow_layout.fragments; content_block_size = flow_layout.content_block_size; let mut collapsible_margins_in_children = flow_layout.collapsible_margins_in_children; - if this_start_margin_can_collapse_with_children { + if start_margin_can_collapse_with_children { block_margins_collapsed_with_children .start .adjoin_assign(&collapsible_margins_in_children.start); @@ -457,7 +450,7 @@ fn layout_in_flow_non_replaced_block_level( )); } } - if this_end_margin_can_collapse_with_children { + if end_margin_can_collapse_with_children { block_margins_collapsed_with_children .end .adjoin_assign(&collapsible_margins_in_children.end); @@ -465,8 +458,8 @@ fn layout_in_flow_non_replaced_block_level( content_block_size += collapsible_margins_in_children.end.solve(); } block_margins_collapsed_with_children.collapsed_through = - this_start_margin_can_collapse_with_children && - this_end_margin_can_collapse_with_children && + start_margin_can_collapse_with_children && + end_margin_can_collapse_with_children && collapsible_margins_in_children.collapsed_through; }, NonReplacedContents::EstablishesAnIndependentFormattingContext(non_replaced) => { @@ -485,8 +478,8 @@ fn layout_in_flow_non_replaced_block_level( }); let content_rect = Rect { start_corner: Vec2 { - block: pb.block_start, - inline: pb.inline_start + margin.inline_start, + block: pbm.padding.block_start + pbm.border.block_start, + inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start, }, size: Vec2 { block: block_size, @@ -498,8 +491,8 @@ fn layout_in_flow_non_replaced_block_level( style.clone(), fragments, content_rect, - padding, - border, + pbm.padding, + pbm.border, margin, block_margins_collapsed_with_children, ) @@ -514,32 +507,22 @@ fn layout_in_flow_replaced_block_level<'a>( style: &Arc, replaced: &ReplacedContent, ) -> BoxFragment { + let pbm = style.padding_border_margin(containing_block); let size = replaced.used_size_as_if_inline_element(containing_block, style); - let cbis = containing_block.inline_size; - let padding = style.padding().percentages_relative_to(cbis); - let border = style.border_width(); - let computed_margin = style.margin().percentages_relative_to(cbis); - let pb = &padding + &border; - - let (margin_inline_start, margin_inline_end) = solve_inline_margins_for_in_flow_block_level( - containing_block, - pb.inline_sum(), - computed_margin.inline_start, - computed_margin.inline_end, - size.inline, - ); + let (margin_inline_start, margin_inline_end) = + solve_inline_margins_for_in_flow_block_level(containing_block, &pbm, size.inline); let margin = Sides { inline_start: margin_inline_start, inline_end: margin_inline_end, - block_start: computed_margin.block_start.auto_is(Length::zero), - block_end: computed_margin.block_end.auto_is(Length::zero), + block_start: pbm.margin.block_start.auto_is(Length::zero), + block_end: pbm.margin.block_end.auto_is(Length::zero), }; let fragments = replaced.make_fragments(style, size.clone()); let content_rect = Rect { start_corner: Vec2 { - block: pb.block_start, - inline: pb.inline_start + margin.inline_start, + block: pbm.padding.block_start + pbm.border.block_start, + inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start, }, size, }; @@ -549,8 +532,8 @@ fn layout_in_flow_replaced_block_level<'a>( style.clone(), fragments, content_rect, - padding, - border, + pbm.padding, + pbm.border, margin, block_margins_collapsed_with_children, ) @@ -558,15 +541,13 @@ fn layout_in_flow_replaced_block_level<'a>( fn solve_inline_margins_for_in_flow_block_level( containing_block: &ContainingBlock, - padding_border_inline_sum: Length, - computed_margin_inline_start: LengthOrAuto, - computed_margin_inline_end: LengthOrAuto, + pbm: &PaddingBorderMargin, inline_size: Length, ) -> (Length, Length) { - let inline_margins = containing_block.inline_size - padding_border_inline_sum - inline_size; - match (computed_margin_inline_start, computed_margin_inline_end) { - (LengthOrAuto::Auto, LengthOrAuto::Auto) => (inline_margins / 2., inline_margins / 2.), - (LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => (inline_margins - end, end), - (LengthOrAuto::LengthPercentage(start), _) => (start, inline_margins - start), + let available = containing_block.inline_size - pbm.padding_border_sums.inline - inline_size; + match (pbm.margin.inline_start, pbm.margin.inline_end) { + (LengthOrAuto::Auto, LengthOrAuto::Auto) => (available / 2., available / 2.), + (LengthOrAuto::Auto, LengthOrAuto::LengthPercentage(end)) => (available - end, end), + (LengthOrAuto::LengthPercentage(start), _) => (start, available - start), } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 2ca2376726ab..993cf40786f3 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -405,9 +405,10 @@ impl HoistedAbsolutelyPositionedBox { for_nearest_containing_block_for_all_descendants: &mut Vec, containing_block: &DefiniteContainingBlock, ) -> BoxFragment { - let style = &self.absolutely_positioned_box.contents.style; let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; + let style = &self.absolutely_positioned_box.contents.style; + let pbm = style.padding_border_margin(&containing_block.into()); let size; let replaced_used_size; @@ -432,16 +433,11 @@ impl HoistedAbsolutelyPositionedBox { }, } - let padding = style.padding().percentages_relative_to(cbis); - let border = style.border_width(); - let computed_margin = style.margin().percentages_relative_to(cbis); - let pb = &padding + &border; - let inline_axis = solve_axis( cbis, - pb.inline_sum(), - computed_margin.inline_start.clone(), - computed_margin.inline_end.clone(), + pbm.padding_border_sums.inline, + pbm.margin.inline_start, + pbm.margin.inline_end, /* avoid_negative_margin_start */ true, self.box_offsets.inline.clone(), size.inline, @@ -449,9 +445,9 @@ impl HoistedAbsolutelyPositionedBox { let block_axis = solve_axis( cbis, - pb.block_sum(), - computed_margin.block_start.clone(), - computed_margin.block_end.clone(), + pbm.padding_border_sums.block, + pbm.margin.block_start, + pbm.margin.block_end, /* avoid_negative_margin_start */ false, self.box_offsets.block.clone(), size.block, @@ -483,14 +479,14 @@ impl HoistedAbsolutelyPositionedBox { // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-height let inline_size = inline_axis.size.auto_is(|| { - let available_size = match inline_axis.anchor { - Anchor::Start(start) => { - cbis - start - pb.inline_sum() - margin.inline_sum() - }, - Anchor::End(end) => { - cbis - end - pb.inline_sum() - margin.inline_sum() - }, + let anchor = match inline_axis.anchor { + Anchor::Start(start) => start, + Anchor::End(end) => end, }; + let available_size = cbis - + anchor - + pbm.padding_border_sums.inline - + margin.inline_sum(); self.absolutely_positioned_box .contents .content_sizes @@ -526,6 +522,7 @@ impl HoistedAbsolutelyPositionedBox { }, }; + let pb = &pbm.padding + &pbm.border; let inline_start = match inline_axis.anchor { Anchor::Start(start) => start + pb.inline_start + margin.inline_start, Anchor::End(end) => { @@ -550,8 +547,8 @@ impl HoistedAbsolutelyPositionedBox { style.clone(), fragments, content_rect, - padding, - border, + pbm.padding, + pbm.border, margin, CollapsedBlockMargins::zero(), ) diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index cdde69a7866a..60399f33f357 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -3,11 +3,12 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::geom::{flow_relative, PhysicalSides, PhysicalSize}; +use crate::ContainingBlock; use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; use style::computed_values::position::T as ComputedPosition; use style::computed_values::transform_style::T as ComputedTransformStyle; use style::properties::ComputedValues; -use style::values::computed::{Length, LengthPercentage, LengthPercentageOrAuto}; +use style::values::computed::{Length, LengthOrAuto, LengthPercentage, LengthPercentageOrAuto}; use style::values::computed::{NonNegativeLengthPercentage, Size}; use style::values::generics::box_::Perspective; use style::values::generics::length::MaxSize; @@ -43,6 +44,16 @@ pub(crate) enum DisplayInside { FlowRoot, } +/// Percentages resolved but not `auto` margins +pub(crate) struct PaddingBorderMargin { + pub padding: flow_relative::Sides, + pub border: flow_relative::Sides, + pub margin: flow_relative::Sides, + + /// Pre-computed sums in each axis + pub padding_border_sums: flow_relative::Vec2, +} + pub(crate) trait ComputedValuesExt { fn inline_size_is_length(&self) -> bool; fn inline_box_offsets_are_both_non_auto(&self) -> bool; @@ -50,6 +61,7 @@ pub(crate) trait ComputedValuesExt { fn box_size(&self) -> flow_relative::Vec2; fn min_box_size(&self) -> flow_relative::Vec2; fn max_box_size(&self) -> flow_relative::Vec2>; + fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin; fn padding(&self) -> flow_relative::Sides; fn border_width(&self) -> flow_relative::Sides; fn margin(&self) -> flow_relative::Sides; @@ -135,7 +147,21 @@ impl ComputedValuesExt for ComputedValues { ) } - #[inline] + fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin { + let cbis = containing_block.inline_size; + let padding = self.padding().percentages_relative_to(cbis); + let border = self.border_width(); + PaddingBorderMargin { + padding_border_sums: flow_relative::Vec2 { + inline: padding.inline_sum() + border.inline_sum(), + block: padding.block_sum() + border.block_sum(), + }, + padding, + border, + margin: self.margin().percentages_relative_to(cbis), + } + } + fn padding(&self) -> flow_relative::Sides { let padding = self.get_padding(); flow_relative::Sides::from_physical(