diff options
author | Anthony Ramine <nox@nox.paris> | 2020-06-18 14:11:02 +0200 |
---|---|---|
committer | Anthony Ramine <nox@nox.paris> | 2020-06-18 14:11:02 +0200 |
commit | 235df94f2eb9227fb35a51a5bc486aa9d29b5036 (patch) | |
tree | f1d87a305d07d5e484ca0fbd2cbc269a5f6f4ca9 | |
parent | ba5568a0a60cbd4bbedd3b766b7182824d75b131 (diff) | |
download | servo-235df94f2eb9227fb35a51a5bc486aa9d29b5036.tar.gz servo-235df94f2eb9227fb35a51a5bc486aa9d29b5036.zip |
Compute content sizes lazily in layout 2020
-rw-r--r-- | components/layout_2020/flexbox/construct.rs | 13 | ||||
-rw-r--r-- | components/layout_2020/flexbox/mod.rs | 7 | ||||
-rw-r--r-- | components/layout_2020/flow/construct.rs | 123 | ||||
-rw-r--r-- | components/layout_2020/flow/float.rs | 5 | ||||
-rw-r--r-- | components/layout_2020/flow/inline.rs | 11 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 47 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 2 | ||||
-rw-r--r-- | components/layout_2020/formatting_contexts.rs | 137 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 15 | ||||
-rw-r--r-- | components/layout_2020/sizing.rs | 61 | ||||
-rw-r--r-- | components/style/values/generics/length.rs | 2 |
11 files changed, 176 insertions, 247 deletions
diff --git a/components/layout_2020/flexbox/construct.rs b/components/layout_2020/flexbox/construct.rs index 385b45985e1..6c7c90635f2 100644 --- a/components/layout_2020/flexbox/construct.rs +++ b/components/layout_2020/flexbox/construct.rs @@ -12,7 +12,6 @@ use crate::element_data::LayoutBox; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::Tag; use crate::positioned::AbsolutelyPositionedBox; -use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::style_ext::DisplayGeneratingBox; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use std::borrow::Cow; @@ -23,9 +22,8 @@ impl FlexContainer { context: &LayoutContext, info: &NodeAndStyleInfo<impl NodeExt<'dom>>, contents: NonReplacedContents, - content_sizes: ContentSizesRequest, propagated_text_decoration_line: TextDecorationLine, - ) -> (Self, BoxContentSizes) { + ) -> Self { let text_decoration_line = propagated_text_decoration_line | info.style.clone_text_decoration_line(); let mut builder = FlexContainerBuilder { @@ -37,11 +35,7 @@ impl FlexContainer { has_text_runs: false, }; contents.traverse(context, info, &mut builder); - let content_sizes = content_sizes.compute(|| { - // FIXME - ContentSizes::zero() - }); - (builder.finish(), content_sizes) + builder.finish() } } @@ -152,7 +146,6 @@ where .map(|job| match job { FlexLevelJob::TextRuns(runs) => ArcRefCell::new(FlexLevelBox::FlexItem( IndependentFormattingContext::construct_for_text_runs( - self.context, &self .info .new_replacing_style(anonymous_style.clone().unwrap()), @@ -161,7 +154,6 @@ where text: run.text.into(), parent_style: run.info.style, }), - ContentSizesRequest::None, // FIXME: request sizes when we start using them self.text_decoration_line, ), )), @@ -191,7 +183,6 @@ where &info, display_inside, contents, - ContentSizesRequest::None, // FIXME: request sizes when we start using them self.text_decoration_line, ), )) diff --git a/components/layout_2020/flexbox/mod.rs b/components/layout_2020/flexbox/mod.rs index c7aed0bd0e9..5dd0c476727 100644 --- a/components/layout_2020/flexbox/mod.rs +++ b/components/layout_2020/flexbox/mod.rs @@ -5,6 +5,7 @@ use crate::cell::ArcRefCell; use crate::formatting_contexts::IndependentFormattingContext; use crate::positioned::AbsolutelyPositionedBox; +use crate::sizing::ContentSizes; mod construct; mod layout; @@ -19,3 +20,9 @@ pub(crate) enum FlexLevelBox { FlexItem(IndependentFormattingContext), OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>), } + +impl FlexContainer { + pub fn inline_content_sizes(&self) -> ContentSizes { + unimplemented!() + } +} diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 7d72209c6e8..0f49fb85422 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -14,14 +14,12 @@ use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::Tag; use crate::positioned::AbsolutelyPositionedBox; -use crate::sizing::{self, BoxContentSizes, ContentSizes, ContentSizesRequest}; -use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside}; +use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; use std::borrow::Cow; use std::convert::{TryFrom, TryInto}; -use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; use style::values::specified::text::TextDecorationLine; @@ -31,34 +29,24 @@ impl BlockFormattingContext { context: &LayoutContext, info: &NodeAndStyleInfo<Node>, contents: NonReplacedContents, - content_sizes: ContentSizesRequest, propagated_text_decoration_line: TextDecorationLine, - ) -> (Self, BoxContentSizes) + ) -> Self where Node: NodeExt<'dom>, { - let (contents, contains_floats, inline_content_sizes) = BlockContainer::construct( - context, - info, - contents, - content_sizes, - propagated_text_decoration_line, - ); - // FIXME: add contribution to `inline_content_sizes` of floats in this formatting context - // https://dbaron.org/css/intrinsic/#intrinsic + let (contents, contains_floats) = + BlockContainer::construct(context, info, contents, propagated_text_decoration_line); let bfc = Self { contents, contains_floats: contains_floats == ContainsFloats::Yes, }; - (bfc, inline_content_sizes) + bfc } pub fn construct_for_text_runs<'dom>( - context: &LayoutContext, runs: impl Iterator<Item = TextRun>, - content_sizes: ContentSizesRequest, text_decoration_line: TextDecorationLine, - ) -> (Self, BoxContentSizes) { + ) -> Self { // FIXME: do white space collapsing let inline_level_boxes = runs .map(|run| ArcRefCell::new(InlineLevelBox::TextRun(run))) @@ -68,18 +56,12 @@ impl BlockFormattingContext { inline_level_boxes, text_decoration_line, }; - // FIXME: this is the wrong writing mode - // but we plan to remove eager content size computation. - let not_actually_containing_block_writing_mode = WritingMode::empty(); - let content_sizes = content_sizes.compute(|| { - ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode) - }); let contents = BlockContainer::InlineFormattingContext(ifc); let bfc = Self { contents, contains_floats: false, }; - (bfc, content_sizes) + bfc } } @@ -181,9 +163,8 @@ impl BlockContainer { context: &LayoutContext, info: &NodeAndStyleInfo<Node>, contents: NonReplacedContents, - content_sizes: ContentSizesRequest, propagated_text_decoration_line: TextDecorationLine, - ) -> (BlockContainer, ContainsFloats, BoxContentSizes) + ) -> (BlockContainer, ContainsFloats) where Node: NodeExt<'dom>, { @@ -209,35 +190,22 @@ impl BlockContainer { .is_empty() { if builder.block_level_boxes.is_empty() { - // FIXME: this is the wrong writing mode - // but we plan to remove eager content size computation. - let not_actually_containing_block_writing_mode = info.style.writing_mode; - let content_sizes = content_sizes.compute(|| { - builder - .ongoing_inline_formatting_context - .inline_content_sizes(context, not_actually_containing_block_writing_mode) - }); let container = BlockContainer::InlineFormattingContext( builder.ongoing_inline_formatting_context, ); - return (container, builder.contains_floats, content_sizes); + return (container, builder.contains_floats); } builder.end_ongoing_inline_formatting_context(); } struct Accumulator { contains_floats: ContainsFloats, - outer_content_sizes_of_children: ContentSizes, } let mut acc = Accumulator { contains_floats: builder.contains_floats, - outer_content_sizes_of_children: ContentSizes::zero(), }; let mapfold = |acc: &mut Accumulator, creator: BlockLevelJob<'dom, _>| { - let (block_level_box, box_contains_floats) = creator.finish( - context, - content_sizes.if_requests_inline(|| &mut acc.outer_content_sizes_of_children), - ); + let (block_level_box, box_contains_floats) = creator.finish(context); acc.contains_floats |= box_contains_floats; block_level_box }; @@ -250,14 +218,9 @@ impl BlockContainer { mapfold, || Accumulator { contains_floats: ContainsFloats::No, - outer_content_sizes_of_children: ContentSizes::zero(), }, |left, right| { left.contains_floats |= right.contains_floats; - if content_sizes.requests_inline() { - left.outer_content_sizes_of_children - .max_assign(&right.outer_content_sizes_of_children) - } }, ) .collect() @@ -270,12 +233,8 @@ impl BlockContainer { }; let container = BlockContainer::BlockLevelBoxes(block_level_boxes); - let Accumulator { - contains_floats, - outer_content_sizes_of_children, - } = acc; - let content_sizes = content_sizes.compute(|| outer_content_sizes_of_children); - (container, contains_floats, content_sizes) + let Accumulator { contains_floats } = acc; + (container, contains_floats) } } @@ -439,7 +398,6 @@ where display_inside: DisplayInside, contents: Contents, ) -> ArcRefCell<InlineLevelBox> { - let style = &info.style; let box_ = if display_inside == DisplayInside::Flow && !contents.is_replaced() { // We found un inline box. // Whatever happened before, all we need to do before recurring @@ -464,14 +422,12 @@ where inline_box.last_fragment = true; ArcRefCell::new(InlineLevelBox::InlineBox(inline_box)) } else { - let content_sizes = ContentSizesRequest::inline_if(!style.inline_size_is_length()); ArcRefCell::new(InlineLevelBox::Atomic( IndependentFormattingContext::construct( self.context, info, display_inside, contents, - content_sizes, // Text decorations are not propagated to atomic inline-level descendants. TextDecorationLine::NONE, ), @@ -681,32 +637,11 @@ impl<'dom, Node> BlockLevelJob<'dom, Node> where Node: NodeExt<'dom>, { - fn finish( - self, - context: &LayoutContext, - max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>, - ) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) { + fn finish(self, context: &LayoutContext) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) { let info = &self.info; - // FIXME: this is the wrong writing mode - // but we plan to remove eager content size computation. - let not_actually_containing_block_writing_mode = info.style.writing_mode; let (block_level_box, contains_floats) = match self.kind { BlockLevelCreator::SameFormattingContextBlock(contents) => { - let (contents, contains_floats, box_content_sizes) = contents.finish( - context, - info, - ContentSizesRequest::inline_if( - max_assign_in_flow_outer_content_sizes_to.is_some() && - !info.style.inline_size_is_length(), - ), - ); - if let Some(to) = max_assign_in_flow_outer_content_sizes_to { - to.max_assign(&sizing::outer_inline( - &info.style, - not_actually_containing_block_writing_mode, - || box_content_sizes.expect_inline().clone(), - )) - } + let (contents, contains_floats) = contents.finish(context, info); let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock { tag: Tag::from_node_and_style_info(info), contents, @@ -719,25 +654,13 @@ where contents, propagated_text_decoration_line, } => { - let content_sizes = ContentSizesRequest::inline_if( - max_assign_in_flow_outer_content_sizes_to.is_some() && - !info.style.inline_size_is_length(), - ); let context = IndependentFormattingContext::construct( context, info, display_inside, contents, - content_sizes, propagated_text_decoration_line, ); - if let Some(to) = max_assign_in_flow_outer_content_sizes_to { - to.max_assign(&sizing::outer_inline( - &context.style(), - not_actually_containing_block_writing_mode, - || context.content_sizes(), - )) - } ( ArcRefCell::new(BlockLevelBox::Independent(context)), ContainsFloats::No, @@ -775,35 +698,21 @@ impl IntermediateBlockContainer { self, context: &LayoutContext, info: &NodeAndStyleInfo<Node>, - content_sizes: ContentSizesRequest, - ) -> (BlockContainer, ContainsFloats, BoxContentSizes) + ) -> (BlockContainer, ContainsFloats) where Node: NodeExt<'dom>, { match self { IntermediateBlockContainer::Deferred(contents, propagated_text_decoration_line) => { - BlockContainer::construct( - context, - info, - contents, - content_sizes, - propagated_text_decoration_line, - ) + BlockContainer::construct(context, info, contents, propagated_text_decoration_line) }, IntermediateBlockContainer::InlineFormattingContext(ifc) => { - // FIXME: this is the wrong writing mode - // but we plan to remove eager content size computation. - let not_actually_containing_block_writing_mode = info.style.writing_mode; - let content_sizes = content_sizes.compute(|| { - ifc.inline_content_sizes(context, not_actually_containing_block_writing_mode) - }); // If that inline formatting context contained any float, those // were already taken into account during the first phase of // box construction. ( BlockContainer::InlineFormattingContext(ifc), ContainsFloats::No, - content_sizes, ) }, } diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index da70838499f..22b0b1bb66e 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -5,8 +5,7 @@ use crate::context::LayoutContext; use crate::dom_traversal::{Contents, NodeAndStyleInfo, NodeExt}; use crate::formatting_contexts::IndependentFormattingContext; -use crate::sizing::ContentSizesRequest; -use crate::style_ext::{ComputedValuesExt, DisplayInside}; +use crate::style_ext::DisplayInside; use style::values::specified::text::TextDecorationLine; #[derive(Debug, Serialize)] @@ -32,14 +31,12 @@ impl FloatBox { display_inside: DisplayInside, contents: Contents, ) -> Self { - let content_sizes = ContentSizesRequest::inline_if(!info.style.inline_size_is_length()); Self { contents: IndependentFormattingContext::construct( context, info, display_inside, contents, - content_sizes, // Text decorations are not propagated to any out-of-flow descendants TextDecorationLine::NONE, ), diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index f6895258dab..910f9e20cea 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -16,7 +16,7 @@ use crate::positioned::{ relative_adjustement, AbsolutelyPositionedBox, HoistedAbsolutelyPositionedBox, PositioningContext, }; -use crate::sizing::{self, ContentSizes}; +use crate::sizing::ContentSizes; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; use crate::ContainingBlock; use app_units::Au; @@ -200,10 +200,9 @@ impl InlineFormattingContext { } }, InlineLevelBox::Atomic(atomic) => { - let (outer, pc) = sizing::outer_inline_and_percentages( - &atomic.style(), + let (outer, pc) = atomic.outer_inline_and_percentages( + self.layout_context, self.containing_block_writing_mode, - || atomic.content_sizes(), ); self.current_line.min_content += outer.min_content; self.current_line.max_content += outer.max_content; @@ -595,7 +594,9 @@ fn layout_atomic( // https://drafts.csswg.org/css2/visudet.html#inlineblock-width let tentative_inline_size = box_size.inline.auto_is(|| { let available_size = ifc.containing_block.inline_size - pbm_sums.inline_sum(); - non_replaced.content_sizes.shrink_to_fit(available_size) + non_replaced + .inline_content_sizes(layout_context) + .shrink_to_fit(available_size) }); // https://drafts.csswg.org/css2/visudet.html#min-max-widths diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index b8c0d7e500d..c256c6c9a23 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -18,11 +18,13 @@ use crate::fragments::{ use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext}; use crate::replaced::ReplacedContent; +use crate::sizing::{self, ContentSizes}; use crate::style_ext::{ComputedValuesExt, PaddingBorderMargin}; use crate::ContainingBlock; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; use style::values::computed::{Length, LengthOrAuto}; use style::Zero; @@ -132,6 +134,29 @@ impl BlockContainer { ), } } + + pub(super) fn inline_content_sizes( + &self, + layout_context: &LayoutContext, + containing_block_writing_mode: WritingMode, + ) -> ContentSizes { + match &self { + Self::BlockLevelBoxes(boxes) => { + let mut content_sizes = ContentSizes::zero(); + for box_ in boxes { + content_sizes.max_assign( + &box_ + .borrow_mut() + .inline_content_sizes(layout_context, containing_block_writing_mode), + ); + } + content_sizes + }, + Self::InlineFormattingContext(context) => { + context.inline_content_sizes(layout_context, containing_block_writing_mode) + }, + } + } } fn layout_block_level_children( @@ -350,6 +375,28 @@ impl BlockLevelBox { }, } } + + fn inline_content_sizes( + &mut self, + layout_context: &LayoutContext, + containing_block_writing_mode: WritingMode, + ) -> ContentSizes { + match self { + Self::SameFormattingContextBlock { + style, contents, .. + } => sizing::outer_inline(style, containing_block_writing_mode, || { + contents.inline_content_sizes(layout_context, style.writing_mode) + }), + Self::Independent(independent) => { + independent.outer_inline(layout_context, containing_block_writing_mode) + }, + BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(_) => ContentSizes::zero(), + BlockLevelBox::OutOfFlowFloatBox(_box_) => { + // TODO: Actually implement that. + ContentSizes::zero() + }, + } + } } enum NonReplacedContents<'a> { diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 55c325a3cd0..247d6bde904 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -22,7 +22,6 @@ use crate::geom::{PhysicalPoint, PhysicalRect, PhysicalSize}; use crate::positioned::AbsolutelyPositionedBox; use crate::positioned::PositioningContext; use crate::replaced::ReplacedContent; -use crate::sizing::ContentSizesRequest; use crate::style_ext::ComputedValuesExt; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; use crate::wrapper::GetStyleAndLayoutData; @@ -291,7 +290,6 @@ fn construct_for_root_element<'dom>( &info, display_inside, contents, - ContentSizesRequest::None, propagated_text_decoration_line, )), ) diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 5f9549238af..9b493f5e168 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -9,13 +9,14 @@ use crate::flow::BlockFormattingContext; use crate::fragments::{Fragment, Tag}; use crate::positioned::PositioningContext; use crate::replaced::ReplacedContent; -use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; +use crate::sizing::{self, ContentSizes}; use crate::style_ext::DisplayInside; use crate::ContainingBlock; use servo_arc::Arc; use std::convert::TryInto; +use style::logical_geometry::WritingMode; use style::properties::ComputedValues; -use style::values::computed::Length; +use style::values::computed::{Length, Percentage}; use style::values::specified::text::TextDecorationLine; /// https://drafts.csswg.org/css-display/#independent-formatting-context @@ -31,7 +32,7 @@ pub(crate) struct NonReplacedFormattingContext { #[serde(skip_serializing)] pub style: Arc<ComputedValues>, /// If it was requested during construction - pub content_sizes: BoxContentSizes, + pub content_sizes: Option<ContentSizes>, pub contents: NonReplacedFormattingContextContents, } @@ -65,41 +66,36 @@ impl IndependentFormattingContext { info: &NodeAndStyleInfo<impl NodeExt<'dom>>, display_inside: DisplayInside, contents: Contents, - content_sizes: ContentSizesRequest, propagated_text_decoration_line: TextDecorationLine, ) -> Self { match contents.try_into() { - Ok(non_replaced) => match display_inside { - DisplayInside::Flow | DisplayInside::FlowRoot => { - let (bfc, content_sizes) = BlockFormattingContext::construct( - context, - info, - non_replaced, - content_sizes, - propagated_text_decoration_line, - ); - Self::NonReplaced(NonReplacedFormattingContext { - tag: Tag::from_node_and_style_info(info), - style: Arc::clone(&info.style), - content_sizes, - contents: NonReplacedFormattingContextContents::Flow(bfc), - }) - }, - DisplayInside::Flex => { - let (fc, content_sizes) = FlexContainer::construct( - context, - info, - non_replaced, - content_sizes, - propagated_text_decoration_line, - ); - Self::NonReplaced(NonReplacedFormattingContext { - tag: Tag::from_node_and_style_info(info), - style: Arc::clone(&info.style), - content_sizes, - contents: NonReplacedFormattingContextContents::Flex(fc), - }) - }, + Ok(non_replaced) => { + let contents = match display_inside { + DisplayInside::Flow | DisplayInside::FlowRoot => { + NonReplacedFormattingContextContents::Flow( + BlockFormattingContext::construct( + context, + info, + non_replaced, + propagated_text_decoration_line, + ), + ) + }, + DisplayInside::Flex => { + NonReplacedFormattingContextContents::Flex(FlexContainer::construct( + context, + info, + non_replaced, + propagated_text_decoration_line, + )) + }, + }; + Self::NonReplaced(NonReplacedFormattingContext { + tag: Tag::from_node_and_style_info(info), + style: Arc::clone(&info.style), + content_sizes: None, + contents, + }) }, Err(contents) => Self::Replaced(ReplacedFormattingContext { tag: Tag::from_node_and_style_info(info), @@ -110,22 +106,16 @@ impl IndependentFormattingContext { } pub fn construct_for_text_runs<'dom>( - context: &LayoutContext, info: &NodeAndStyleInfo<impl NodeExt<'dom>>, runs: impl Iterator<Item = crate::flow::inline::TextRun>, - content_sizes: ContentSizesRequest, propagated_text_decoration_line: TextDecorationLine, ) -> Self { - let (bfc, content_sizes) = BlockFormattingContext::construct_for_text_runs( - context, - runs, - content_sizes, - propagated_text_decoration_line, - ); + let bfc = + BlockFormattingContext::construct_for_text_runs(runs, propagated_text_decoration_line); Self::NonReplaced(NonReplacedFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), - content_sizes, + content_sizes: None, contents: NonReplacedFormattingContextContents::Flow(bfc), }) } @@ -144,10 +134,40 @@ impl IndependentFormattingContext { } } - pub fn content_sizes(&self) -> ContentSizes { + pub fn outer_inline( + &mut self, + layout_context: &LayoutContext, + containing_block_writing_mode: WritingMode, + ) -> ContentSizes { + let (mut outer, percentages) = + self.outer_inline_and_percentages(layout_context, containing_block_writing_mode); + outer.adjust_for_pbm_percentages(percentages); + outer + } + + pub fn outer_inline_and_percentages( + &mut self, + layout_context: &LayoutContext, + containing_block_writing_mode: WritingMode, + ) -> (ContentSizes, Percentage) { match self { - Self::NonReplaced(inner) => inner.content_sizes.expect_inline().clone(), - Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style), + Self::NonReplaced(non_replaced) => { + let style = &non_replaced.style; + let content_sizes = &mut non_replaced.content_sizes; + let contents = &non_replaced.contents; + sizing::outer_inline_and_percentages(&style, containing_block_writing_mode, || { + content_sizes + .get_or_insert_with(|| { + contents.inline_content_sizes(layout_context, style.writing_mode) + }) + .clone() + }) + }, + Self::Replaced(replaced) => sizing::outer_inline_and_percentages( + &replaced.style, + containing_block_writing_mode, + || replaced.contents.inline_content_sizes(&replaced.style), + ), } } } @@ -175,4 +195,27 @@ impl NonReplacedFormattingContext { ), } } + + pub fn inline_content_sizes(&mut self, layout_context: &LayoutContext) -> ContentSizes { + let writing_mode = self.style.writing_mode; + let contents = &self.contents; + self.content_sizes + .get_or_insert_with(|| contents.inline_content_sizes(layout_context, writing_mode)) + .clone() + } +} + +impl NonReplacedFormattingContextContents { + pub fn inline_content_sizes( + &self, + layout_context: &LayoutContext, + containing_block_writing_mode: WritingMode, + ) -> ContentSizes { + match self { + Self::Flow(inner) => inner + .contents + .inline_content_sizes(layout_context, containing_block_writing_mode), + Self::Flex(inner) => inner.inline_content_sizes(), + } + } } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index dcb1388b36c..853b22347e9 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -9,7 +9,6 @@ use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::{BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::{LengthOrAuto, LengthPercentageOrAuto}; -use crate::sizing::ContentSizesRequest; use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend}; @@ -74,22 +73,12 @@ impl AbsolutelyPositionedBox { display_inside: DisplayInside, contents: Contents, ) -> Self { - // "Shrink-to-fit" in https://drafts.csswg.org/css2/visudet.html#abs-non-replaced-width - let content_sizes = ContentSizesRequest::inline_if( - // If inline-size is non-auto, that value is used without shrink-to-fit - !node_info.style.inline_size_is_length() && - // If it is, then the only case where shrink-to-fit is *not* used is - // if both offsets are non-auto, leaving inline-size as the only variable - // in the constraint equation. - !node_info.style.inline_box_offsets_are_both_non_auto(), - ); Self { context: IndependentFormattingContext::construct( context, node_info, display_inside, contents, - content_sizes, // Text decorations are not propagated to any out-of-flow descendants. TextDecorationLine::NONE, ), @@ -472,7 +461,9 @@ impl HoistedAbsolutelyPositionedBox { }; let available_size = cbis - anchor - pbm.padding_border_sums.inline - margin.inline_sum(); - non_replaced.content_sizes.shrink_to_fit(available_size) + non_replaced + .inline_content_sizes(layout_context) + .shrink_to_fit(available_size) }); let containing_block_for_children = ContainingBlock { diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index dd9574d4f85..ec07861c374 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -11,44 +11,6 @@ use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage, Percentage}; use style::Zero; -/// Which min/max-content values should be computed during box construction -#[derive(Clone, Copy, Debug)] -pub(crate) enum ContentSizesRequest { - Inline, - None, -} - -impl ContentSizesRequest { - pub fn inline_if(condition: bool) -> Self { - if condition { - Self::Inline - } else { - Self::None - } - } - - pub fn requests_inline(self) -> bool { - match self { - Self::Inline => true, - Self::None => false, - } - } - - pub fn if_requests_inline<T>(self, f: impl FnOnce() -> T) -> Option<T> { - match self { - Self::Inline => Some(f()), - Self::None => None, - } - } - - pub fn compute(self, compute_inline: impl FnOnce() -> ContentSizes) -> BoxContentSizes { - match self { - Self::Inline => BoxContentSizes::Inline(compute_inline()), - Self::None => BoxContentSizes::NoneWereRequested, - } - } -} - #[derive(Clone, Debug, Serialize)] pub(crate) struct ContentSizes { pub min_content: Length, @@ -90,27 +52,10 @@ impl ContentSizes { } } -/// Optional min/max-content for storage in the box tree -#[derive(Debug, Serialize)] -pub(crate) enum BoxContentSizes { - NoneWereRequested, // … during box construction - Inline(ContentSizes), -} - -impl BoxContentSizes { - pub fn expect_inline(&self) -> &ContentSizes { - match self { - Self::NoneWereRequested => panic!("Accessing content size that was not requested"), - Self::Inline(s) => s, - } - } - +impl ContentSizes { /// https://drafts.csswg.org/css2/visudet.html#shrink-to-fit-float - pub(crate) fn shrink_to_fit(&self, available_size: Length) -> Length { - let inline = self.expect_inline(); - available_size - .max(inline.min_content) - .min(inline.max_content) + pub fn shrink_to_fit(&self, available_size: Length) -> Length { + available_size.max(self.min_content).min(self.max_content) } } diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index bed574861cb..9ae86c7d991 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -75,7 +75,7 @@ where { /// Resolves `auto` values by calling `f`. #[inline] - pub fn auto_is(&self, f: impl Fn() -> LengthPercentage) -> LengthPercentage { + pub fn auto_is(&self, f: impl FnOnce() -> LengthPercentage) -> LengthPercentage { match self { LengthPercentageOrAuto::LengthPercentage(length) => length.clone(), LengthPercentageOrAuto::Auto => f(), |