diff options
author | Anthony Ramine <nox@nox.paris> | 2020-06-09 13:44:43 +0200 |
---|---|---|
committer | Anthony Ramine <nox@nox.paris> | 2020-06-09 15:13:18 +0200 |
commit | e975d24c4bb705f7897edde83f61725655399e8f (patch) | |
tree | 24785850cbc7a7bf9f635b01986ed875f241e530 | |
parent | e044d8582c854d29479fe4235058962dd07ecb64 (diff) | |
download | servo-e975d24c4bb705f7897edde83f61725655399e8f.tar.gz servo-e975d24c4bb705f7897edde83f61725655399e8f.zip |
Store abspos boxes in a RefCell too
We want to mutate them when lazily computing their content sizes, but they
are behind an Arc for the hoisting infra, so it also needs its own layer
of inner mutability.
-rw-r--r-- | components/layout_2020/flexbox.rs | 11 | ||||
-rw-r--r-- | components/layout_2020/flow/construct.rs | 18 | ||||
-rw-r--r-- | components/layout_2020/flow/inline.rs | 8 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 4 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 57 | ||||
-rw-r--r-- | components/layout_2020/style_ext.rs | 16 |
7 files changed, 65 insertions, 53 deletions
diff --git a/components/layout_2020/flexbox.rs b/components/layout_2020/flexbox.rs index c0d852ff47c..32ea3340ff7 100644 --- a/components/layout_2020/flexbox.rs +++ b/components/layout_2020/flexbox.rs @@ -15,7 +15,6 @@ use crate::sizing::{BoxContentSizes, ContentSizes, ContentSizesRequest}; use crate::style_ext::DisplayGeneratingBox; use crate::ContainingBlock; use rayon::iter::{IntoParallelIterator, ParallelIterator}; -use servo_arc::Arc; use std::borrow::Cow; use style::values::computed::Length; use style::values::specified::text::TextDecorationLine; @@ -31,7 +30,7 @@ pub(crate) struct FlexContainer { #[derive(Debug, Serialize)] pub(crate) enum FlexLevelBox { FlexItem(IndependentFormattingContext), - OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>), + OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>), } impl FlexContainer { @@ -192,14 +191,14 @@ where }; let box_ = if info.style.get_box().position.is_absolutely_positioned() { // https://drafts.csswg.org/css-flexbox/#abspos-items - ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( - AbsolutelyPositionedBox::construct( + ArcRefCell::new(FlexLevelBox::OutOfFlowAbsolutelyPositionedBox( + ArcRefCell::new(AbsolutelyPositionedBox::construct( self.context, &info, display_inside, contents, - ), - ))) + )), + )) } else { ArcRefCell::new(FlexLevelBox::FlexItem( IndependentFormattingContext::construct( diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 4219bc7bf47..bd2d0bce23d 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -571,9 +571,14 @@ where kind, }); } else { - let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( - AbsolutelyPositionedBox::construct(self.context, info, display_inside, contents), - ))); + let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox( + ArcRefCell::new(AbsolutelyPositionedBox::construct( + self.context, + info, + display_inside, + contents, + )), + )); self.current_inline_level_boxes().push(box_.clone()); box_slot.set(LayoutBox::InlineLevel(box_)) } @@ -722,10 +727,11 @@ where display_inside, contents, } => { - let block_level_box = - ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( + let block_level_box = ArcRefCell::new( + BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new( AbsolutelyPositionedBox::construct(context, info, display_inside, contents), - ))); + )), + ); (block_level_box, ContainsFloats::No) }, BlockLevelCreator::OutOfFlowFloatBox { diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index f3d0e45e3b7..47d9deacfbf 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -20,6 +20,7 @@ use crate::sizing::ContentSizes; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; use crate::ContainingBlock; use app_units::Au; +use atomic_refcell::AtomicRef; use gfx::text::text_run::GlyphRun; use servo_arc::Arc; use style::properties::ComputedValues; @@ -39,7 +40,7 @@ pub(crate) struct InlineFormattingContext { pub(crate) enum InlineLevelBox { InlineBox(InlineBox), TextRun(TextRun), - OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>), + OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>), OutOfFlowFloatBox(FloatBox), Atomic(IndependentFormattingContext), } @@ -283,8 +284,9 @@ 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 initial_start_corner = - match Display::from(box_.contents.style.get_box().original_display) { + match Display::from(style.get_box().original_display) { Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { outside, inside: _, @@ -313,7 +315,7 @@ impl InlineFormattingContext { Fragment::AbsoluteOrFixedPositioned( AbsoluteOrFixedPositionedFragment { hoisted_fragment, - position: box_.contents.style.clone_position(), + position: style.clone_position(), }, ), ); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index be56a3e2226..4f22b857e84 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -52,7 +52,7 @@ pub(crate) enum BlockLevelBox { style: Arc<ComputedValues>, contents: BlockContainer, }, - OutOfFlowAbsolutelyPositionedBox(Arc<AbsolutelyPositionedBox>), + OutOfFlowAbsolutelyPositionedBox(ArcRefCell<AbsolutelyPositionedBox>), OutOfFlowFloatBox(FloatBox), Independent(IndependentFormattingContext), } @@ -322,7 +322,7 @@ impl BlockLevelBox { positioning_context.push(hoisted_box); Fragment::AbsoluteOrFixedPositioned(AbsoluteOrFixedPositionedFragment { hoisted_fragment, - position: box_.contents.style.clone_position(), + position: box_.borrow().contents.style.clone_position(), }) }, BlockLevelBox::OutOfFlowFloatBox(_box_) => { diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 7de94e95ff8..46b7cf8438c 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -207,7 +207,7 @@ impl BoxTree { let contents = ReplacedContent::for_element(dirty_node) .map_or(Contents::OfElement, Contents::Replaced); let info = NodeAndStyleInfo::new(dirty_node, Arc::clone(&primary_style)); - let out_of_flow_absolutely_positioned_box = Arc::new( + let out_of_flow_absolutely_positioned_box = ArcRefCell::new( AbsolutelyPositionedBox::construct(context, &info, display_inside, contents), ); match update_point { @@ -267,7 +267,7 @@ fn construct_for_root_element<'dom>( let (contains_floats, root_box) = if box_style.position.is_absolutely_positioned() { ( ContainsFloats::No, - BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( + BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(ArcRefCell::new( AbsolutelyPositionedBox::construct(context, &info, display_inside, contents), )), ) diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index d865bab6424..7a5496d10e1 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -12,9 +12,8 @@ use crate::geom::{LengthOrAuto, LengthPercentageOrAuto}; use crate::sizing::ContentSizesRequest; use crate::style_ext::{ComputedValuesExt, DisplayInside}; use crate::{ContainingBlock, DefiniteContainingBlock}; -use rayon::iter::{IntoParallelRefIterator, ParallelExtend}; +use rayon::iter::{IntoParallelRefMutIterator, ParallelExtend}; use rayon_croissant::ParallelIteratorExt; -use servo_arc::Arc; use style::computed_values::position::T as Position; use style::properties::ComputedValues; use style::values::computed::{Length, LengthPercentage}; @@ -36,7 +35,7 @@ pub(crate) struct PositioningContext { } pub(crate) struct HoistedAbsolutelyPositionedBox { - absolutely_positioned_box: Arc<AbsolutelyPositionedBox>, + absolutely_positioned_box: ArcRefCell<AbsolutelyPositionedBox>, /// The rank of the child from which this absolutely positioned fragment /// came from, when doing the layout of a block container. Used to compute @@ -98,14 +97,14 @@ impl AbsolutelyPositionedBox { } pub(crate) fn to_hoisted( - self_: Arc<Self>, + self_: ArcRefCell<Self>, initial_start_corner: Vec2<Length>, tree_rank: usize, ) -> HoistedAbsolutelyPositionedBox { fn absolute_box_offsets( initial_static_start: Length, - start: LengthPercentageOrAuto, - end: LengthPercentageOrAuto, + start: LengthPercentageOrAuto<'_>, + end: LengthPercentageOrAuto<'_>, ) -> AbsoluteBoxOffsets { match (start.non_auto(), end.non_auto()) { (None, None) => AbsoluteBoxOffsets::StaticStart { @@ -122,10 +121,10 @@ impl AbsolutelyPositionedBox { } } - let box_offsets = self_.contents.style.box_offsets(); - HoistedAbsolutelyPositionedBox { - tree_rank, - box_offsets: Vec2 { + let box_offsets = { + let box_ = self_.borrow(); + let box_offsets = box_.contents.style.box_offsets(); + Vec2 { inline: absolute_box_offsets( initial_start_corner.inline, box_offsets.inline_start, @@ -136,7 +135,11 @@ impl AbsolutelyPositionedBox { box_offsets.block_start, box_offsets.block_end, ), - }, + } + }; + HoistedAbsolutelyPositionedBox { + tree_rank, + box_offsets, fragment: ArcRefCell::new(None), absolutely_positioned_box: self_, } @@ -268,7 +271,7 @@ impl PositioningContext { while !hoisted_boxes.is_empty() { HoistedAbsolutelyPositionedBox::layout_many( layout_context, - &hoisted_boxes, + &mut hoisted_boxes, &mut laid_out_child_fragments, &mut self.for_nearest_containing_block_for_all_descendants, &containing_block, @@ -281,12 +284,13 @@ impl PositioningContext { pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) { if let Some(nearest) = &mut self.for_nearest_positioned_ancestor { - match box_ + let position = box_ .absolutely_positioned_box + .borrow() .contents .style - .clone_position() - { + .clone_position(); + match position { Position::Fixed => {}, // fall through Position::Absolute => return nearest.push(box_), Position::Static | Position::Relative => unreachable!(), @@ -357,7 +361,7 @@ impl PositioningContext { { HoistedAbsolutelyPositionedBox::layout_many( layout_context, - &std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants), + &mut std::mem::take(&mut self.for_nearest_containing_block_for_all_descendants), fragments, &mut self.for_nearest_containing_block_for_all_descendants, initial_containing_block, @@ -369,13 +373,13 @@ impl PositioningContext { impl HoistedAbsolutelyPositionedBox { pub(crate) fn layout_many( layout_context: &LayoutContext, - boxes: &[Self], + boxes: &mut [Self], fragments: &mut Vec<ArcRefCell<Fragment>>, for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>, containing_block: &DefiniteContainingBlock, ) { if layout_context.use_rayon { - fragments.par_extend(boxes.par_iter().mapfold_reduce_into( + fragments.par_extend(boxes.par_iter_mut().mapfold_reduce_into( for_nearest_containing_block_for_all_descendants, |for_nearest_containing_block_for_all_descendants, box_| { let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout( @@ -391,7 +395,7 @@ impl HoistedAbsolutelyPositionedBox { vec_append_owned, )) } else { - fragments.extend(boxes.iter().map(|box_| { + fragments.extend(boxes.iter_mut().map(|box_| { let new_fragment = ArcRefCell::new(Fragment::Box(box_.layout( layout_context, for_nearest_containing_block_for_all_descendants, @@ -404,19 +408,20 @@ impl HoistedAbsolutelyPositionedBox { } pub(crate) fn layout( - &self, + &mut self, layout_context: &LayoutContext, for_nearest_containing_block_for_all_descendants: &mut Vec<HoistedAbsolutelyPositionedBox>, containing_block: &DefiniteContainingBlock, ) -> BoxFragment { let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; - let style = &self.absolutely_positioned_box.contents.style; + let absolutely_positioned_box = self.absolutely_positioned_box.borrow_mut(); + let style = &absolutely_positioned_box.contents.style; let pbm = style.padding_border_margin(&containing_block.into()); let size; let replaced_used_size; - match self.absolutely_positioned_box.contents.as_replaced() { + match absolutely_positioned_box.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 @@ -468,11 +473,11 @@ impl HoistedAbsolutelyPositionedBox { |positioning_context| { let size; let fragments; - match self.absolutely_positioned_box.contents.as_replaced() { + match absolutely_positioned_box.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 = &self.absolutely_positioned_box.contents.style; + let style = &absolutely_positioned_box.contents.style; size = replaced_used_size.unwrap(); fragments = replaced.make_fragments(style, size.clone()); }, @@ -488,7 +493,7 @@ impl HoistedAbsolutelyPositionedBox { anchor - pbm.padding_border_sums.inline - margin.inline_sum(); - self.absolutely_positioned_box + absolutely_positioned_box .contents .content_sizes .shrink_to_fit(available_size) @@ -544,7 +549,7 @@ impl HoistedAbsolutelyPositionedBox { }; BoxFragment::new( - self.absolutely_positioned_box.contents.tag, + absolutely_positioned_box.contents.tag, style.clone(), fragments, content_rect, diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index f5e1a9dbca3..0bc10fc5e68 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -64,9 +64,9 @@ pub(crate) struct PaddingBorderMargin { pub(crate) trait ComputedValuesExt { fn inline_size_is_length(&self) -> bool; fn inline_box_offsets_are_both_non_auto(&self) -> bool; - fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto>; - fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>; - fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto>; + fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>; + fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>; + fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>>; fn max_box_size(&self) -> flow_relative::Vec2<Option<&LengthPercentage>>; fn content_box_size( &self, @@ -86,7 +86,7 @@ pub(crate) trait ComputedValuesExt { fn padding_border_margin(&self, containing_block: &ContainingBlock) -> PaddingBorderMargin; fn padding(&self) -> flow_relative::Sides<&LengthPercentage>; fn border_width(&self) -> flow_relative::Sides<Length>; - fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto>; + fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>>; fn has_transform_or_perspective(&self) -> bool; fn effective_z_index(&self) -> i32; fn establishes_stacking_context(&self) -> bool; @@ -117,7 +117,7 @@ impl ComputedValuesExt for ComputedValues { !a.is_auto() && !b.is_auto() } - fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto> { + fn box_offsets(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> { let position = self.get_position(); flow_relative::Sides::from_physical( &PhysicalSides::new( @@ -130,7 +130,7 @@ impl ComputedValuesExt for ComputedValues { ) } - fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> { + fn box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> { let position = self.get_position(); flow_relative::Vec2::from_physical_size( &PhysicalSize::new( @@ -141,7 +141,7 @@ impl ComputedValuesExt for ComputedValues { ) } - fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto> { + fn min_box_size(&self) -> flow_relative::Vec2<LengthPercentageOrAuto<'_>> { let position = self.get_position(); flow_relative::Vec2::from_physical_size( &PhysicalSize::new( @@ -271,7 +271,7 @@ impl ComputedValuesExt for ComputedValues { ) } - fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto> { + fn margin(&self) -> flow_relative::Sides<LengthPercentageOrAuto<'_>> { let margin = self.get_margin(); flow_relative::Sides::from_physical( &PhysicalSides::new( |