diff options
Diffstat (limited to 'components/layout_2020')
-rw-r--r-- | components/layout_2020/flexbox/layout.rs | 88 | ||||
-rw-r--r-- | components/layout_2020/flexbox/mod.rs | 25 | ||||
-rw-r--r-- | components/layout_2020/flow/inline/mod.rs | 18 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 49 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 1 | ||||
-rw-r--r-- | components/layout_2020/formatting_contexts.rs | 101 | ||||
-rw-r--r-- | components/layout_2020/fragment_tree/fragment.rs | 1 | ||||
-rw-r--r-- | components/layout_2020/layout_box_base.rs | 54 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 2 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 5 | ||||
-rw-r--r-- | components/layout_2020/table/layout.rs | 23 | ||||
-rw-r--r-- | components/layout_2020/taffy/layout.rs | 9 |
12 files changed, 216 insertions, 160 deletions
diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index 77076898f57..880847617f6 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -25,16 +25,13 @@ use style::values::generics::length::LengthPercentageOrNormal; use style::values::specified::align::AlignFlags; use super::geom::{FlexAxis, FlexRelativeRect, FlexRelativeSides, FlexRelativeVec2}; -use super::{ - CachedBlockSizeContribution, FlexContainer, FlexContainerConfig, FlexItemBox, FlexLevelBox, -}; +use super::{FlexContainer, FlexContainerConfig, FlexItemBox, FlexLevelBox}; use crate::cell::ArcRefCell; use crate::context::LayoutContext; -use crate::formatting_contexts::{ - Baselines, IndependentFormattingContextContents, IndependentLayout, -}; +use crate::formatting_contexts::{Baselines, IndependentFormattingContextContents}; use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags}; use crate::geom::{AuOrAuto, LogicalRect, LogicalSides, LogicalVec2, Size, Sizes}; +use crate::layout_box_base::CacheableLayoutResult; use crate::positioned::{ AbsolutelyPositionedBox, PositioningContext, PositioningContextLength, relative_adjustement, }; @@ -650,8 +647,10 @@ impl FlexContainer { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - ) -> IndependentLayout { - let depends_on_block_constraints = self.config.flex_direction == FlexDirection::Column; + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { + let depends_on_block_constraints = + depends_on_block_constraints || self.config.flex_direction == FlexDirection::Column; let mut flex_context = FlexContext { config: self.config.clone(), @@ -985,13 +984,14 @@ impl FlexContainer { .or(all_baselines.last), }; - IndependentLayout { + CacheableLayoutResult { fragments, content_block_size, content_inline_size_for_table: None, baselines, depends_on_block_constraints, specific_layout_info: None, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), } } @@ -1950,29 +1950,23 @@ impl FlexItem<'_> { } } - let cache = self.box_.block_content_size_cache.borrow_mut().take(); - let layout = if let Some(cache) = cache.filter(|cache| { - cache.compatible_with_item_as_containing_block(&item_as_containing_block) - }) { - positioning_context = cache.positioning_context; - cache.layout - } else { - non_replaced.layout( - flex_context.layout_context, - &mut positioning_context, - &item_as_containing_block, - containing_block, - ) - }; - let IndependentLayout { + let layout = non_replaced.layout_with_caching( + flex_context.layout_context, + &mut positioning_context, + &item_as_containing_block, + containing_block, + &independent_formatting_context.base, + flex_axis == FlexAxis::Column || + self.stretches_to_line() || + self.depends_on_block_constraints, + ); + let CacheableLayoutResult { fragments, content_block_size, baselines: content_box_baselines, depends_on_block_constraints, .. } = layout; - let depends_on_block_constraints = depends_on_block_constraints || - (flex_axis == FlexAxis::Row && self.stretches_to_line()); let has_child_which_depends_on_block_constraints = fragments.iter().any(|fragment| { fragment.base().is_some_and(|base| @@ -2693,37 +2687,17 @@ impl FlexItemBox { }, style, }; - let content_block_size = || { - if let Some(cache) = &*self.block_content_size_cache.borrow() { - if inline_size == cache.containing_block_inline_size { - return cache.layout.content_block_size; - } else { - #[cfg(feature = "tracing")] - tracing::warn!( - name: "NonReplaced cache miss", - cached = ?cache.containing_block_inline_size, - required = ?inline_size, - ); - } - } else { - #[cfg(feature = "tracing")] - tracing::warn!(name: "NonReplaced no cache", required = ?inline_size); - } - - let layout = non_replaced.layout( - flex_context.layout_context, - &mut positioning_context, - &item_as_containing_block, - flex_context.containing_block, - ); - let content_block_size = layout.content_block_size; - *self.block_content_size_cache.borrow_mut() = - Some(CachedBlockSizeContribution { - containing_block_inline_size: item_as_containing_block.size.inline, - layout, - positioning_context, - }); - content_block_size + let mut content_block_size = || { + non_replaced + .layout_with_caching( + flex_context.layout_context, + &mut positioning_context, + &item_as_containing_block, + flex_context.containing_block, + &self.independent_formatting_context.base, + false, /* depends_on_block_constraints */ + ) + .content_block_size }; match intrinsic_sizing_mode { IntrinsicSizingMode::Contribution => { diff --git a/components/layout_2020/flexbox/mod.rs b/components/layout_2020/flexbox/mod.rs index fbe2786d078..46d7a2387a8 100644 --- a/components/layout_2020/flexbox/mod.rs +++ b/components/layout_2020/flexbox/mod.rs @@ -2,7 +2,6 @@ * 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 app_units::Au; use geom::{FlexAxis, MainStartCrossStart}; use servo_arc::Arc as ServoArc; use style::logical_geometry::WritingMode; @@ -13,15 +12,15 @@ use style::properties::longhands::flex_wrap::computed_value::T as FlexWrap; use style::values::computed::{AlignContent, JustifyContent}; use style::values::specified::align::AlignFlags; +use crate::PropagatedBoxTreeData; use crate::cell::ArcRefCell; use crate::construct_modern::{ModernContainerBuilder, ModernItemKind}; use crate::context::LayoutContext; use crate::dom::{LayoutBox, NodeExt}; use crate::dom_traversal::{NodeAndStyleInfo, NonReplacedContents}; -use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout}; +use crate::formatting_contexts::IndependentFormattingContext; use crate::fragment_tree::BaseFragmentInfo; -use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; -use crate::{ContainingBlock, PropagatedBoxTreeData}; +use crate::positioned::AbsolutelyPositionedBox; mod geom; mod layout; @@ -146,7 +145,6 @@ pub(crate) enum FlexLevelBox { pub(crate) struct FlexItemBox { independent_formatting_context: IndependentFormattingContext, - block_content_size_cache: ArcRefCell<Option<CachedBlockSizeContribution>>, } impl std::fmt::Debug for FlexItemBox { @@ -159,7 +157,6 @@ impl FlexItemBox { fn new(independent_formatting_context: IndependentFormattingContext) -> Self { Self { independent_formatting_context, - block_content_size_cache: Default::default(), } } @@ -171,19 +168,3 @@ impl FlexItemBox { self.independent_formatting_context.base_fragment_info() } } - -struct CachedBlockSizeContribution { - containing_block_inline_size: Au, - layout: IndependentLayout, - positioning_context: PositioningContext, -} - -impl CachedBlockSizeContribution { - fn compatible_with_item_as_containing_block( - &self, - item_as_containing_block: &ContainingBlock, - ) -> bool { - item_as_containing_block.size.inline == self.containing_block_inline_size && - !item_as_containing_block.size.block.is_definite() - } -} diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index a43a9333040..e9007ce2e45 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -109,15 +109,17 @@ use unicode_bidi::{BidiInfo, Level}; use webrender_api::FontInstanceKey; use xi_unicode::linebreak_property; -use super::IndependentFormattingContextContents; use super::float::{Clear, PlacementAmongFloats}; +use super::{ + CacheableLayoutResult, IndependentFloatOrAtomicLayoutResult, + IndependentFormattingContextContents, +}; use crate::cell::ArcRefCell; use crate::context::LayoutContext; +use crate::flow::CollapsibleWithParentStartMargin; use crate::flow::float::{FloatBox, SequentialLayoutState}; -use crate::flow::{CollapsibleWithParentStartMargin, FlowLayout}; use crate::formatting_contexts::{ - Baselines, IndependentFormattingContext, IndependentLayoutResult, - IndependentNonReplacedContents, + Baselines, IndependentFormattingContext, IndependentNonReplacedContents, }; use crate::fragment_tree::{ BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, @@ -1585,7 +1587,7 @@ impl InlineFormattingContext { containing_block: &ContainingBlock, sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, - ) -> FlowLayout { + ) -> CacheableLayoutResult { let first_line_inline_start = if self.has_first_formatted_line { containing_block .style @@ -1697,12 +1699,14 @@ impl InlineFormattingContext { content_block_size == Au::zero() && collapsible_with_parent_start_margin.0; - FlowLayout { + CacheableLayoutResult { fragments: layout.fragments, content_block_size, collapsible_margins_in_children, baselines: layout.baselines, depends_on_block_constraints: layout.depends_on_block_constraints, + content_inline_size_for_table: None, + specific_layout_info: None, } } @@ -1922,7 +1926,7 @@ impl IndependentFormattingContext { // We need to know the inline size of the atomic before deciding whether to do the line break. let mut child_positioning_context = PositioningContext::new_for_style(self.style()) .unwrap_or_else(|| PositioningContext::new_for_subtree(true)); - let IndependentLayoutResult { + let IndependentFloatOrAtomicLayoutResult { mut fragment, baselines, pbm_sums, diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 58e7310d6cd..8f38e0d4b23 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -26,7 +26,7 @@ use crate::flow::float::{ }; use crate::formatting_contexts::{ Baselines, IndependentFormattingContext, IndependentFormattingContextContents, - IndependentLayout, IndependentLayoutResult, IndependentNonReplacedContents, + IndependentNonReplacedContents, }; use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, FragmentFlags, @@ -35,7 +35,7 @@ use crate::geom::{ AuOrAuto, LogicalRect, LogicalSides, LogicalSides1D, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, Size, Sizes, ToLogical, ToLogicalWithContainingBlock, }; -use crate::layout_box_base::LayoutBoxBase; +use crate::layout_box_base::{CacheableLayoutResult, LayoutBoxBase}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; use crate::replaced::ReplacedContents; use crate::sizing::{self, ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; @@ -219,18 +219,6 @@ impl BlockLevelBox { } } -pub(crate) struct FlowLayout { - pub fragments: Vec<Fragment>, - pub content_block_size: Au, - pub collapsible_margins_in_children: CollapsedBlockMargins, - /// The offset of the baselines in this layout in the content area, if there were some. This is - /// used to propagate inflow baselines to the ancestors of `display: inline-block` elements - /// and table content. - pub baselines: Baselines, - /// Whether or not this layout depends on the block size of its containing block. - pub depends_on_block_constraints: bool, -} - #[derive(Clone, Copy)] pub(crate) struct CollapsibleWithParentStartMargin(bool); @@ -362,7 +350,8 @@ impl BlockFormattingContext { layout_context: &LayoutContext, positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - ) -> IndependentLayout { + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { let mut sequential_layout_state = if self.contains_floats || !layout_context.use_rayon { Some(SequentialLayoutState::new(containing_block.size.inline)) } else { @@ -395,15 +384,17 @@ impl BlockFormattingContext { sequential_layout_state.calculate_clearance(Clear::Both, &CollapsedMargin::zero()) }); - IndependentLayout { + CacheableLayoutResult { fragments: flow_layout.fragments, content_block_size: flow_layout.content_block_size + flow_layout.collapsible_margins_in_children.end.solve() + clearance.unwrap_or_default(), content_inline_size_for_table: None, baselines: flow_layout.baselines, - depends_on_block_constraints: flow_layout.depends_on_block_constraints, + depends_on_block_constraints: depends_on_block_constraints || + flow_layout.depends_on_block_constraints, specific_layout_info: None, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), } } @@ -573,7 +564,7 @@ impl BlockContainer { sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ignore_block_margins_for_stretch: LogicalSides1D<bool>, - ) -> FlowLayout { + ) -> CacheableLayoutResult { match self { BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children( layout_context, @@ -627,7 +618,7 @@ fn layout_block_level_children( mut sequential_layout_state: Option<&mut SequentialLayoutState>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, ignore_block_margins_for_stretch: LogicalSides1D<bool>, -) -> FlowLayout { +) -> CacheableLayoutResult { let mut placement_state = PlacementState::new(collapsible_with_parent_start_margin, containing_block); @@ -660,12 +651,14 @@ fn layout_block_level_children( }); let (content_block_size, collapsible_margins_in_children, baselines) = placement_state.finish(); - FlowLayout { + CacheableLayoutResult { fragments, content_block_size, collapsible_margins_in_children, baselines, depends_on_block_constraints, + content_inline_size_for_table: None, + specific_layout_info: None, } } @@ -1150,6 +1143,7 @@ impl IndependentNonReplacedContents { positioning_context, &containing_block_for_children, containing_block, + false, /* depends_on_block_constraints */ ); let inline_size = layout @@ -1299,7 +1293,7 @@ impl IndependentNonReplacedContents { ) }; - let compute_block_size = |layout: &IndependentLayout| { + let compute_block_size = |layout: &CacheableLayoutResult| { content_box_sizes.block.resolve( Direction::Block, Size::FitContent, @@ -1335,6 +1329,7 @@ impl IndependentNonReplacedContents { style, }, containing_block, + false, /* depends_on_block_constraints */ ); content_size = LogicalVec2 { @@ -1398,6 +1393,7 @@ impl IndependentNonReplacedContents { style, }, containing_block, + false, /* depends_on_block_constraints */ ); let inline_size = if let Some(inline_size) = layout.content_inline_size_for_table { @@ -2162,6 +2158,12 @@ fn block_size_is_zero_or_intrinsic(size: &StyleSize, containing_block: &Containi } } +pub(crate) struct IndependentFloatOrAtomicLayoutResult { + pub fragment: BoxFragment, + pub baselines: Option<Baselines>, + pub pbm_sums: LogicalSides<Au>, +} + impl IndependentFormattingContext { pub(crate) fn layout_in_flow_block_level( &self, @@ -2196,7 +2198,7 @@ impl IndependentFormattingContext { layout_context: &LayoutContext, child_positioning_context: &mut PositioningContext, containing_block: &ContainingBlock, - ) -> IndependentLayoutResult { + ) -> IndependentFloatOrAtomicLayoutResult { let style = self.style(); let container_writing_mode = containing_block.style.writing_mode; let layout_style = self.layout_style(); @@ -2280,6 +2282,7 @@ impl IndependentFormattingContext { child_positioning_context, &containing_block_for_children, containing_block, + false, /* depends_on_block_constraints */ ); let inline_size = independent_layout .content_inline_size_for_table @@ -2330,7 +2333,7 @@ impl IndependentFormattingContext { CollapsedBlockMargins::zero(), ); - IndependentLayoutResult { + IndependentFloatOrAtomicLayoutResult { fragment, baselines, pbm_sums, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 5b7cf077bab..4fb33bf71d4 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -365,6 +365,7 @@ impl BoxTree { layout_context, &mut positioning_context, &(&initial_containing_block).into(), + false, /* depends_on_block_constraints */ ); let mut root_fragments = independent_layout.fragments.into_iter().collect::<Vec<_>>(); diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 96b78bf6eef..573e9100cec 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -12,11 +12,10 @@ use crate::dom::NodeExt; use crate::dom_traversal::{Contents, NodeAndStyleInfo}; use crate::flexbox::FlexContainer; use crate::flow::BlockFormattingContext; -use crate::fragment_tree::{ - BaseFragmentInfo, BoxFragment, Fragment, FragmentFlags, SpecificLayoutInfo, +use crate::fragment_tree::{BaseFragmentInfo, FragmentFlags}; +use crate::layout_box_base::{ + CacheableLayoutResult, CacheableLayoutResultAndInputs, LayoutBoxBase, }; -use crate::geom::LogicalSides; -use crate::layout_box_base::LayoutBoxBase; use crate::positioned::PositioningContext; use crate::replaced::ReplacedContents; use crate::sizing::{self, ComputeInlineContentSizes, InlineContentSizesResult}; @@ -68,35 +67,6 @@ impl Baselines { } } -pub(crate) struct IndependentLayout { - pub fragments: Vec<Fragment>, - - /// <https://drafts.csswg.org/css2/visudet.html#root-height> - pub content_block_size: Au, - - /// If a table has collapsed columns, it can become smaller than what the parent - /// formatting context decided. This is the resulting inline content size. - /// This is None for non-table layouts and for tables without collapsed columns. - pub content_inline_size_for_table: Option<Au>, - - /// The offset of the last inflow baseline of this layout in the content area, if - /// there was one. This is used to propagate baselines to the ancestors of `display: - /// inline-block`. - pub baselines: Baselines, - - /// Whether or not this layout depends on the containing block size. - pub depends_on_block_constraints: bool, - - /// Additional information of this layout that could be used by Javascripts and devtools. - pub specific_layout_info: Option<SpecificLayoutInfo>, -} - -pub(crate) struct IndependentLayoutResult { - pub fragment: BoxFragment, - pub baselines: Option<Baselines>, - pub pbm_sums: LogicalSides<Au>, -} - impl IndependentFormattingContext { pub fn construct<'dom, Node: NodeExt<'dom>>( context: &LayoutContext, @@ -255,17 +225,20 @@ impl IndependentNonReplacedContents { positioning_context: &mut PositioningContext, containing_block_for_children: &ContainingBlock, containing_block: &ContainingBlock, - ) -> IndependentLayout { + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { match self { IndependentNonReplacedContents::Flow(bfc) => bfc.layout( layout_context, positioning_context, containing_block_for_children, + depends_on_block_constraints, ), IndependentNonReplacedContents::Flex(fc) => fc.layout( layout_context, positioning_context, containing_block_for_children, + depends_on_block_constraints, ), IndependentNonReplacedContents::Grid(fc) => fc.layout( layout_context, @@ -278,10 +251,70 @@ impl IndependentNonReplacedContents { positioning_context, containing_block_for_children, containing_block, + depends_on_block_constraints, ), } } + #[cfg_attr( + feature = "tracing", + tracing::instrument( + name = "IndependentNonReplacedContents::layout_with_caching", + skip_all, + fields(servo_profiling = true), + level = "trace", + ) + )] + pub fn layout_with_caching( + &self, + layout_context: &LayoutContext, + positioning_context: &mut PositioningContext, + containing_block_for_children: &ContainingBlock, + containing_block: &ContainingBlock, + base: &LayoutBoxBase, + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { + if let Some(cache) = base.cached_layout_result.borrow().as_ref() { + if cache.containing_block_for_children_size.inline == + containing_block_for_children.size.inline && + (cache.containing_block_for_children_size.block == + containing_block_for_children.size.block || + !(cache.result.depends_on_block_constraints || + depends_on_block_constraints)) + { + positioning_context.append(cache.positioning_context.clone()); + return cache.result.clone(); + } + #[cfg(feature = "tracing")] + tracing::debug!( + name: "NonReplaced cache miss", + cached = ?cache.containing_block_for_children_size, + required = ?containing_block_for_children.size, + ); + } + + let mut child_positioning_context = PositioningContext::new_for_subtree( + positioning_context.collects_for_nearest_positioned_ancestor(), + ); + + let result = self.layout( + layout_context, + &mut child_positioning_context, + containing_block_for_children, + containing_block, + depends_on_block_constraints, + ); + + *base.cached_layout_result.borrow_mut() = Some(CacheableLayoutResultAndInputs { + result: result.clone(), + positioning_context: child_positioning_context.clone(), + containing_block_for_children_size: containing_block_for_children.size.clone(), + }); + positioning_context.append(child_positioning_context); + + result + } + #[inline] pub(crate) fn layout_style<'a>(&'a self, base: &'a LayoutBoxBase) -> LayoutStyle<'a> { match self { diff --git a/components/layout_2020/fragment_tree/fragment.rs b/components/layout_2020/fragment_tree/fragment.rs index ba52f28bc3b..fbc95ce3d5a 100644 --- a/components/layout_2020/fragment_tree/fragment.rs +++ b/components/layout_2020/fragment_tree/fragment.rs @@ -45,6 +45,7 @@ pub(crate) enum Fragment { IFrame(ArcRefCell<IFrameFragment>), } +#[derive(Clone)] pub(crate) struct CollapsedBlockMargins { pub collapsed_through: bool, pub start: CollapsedMargin, diff --git a/components/layout_2020/layout_box_base.rs b/components/layout_2020/layout_box_base.rs index 0de9987bde7..bb2d37698f1 100644 --- a/components/layout_2020/layout_box_base.rs +++ b/components/layout_2020/layout_box_base.rs @@ -2,15 +2,20 @@ * 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 std::fmt::{Debug, Formatter}; + +use app_units::Au; use atomic_refcell::AtomicRefCell; use servo_arc::Arc; use style::properties::ComputedValues; -use crate::ConstraintSpace; use crate::context::LayoutContext; -use crate::fragment_tree::BaseFragmentInfo; +use crate::formatting_contexts::Baselines; +use crate::fragment_tree::{BaseFragmentInfo, CollapsedBlockMargins, Fragment, SpecificLayoutInfo}; use crate::geom::SizeConstraint; +use crate::positioned::PositioningContext; use crate::sizing::{ComputeInlineContentSizes, InlineContentSizesResult}; +use crate::{ConstraintSpace, ContainingBlockSize}; /// 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 @@ -18,12 +23,12 @@ use crate::sizing::{ComputeInlineContentSizes, InlineContentSizesResult}; /// passes. /// /// In the future, this will hold layout results to support incremental layout. -#[derive(Debug)] pub(crate) struct LayoutBoxBase { pub base_fragment_info: BaseFragmentInfo, pub style: Arc<ComputedValues>, pub cached_inline_content_size: AtomicRefCell<Option<(SizeConstraint, InlineContentSizesResult)>>, + pub cached_layout_result: AtomicRefCell<Option<CacheableLayoutResultAndInputs>>, } impl LayoutBoxBase { @@ -32,6 +37,7 @@ impl LayoutBoxBase { base_fragment_info, style, cached_inline_content_size: AtomicRefCell::default(), + cached_layout_result: AtomicRefCell::default(), } } @@ -58,3 +64,45 @@ impl LayoutBoxBase { result } } + +impl Debug for LayoutBoxBase { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> { + f.debug_struct("LayoutBoxBase").finish() + } +} + +#[derive(Clone)] +pub(crate) struct CacheableLayoutResult { + pub fragments: Vec<Fragment>, + + /// <https://drafts.csswg.org/css2/visudet.html#root-height> + pub content_block_size: Au, + + /// If this layout is for a block container, this tracks the collapsable size + /// of start and end margins and whether or not the block container collapsed through. + pub collapsible_margins_in_children: CollapsedBlockMargins, + + /// The contents of a table may force it to become wider than what we would expect + /// from 'width' and 'min-width'. This is the resulting inline content size, + /// or None for non-table layouts. + pub content_inline_size_for_table: Option<Au>, + + /// The offset of the last inflow baseline of this layout in the content area, if + /// there was one. This is used to propagate baselines to the ancestors of `display: + /// inline-block`. + pub baselines: Baselines, + + /// Whether or not this layout depends on the containing block size. + pub depends_on_block_constraints: bool, + + /// Additional information of this layout that could be used by Javascripts and devtools. + pub specific_layout_info: Option<SpecificLayoutInfo>, +} + +pub(crate) struct CacheableLayoutResultAndInputs { + pub result: CacheableLayoutResult, + + pub containing_block_for_children_size: ContainingBlockSize, + + pub positioning_context: PositioningContext, +} diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index 780d670c541..640f9ff938b 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -112,7 +112,7 @@ impl<'a> From<&'_ DefiniteContainingBlock<'a>> for IndefiniteContainingBlock { } } -#[derive(Debug)] +#[derive(Clone, Debug)] pub(crate) struct ContainingBlockSize { inline: Au, block: SizeConstraint, diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 8b10a79b59c..238eb1e3b2a 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -41,6 +41,7 @@ pub(crate) struct AbsolutelyPositionedBox { pub context: IndependentFormattingContext, } +#[derive(Clone)] pub(crate) struct PositioningContext { for_nearest_positioned_ancestor: Option<Vec<HoistedAbsolutelyPositionedBox>>, @@ -50,6 +51,7 @@ pub(crate) struct PositioningContext { for_nearest_containing_block_for_all_descendants: Vec<HoistedAbsolutelyPositionedBox>, } +#[derive(Clone)] pub(crate) struct HoistedAbsolutelyPositionedBox { absolutely_positioned_box: ArcRefCell<AbsolutelyPositionedBox>, @@ -299,7 +301,7 @@ impl PositioningContext { .push(box_) } - fn is_empty(&self) -> bool { + pub(crate) fn is_empty(&self) -> bool { self.for_nearest_containing_block_for_all_descendants .is_empty() && self.for_nearest_positioned_ancestor @@ -627,6 +629,7 @@ impl HoistedAbsolutelyPositionedBox { &mut positioning_context, &containing_block_for_children, containing_block, + false, /* depends_on_block_constraints */ ); let inline_size = if let Some(inline_size) = diff --git a/components/layout_2020/table/layout.rs b/components/layout_2020/table/layout.rs index 29014ae171c..ed35cff6049 100644 --- a/components/layout_2020/table/layout.rs +++ b/components/layout_2020/table/layout.rs @@ -29,7 +29,7 @@ use super::{ TableLayoutStyle, TableSlot, TableSlotCell, TableSlotCoordinates, TableTrack, TableTrackGroup, }; use crate::context::LayoutContext; -use crate::formatting_contexts::{Baselines, IndependentLayout}; +use crate::formatting_contexts::Baselines; use crate::fragment_tree::{ BaseFragmentInfo, BoxFragment, CollapsedBlockMargins, ExtraBackground, Fragment, FragmentFlags, PositioningFragment, SpecificLayoutInfo, @@ -38,6 +38,7 @@ use crate::geom::{ LogicalRect, LogicalSides, LogicalSides1D, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalVec, Size, SizeConstraint, ToLogical, ToLogicalWithContainingBlock, }; +use crate::layout_box_base::CacheableLayoutResult; use crate::positioned::{PositioningContext, PositioningContextLength, relative_adjustement}; use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ @@ -51,7 +52,7 @@ use crate::{ /// the table. Note that this is only done for slots that are not /// covered by spans or empty. struct CellLayout { - layout: IndependentLayout, + layout: CacheableLayoutResult, padding: LogicalSides<Au>, border: LogicalSides<Au>, positioning_context: PositioningContext, @@ -1137,6 +1138,7 @@ impl<'a> TableLayout<'a> { layout_context, &mut positioning_context, &containing_block_for_children, + false, /* depends_on_block_constraints */ ); Some(CellLayout { @@ -1539,13 +1541,15 @@ impl<'a> TableLayout<'a> { positioning_context: &mut PositioningContext, containing_block_for_children: &ContainingBlock, containing_block_for_table: &ContainingBlock, - ) -> IndependentLayout { + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { let table_writing_mode = containing_block_for_children.style.writing_mode; self.compute_border_collapse(table_writing_mode); let layout_style = self.table.layout_style(Some(&self)); - let depends_on_block_constraints = layout_style - .content_box_sizes_and_padding_border_margin(&containing_block_for_table.into()) - .depends_on_block_constraints; + let depends_on_block_constraints = depends_on_block_constraints || + layout_style + .content_box_sizes_and_padding_border_margin(&containing_block_for_table.into()) + .depends_on_block_constraints; self.pbm = layout_style .padding_border_margin_with_writing_mode_and_containing_block_inline_size( @@ -1579,13 +1583,14 @@ impl<'a> TableLayout<'a> { let offset_from_wrapper = -self.pbm.padding - self.pbm.border; let mut current_block_offset = offset_from_wrapper.block_start; - let mut table_layout = IndependentLayout { + let mut table_layout = CacheableLayoutResult { fragments: Vec::new(), content_block_size: Zero::zero(), content_inline_size_for_table: None, baselines: Baselines::default(), depends_on_block_constraints, specific_layout_info: Some(SpecificLayoutInfo::TableWrapper), + collapsible_margins_in_children: CollapsedBlockMargins::zero(), }; table_layout @@ -2664,12 +2669,14 @@ impl Table { positioning_context: &mut PositioningContext, containing_block_for_children: &ContainingBlock, containing_block_for_table: &ContainingBlock, - ) -> IndependentLayout { + depends_on_block_constraints: bool, + ) -> CacheableLayoutResult { TableLayout::new(self).layout( layout_context, positioning_context, containing_block_for_children, containing_block_for_table, + depends_on_block_constraints, ) } } diff --git a/components/layout_2020/taffy/layout.rs b/components/layout_2020/taffy/layout.rs index 1e58464629f..6c1b931599c 100644 --- a/components/layout_2020/taffy/layout.rs +++ b/components/layout_2020/taffy/layout.rs @@ -18,7 +18,6 @@ use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::formatting_contexts::{ Baselines, IndependentFormattingContext, IndependentFormattingContextContents, - IndependentLayout, }; use crate::fragment_tree::{ BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags, SpecificLayoutInfo, @@ -27,6 +26,7 @@ use crate::geom::{ LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size, SizeConstraint, Sizes, }; +use crate::layout_box_base::CacheableLayoutResult; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; use crate::sizing::{ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; use crate::style_ext::{ComputedValuesExt, LayoutStyle}; @@ -264,6 +264,7 @@ impl taffy::LayoutPartialTree for TaffyContainerContext<'_> { &mut child_positioning_context, &content_box_size_override, containing_block, + false, /* depends_on_block_constraints */ ); // Store layout data on child for later access @@ -425,7 +426,7 @@ impl TaffyContainer { positioning_context: &mut PositioningContext, content_box_size_override: &ContainingBlock, containing_block: &ContainingBlock, - ) -> IndependentLayout { + ) -> CacheableLayoutResult { let mut container_ctx = TaffyContainerContext { layout_context, positioning_context, @@ -643,7 +644,7 @@ impl TaffyContainer { }) .collect(); - IndependentLayout { + CacheableLayoutResult { fragments, content_block_size: Au::from_f32_px(output.size.height) - pbm.padding_border_sums.block, content_inline_size_for_table: None, @@ -654,8 +655,8 @@ impl TaffyContainer { // "true" is a safe default as it will prevent Servo from performing optimizations based // on the assumption that the node's size does not depend on block constraints. depends_on_block_constraints: true, - specific_layout_info: container_ctx.specific_layout_info, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), } } |