From b66dd66403f990db1a287ea70841194aa388a519 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 10 Jun 2020 14:06:16 +0200 Subject: [PATCH 1/5] Rename contents to context in AbsolutelyPositionedBox --- components/layout_2020/flow/inline.rs | 2 +- components/layout_2020/flow/mod.rs | 2 +- components/layout_2020/positioned.rs | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index c1ca982d41b..ccb7d3caf39 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -294,7 +294,7 @@ impl InlineFormattingContext { InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc), InlineLevelBox::Atomic(a) => layout_atomic(layout_context, &mut ifc, a), InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { - let style = AtomicRef::map(box_.borrow(), |box_| &box_.contents.style); + let style = AtomicRef::map(box_.borrow(), |box_| &box_.context.style); let initial_start_corner = match Display::from(style.get_box().original_display) { Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 8558d7a68bd..f3dbbc19e9c 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -326,7 +326,7 @@ impl BlockLevelBox { positioning_context.push(hoisted_box); Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment { hoisted_fragment, - position: box_.borrow().contents.style.clone_position(), + position: box_.borrow().context.style.clone_position(), }) }, BlockLevelBox::OutOfFlowFloatBox(_box_) => { diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 1c873cbc8f5..838a36febe9 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -22,7 +22,7 @@ use style::Zero; #[derive(Debug, Serialize)] pub(crate) struct AbsolutelyPositionedBox { - pub contents: IndependentFormattingContext, + pub context: IndependentFormattingContext, } pub(crate) struct PositioningContext { @@ -84,7 +84,7 @@ impl AbsolutelyPositionedBox { !node_info.style.inline_box_offsets_are_both_non_auto(), ); Self { - contents: IndependentFormattingContext::construct( + context: IndependentFormattingContext::construct( context, node_info, display_inside, @@ -124,7 +124,7 @@ impl AbsolutelyPositionedBox { let box_offsets = { let box_ = self_.borrow(); - let box_offsets = box_.contents.style.box_offsets(containing_block); + let box_offsets = box_.context.style.box_offsets(containing_block); Vec2 { inline: absolute_box_offsets( initial_start_corner.inline, @@ -288,7 +288,7 @@ impl PositioningContext { let position = box_ .absolutely_positioned_box .borrow() - .contents + .context .style .clone_position(); match position { @@ -417,12 +417,12 @@ impl HoistedAbsolutelyPositionedBox { let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; let absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); - let style = &absolutely_positioned_box.contents.style; + let style = &absolutely_positioned_box.context.style; let pbm = style.padding_border_margin(&containing_block.into()); let size; let replaced_used_size; - match absolutely_positioned_box.contents.as_replaced() { + match absolutely_positioned_box.context.as_replaced() { Ok(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height @@ -474,11 +474,11 @@ impl HoistedAbsolutelyPositionedBox { |positioning_context| { let size; let fragments; - match absolutely_positioned_box.contents.as_replaced() { + match absolutely_positioned_box.context.as_replaced() { Ok(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height - let style = &absolutely_positioned_box.contents.style; + let style = &absolutely_positioned_box.context.style; size = replaced_used_size.unwrap(); fragments = replaced.make_fragments(style, size.clone()); }, @@ -495,7 +495,7 @@ impl HoistedAbsolutelyPositionedBox { pbm.padding_border_sums.inline - margin.inline_sum(); absolutely_positioned_box - .contents + .context .content_sizes .shrink_to_fit(available_size) }); @@ -550,7 +550,7 @@ impl HoistedAbsolutelyPositionedBox { }; BoxFragment::new( - absolutely_positioned_box.contents.tag, + absolutely_positioned_box.context.tag, style.clone(), fragments, content_rect, From b53959d23d54e3a30a4c9d01ab2eb5b605d2579c Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Wed, 10 Jun 2020 14:23:55 +0200 Subject: [PATCH 2/5] Move IndependentFormattingContext::as_replaced to IndependentFormattingContextContents --- components/layout_2020/flow/inline.rs | 2 +- components/layout_2020/flow/mod.rs | 14 ++++----- components/layout_2020/formatting_contexts.rs | 31 +++++++++++++------ components/layout_2020/positioned.rs | 4 +-- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index ccb7d3caf39..4736cb27203 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -556,7 +556,7 @@ fn layout_atomic( start_corner += &relative_adjustement(&atomic.style, ifc.containing_block) } - let fragment = match atomic.as_replaced() { + let fragment = match atomic.contents.as_replaced() { Ok(replaced) => { let size = replaced.used_size_as_if_inline_element(ifc.containing_block, &atomic.style, &pbm); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index f3dbbc19e9c..2056a1bab15 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -288,24 +288,24 @@ impl BlockLevelBox { ) }, )), - BlockLevelBox::Independent(contents) => { + BlockLevelBox::Independent(independent) => { Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( layout_context, containing_block, - &contents.style, - |positioning_context| match contents.as_replaced() { + &independent.style, + |positioning_context| match independent.contents.as_replaced() { Ok(replaced) => layout_in_flow_replaced_block_level( containing_block, - contents.tag, - &contents.style, + independent.tag, + &independent.style, replaced, ), Err(non_replaced) => layout_in_flow_non_replaced_block_level( layout_context, positioning_context, containing_block, - contents.tag, - &contents.style, + independent.tag, + &independent.style, NonReplacedContents::EstablishesAnIndependentFormattingContext( non_replaced, ), diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index 189ec36cb9a..d4c32e896cb 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -28,7 +28,7 @@ pub(crate) struct IndependentFormattingContext { /// If it was requested during construction pub content_sizes: BoxContentSizes, - contents: IndependentFormattingContextContents, + pub contents: IndependentFormattingContextContents, } pub(crate) struct IndependentLayout { @@ -38,10 +38,13 @@ pub(crate) struct IndependentLayout { pub content_block_size: Length, } +#[derive(Debug, Serialize)] +pub(crate) struct IndependentFormattingContextContents(IndependentFormattingContextContentsKind); + // Private so that code outside of this module cannot match variants. // It should got through methods instead. #[derive(Debug, Serialize)] -enum IndependentFormattingContextContents { +enum IndependentFormattingContextContentsKind { Flow(BlockFormattingContext), Flex(FlexContainer), @@ -80,7 +83,9 @@ impl IndependentFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents::Flow(bfc), + contents: IndependentFormattingContextContents( + IndependentFormattingContextContentsKind::Flow(bfc), + ), } }, DisplayInside::Flex => { @@ -95,7 +100,9 @@ impl IndependentFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents::Flex(fc), + contents: IndependentFormattingContextContents( + IndependentFormattingContextContentsKind::Flex(fc), + ), } }, }, @@ -106,7 +113,9 @@ impl IndependentFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents::Replaced(replaced), + contents: IndependentFormattingContextContents( + IndependentFormattingContextContentsKind::Replaced(replaced), + ), } }, } @@ -129,15 +138,19 @@ impl IndependentFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents::Flow(bfc), + contents: IndependentFormattingContextContents( + IndependentFormattingContextContentsKind::Flow(bfc), + ), } } +} - pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> { - use self::IndependentFormattingContextContents as Contents; +impl IndependentFormattingContextContents { + pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC<'_>> { + use self::IndependentFormattingContextContentsKind as Contents; use self::NonReplacedIFC as NR; use self::NonReplacedIFCKind as Kind; - match &self.contents { + match &self.0 { Contents::Replaced(r) => Ok(r), Contents::Flow(f) => Err(NR(Kind::Flow(f))), Contents::Flex(f) => Err(NR(Kind::Flex(f))), diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 838a36febe9..ca46f65cc2f 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -422,7 +422,7 @@ impl HoistedAbsolutelyPositionedBox { let size; let replaced_used_size; - match absolutely_positioned_box.context.as_replaced() { + match absolutely_positioned_box.context.contents.as_replaced() { Ok(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height @@ -474,7 +474,7 @@ impl HoistedAbsolutelyPositionedBox { |positioning_context| { let size; let fragments; - match absolutely_positioned_box.context.as_replaced() { + match absolutely_positioned_box.context.contents.as_replaced() { Ok(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height From d0a1066d2d4fee2ac307bb4ec11ac843a76a26f7 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Thu, 11 Jun 2020 14:10:26 +0200 Subject: [PATCH 3/5] Remove PositioningContext::create_and_layout_positioned It has only one call site. --- components/layout_2020/positioned.rs | 195 ++++++++++++--------------- 1 file changed, 85 insertions(+), 110 deletions(-) diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index ca46f65cc2f..2a6fb99764f 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -218,27 +218,6 @@ impl PositioningContext { new_fragment } - /// Given `fragment_layout_fn`, a closure which lays out a fragment in a provided - /// `PositioningContext`, create a positioning context for a positioned fragment and lay out - /// the fragment and all its children. Returns the resulting `BoxFragment`. - fn create_and_layout_positioned( - layout_context: &LayoutContext, - style: &ComputedValues, - for_nearest_containing_block_for_all_descendants: &mut Vec, - fragment_layout_fn: impl FnOnce(&mut Self) -> BoxFragment, - ) -> BoxFragment { - let mut new_context = match Self::new_for_style(style) { - Some(new_context) => new_context, - None => unreachable!(), - }; - - let mut new_fragment = fragment_layout_fn(&mut new_context); - new_context.layout_collected_children(layout_context, &mut new_fragment); - for_nearest_containing_block_for_all_descendants - .extend(new_context.for_nearest_containing_block_for_all_descendants); - new_fragment - } - // Lay out the hoisted boxes collected into this `PositioningContext` and add them // to the given `BoxFragment`. pub fn layout_collected_children( @@ -467,100 +446,96 @@ impl HoistedAbsolutelyPositionedBox { block_end: block_axis.margin_end, }; - PositioningContext::create_and_layout_positioned( - layout_context, - style, - for_nearest_containing_block_for_all_descendants, - |positioning_context| { - let size; - let fragments; - match absolutely_positioned_box.context.contents.as_replaced() { - Ok(replaced) => { - // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width - // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height - let style = &absolutely_positioned_box.context.style; - size = replaced_used_size.unwrap(); - fragments = replaced.make_fragments(style, size.clone()); - }, - Err(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.auto_is(|| { - let anchor = match inline_axis.anchor { - Anchor::Start(start) => start, - Anchor::End(end) => end, - }; - let available_size = cbis - - anchor - - pbm.padding_border_sums.inline - - margin.inline_sum(); - absolutely_positioned_box - .context - .content_sizes - .shrink_to_fit(available_size) - }); - - let containing_block_for_children = ContainingBlock { - inline_size, - block_size: block_axis.size, - style, + let mut positioning_context = PositioningContext::new_for_style(style).unwrap(); + let mut new_fragment = { + let size; + let fragments; + match absolutely_positioned_box.context.contents.as_replaced() { + Ok(replaced) => { + // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width + // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height + let style = &absolutely_positioned_box.context.style; + size = replaced_used_size.unwrap(); + fragments = replaced.make_fragments(style, size.clone()); + }, + Err(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.auto_is(|| { + let anchor = match inline_axis.anchor { + Anchor::Start(start) => start, + Anchor::End(end) => end, }; - // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows - assert_eq!( - containing_block.style.writing_mode, - containing_block_for_children.style.writing_mode, - "Mixed writing modes are not supported yet" - ); - let dummy_tree_rank = 0; - let independent_layout = non_replaced.layout( - layout_context, - positioning_context, - &containing_block_for_children, - dummy_tree_rank, - ); + let available_size = + cbis - anchor - pbm.padding_border_sums.inline - margin.inline_sum(); + absolutely_positioned_box + .context + .content_sizes + .shrink_to_fit(available_size) + }); - size = Vec2 { - inline: inline_size, - block: block_axis - .size - .auto_is(|| independent_layout.content_block_size), - }; - fragments = independent_layout.fragments - }, - }; + let containing_block_for_children = ContainingBlock { + inline_size, + block_size: block_axis.size, + style, + }; + // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows + assert_eq!( + containing_block.style.writing_mode, + containing_block_for_children.style.writing_mode, + "Mixed writing modes are not supported yet" + ); + let dummy_tree_rank = 0; + let independent_layout = non_replaced.layout( + layout_context, + &mut positioning_context, + &containing_block_for_children, + dummy_tree_rank, + ); - let pb = &pbm.padding + &pbm.border; - let inline_start = match inline_axis.anchor { - Anchor::Start(start) => start + pb.inline_start + margin.inline_start, - Anchor::End(end) => { - cbis - end - pb.inline_end - margin.inline_end - size.inline - }, - }; - let block_start = match block_axis.anchor { - Anchor::Start(start) => start + pb.block_start + margin.block_start, - Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - size.block, - }; + size = Vec2 { + inline: inline_size, + block: block_axis + .size + .auto_is(|| independent_layout.content_block_size), + }; + fragments = independent_layout.fragments + }, + }; - let content_rect = Rect { - start_corner: Vec2 { - inline: inline_start, - block: block_start, - }, - size, - }; + let pb = &pbm.padding + &pbm.border; + let inline_start = match inline_axis.anchor { + Anchor::Start(start) => start + pb.inline_start + margin.inline_start, + Anchor::End(end) => cbis - end - pb.inline_end - margin.inline_end - size.inline, + }; + let block_start = match block_axis.anchor { + Anchor::Start(start) => start + pb.block_start + margin.block_start, + Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - size.block, + }; - BoxFragment::new( - absolutely_positioned_box.context.tag, - style.clone(), - fragments, - content_rect, - pbm.padding, - pbm.border, - margin, - CollapsedBlockMargins::zero(), - ) - }, - ) + let content_rect = Rect { + start_corner: Vec2 { + inline: inline_start, + block: block_start, + }, + size, + }; + + BoxFragment::new( + absolutely_positioned_box.context.tag, + style.clone(), + fragments, + content_rect, + pbm.padding, + pbm.border, + margin, + CollapsedBlockMargins::zero(), + ) + }; + positioning_context.layout_collected_children(layout_context, &mut new_fragment); + for_nearest_containing_block_for_all_descendants + .extend(positioning_context.for_nearest_containing_block_for_all_descendants); + new_fragment } } From 07d8c28d4aa8c2834bba0759321ae1363ba43d54 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 15 Jun 2020 13:35:46 +0200 Subject: [PATCH 4/5] Make outer_inline and outer_inline_and_percentages free functions They now take a closure that will compute the content sizes on demand. --- components/layout_2020/flow/construct.rs | 22 +-- components/layout_2020/flow/inline.rs | 5 +- components/layout_2020/sizing.rs | 167 +++++++++++------------ 3 files changed, 97 insertions(+), 97 deletions(-) diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index f72bbf1ad13..666a39d2932 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -14,7 +14,7 @@ use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::Tag; use crate::positioned::AbsolutelyPositionedBox; -use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; +use crate::sizing::{self, BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::style_ext::{ComputedValuesExt, DisplayGeneratingBox, DisplayInside, DisplayOutside}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; @@ -701,10 +701,11 @@ where ), ); if let Some(to) = max_assign_in_flow_outer_content_sizes_to { - to.max_assign( - &box_content_sizes - .outer_inline(&info.style, not_actually_containing_block_writing_mode), - ) + to.max_assign(&sizing::outer_inline( + &info.style, + not_actually_containing_block_writing_mode, + || box_content_sizes.expect_inline().clone(), + )) } let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock { tag: Tag::from_node_and_style_info(info), @@ -731,12 +732,11 @@ where propagated_text_decoration_line, ); if let Some(to) = max_assign_in_flow_outer_content_sizes_to { - to.max_assign( - &contents.content_sizes.outer_inline( - &contents.style, - not_actually_containing_block_writing_mode, - ), - ) + to.max_assign(&sizing::outer_inline( + &contents.style, + not_actually_containing_block_writing_mode, + || contents.content_sizes.expect_inline().clone(), + )) } ( ArcRefCell::new(BlockLevelBox::Independent(contents)), diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 4736cb27203..7872dd8110e 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::ContentSizes; +use crate::sizing::{self, ContentSizes}; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; use crate::ContainingBlock; use app_units::Au; @@ -200,9 +200,10 @@ impl InlineFormattingContext { } }, InlineLevelBox::Atomic(atomic) => { - let (outer, pc) = atomic.content_sizes.outer_inline_and_percentages( + let (outer, pc) = sizing::outer_inline_and_percentages( &atomic.style, self.containing_block_writing_mode, + || atomic.content_sizes.expect_inline().clone(), ); self.current_line.min_content += outer.min_content; self.current_line.max_content += outer.max_content; diff --git a/components/layout_2020/sizing.rs b/components/layout_2020/sizing.rs index af8c6ac0ecb..dd9574d4f85 100644 --- a/components/layout_2020/sizing.rs +++ b/components/layout_2020/sizing.rs @@ -64,7 +64,7 @@ impl ContentSizes { } } - fn map(&self, f: impl Fn(Length) -> Length) -> Self { + pub fn map(&self, f: impl Fn(Length) -> Length) -> Self { Self { min_content: f(self.min_content), max_content: f(self.max_content), @@ -98,95 +98,13 @@ pub(crate) enum BoxContentSizes { } impl BoxContentSizes { - fn expect_inline(&self) -> &ContentSizes { + pub fn expect_inline(&self) -> &ContentSizes { match self { Self::NoneWereRequested => panic!("Accessing content size that was not requested"), Self::Inline(s) => s, } } - /// https://dbaron.org/css/intrinsic/#outer-intrinsic - pub fn outer_inline( - &self, - style: &ComputedValues, - containing_block_writing_mode: WritingMode, - ) -> ContentSizes { - let (mut outer, percentages) = - self.outer_inline_and_percentages(style, containing_block_writing_mode); - outer.adjust_for_pbm_percentages(percentages); - outer - } - - pub(crate) fn outer_inline_and_percentages( - &self, - style: &ComputedValues, - containing_block_writing_mode: WritingMode, - ) -> (ContentSizes, Percentage) { - let padding = style.padding(containing_block_writing_mode); - let border = style.border_width(containing_block_writing_mode); - let margin = style.margin(containing_block_writing_mode); - - let mut pbm_percentages = Percentage::zero(); - let mut decompose = |x: &LengthPercentage| { - pbm_percentages += x.to_percentage().unwrap_or_else(Zero::zero); - x.to_length().unwrap_or_else(Zero::zero) - }; - let pb_lengths = - border.inline_sum() + decompose(padding.inline_start) + decompose(padding.inline_end); - let mut m_lengths = Length::zero(); - if let Some(m) = margin.inline_start.non_auto() { - m_lengths += decompose(m) - } - if let Some(m) = margin.inline_end.non_auto() { - m_lengths += decompose(m) - } - - let box_sizing = style.get_position().box_sizing; - let inline_size = style - .box_size(containing_block_writing_mode) - .inline - .non_auto() - // Percentages for 'width' are treated as 'auto' - .and_then(|lp| lp.to_length()); - let min_inline_size = style - .min_box_size(containing_block_writing_mode) - .inline - // Percentages for 'min-width' are treated as zero - .percentage_relative_to(Length::zero()) - // FIXME: 'auto' is not zero in Flexbox - .auto_is(Length::zero); - let max_inline_size = style - .max_box_size(containing_block_writing_mode) - .inline - // Percentages for 'max-width' are treated as 'none' - .and_then(|lp| lp.to_length()); - let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size); - - let border_box_sizes = match inline_size { - Some(non_auto) => { - let clamped = clamp(non_auto); - let border_box_size = match box_sizing { - BoxSizing::ContentBox => clamped + pb_lengths, - BoxSizing::BorderBox => clamped, - }; - ContentSizes { - min_content: border_box_size, - max_content: border_box_size, - } - }, - None => self.expect_inline().map(|content_box_size| { - match box_sizing { - // Clamp to 'min-width' and 'max-width', which are sizing the… - BoxSizing::ContentBox => clamp(content_box_size) + pb_lengths, - BoxSizing::BorderBox => clamp(content_box_size + pb_lengths), - } - }), - }; - - let outer = border_box_sizes.map(|s| s + m_lengths); - (outer, pbm_percentages) - } - /// 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(); @@ -195,3 +113,84 @@ impl BoxContentSizes { .min(inline.max_content) } } + +pub(crate) fn outer_inline( + style: &ComputedValues, + containing_block_writing_mode: WritingMode, + get_content_size: impl FnOnce() -> ContentSizes, +) -> ContentSizes { + let (mut outer, percentages) = + outer_inline_and_percentages(style, containing_block_writing_mode, get_content_size); + outer.adjust_for_pbm_percentages(percentages); + outer +} + +pub(crate) fn outer_inline_and_percentages( + style: &ComputedValues, + containing_block_writing_mode: WritingMode, + get_content_size: impl FnOnce() -> ContentSizes, +) -> (ContentSizes, Percentage) { + let padding = style.padding(containing_block_writing_mode); + let border = style.border_width(containing_block_writing_mode); + let margin = style.margin(containing_block_writing_mode); + + let mut pbm_percentages = Percentage::zero(); + let mut decompose = |x: &LengthPercentage| { + pbm_percentages += x.to_percentage().unwrap_or_else(Zero::zero); + x.to_length().unwrap_or_else(Zero::zero) + }; + let pb_lengths = + border.inline_sum() + decompose(padding.inline_start) + decompose(padding.inline_end); + let mut m_lengths = Length::zero(); + if let Some(m) = margin.inline_start.non_auto() { + m_lengths += decompose(m) + } + if let Some(m) = margin.inline_end.non_auto() { + m_lengths += decompose(m) + } + + let box_sizing = style.get_position().box_sizing; + let inline_size = style + .box_size(containing_block_writing_mode) + .inline + .non_auto() + // Percentages for 'width' are treated as 'auto' + .and_then(|lp| lp.to_length()); + let min_inline_size = style + .min_box_size(containing_block_writing_mode) + .inline + // Percentages for 'min-width' are treated as zero + .percentage_relative_to(Length::zero()) + // FIXME: 'auto' is not zero in Flexbox + .auto_is(Length::zero); + let max_inline_size = style + .max_box_size(containing_block_writing_mode) + .inline + // Percentages for 'max-width' are treated as 'none' + .and_then(|lp| lp.to_length()); + let clamp = |l: Length| l.clamp_between_extremums(min_inline_size, max_inline_size); + + let border_box_sizes = match inline_size { + Some(non_auto) => { + let clamped = clamp(non_auto); + let border_box_size = match box_sizing { + BoxSizing::ContentBox => clamped + pb_lengths, + BoxSizing::BorderBox => clamped, + }; + ContentSizes { + min_content: border_box_size, + max_content: border_box_size, + } + }, + None => get_content_size().map(|content_box_size| { + match box_sizing { + // Clamp to 'min-width' and 'max-width', which are sizing the… + BoxSizing::ContentBox => clamp(content_box_size) + pb_lengths, + BoxSizing::BorderBox => clamp(content_box_size + pb_lengths), + } + }), + }; + + let outer = border_box_sizes.map(|s| s + m_lengths); + (outer, pbm_percentages) +} From db80b8e3c15006c54ba2d2a9c919ca7f87ba2b35 Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Mon, 15 Jun 2020 14:40:01 +0200 Subject: [PATCH 5/5] Make IndependentFormattingContext an enum --- components/layout_2020/flexbox/construct.rs | 2 +- components/layout_2020/flow/construct.rs | 8 +- components/layout_2020/flow/inline.rs | 52 ++++--- components/layout_2020/flow/mod.rs | 71 ++++++---- components/layout_2020/formatting_contexts.rs | 132 +++++++++--------- components/layout_2020/positioned.rs | 81 ++++++----- 6 files changed, 183 insertions(+), 163 deletions(-) diff --git a/components/layout_2020/flexbox/construct.rs b/components/layout_2020/flexbox/construct.rs index e23858efe7f..385b45985e1 100644 --- a/components/layout_2020/flexbox/construct.rs +++ b/components/layout_2020/flexbox/construct.rs @@ -204,7 +204,7 @@ where // https://drafts.csswg.org/css-flexbox/#order-modified-document-order children.sort_by_key(|child| match &*child.borrow() { - FlexLevelBox::FlexItem(item) => item.style.clone_order(), + FlexLevelBox::FlexItem(item) => item.style().clone_order(), // “Absolutely-positioned children of a flex container are treated // as having order: 0 for the purpose of determining their painting order diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 666a39d2932..7d72209c6e8 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -723,7 +723,7 @@ where max_assign_in_flow_outer_content_sizes_to.is_some() && !info.style.inline_size_is_length(), ); - let contents = IndependentFormattingContext::construct( + let context = IndependentFormattingContext::construct( context, info, display_inside, @@ -733,13 +733,13 @@ where ); if let Some(to) = max_assign_in_flow_outer_content_sizes_to { to.max_assign(&sizing::outer_inline( - &contents.style, + &context.style(), not_actually_containing_block_writing_mode, - || contents.content_sizes.expect_inline().clone(), + || context.content_sizes(), )) } ( - ArcRefCell::new(BlockLevelBox::Independent(contents)), + ArcRefCell::new(BlockLevelBox::Independent(context)), ContainsFloats::No, ) }, diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 7872dd8110e..f6895258dab 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -155,7 +155,7 @@ impl InlineFormattingContext { impl Computation<'_> { fn traverse(&mut self, inline_level_boxes: &[ArcRefCell]) { for inline_level_box in inline_level_boxes { - match &*inline_level_box.borrow() { + match &mut *inline_level_box.borrow_mut() { InlineLevelBox::InlineBox(inline_box) => { let padding = inline_box.style.padding(self.containing_block_writing_mode); @@ -201,9 +201,9 @@ impl InlineFormattingContext { }, InlineLevelBox::Atomic(atomic) => { let (outer, pc) = sizing::outer_inline_and_percentages( - &atomic.style, + &atomic.style(), self.containing_block_writing_mode, - || atomic.content_sizes.expect_inline().clone(), + || atomic.content_sizes(), ); self.current_line.min_content += outer.min_content; self.current_line.max_content += outer.max_content; @@ -295,7 +295,7 @@ impl InlineFormattingContext { InlineLevelBox::TextRun(run) => run.layout(layout_context, &mut ifc), InlineLevelBox::Atomic(a) => layout_atomic(layout_context, &mut ifc, a), InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { - let style = AtomicRef::map(box_.borrow(), |box_| &box_.context.style); + let style = AtomicRef::map(box_.borrow(), |box_| box_.context.style()); let initial_start_corner = match Display::from(style.get_box().original_display) { Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { @@ -545,7 +545,8 @@ fn layout_atomic( ifc: &mut InlineFormattingContextState, atomic: &mut IndependentFormattingContext, ) { - let pbm = atomic.style.padding_border_margin(&ifc.containing_block); + let style = atomic.style(); + let pbm = style.padding_border_margin(&ifc.containing_block); let margin = pbm.margin.auto_is(Length::zero); let pbm_sums = &(&pbm.padding + &pbm.border) + &margin; ifc.inline_position += pbm_sums.inline_start; @@ -553,19 +554,24 @@ fn layout_atomic( block: pbm_sums.block_start, inline: ifc.inline_position - ifc.current_nesting_level.inline_start, }; - if atomic.style.clone_position().is_relative() { - start_corner += &relative_adjustement(&atomic.style, ifc.containing_block) + if style.clone_position().is_relative() { + start_corner += &relative_adjustement(&style, ifc.containing_block) } - let fragment = match atomic.contents.as_replaced() { - Ok(replaced) => { - let size = - replaced.used_size_as_if_inline_element(ifc.containing_block, &atomic.style, &pbm); - let fragments = replaced.make_fragments(&atomic.style, size.clone()); + let fragment = match atomic { + IndependentFormattingContext::Replaced(replaced) => { + let size = replaced.contents.used_size_as_if_inline_element( + ifc.containing_block, + &replaced.style, + &pbm, + ); + let fragments = replaced + .contents + .make_fragments(&replaced.style, size.clone()); let content_rect = Rect { start_corner, size }; BoxFragment::new( - atomic.tag, - atomic.style.clone(), + replaced.tag, + replaced.style.clone(), fragments, content_rect, pbm.padding, @@ -574,12 +580,14 @@ fn layout_atomic( CollapsedBlockMargins::zero(), ) }, - Err(non_replaced) => { - let box_size = atomic.style.content_box_size(&ifc.containing_block, &pbm); - let max_box_size = atomic + IndependentFormattingContext::NonReplaced(non_replaced) => { + let box_size = non_replaced + .style + .content_box_size(&ifc.containing_block, &pbm); + let max_box_size = non_replaced .style .content_max_box_size(&ifc.containing_block, &pbm); - let min_box_size = atomic + let min_box_size = non_replaced .style .content_min_box_size(&ifc.containing_block, &pbm) .auto_is(Length::zero); @@ -587,7 +595,7 @@ 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(); - atomic.content_sizes.shrink_to_fit(available_size) + non_replaced.content_sizes.shrink_to_fit(available_size) }); // https://drafts.csswg.org/css2/visudet.html#min-max-widths @@ -599,7 +607,7 @@ fn layout_atomic( let containing_block_for_children = ContainingBlock { inline_size, block_size: box_size.block, - style: &atomic.style, + style: &non_replaced.style, }; assert_eq!( ifc.containing_block.style.writing_mode, @@ -635,8 +643,8 @@ fn layout_atomic( }, }; BoxFragment::new( - atomic.tag, - atomic.style.clone(), + non_replaced.tag, + non_replaced.style.clone(), independent_layout.fragments, content_rect, pbm.padding, diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 2056a1bab15..b8c0d7e500d 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -8,7 +8,9 @@ use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::inline::InlineFormattingContext; -use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout, NonReplacedIFC}; +use crate::formatting_contexts::{ + IndependentFormattingContext, IndependentLayout, NonReplacedFormattingContext, +}; use crate::fragments::{ AbsoluteOrFixedPositionedFragment, AnonymousFragment, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, Tag, @@ -288,32 +290,43 @@ impl BlockLevelBox { ) }, )), - BlockLevelBox::Independent(independent) => { - Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( - layout_context, - containing_block, - &independent.style, - |positioning_context| match independent.contents.as_replaced() { - Ok(replaced) => layout_in_flow_replaced_block_level( - containing_block, - independent.tag, - &independent.style, - replaced, - ), - Err(non_replaced) => layout_in_flow_non_replaced_block_level( - layout_context, - positioning_context, - containing_block, - independent.tag, - &independent.style, - NonReplacedContents::EstablishesAnIndependentFormattingContext( - non_replaced, - ), - tree_rank, - float_context, - ), - }, - )) + 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.tag, + &replaced.style, + &replaced.contents, + ) + }, + )) + }, + IndependentFormattingContext::NonReplaced(non_replaced) => { + Fragment::Box(positioning_context.layout_maybe_position_relative_fragment( + layout_context, + containing_block, + &non_replaced.style, + |positioning_context| { + layout_in_flow_non_replaced_block_level( + layout_context, + positioning_context, + containing_block, + non_replaced.tag, + &non_replaced.style, + NonReplacedContents::EstablishesAnIndependentFormattingContext( + non_replaced, + ), + tree_rank, + float_context, + ) + }, + )) + }, }, BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { let hoisted_box = AbsolutelyPositionedBox::to_hoisted( @@ -326,7 +339,7 @@ impl BlockLevelBox { positioning_context.push(hoisted_box); Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment { hoisted_fragment, - position: box_.borrow().context.style.clone_position(), + position: box_.borrow().context.style().clone_position(), }) }, BlockLevelBox::OutOfFlowFloatBox(_box_) => { @@ -341,7 +354,7 @@ impl BlockLevelBox { enum NonReplacedContents<'a> { SameFormattingContextBlock(&'a BlockContainer), - EstablishesAnIndependentFormattingContext(NonReplacedIFC<'a>), + EstablishesAnIndependentFormattingContext(&'a NonReplacedFormattingContext), } /// https://drafts.csswg.org/css2/visudet.html#blockwidth diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs index d4c32e896cb..5f9549238af 100644 --- a/components/layout_2020/formatting_contexts.rs +++ b/components/layout_2020/formatting_contexts.rs @@ -9,7 +9,7 @@ use crate::flow::BlockFormattingContext; use crate::fragments::{Fragment, Tag}; use crate::positioned::PositioningContext; use crate::replaced::ReplacedContent; -use crate::sizing::{BoxContentSizes, ContentSizesRequest}; +use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::style_ext::DisplayInside; use crate::ContainingBlock; use servo_arc::Arc; @@ -20,15 +20,36 @@ use style::values::specified::text::TextDecorationLine; /// https://drafts.csswg.org/css-display/#independent-formatting-context #[derive(Debug, Serialize)] -pub(crate) struct IndependentFormattingContext { +pub(crate) enum IndependentFormattingContext { + NonReplaced(NonReplacedFormattingContext), + Replaced(ReplacedFormattingContext), +} + +#[derive(Debug, Serialize)] +pub(crate) struct NonReplacedFormattingContext { pub tag: Tag, #[serde(skip_serializing)] pub style: Arc, - /// If it was requested during construction pub content_sizes: BoxContentSizes, + pub contents: NonReplacedFormattingContextContents, +} - pub contents: IndependentFormattingContextContents, +#[derive(Debug, Serialize)] +pub(crate) struct ReplacedFormattingContext { + pub tag: Tag, + #[serde(skip_serializing)] + pub style: Arc, + pub contents: ReplacedContent, +} + +// Private so that code outside of this module cannot match variants. +// It should got through methods instead. +#[derive(Debug, Serialize)] +pub(crate) enum NonReplacedFormattingContextContents { + Flow(BlockFormattingContext), + Flex(FlexContainer), + // Other layout modes go here } pub(crate) struct IndependentLayout { @@ -38,28 +59,6 @@ pub(crate) struct IndependentLayout { pub content_block_size: Length, } -#[derive(Debug, Serialize)] -pub(crate) struct IndependentFormattingContextContents(IndependentFormattingContextContentsKind); - -// Private so that code outside of this module cannot match variants. -// It should got through methods instead. -#[derive(Debug, Serialize)] -enum IndependentFormattingContextContentsKind { - Flow(BlockFormattingContext), - Flex(FlexContainer), - - // Not called FC in specs, but behaves close enough - Replaced(ReplacedContent), - // Other layout modes go here -} - -pub(crate) struct NonReplacedIFC<'a>(NonReplacedIFCKind<'a>); - -enum NonReplacedIFCKind<'a> { - Flow(&'a BlockFormattingContext), - Flex(&'a FlexContainer), -} - impl IndependentFormattingContext { pub fn construct<'dom>( context: &LayoutContext, @@ -79,14 +78,12 @@ impl IndependentFormattingContext { content_sizes, propagated_text_decoration_line, ); - Self { + Self::NonReplaced(NonReplacedFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents( - IndependentFormattingContextContentsKind::Flow(bfc), - ), - } + contents: NonReplacedFormattingContextContents::Flow(bfc), + }) }, DisplayInside::Flex => { let (fc, content_sizes) = FlexContainer::construct( @@ -96,28 +93,19 @@ impl IndependentFormattingContext { content_sizes, propagated_text_decoration_line, ); - Self { + Self::NonReplaced(NonReplacedFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents( - IndependentFormattingContextContentsKind::Flex(fc), - ), - } + contents: NonReplacedFormattingContextContents::Flex(fc), + }) }, }, - Err(replaced) => { - let content_sizes = - content_sizes.compute(|| replaced.inline_content_sizes(&info.style)); - Self { - tag: Tag::from_node_and_style_info(info), - style: Arc::clone(&info.style), - content_sizes, - contents: IndependentFormattingContextContents( - IndependentFormattingContextContentsKind::Replaced(replaced), - ), - } - }, + Err(contents) => Self::Replaced(ReplacedFormattingContext { + tag: Tag::from_node_and_style_info(info), + style: Arc::clone(&info.style), + contents, + }), } } @@ -134,31 +122,37 @@ impl IndependentFormattingContext { content_sizes, propagated_text_decoration_line, ); - Self { + Self::NonReplaced(NonReplacedFormattingContext { tag: Tag::from_node_and_style_info(info), style: Arc::clone(&info.style), content_sizes, - contents: IndependentFormattingContextContents( - IndependentFormattingContextContentsKind::Flow(bfc), - ), + contents: NonReplacedFormattingContextContents::Flow(bfc), + }) + } + + pub fn style(&self) -> &Arc { + match self { + Self::NonReplaced(inner) => &inner.style, + Self::Replaced(inner) => &inner.style, + } + } + + pub fn tag(&self) -> Tag { + match self { + Self::NonReplaced(inner) => inner.tag, + Self::Replaced(inner) => inner.tag, + } + } + + pub fn content_sizes(&self) -> ContentSizes { + match self { + Self::NonReplaced(inner) => inner.content_sizes.expect_inline().clone(), + Self::Replaced(inner) => inner.contents.inline_content_sizes(&inner.style), } } } -impl IndependentFormattingContextContents { - pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC<'_>> { - use self::IndependentFormattingContextContentsKind as Contents; - use self::NonReplacedIFC as NR; - use self::NonReplacedIFCKind as Kind; - match &self.0 { - Contents::Replaced(r) => Ok(r), - Contents::Flow(f) => Err(NR(Kind::Flow(f))), - Contents::Flex(f) => Err(NR(Kind::Flex(f))), - } - } -} - -impl NonReplacedIFC<'_> { +impl NonReplacedFormattingContext { pub fn layout( &self, layout_context: &LayoutContext, @@ -166,14 +160,14 @@ impl NonReplacedIFC<'_> { containing_block: &ContainingBlock, tree_rank: usize, ) -> IndependentLayout { - match &self.0 { - NonReplacedIFCKind::Flow(bfc) => bfc.layout( + match &self.contents { + NonReplacedFormattingContextContents::Flow(bfc) => bfc.layout( layout_context, positioning_context, containing_block, tree_rank, ), - NonReplacedIFCKind::Flex(fc) => fc.layout( + NonReplacedFormattingContextContents::Flex(fc) => fc.layout( layout_context, positioning_context, containing_block, diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index 2a6fb99764f..dcb1388b36c 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -124,7 +124,7 @@ impl AbsolutelyPositionedBox { let box_offsets = { let box_ = self_.borrow(); - let box_offsets = box_.context.style.box_offsets(containing_block); + let box_offsets = box_.context.style().box_offsets(containing_block); Vec2 { inline: absolute_box_offsets( initial_start_corner.inline, @@ -268,7 +268,7 @@ impl PositioningContext { .absolutely_positioned_box .borrow() .context - .style + .style() .clone_position(); match position { Position::Fixed => {}, // fall through @@ -395,29 +395,30 @@ impl HoistedAbsolutelyPositionedBox { ) -> BoxFragment { let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; - let absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); - let style = &absolutely_positioned_box.context.style; - let pbm = style.padding_border_margin(&containing_block.into()); + let mut absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); + let pbm = absolutely_positioned_box + .context + .style() + .padding_border_margin(&containing_block.into()); - let size; - let replaced_used_size; - match absolutely_positioned_box.context.contents.as_replaced() { - Ok(replaced) => { + let size = match &absolutely_positioned_box.context { + IndependentFormattingContext::Replaced(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height - let used_size = - replaced.used_size_as_if_inline_element(&containing_block.into(), style, &pbm); - size = Vec2 { + let used_size = replaced.contents.used_size_as_if_inline_element( + &containing_block.into(), + &replaced.style, + &pbm, + ); + Vec2 { inline: LengthOrAuto::LengthPercentage(used_size.inline), block: LengthOrAuto::LengthPercentage(used_size.block), - }; - replaced_used_size = Some(used_size); + } }, - Err(_non_replaced) => { - size = style.content_box_size(&containing_block.into(), &pbm); - replaced_used_size = None; - }, - } + IndependentFormattingContext::NonReplaced(non_replaced) => non_replaced + .style + .content_box_size(&containing_block.into(), &pbm), + }; let inline_axis = solve_axis( cbis, @@ -446,19 +447,22 @@ impl HoistedAbsolutelyPositionedBox { block_end: block_axis.margin_end, }; - let mut positioning_context = PositioningContext::new_for_style(style).unwrap(); + let mut positioning_context = + PositioningContext::new_for_style(absolutely_positioned_box.context.style()).unwrap(); let mut new_fragment = { - let size; + let content_size; let fragments; - match absolutely_positioned_box.context.contents.as_replaced() { - Ok(replaced) => { + match &mut absolutely_positioned_box.context { + IndependentFormattingContext::Replaced(replaced) => { // https://drafts.csswg.org/css2/visudet.html#abs-replaced-width // https://drafts.csswg.org/css2/visudet.html#abs-replaced-height - let style = &absolutely_positioned_box.context.style; - size = replaced_used_size.unwrap(); - fragments = replaced.make_fragments(style, size.clone()); + let style = &replaced.style; + content_size = size.auto_is(|| unreachable!()); + fragments = replaced + .contents + .make_fragments(style, content_size.clone()); }, - Err(non_replaced) => { + IndependentFormattingContext::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.auto_is(|| { @@ -468,16 +472,13 @@ impl HoistedAbsolutelyPositionedBox { }; let available_size = cbis - anchor - pbm.padding_border_sums.inline - margin.inline_sum(); - absolutely_positioned_box - .context - .content_sizes - .shrink_to_fit(available_size) + non_replaced.content_sizes.shrink_to_fit(available_size) }); let containing_block_for_children = ContainingBlock { inline_size, block_size: block_axis.size, - style, + style: &non_replaced.style, }; // https://drafts.csswg.org/css-writing-modes/#orthogonal-flows assert_eq!( @@ -493,7 +494,7 @@ impl HoistedAbsolutelyPositionedBox { dummy_tree_rank, ); - size = Vec2 { + content_size = Vec2 { inline: inline_size, block: block_axis .size @@ -506,11 +507,15 @@ impl HoistedAbsolutelyPositionedBox { let pb = &pbm.padding + &pbm.border; let inline_start = match inline_axis.anchor { Anchor::Start(start) => start + pb.inline_start + margin.inline_start, - Anchor::End(end) => cbis - end - pb.inline_end - margin.inline_end - size.inline, + Anchor::End(end) => { + cbis - end - pb.inline_end - margin.inline_end - content_size.inline + }, }; let block_start = match block_axis.anchor { Anchor::Start(start) => start + pb.block_start + margin.block_start, - Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - size.block, + Anchor::End(end) => { + cbbs - end - pb.block_end - margin.block_end - content_size.block + }, }; let content_rect = Rect { @@ -518,12 +523,12 @@ impl HoistedAbsolutelyPositionedBox { inline: inline_start, block: block_start, }, - size, + size: content_size, }; BoxFragment::new( - absolutely_positioned_box.context.tag, - style.clone(), + absolutely_positioned_box.context.tag(), + absolutely_positioned_box.context.style().clone(), fragments, content_rect, pbm.padding,