diff options
-rw-r--r-- | components/layout_2020/construct_modern.rs | 17 | ||||
-rw-r--r-- | components/layout_2020/dom_traversal.rs | 10 | ||||
-rw-r--r-- | components/layout_2020/flexbox/layout.rs | 75 | ||||
-rw-r--r-- | components/layout_2020/flow/inline/mod.rs | 15 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 335 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 6 | ||||
-rw-r--r-- | components/layout_2020/formatting_contexts.rs | 215 | ||||
-rw-r--r-- | components/layout_2020/layout_box_base.rs | 61 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 1 | ||||
-rw-r--r-- | components/layout_2020/lists.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 34 | ||||
-rw-r--r-- | components/layout_2020/replaced.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/table/construct.rs | 41 | ||||
-rw-r--r-- | components/layout_2020/table/layout.rs | 6 | ||||
-rw-r--r-- | components/layout_2020/table/mod.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/taffy/layout.rs | 34 |
16 files changed, 423 insertions, 439 deletions
diff --git a/components/layout_2020/construct_modern.rs b/components/layout_2020/construct_modern.rs index 5ff9aa08216..713954a39c8 100644 --- a/components/layout_2020/construct_modern.rs +++ b/components/layout_2020/construct_modern.rs @@ -15,9 +15,10 @@ use crate::dom_traversal::{Contents, NodeAndStyleInfo, TraversalHandler}; use crate::flow::inline::construct::InlineFormattingContextBuilder; use crate::flow::{BlockContainer, BlockFormattingContext}; use crate::formatting_contexts::{ - IndependentFormattingContext, NonReplacedFormattingContext, - NonReplacedFormattingContextContents, + IndependentFormattingContext, IndependentFormattingContextContents, + IndependentNonReplacedContents, }; +use crate::layout_box_base::LayoutBoxBase; use crate::style_ext::DisplayGeneratingBox; /// <https://drafts.csswg.org/css-flexbox/#flex-items> @@ -173,16 +174,12 @@ where BlockContainer::InlineFormattingContext(inline_formatting_context), ); let info = &self.info.new_anonymous(anonymous_style.clone().unwrap()); - let non_replaced = NonReplacedFormattingContext { - base_fragment_info: info.into(), - style: info.style.clone(), - content_sizes_result: Default::default(), - contents: NonReplacedFormattingContextContents::Flow( - block_formatting_context, + let formatting_context = IndependentFormattingContext { + base: LayoutBoxBase::new(info.into(), info.style.clone()), + contents: IndependentFormattingContextContents::NonReplaced( + IndependentNonReplacedContents::Flow(block_formatting_context), ), }; - let formatting_context = - IndependentFormattingContext::NonReplaced(non_replaced); Some(ModernItem { kind: ModernItemKind::InFlow, diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index c6a920aa060..2c532e2ebc4 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -16,7 +16,7 @@ use style::values::generics::counters::{Content, ContentItem}; use crate::context::LayoutContext; use crate::dom::{BoxSlot, LayoutBox, NodeExt}; use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags, Tag}; -use crate::replaced::ReplacedContent; +use crate::replaced::ReplacedContents; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOutside}; #[derive(Clone, Copy, Debug)] @@ -126,7 +126,7 @@ pub(super) enum Contents { NonReplaced(NonReplacedContents), /// Example: an `<img src=…>` element. /// <https://drafts.csswg.org/css2/conform.html#replaced-element> - Replaced(ReplacedContent), + Replaced(ReplacedContents), } #[derive(Debug)] @@ -141,7 +141,7 @@ pub(super) enum NonReplacedContents { #[derive(Debug)] pub(super) enum PseudoElementContentItem { Text(String), - Replaced(ReplacedContent), + Replaced(ReplacedContents), } pub(super) trait TraversalHandler<'dom, Node> @@ -216,7 +216,7 @@ fn traverse_element<'dom, Node>( ) where Node: NodeExt<'dom>, { - let replaced = ReplacedContent::for_element(element, context); + let replaced = ReplacedContents::for_element(element, context); let style = element.style(context); match Display::from(style.get_box().display) { Display::None => element.unset_all_boxes(), @@ -421,7 +421,7 @@ where }, ContentItem::Image(image) => { if let Some(replaced_content) = - ReplacedContent::from_image(element, context, image) + ReplacedContents::from_image(element, context, image) { vec.push(PseudoElementContentItem::Replaced(replaced_content)); } diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 0848c3ab2f0..2acdc862de4 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -30,7 +30,9 @@ use super::{ }; use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout}; +use crate::formatting_contexts::{ + Baselines, IndependentFormattingContextContents, IndependentLayout, +}; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags}; use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, Size}; use crate::positioned::{ @@ -1893,8 +1895,8 @@ impl FlexItem<'_> { }), }; - let context = &self.box_.independent_formatting_context; - let item_writing_mode = context.style().writing_mode; + let independent_formatting_context = &self.box_.independent_formatting_context; + let item_writing_mode = independent_formatting_context.style().writing_mode; let item_is_horizontal = item_writing_mode.is_horizontal(); let flex_axis = flex_context.config.flex_axis; let cross_axis_is_item_block_axis = cross_axis_is_item_block_axis( @@ -1922,7 +1924,7 @@ impl FlexItem<'_> { item_writing_mode, self.preferred_aspect_ratio, ); - context + independent_formatting_context .inline_content_sizes(flex_context.layout_context, &constraint_space) .sizes .shrink_to_fit(stretch_size) @@ -1945,26 +1947,25 @@ impl FlexItem<'_> { }; let container_writing_mode = containing_block.style.writing_mode; - match context { - IndependentFormattingContext::Replaced(replaced) => { - let size = replaced - .contents - .used_size_as_if_inline_element_from_content_box_sizes( - containing_block, - &replaced.style, - self.preferred_aspect_ratio, - LogicalVec2 { - inline: Size::Numeric(inline_size), - block: block_size.non_auto().map_or(Size::Initial, Size::Numeric), - }, - flex_axis - .vec2_to_flow_relative(self.content_min_size) - .map(|size| Size::Numeric(*size)), - flex_axis - .vec2_to_flow_relative(self.content_max_size) - .map(|size| size.map_or(Size::Initial, Size::Numeric)), - flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero), - ); + let item_style = independent_formatting_context.style(); + match &independent_formatting_context.contents { + IndependentFormattingContextContents::Replaced(replaced) => { + let size = replaced.used_size_as_if_inline_element_from_content_box_sizes( + containing_block, + item_style, + self.preferred_aspect_ratio, + LogicalVec2 { + inline: Size::Numeric(inline_size), + block: block_size.non_auto().map_or(Size::Initial, Size::Numeric), + }, + flex_axis + .vec2_to_flow_relative(self.content_min_size) + .map(|size| Size::Numeric(*size)), + flex_axis + .vec2_to_flow_relative(self.content_max_size) + .map(|size| size.map_or(Size::Initial, Size::Numeric)), + flex_axis.vec2_to_flow_relative(self.pbm_auto_is_zero), + ); let hypothetical_cross_size = flex_axis.vec2_to_flex_relative(size).cross; if let Some(non_stretch_layout_result) = non_stretch_layout_result { @@ -1979,10 +1980,8 @@ impl FlexItem<'_> { } } - let fragments = replaced.contents.make_fragments( - &replaced.style, - size.to_physical_size(container_writing_mode), - ); + let fragments = replaced + .make_fragments(item_style, size.to_physical_size(container_writing_mode)); Some(FlexItemLayoutResult { hypothetical_cross_size, @@ -2000,7 +1999,7 @@ impl FlexItem<'_> { baseline_relative_to_margin_box: None, }) }, - IndependentFormattingContext::NonReplaced(non_replaced) => { + IndependentFormattingContextContents::NonReplaced(non_replaced) => { let calculate_hypothetical_cross_size = |content_block_size| { self.content_box_size .cross @@ -2020,7 +2019,7 @@ impl FlexItem<'_> { let item_as_containing_block = ContainingBlock { inline_size, block_size, - style: &non_replaced.style, + style: item_style, }; if let Some(non_stretch_layout_result) = non_stretch_layout_result { @@ -2067,7 +2066,7 @@ impl FlexItem<'_> { let item_writing_mode_is_orthogonal_to_container_writing_mode = flex_context.config.writing_mode.is_horizontal() != - non_replaced.style.writing_mode.is_horizontal(); + item_style.writing_mode.is_horizontal(); let has_compatible_baseline = match flex_axis { FlexAxis::Row => !item_writing_mode_is_orthogonal_to_container_writing_mode, FlexAxis::Column => item_writing_mode_is_orthogonal_to_container_writing_mode, @@ -2752,8 +2751,9 @@ impl FlexItemBox { .collects_for_nearest_positioned_ancestor(), ); - match &self.independent_formatting_context { - IndependentFormattingContext::Replaced(replaced) => { + let style = self.independent_formatting_context.style(); + match &self.independent_formatting_context.contents { + IndependentFormattingContextContents::Replaced(replaced) => { content_box_size.inline = content_box_size.inline.map(|v| v.max(Au::zero())); if intrinsic_sizing_mode == IntrinsicSizingMode::Size { content_box_size.block = AuOrAuto::Auto; @@ -2761,10 +2761,9 @@ impl FlexItemBox { max_size.block = None; } replaced - .contents .used_size_as_if_inline_element_from_content_box_sizes( flex_context.containing_block, - &replaced.style, + style, preferred_aspect_ratio, content_box_size .map(|size| size.non_auto().map_or(Size::Initial, Size::Numeric)), @@ -2775,7 +2774,7 @@ impl FlexItemBox { ) .block }, - IndependentFormattingContext::NonReplaced(non_replaced) => { + IndependentFormattingContextContents::NonReplaced(non_replaced) => { // TODO: This is wrong if the item writing mode is different from the flex // container's writing mode. let inline_size = content_box_size @@ -2792,7 +2791,7 @@ impl FlexItemBox { } else { let constraint_space = ConstraintSpace::new( SizeConstraint::default(), - non_replaced.style.writing_mode, + style.writing_mode, non_replaced.preferred_aspect_ratio(), ); non_replaced @@ -2808,7 +2807,7 @@ impl FlexItemBox { let item_as_containing_block = ContainingBlock { inline_size, block_size: AuOrAuto::Auto, - style: &non_replaced.style, + style, }; let content_block_size = || { if let Some(cache) = &*self.block_content_size_cache.borrow() { diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index d48f765a55c..a23abcd5d89 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -111,13 +111,14 @@ use webrender_api::FontInstanceKey; use xi_unicode::linebreak_property; use super::float::{Clear, PlacementAmongFloats}; +use super::IndependentFormattingContextContents; use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::flow::float::{FloatBox, SequentialLayoutState}; use crate::flow::{CollapsibleWithParentStartMargin, FlowLayout}; use crate::formatting_contexts::{ Baselines, IndependentFormattingContext, IndependentLayoutResult, - NonReplacedFormattingContextContents, + IndependentNonReplacedContents, }; use crate::fragment_tree::{ BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, @@ -2034,13 +2035,11 @@ impl IndependentFormattingContext { match self.style().clone_baseline_source() { BaselineSource::First => baselines.first, BaselineSource::Last => baselines.last, - BaselineSource::Auto => { - if let Self::NonReplaced(non_replaced) = self { - if let NonReplacedFormattingContextContents::Flow(_) = non_replaced.contents { - return baselines.last; - } - } - baselines.first + BaselineSource::Auto => match &self.contents { + IndependentFormattingContextContents::NonReplaced( + IndependentNonReplacedContents::Flow(_), + ) => baselines.last, + _ => baselines.first, }, } } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 46ccf221b41..4f76a39b6eb 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -27,8 +27,8 @@ use crate::flow::float::{ SequentialLayoutState, }; use crate::formatting_contexts::{ - Baselines, IndependentFormattingContext, IndependentLayout, IndependentLayoutResult, - NonReplacedFormattingContext, + Baselines, IndependentFormattingContext, IndependentFormattingContextContents, + IndependentLayout, IndependentLayoutResult, IndependentNonReplacedContents, }; use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, @@ -37,8 +37,9 @@ use crate::geom::{ AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, Size, ToLogical, ToLogicalWithContainingBlock, }; +use crate::layout_box_base::LayoutBoxBase; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; -use crate::replaced::ReplacedContent; +use crate::replaced::ReplacedContents; use crate::sizing::{self, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ Clamp, ComputedValuesExt, ContentBoxSizesAndPBMDeprecated, PaddingBorderMargin, @@ -714,38 +715,20 @@ impl BlockLevelBox { ) }, )), - BlockLevelBox::Independent(independent) => match independent { - IndependentFormattingContext::Replaced(replaced) => { - Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( - layout_context, - containing_block, - &replaced.style, - |_positioning_context| { - layout_in_flow_replaced_block_level( - containing_block, - replaced.base_fragment_info, - &replaced.style, - &replaced.contents, - sequential_layout_state, - ) - }, - )) - }, - IndependentFormattingContext::NonReplaced(non_replaced) => { - Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( - layout_context, - containing_block, - &non_replaced.style, - |positioning_context| { - non_replaced.layout_in_flow_block_level( - layout_context, - positioning_context, - containing_block, - sequential_layout_state, - ) - }, - )) - }, + BlockLevelBox::Independent(independent) => { + Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( + layout_context, + containing_block, + independent.style(), + |positioning_context| { + independent.layout_in_flow_block_level( + layout_context, + positioning_context, + containing_block, + sequential_layout_state, + ) + }, + )) }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { // The static position of zero here is incorrect, however we do not know @@ -1006,7 +989,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context( .with_baselines(flow_layout.baselines) } -impl NonReplacedFormattingContext { +impl IndependentNonReplacedContents { /// Lay out a normal in flow non-replaced block that establishes an independent /// formatting context in its containing formatting context. /// @@ -1014,6 +997,7 @@ impl NonReplacedFormattingContext { /// - <https://drafts.csswg.org/css2/visudet.html#normal-block> pub(crate) fn layout_in_flow_block_level( &self, + base: &LayoutBoxBase, layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, @@ -1021,6 +1005,7 @@ impl NonReplacedFormattingContext { ) -> BoxFragment { if let Some(sequential_layout_state) = sequential_layout_state { return self.layout_in_flow_block_level_sequentially( + base, layout_context, positioning_context, containing_block, @@ -1037,7 +1022,7 @@ impl NonReplacedFormattingContext { depends_on_block_constraints, } = solve_containing_block_padding_and_border_for_in_flow_box( containing_block, - &self.style, + &base.style, ); let layout = self.layout( @@ -1079,7 +1064,7 @@ impl NonReplacedFormattingContext { let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin); let containing_block_writing_mode = containing_block.style.writing_mode; - let mut base_fragment_info = self.base_fragment_info; + let mut base_fragment_info = base.base_fragment_info; if depends_on_block_constraints { base_fragment_info.flags.insert( FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM, @@ -1087,7 +1072,7 @@ impl NonReplacedFormattingContext { } BoxFragment::new( base_fragment_info, - self.style.clone(), + base.style.clone(), layout.fragments, content_rect.to_physical(Some(containing_block)), pbm.padding.to_physical(containing_block_writing_mode), @@ -1104,6 +1089,7 @@ impl NonReplacedFormattingContext { /// layout concerns, such clearing and placing the content next to floats. fn layout_in_flow_block_level_sequentially( &self, + base: &LayoutBoxBase, layout_context: &LayoutContext<'_>, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock<'_>, @@ -1116,7 +1102,7 @@ impl NonReplacedFormattingContext { content_max_box_size, pbm, depends_on_block_constraints, - } = self + } = base .style .content_box_sizes_and_padding_border_margin(&containing_block.into()) .into(); @@ -1147,6 +1133,7 @@ impl NonReplacedFormattingContext { let clearance; let mut content_size; let mut layout; + let style = &base.style; if let AuOrAuto::LengthPercentage(ref inline_size) = content_box_size.inline { let inline_size = inline_size .clamp_between_extremums(content_min_box_size.inline, content_max_box_size.inline); @@ -1156,7 +1143,7 @@ impl NonReplacedFormattingContext { &ContainingBlock { inline_size, block_size, - style: &self.style, + style, }, containing_block, ); @@ -1188,17 +1175,14 @@ impl NonReplacedFormattingContext { containing_block, &pbm, content_size + pbm.padding_border_sums, - &self.style, + style, ); } else { // First compute the clear position required by the 'clear' property. // The code below may then add extra clearance when the element can't fit // next to floats not covered by 'clear'. let clear_position = sequential_layout_state.calculate_clear_position( - Clear::from_style_and_container_writing_mode( - &self.style, - containing_block_writing_mode, - ), + Clear::from_style_and_container_writing_mode(style, containing_block_writing_mode), &collapsed_margin_block_start, ); let ceiling = clear_position.unwrap_or_else(|| { @@ -1238,7 +1222,7 @@ impl NonReplacedFormattingContext { &ContainingBlock { inline_size: proposed_inline_size, block_size, - style: &self.style, + style, }, containing_block, ); @@ -1347,7 +1331,7 @@ impl NonReplacedFormattingContext { size: content_size, }; - let mut base_fragment_info = self.base_fragment_info; + let mut base_fragment_info = base.base_fragment_info; if depends_on_block_constraints { base_fragment_info.flags.insert( FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM, @@ -1356,7 +1340,7 @@ impl NonReplacedFormattingContext { BoxFragment::new( base_fragment_info, - self.style.clone(), + style.clone(), layout.fragments, content_rect.to_physical(Some(containing_block)), pbm.padding.to_physical(containing_block_writing_mode), @@ -1369,121 +1353,127 @@ impl NonReplacedFormattingContext { } } -/// <https://drafts.csswg.org/css2/visudet.html#block-replaced-width> -/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width> -/// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height> -fn layout_in_flow_replaced_block_level( - containing_block: &ContainingBlock, - mut base_fragment_info: BaseFragmentInfo, - style: &Arc<ComputedValues>, - replaced: &ReplacedContent, - mut sequential_layout_state: Option<&mut SequentialLayoutState>, -) -> BoxFragment { - let content_box_sizes_and_pbm = - style.content_box_sizes_and_padding_border_margin(&containing_block.into()); - let pbm = &content_box_sizes_and_pbm.pbm; - let content_size = replaced.used_size_as_if_inline_element( - containing_block, - style, - &content_box_sizes_and_pbm, - ); +impl ReplacedContents { + /// <https://drafts.csswg.org/css2/visudet.html#block-replaced-width> + /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-width> + /// <https://drafts.csswg.org/css2/visudet.html#inline-replaced-height> + fn layout_in_flow_block_level( + &self, + base: &LayoutBoxBase, + containing_block: &ContainingBlock, + mut sequential_layout_state: Option<&mut SequentialLayoutState>, + ) -> BoxFragment { + let content_box_sizes_and_pbm = base + .style + .content_box_sizes_and_padding_border_margin(&containing_block.into()); + let pbm = &content_box_sizes_and_pbm.pbm; + let content_size = self.used_size_as_if_inline_element( + containing_block, + &base.style, + &content_box_sizes_and_pbm, + ); - let margin_inline_start; - let margin_inline_end; - let effective_margin_inline_start; - let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(pbm); + let margin_inline_start; + let margin_inline_end; + let effective_margin_inline_start; + let (margin_block_start, margin_block_end) = + solve_block_margins_for_in_flow_block_level(pbm); - let containing_block_writing_mode = containing_block.style.writing_mode; - let physical_content_size = content_size.to_physical_size(containing_block_writing_mode); - let fragments = replaced.make_fragments(style, physical_content_size); + let containing_block_writing_mode = containing_block.style.writing_mode; + let physical_content_size = content_size.to_physical_size(containing_block_writing_mode); + let fragments = self.make_fragments(&base.style, physical_content_size); - let clearance; - if let Some(ref mut sequential_layout_state) = sequential_layout_state { - // From https://drafts.csswg.org/css2/#floats: - // "The border box of a table, a block-level replaced element, or an element in - // the normal flow that establishes a new block formatting context (such as an - // element with overflow other than visible) must not overlap the margin box of - // any floats in the same block formatting context as the element itself. If - // necessary, implementations should clear the said element by placing it below - // any preceding floats, but may place it adjacent to such floats if there is - // sufficient space. They may even make the border box of said element narrower - // than defined by section 10.3.3. CSS 2 does not define when a UA may put said - // element next to the float or by how much said element may become narrower." - let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start); - let size = content_size + pbm.padding_border_sums; - ( - clearance, - (margin_inline_start, margin_inline_end), - effective_margin_inline_start, - ) = solve_clearance_and_inline_margins_avoiding_floats( - sequential_layout_state, - &collapsed_margin_block_start, - containing_block, - pbm, - size, - style, - ); + let clearance; + if let Some(ref mut sequential_layout_state) = sequential_layout_state { + // From https://drafts.csswg.org/css2/#floats: + // "The border box of a table, a block-level replaced element, or an element in + // the normal flow that establishes a new block formatting context (such as an + // element with overflow other than visible) must not overlap the margin box of + // any floats in the same block formatting context as the element itself. If + // necessary, implementations should clear the said element by placing it below + // any preceding floats, but may place it adjacent to such floats if there is + // sufficient space. They may even make the border box of said element narrower + // than defined by section 10.3.3. CSS 2 does not define when a UA may put said + // element next to the float or by how much said element may become narrower." + let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start); + let size = content_size + pbm.padding_border_sums; + ( + clearance, + (margin_inline_start, margin_inline_end), + effective_margin_inline_start, + ) = solve_clearance_and_inline_margins_avoiding_floats( + sequential_layout_state, + &collapsed_margin_block_start, + containing_block, + pbm, + size, + &base.style, + ); - // Clearance prevents margin collapse between this block and previous ones, - // so in that case collapse margins before adjoining them below. - if clearance.is_some() { + // Clearance prevents margin collapse between this block and previous ones, + // so in that case collapse margins before adjoining them below. + if clearance.is_some() { + sequential_layout_state.collapse_margins(); + } + sequential_layout_state.adjoin_assign(&collapsed_margin_block_start); + + // Margins can never collapse into replaced elements. sequential_layout_state.collapse_margins(); - } - sequential_layout_state.adjoin_assign(&collapsed_margin_block_start); + sequential_layout_state + .advance_block_position(size.block + clearance.unwrap_or_else(Au::zero)); + sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin_block_end)); + } else { + clearance = None; + ( + (margin_inline_start, margin_inline_end), + effective_margin_inline_start, + ) = solve_inline_margins_for_in_flow_block_level( + containing_block, + pbm, + content_size.inline, + ); + }; - // Margins can never collapse into replaced elements. - sequential_layout_state.collapse_margins(); - sequential_layout_state - .advance_block_position(size.block + clearance.unwrap_or_else(Au::zero)); - sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin_block_end)); - } else { - clearance = None; - ( - (margin_inline_start, margin_inline_end), - effective_margin_inline_start, - ) = solve_inline_margins_for_in_flow_block_level( - containing_block, - pbm, - content_size.inline, - ); - }; + let margin = LogicalSides { + inline_start: margin_inline_start, + inline_end: margin_inline_end, + block_start: margin_block_start, + block_end: margin_block_end, + }; - let margin = LogicalSides { - inline_start: margin_inline_start, - inline_end: margin_inline_end, - block_start: margin_block_start, - block_end: margin_block_end, - }; + let start_corner = LogicalVec2 { + block: pbm.padding.block_start + + pbm.border.block_start + + clearance.unwrap_or_else(Au::zero), + inline: pbm.padding.inline_start + + pbm.border.inline_start + + effective_margin_inline_start, + }; + let content_rect = LogicalRect { + start_corner, + size: content_size, + } + .to_physical(Some(containing_block)); - let start_corner = LogicalVec2 { - block: pbm.padding.block_start + - pbm.border.block_start + - clearance.unwrap_or_else(Au::zero), - inline: pbm.padding.inline_start + pbm.border.inline_start + effective_margin_inline_start, - }; - let content_rect = LogicalRect { - start_corner, - size: content_size, - } - .to_physical(Some(containing_block)); + let mut base_fragment_info = base.base_fragment_info; + if content_box_sizes_and_pbm.depends_on_block_constraints { + base_fragment_info.flags.insert( + FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM, + ); + } - if content_box_sizes_and_pbm.depends_on_block_constraints { - base_fragment_info - .flags - .insert(FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM); + BoxFragment::new( + base_fragment_info, + base.style.clone(), + fragments, + content_rect, + pbm.padding.to_physical(containing_block_writing_mode), + pbm.border.to_physical(containing_block_writing_mode), + margin.to_physical(containing_block_writing_mode), + clearance, + CollapsedBlockMargins::from_margin(&margin), + ) } - - BoxFragment::new( - base_fragment_info, - style.clone(), - fragments, - content_rect, - pbm.padding.to_physical(containing_block_writing_mode), - pbm.border.to_physical(containing_block_writing_mode), - margin.to_physical(containing_block_writing_mode), - clearance, - CollapsedBlockMargins::from_margin(&margin), - ) } struct ContainingBlockPaddingAndBorder<'a> { @@ -2017,6 +2007,26 @@ fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &Containi } impl IndependentFormattingContext { + pub(crate) fn layout_in_flow_block_level( + &self, + layout_context: &LayoutContext, + positioning_context: &mut PositioningContext, + containing_block: &ContainingBlock, + sequential_layout_state: Option<&mut SequentialLayoutState>, + ) -> BoxFragment { + match &self.contents { + IndependentFormattingContextContents::NonReplaced(contents) => contents + .layout_in_flow_block_level( + &self.base, + layout_context, + positioning_context, + containing_block, + sequential_layout_state, + ), + IndependentFormattingContextContents::Replaced(contents) => contents + .layout_in_flow_block_level(&self.base, containing_block, sequential_layout_state), + } + } pub(crate) fn layout_float_or_atomic_inline( &self, layout_context: &LayoutContext, @@ -2031,27 +2041,24 @@ impl IndependentFormattingContext { let margin = pbm.margin.auto_is(Au::zero); let pbm_sums = pbm.padding + pbm.border + margin; - let (fragments, content_rect, baselines) = match self { - IndependentFormattingContext::Replaced(replaced) => { + let (fragments, content_rect, baselines) = match &self.contents { + IndependentFormattingContextContents::Replaced(replaced) => { // https://drafts.csswg.org/css2/visudet.html#float-replaced-width // https://drafts.csswg.org/css2/visudet.html#inline-replaced-height let content_size = replaced - .contents .used_size_as_if_inline_element( containing_block, - &replaced.style, + style, &content_box_sizes_and_pbm, ) .to_physical_size(container_writing_mode); - let fragments = replaced - .contents - .make_fragments(&replaced.style, content_size); + let fragments = replaced.make_fragments(style, content_size); let content_rect = PhysicalRect::new(PhysicalPoint::zero(), content_size); (fragments, content_rect, None) }, - IndependentFormattingContext::NonReplaced(non_replaced) => { - let writing_mode = non_replaced.style.writing_mode; + IndependentFormattingContextContents::NonReplaced(non_replaced) => { + let writing_mode = self.style().writing_mode; let available_inline_size = (containing_block.inline_size - pbm_sums.inline_sum()).max(Au::zero()); let available_block_size = containing_block @@ -2110,7 +2117,7 @@ impl IndependentFormattingContext { let containing_block_for_children = ContainingBlock { inline_size, block_size: tentative_block_size.to_auto_or(), - style: &non_replaced.style, + style: self.style(), }; assert_eq!( container_writing_mode.is_horizontal(), diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index b1c62416ecc..f9828e2308a 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -28,7 +28,7 @@ use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::FragmentTree; use crate::geom::{LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSize}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; -use crate::replaced::ReplacedContent; +use crate::replaced::ReplacedContents; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayInside}; use crate::taffy::{TaffyItemBox, TaffyItemBoxInner}; use crate::DefiniteContainingBlock; @@ -222,7 +222,7 @@ impl BoxTree { loop { if let Some((primary_style, display_inside, update_point)) = update_point(dirty_node) { - let contents = ReplacedContent::for_element(dirty_node, context) + let contents = ReplacedContents::for_element(dirty_node, context) .map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced); let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style)); let out_of_flow_absolutely_positioned_box = ArcRefCell::new( @@ -290,7 +290,7 @@ fn construct_for_root_element<'dom>( Display::GeneratingBox(display_generating_box) => display_generating_box.display_inside(), }; - let contents = ReplacedContent::for_element(root_element, context) + let contents = ReplacedContents::for_element(root_element, context) .map_or_else(|| NonReplacedContents::OfElement.into(), Contents::Replaced); let root_box = if box_style.position.is_absolutely_positioned() { BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new( diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 8e22ef33122..d1bc21448a1 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -3,7 +3,6 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use app_units::Au; -use atomic_refcell::AtomicRefCell; use serde::Serialize; use servo_arc::Arc; use style::properties::ComputedValues; @@ -17,46 +16,32 @@ use crate::flexbox::FlexContainer; use crate::flow::BlockFormattingContext; use crate::fragment_tree::{BaseFragmentInfo, BoxFragment, Fragment, FragmentFlags}; use crate::geom::LogicalSides; +use crate::layout_box_base::LayoutBoxBase; use crate::positioned::PositioningContext; -use crate::replaced::ReplacedContent; +use crate::replaced::ReplacedContents; use crate::sizing::{self, InlineContentSizesResult}; use crate::style_ext::{AspectRatio, DisplayInside}; use crate::table::Table; use crate::taffy::TaffyContainer; -use crate::{ - ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2, SizeConstraint, -}; +use crate::{ConstraintSpace, ContainingBlock, IndefiniteContainingBlock, LogicalVec2}; /// <https://drafts.csswg.org/css-display/#independent-formatting-context> #[derive(Debug, Serialize)] -pub(crate) enum IndependentFormattingContext { - NonReplaced(NonReplacedFormattingContext), - Replaced(ReplacedFormattingContext), +pub(crate) struct IndependentFormattingContext { + pub base: LayoutBoxBase, + pub contents: IndependentFormattingContextContents, } #[derive(Debug, Serialize)] -pub(crate) struct NonReplacedFormattingContext { - pub base_fragment_info: BaseFragmentInfo, - #[serde(skip_serializing)] - pub style: Arc<ComputedValues>, - /// If it was requested during construction - #[serde(skip_serializing)] - pub content_sizes_result: AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>, - pub contents: NonReplacedFormattingContextContents, -} - -#[derive(Debug, Serialize)] -pub(crate) struct ReplacedFormattingContext { - pub base_fragment_info: BaseFragmentInfo, - #[serde(skip_serializing)] - pub style: Arc<ComputedValues>, - pub contents: ReplacedContent, +pub(crate) enum IndependentFormattingContextContents { + NonReplaced(IndependentNonReplacedContents), + Replaced(ReplacedContents), } // Private so that code outside of this module cannot match variants. // It should got through methods instead. #[derive(Debug, Serialize)] -pub(crate) enum NonReplacedFormattingContextContents { +pub(crate) enum IndependentNonReplacedContents { Flow(BlockFormattingContext), Flex(FlexContainer), Grid(TaffyContainer), @@ -115,24 +100,23 @@ impl IndependentFormattingContext { contents: Contents, propagated_text_decoration_line: TextDecorationLine, ) -> Self { + let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into(); + match contents { Contents::NonReplaced(non_replaced_contents) => { - let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into(); let contents = match display_inside { DisplayInside::Flow { is_list_item } | DisplayInside::FlowRoot { is_list_item } => { - NonReplacedFormattingContextContents::Flow( - BlockFormattingContext::construct( - context, - node_and_style_info, - non_replaced_contents, - propagated_text_decoration_line, - is_list_item, - ), - ) + IndependentNonReplacedContents::Flow(BlockFormattingContext::construct( + context, + node_and_style_info, + non_replaced_contents, + propagated_text_decoration_line, + is_list_item, + )) }, DisplayInside::Grid => { - NonReplacedFormattingContextContents::Grid(TaffyContainer::construct( + IndependentNonReplacedContents::Grid(TaffyContainer::construct( context, node_and_style_info, non_replaced_contents, @@ -140,7 +124,7 @@ impl IndependentFormattingContext { )) }, DisplayInside::Flex => { - NonReplacedFormattingContextContents::Flex(FlexContainer::construct( + IndependentNonReplacedContents::Flex(FlexContainer::construct( context, node_and_style_info, non_replaced_contents, @@ -157,7 +141,7 @@ impl IndependentFormattingContext { &node_and_style_info.style, ); base_fragment_info.flags.insert(FragmentFlags::DO_NOT_PAINT); - NonReplacedFormattingContextContents::Table(Table::construct( + IndependentNonReplacedContents::Table(Table::construct( context, node_and_style_info, table_grid_style, @@ -166,41 +150,36 @@ impl IndependentFormattingContext { )) }, }; - Self::NonReplaced(NonReplacedFormattingContext { - style: Arc::clone(&node_and_style_info.style), - base_fragment_info, - content_sizes_result: AtomicRefCell::default(), - contents, - }) + Self { + base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()), + contents: IndependentFormattingContextContents::NonReplaced(contents), + } }, Contents::Replaced(contents) => { - let mut base_fragment_info: BaseFragmentInfo = node_and_style_info.into(); base_fragment_info.flags.insert(FragmentFlags::IS_REPLACED); - Self::Replaced(ReplacedFormattingContext { - base_fragment_info, - style: Arc::clone(&node_and_style_info.style), - contents, - }) + Self { + base: LayoutBoxBase::new(base_fragment_info, node_and_style_info.style.clone()), + contents: IndependentFormattingContextContents::Replaced(contents), + } }, } } pub fn is_replaced(&self) -> bool { - matches!(self, Self::Replaced(_)) + matches!( + self.contents, + IndependentFormattingContextContents::Replaced(_) + ) } + #[inline] pub fn style(&self) -> &Arc<ComputedValues> { - match self { - Self::NonReplaced(inner) => &inner.style, - Self::Replaced(inner) => &inner.style, - } + &self.base.style } + #[inline] pub fn base_fragment_info(&self) -> BaseFragmentInfo { - match self { - Self::NonReplaced(inner) => inner.base_fragment_info, - Self::Replaced(inner) => inner.base_fragment_info, - } + self.base.base_fragment_info } pub(crate) fn inline_content_sizes( @@ -208,14 +187,15 @@ impl IndependentFormattingContext { layout_context: &LayoutContext, constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { - match self { - Self::NonReplaced(inner) => { - inner.inline_content_sizes(layout_context, constraint_space) - }, - Self::Replaced(inner) => inner - .contents - .inline_content_sizes(layout_context, constraint_space), - } + self.base + .inline_content_sizes(constraint_space, || match &self.contents { + IndependentFormattingContextContents::NonReplaced(contents) => { + contents.inline_content_sizes(layout_context, constraint_space) + }, + IndependentFormattingContextContents::Replaced(contents) => { + contents.inline_content_sizes(layout_context, constraint_space) + }, + }) } pub(crate) fn outer_inline_content_sizes( @@ -225,40 +205,32 @@ impl IndependentFormattingContext { auto_minimum: &LogicalVec2<Au>, auto_block_size_stretches_to_containing_block: bool, ) -> InlineContentSizesResult { - match self { - Self::NonReplaced(non_replaced) => non_replaced.outer_inline_content_sizes( - layout_context, - containing_block, - auto_minimum, - auto_block_size_stretches_to_containing_block, - ), - Self::Replaced(replaced) => sizing::outer_inline( - &replaced.style, - containing_block, - auto_minimum, - auto_block_size_stretches_to_containing_block, - |padding_border_sums| replaced.preferred_aspect_ratio(padding_border_sums), - |constraint_space| { - replaced - .contents - .inline_content_sizes(layout_context, constraint_space) - }, - ), - } + sizing::outer_inline( + self.style(), + containing_block, + auto_minimum, + auto_block_size_stretches_to_containing_block, + |padding_border_sums| self.preferred_aspect_ratio(padding_border_sums), + |constraint_space| self.inline_content_sizes(layout_context, constraint_space), + ) } pub(crate) fn preferred_aspect_ratio( &self, padding_border_sums: &LogicalVec2<Au>, ) -> Option<AspectRatio> { - match self { - Self::NonReplaced(non_replaced) => non_replaced.preferred_aspect_ratio(), - Self::Replaced(replaced) => replaced.preferred_aspect_ratio(padding_border_sums), + match &self.contents { + IndependentFormattingContextContents::NonReplaced(content) => { + content.preferred_aspect_ratio() + }, + IndependentFormattingContextContents::Replaced(content) => { + content.preferred_aspect_ratio(self.style(), padding_border_sums) + }, } } } -impl NonReplacedFormattingContext { +impl IndependentNonReplacedContents { pub fn layout( &self, layout_context: &LayoutContext, @@ -266,25 +238,25 @@ impl NonReplacedFormattingContext { containing_block_for_children: &ContainingBlock, containing_block: &ContainingBlock, ) -> IndependentLayout { - match &self.contents { - NonReplacedFormattingContextContents::Flow(bfc) => bfc.layout( + match self { + IndependentNonReplacedContents::Flow(bfc) => bfc.layout( layout_context, positioning_context, containing_block_for_children, ), - NonReplacedFormattingContextContents::Flex(fc) => fc.layout( + IndependentNonReplacedContents::Flex(fc) => fc.layout( layout_context, positioning_context, containing_block_for_children, containing_block, ), - NonReplacedFormattingContextContents::Grid(fc) => fc.layout( + IndependentNonReplacedContents::Grid(fc) => fc.layout( layout_context, positioning_context, containing_block_for_children, containing_block, ), - NonReplacedFormattingContextContents::Table(table) => table.layout( + IndependentNonReplacedContents::Table(table) => table.layout( layout_context, positioning_context, containing_block_for_children, @@ -304,47 +276,6 @@ impl NonReplacedFormattingContext { layout_context: &LayoutContext, constraint_space: &ConstraintSpace, ) -> InlineContentSizesResult { - let mut cache = self.content_sizes_result.borrow_mut(); - if let Some((previous_cb_block_size, result)) = *cache { - if !result.depends_on_block_constraints || - previous_cb_block_size == constraint_space.block_size - { - return result; - } - // TODO: Should we keep multiple caches for various block sizes? - } - - let result = self - .contents - .inline_content_sizes(layout_context, constraint_space); - *cache = Some((constraint_space.block_size, result)); - result - } - - pub(crate) fn outer_inline_content_sizes( - &self, - layout_context: &LayoutContext, - containing_block: &IndefiniteContainingBlock, - auto_minimum: &LogicalVec2<Au>, - auto_block_size_stretches_to_containing_block: bool, - ) -> InlineContentSizesResult { - sizing::outer_inline( - &self.style, - containing_block, - auto_minimum, - auto_block_size_stretches_to_containing_block, - |_| self.preferred_aspect_ratio(), - |constraint_space| self.inline_content_sizes(layout_context, constraint_space), - ) - } -} - -impl NonReplacedFormattingContextContents { - pub(crate) fn inline_content_sizes( - &self, - layout_context: &LayoutContext, - constraint_space: &ConstraintSpace, - ) -> InlineContentSizesResult { match self { Self::Flow(inner) => inner .contents @@ -355,13 +286,3 @@ impl NonReplacedFormattingContextContents { } } } - -impl ReplacedFormattingContext { - pub(crate) fn preferred_aspect_ratio( - &self, - padding_border_sums: &LogicalVec2<Au>, - ) -> Option<AspectRatio> { - self.contents - .preferred_aspect_ratio(&self.style, padding_border_sums) - } -} diff --git a/components/layout_2020/layout_box_base.rs b/components/layout_2020/layout_box_base.rs new file mode 100644 index 00000000000..10a2d98d149 --- /dev/null +++ b/components/layout_2020/layout_box_base.rs @@ -0,0 +1,61 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use atomic_refcell::AtomicRefCell; +use serde::Serialize; +use servo_arc::Arc; +use style::properties::ComputedValues; + +use crate::fragment_tree::BaseFragmentInfo; +use crate::geom::SizeConstraint; +use crate::sizing::InlineContentSizesResult; +use crate::ConstraintSpace; + +/// A box tree node that handles containing information about style and the original DOM +/// node or pseudo-element that it is based on. This also handles caching of layout values +/// such as the inline content sizes to avoid recalculating these values during layout +/// passes. +/// +/// In the future, this will hold layout results to support incremental layout. +#[derive(Debug, Serialize)] +pub(crate) struct LayoutBoxBase { + pub base_fragment_info: BaseFragmentInfo, + #[serde(skip_serializing)] + pub style: Arc<ComputedValues>, + #[serde(skip_serializing)] + pub cached_inline_content_size: + AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>, +} + +impl LayoutBoxBase { + pub(crate) fn new(base_fragment_info: BaseFragmentInfo, style: Arc<ComputedValues>) -> Self { + Self { + base_fragment_info, + style, + cached_inline_content_size: AtomicRefCell::default(), + } + } + + /// Get the inline content sizes of a box tree node that extends this [`LayoutBoxBase`], fetch + /// the result from a cache when possible. + pub(crate) fn inline_content_sizes( + &self, + constraint_space: &ConstraintSpace, + inline_content_sizes_fn: impl FnOnce() -> InlineContentSizesResult, + ) -> InlineContentSizesResult { + let mut cache = self.cached_inline_content_size.borrow_mut(); + if let Some((previous_cb_block_size, result)) = *cache { + if !result.depends_on_block_constraints || + previous_cb_block_size == constraint_space.block_size + { + return result; + } + // TODO: Should we keep multiple caches for various block sizes? + } + + let result = inline_content_sizes_fn(); + *cache = Some((constraint_space.block_size, result)); + result + } +} diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index 64e5e102887..3232a1aac44 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -14,6 +14,7 @@ pub mod flow; mod formatting_contexts; mod fragment_tree; pub mod geom; +mod layout_box_base; mod taffy; #[macro_use] pub mod layout_debug; diff --git a/components/layout_2020/lists.rs b/components/layout_2020/lists.rs index b0e97ab02e3..ee8db260c8c 100644 --- a/components/layout_2020/lists.rs +++ b/components/layout_2020/lists.rs @@ -10,7 +10,7 @@ use style::values::computed::Image; use crate::context::LayoutContext; use crate::dom::NodeExt; use crate::dom_traversal::{NodeAndStyleInfo, PseudoElementContentItem}; -use crate::replaced::ReplacedContent; +use crate::replaced::ReplacedContents; /// <https://drafts.csswg.org/css-lists/#content-property> pub(crate) fn make_marker<'dom, Node>( @@ -32,7 +32,7 @@ where // https://drafts.csswg.org/css-lists/#marker-image let marker_image = || match &style.list_style_image { Image::Url(url) => Some(vec![ - PseudoElementContentItem::Replaced(ReplacedContent::from_image_url( + PseudoElementContentItem::Replaced(ReplacedContents::from_image_url( node, context, url, )?), PseudoElementContentItem::Text(" ".into()), diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 1cf53ee8768..6fc0ddf66b5 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -20,7 +20,9 @@ use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; -use crate::formatting_contexts::IndependentFormattingContext; +use crate::formatting_contexts::{ + IndependentFormattingContext, IndependentFormattingContextContents, +}; use crate::fragment_tree::{ BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags, HoistedSharedFragment, }; @@ -521,24 +523,22 @@ impl HoistedAbsolutelyPositionedBox { flip_anchor: false, }; - if let IndependentFormattingContext::Replaced(replaced) = context { + if let IndependentFormattingContextContents::Replaced(replaced) = &context.contents { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height let inset_sums = LogicalVec2 { inline: inline_axis_solver.inset_sum(), block: block_axis_solver.inset_sum(), }; - let used_size = replaced - .contents - .used_size_as_if_inline_element_from_content_box_sizes( - containing_block, - &style, - replaced.preferred_aspect_ratio(&pbm.padding_border_sums), - computed_size, - computed_min_size, - computed_max_size, - pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums, - ); + let used_size = replaced.used_size_as_if_inline_element_from_content_box_sizes( + containing_block, + &style, + context.preferred_aspect_ratio(&pbm.padding_border_sums), + computed_size, + computed_min_size, + computed_max_size, + pbm.padding_border_sums + pbm.margin.auto_is(Au::zero).sum() + inset_sums, + ); inline_axis_solver.override_size(used_size.inline); block_axis_solver.override_size(used_size.block); } @@ -561,20 +561,20 @@ impl HoistedAbsolutelyPositionedBox { let mut new_fragment = { let content_size: LogicalVec2<Au>; let fragments; - match context { - IndependentFormattingContext::Replaced(replaced) => { + match &context.contents { + IndependentFormattingContextContents::Replaced(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height content_size = LogicalVec2 { inline: inline_axis.size.to_definite().unwrap(), block: block_axis.size.to_definite().unwrap(), }; - fragments = replaced.contents.make_fragments( + fragments = replaced.make_fragments( &style, content_size.to_physical_size(containing_block_writing_mode), ); }, - IndependentFormattingContext::NonReplaced(non_replaced) => { + IndependentFormattingContextContents::NonReplaced(non_replaced) => { // 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.to_definite().unwrap(); diff --git a/components/layout_2020/replaced.rs b/components/layout_2020/replaced.rs index c1e4236d052..bedfbf54ffe 100644 --- a/components/layout_2020/replaced.rs +++ b/components/layout_2020/replaced.rs @@ -34,7 +34,7 @@ use crate::style_ext::{AspectRatio, Clamp, ComputedValuesExt, ContentBoxSizesAnd use crate::{ConstraintSpace, ContainingBlock, SizeConstraint}; #[derive(Debug, Serialize)] -pub(crate) struct ReplacedContent { +pub(crate) struct ReplacedContents { pub kind: ReplacedContentKind, natural_size: NaturalSizes, base_fragment_info: BaseFragmentInfo, @@ -140,7 +140,7 @@ pub(crate) enum ReplacedContentKind { Video(Option<VideoInfo>), } -impl ReplacedContent { +impl ReplacedContents { pub fn for_element<'dom>(element: impl NodeExt<'dom>, context: &LayoutContext) -> Option<Self> { if let Some(ref data_attribute_string) = element.as_typeless_object_with_data_attribute() { if let Some(url) = try_to_parse_image_data_url(data_attribute_string) { diff --git a/components/layout_2020/table/construct.rs b/components/layout_2020/table/construct.rs index d57e315d3d8..8eb754d8df5 100644 --- a/components/layout_2020/table/construct.rs +++ b/components/layout_2020/table/construct.rs @@ -25,10 +25,11 @@ use crate::dom::{BoxSlot, NodeExt}; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NonReplacedContents, TraversalHandler}; use crate::flow::{BlockContainerBuilder, BlockFormattingContext}; use crate::formatting_contexts::{ - IndependentFormattingContext, NonReplacedFormattingContext, - NonReplacedFormattingContextContents, + IndependentFormattingContext, IndependentFormattingContextContents, + IndependentNonReplacedContents, }; use crate::fragment_tree::BaseFragmentInfo; +use crate::layout_box_base::LayoutBoxBase; use crate::style_ext::{DisplayGeneratingBox, DisplayLayoutInternal}; /// A reference to a slot and its coordinates in the table @@ -134,12 +135,12 @@ impl Table { let mut table = table_builder.finish(); table.anonymous = true; - IndependentFormattingContext::NonReplaced(NonReplacedFormattingContext { - base_fragment_info: (&anonymous_info).into(), - style: grid_and_wrapper_style, - content_sizes_result: Default::default(), - contents: NonReplacedFormattingContextContents::Table(table), - }) + IndependentFormattingContext { + base: LayoutBoxBase::new((&anonymous_info).into(), grid_and_wrapper_style), + contents: IndependentFormattingContextContents::NonReplaced( + IndependentNonReplacedContents::Table(table), + ), + } } /// Push a new slot into the last row of this table. @@ -853,15 +854,13 @@ where DisplayLayoutInternal::TableCaption => { let contents = match contents.try_into() { Ok(non_replaced_contents) => { - NonReplacedFormattingContextContents::Flow( - BlockFormattingContext::construct( - self.context, - info, - non_replaced_contents, - self.current_text_decoration_line, - false, /* is_list_item */ - ), - ) + IndependentNonReplacedContents::Flow(BlockFormattingContext::construct( + self.context, + info, + non_replaced_contents, + self.current_text_decoration_line, + false, /* is_list_item */ + )) }, Err(_replaced) => { unreachable!("Replaced should not have a LayoutInternal display type."); @@ -869,11 +868,9 @@ where }; let caption = TableCaption { - context: ArcRefCell::new(NonReplacedFormattingContext { - style: info.style.clone(), - base_fragment_info: info.into(), - content_sizes_result: Default::default(), - contents, + context: ArcRefCell::new(IndependentFormattingContext { + base: LayoutBoxBase::new(info.into(), info.style.clone()), + contents: IndependentFormattingContextContents::NonReplaced(contents), }), }; diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 673beb604ae..ea7714207dd 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -1613,7 +1613,7 @@ impl<'a> TableLayout<'a> { parent_positioning_context: &mut PositioningContext, ) -> BoxFragment { let context = caption.context.borrow(); - let mut positioning_context = PositioningContext::new_for_style(&context.style); + let mut positioning_context = PositioningContext::new_for_style(context.style()); let containing_block = &ContainingBlock { inline_size: self.table_width + table_pbm.padding_border_sums.inline, block_size: AuOrAuto::Auto, @@ -1711,7 +1711,7 @@ impl<'a> TableLayout<'a> { table_layout .fragments .extend(self.table.captions.iter().filter_map(|caption| { - if caption.context.borrow().style.clone_caption_side() != CaptionSide::Top { + if caption.context.borrow().style().clone_caption_side() != CaptionSide::Top { return None; } @@ -1811,7 +1811,7 @@ impl<'a> TableLayout<'a> { table_layout .fragments .extend(self.table.captions.iter().filter_map(|caption| { - if caption.context.borrow().style.clone_caption_side() != CaptionSide::Bottom { + if caption.context.borrow().style().clone_caption_side() != CaptionSide::Bottom { return None; } diff --git a/components/layout_2020/table/mod.rs b/components/layout_2020/table/mod.rs index 1e29e605605..5a2c335875d 100644 --- a/components/layout_2020/table/mod.rs +++ b/components/layout_2020/table/mod.rs @@ -82,7 +82,7 @@ use style_traits::dom::OpaqueNode; use super::flow::BlockFormattingContext; use crate::cell::ArcRefCell; use crate::flow::BlockContainer; -use crate::formatting_contexts::NonReplacedFormattingContext; +use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::BaseFragmentInfo; pub type TableSize = Size2D<usize, UnknownUnit>; @@ -320,5 +320,5 @@ impl TableTrackGroup { #[derive(Debug, Serialize)] pub struct TableCaption { /// The contents of this cell, with its own layout. - context: ArcRefCell<NonReplacedFormattingContext>, + context: ArcRefCell<IndependentFormattingContext>, } diff --git a/components/layout_2020/taffy/layout.rs b/components/layout_2020/taffy/layout.rs index 33b1ce8a1ab..02c8568c091 100644 --- a/components/layout_2020/taffy/layout.rs +++ b/components/layout_2020/taffy/layout.rs @@ -15,7 +15,10 @@ use taffy::{AvailableSpace, MaybeMath, RequestedAxis, RunMode}; use super::{TaffyContainer, TaffyItemBox, TaffyItemBoxInner, TaffyStyloStyle}; use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::formatting_contexts::{Baselines, IndependentFormattingContext, IndependentLayout}; +use crate::formatting_contexts::{ + Baselines, IndependentFormattingContext, IndependentFormattingContextContents, + IndependentLayout, +}; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::{ LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size, @@ -43,13 +46,12 @@ fn resolve_content_size(constraint: AvailableSpace, content_sizes: ContentSizes) #[inline(always)] fn with_independant_formatting_context<T>( item: &mut TaffyItemBoxInner, - cb: impl FnOnce(&mut IndependentFormattingContext) -> T, + cb: impl FnOnce(&IndependentFormattingContext) -> T, ) -> T { match item { TaffyItemBoxInner::InFlowBox(ref mut context) => cb(context), TaffyItemBoxInner::OutOfFlowAbsolutelyPositionedBox(ref abspos_box) => { - let mut abspos_box = AtomicRefCell::borrow_mut(abspos_box); - cb(&mut abspos_box.context) + cb(&AtomicRefCell::borrow(abspos_box).context) }, } } @@ -132,13 +134,14 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { with_independant_formatting_context( &mut child.taffy_level_box, |independent_context| -> taffy::LayoutOutput { - match independent_context { - IndependentFormattingContext::Replaced(replaced) => { + let style = independent_context.style(); + match &independent_context.contents { + IndependentFormattingContextContents::Replaced(replaced) => { // TODO: re-evaluate sizing constraint conversions in light of recent layout_2020 changes let containing_block = &self.content_box_size_override; // Adjust known_dimensions from border box to content box - let pbm = replaced.style.padding_border_margin(containing_block); + let pbm = style.padding_border_margin(containing_block); let pb_sum = pbm.padding_border_sums.map(|v| v.to_f32_px()); let content_box_known_dimensions = taffy::Size { width: inputs @@ -152,11 +155,11 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { }; let content_box_size = replaced - .contents .used_size_as_if_inline_element_from_content_box_sizes( containing_block, - &replaced.style, - replaced.preferred_aspect_ratio(&pbm.padding_border_sums), + style, + independent_context + .preferred_aspect_ratio(&pbm.padding_border_sums), LogicalVec2 { inline: option_f32_to_size(content_box_known_dimensions.width), block: option_f32_to_size(content_box_known_dimensions.height), @@ -176,9 +179,8 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { // Create fragments if the RunMode if PerformLayout // If the RunMode is ComputeSize then only the returned size will be used if inputs.run_mode == RunMode::PerformLayout { - child.child_fragments = replaced - .contents - .make_fragments(&replaced.style, content_box_size); + child.child_fragments = + replaced.make_fragments(style, content_box_size); } let computed_size = taffy::Size { @@ -198,12 +200,12 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { } }, - IndependentFormattingContext::NonReplaced(non_replaced) => { + IndependentFormattingContextContents::NonReplaced(non_replaced) => { // TODO: re-evaluate sizing constraint conversions in light of recent layout_2020 changes let containing_block = &self.content_box_size_override; // Adjust known_dimensions from border box to content box - let pbm = non_replaced.style.padding_border_margin(containing_block); + let pbm = style.padding_border_margin(containing_block); let margin_sum = pbm.margin.auto_is(Au::zero).sum(); let content_box_inset = (pbm.padding_border_sums + margin_sum).map(|v| v.to_f32_px()); @@ -256,7 +258,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { let content_box_size_override = ContainingBlock { inline_size: Au::from_f32_px(inline_size), block_size: maybe_block_size, - style: &non_replaced.style, + style, }; let layout = { |