diff options
author | Patrick Walton <pcwalton@mimiga.net> | 2020-03-13 19:47:00 -0700 |
---|---|---|
committer | Patrick Walton <pcwalton@mimiga.net> | 2020-03-17 11:15:17 -0700 |
commit | 9cb824e77ca1cea699358971f7568e869c1c4664 (patch) | |
tree | 581f9f329a6de51af60f678e6fd7755a5f89762c /components | |
parent | 2ff776b241f847bff9053e08a8004b6c7edc48b0 (diff) | |
download | servo-9cb824e77ca1cea699358971f7568e869c1c4664.tar.gz servo-9cb824e77ca1cea699358971f7568e869c1c4664.zip |
Wrap `BlockLevelBox` and `InlineLevelBox` with `AtomicRefCell`
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_2020/element_data.rs | 5 | ||||
-rw-r--r-- | components/layout_2020/flow/construct.rs | 144 | ||||
-rw-r--r-- | components/layout_2020/flow/inline.rs | 13 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 9 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 25 |
5 files changed, 101 insertions, 95 deletions
diff --git a/components/layout_2020/element_data.rs b/components/layout_2020/element_data.rs index ccd48ac04e3..e8afab10bc7 100644 --- a/components/layout_2020/element_data.rs +++ b/components/layout_2020/element_data.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::cell::ArcRefCell; use crate::flow::inline::InlineLevelBox; use crate::flow::BlockLevelBox; use atomic_refcell::AtomicRefCell; @@ -21,6 +22,6 @@ pub(super) struct PseudoElementBoxes { pub(super) enum LayoutBox { DisplayContents, - BlockLevel(Arc<BlockLevelBox>), - InlineLevel(Arc<InlineLevelBox>), + BlockLevel(ArcRefCell<BlockLevelBox>), + InlineLevel(ArcRefCell<InlineLevelBox>), } diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 6eee3675a8e..89a54d08840 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::dom_traversal::{BoxSlot, Contents, NodeExt, NonReplacedContents, TraversalHandler}; use crate::element_data::LayoutBox; @@ -282,54 +283,48 @@ where // context with the parent style of that builder. let inlines = self.current_inline_level_boxes(); - fn last_text(inlines: &mut [Arc<InlineLevelBox>]) -> Option<&mut String> { - let last = inlines.last_mut()?; - if let InlineLevelBox::TextRun(_) = &**last { - // We never clone text run boxes, so the refcount is 1 and unwrap succeeds: - let last = Arc::get_mut(last).unwrap(); - if let InlineLevelBox::TextRun(TextRun { text, .. }) = last { - Some(text) - } else { - unreachable!() - } - } else { - None - } - } - let mut new_text_run_contents; let output; - if let Some(text) = last_text(inlines) { - // Append to the existing text run - new_text_run_contents = None; - output = text; - } else { - new_text_run_contents = Some(String::new()); - output = new_text_run_contents.as_mut().unwrap(); - } - if leading_whitespace { - output.push(' ') - } - loop { - if let Some(i) = input.bytes().position(|b| b.is_ascii_whitespace()) { - let (non_whitespace, rest) = input.split_at(i); - output.push_str(non_whitespace); - output.push(' '); - if let Some(i) = rest.bytes().position(|b| !b.is_ascii_whitespace()) { - input = &rest[i..]; + { + let mut last_box = inlines.last_mut().map(|last| last.borrow_mut()); + let last_text = last_box.as_mut().and_then(|last| match &mut **last { + InlineLevelBox::TextRun(last) => Some(&mut last.text), + _ => None, + }); + + if let Some(text) = last_text { + // Append to the existing text run + new_text_run_contents = None; + output = text; + } else { + new_text_run_contents = Some(String::new()); + output = new_text_run_contents.as_mut().unwrap(); + } + + if leading_whitespace { + output.push(' ') + } + loop { + if let Some(i) = input.bytes().position(|b| b.is_ascii_whitespace()) { + let (non_whitespace, rest) = input.split_at(i); + output.push_str(non_whitespace); + output.push(' '); + if let Some(i) = rest.bytes().position(|b| !b.is_ascii_whitespace()) { + input = &rest[i..]; + } else { + break; + } } else { + output.push_str(input); break; } - } else { - output.push_str(input); - break; } } if let Some(text) = new_text_run_contents { let parent_style = parent_style.clone(); - inlines.push(Arc::new(InlineLevelBox::TextRun(TextRun { + inlines.push(ArcRefCell::new(InlineLevelBox::TextRun(TextRun { tag: node.as_opaque(), parent_style, text, @@ -356,23 +351,27 @@ where let mut inline_level_boxes = self.current_inline_level_boxes().iter().rev(); let mut stack = Vec::new(); let preserved = loop { - match inline_level_boxes.next().map(|b| &**b) { - Some(InlineLevelBox::TextRun(r)) => break !r.text.ends_with(' '), - Some(InlineLevelBox::Atomic { .. }) => break false, - Some(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(_)) | - Some(InlineLevelBox::OutOfFlowFloatBox(_)) => {}, - Some(InlineLevelBox::InlineBox(b)) => { + let inline_box = match inline_level_boxes.next() { + Some(box_) => box_, + None => match stack.pop() { + Some(iter) => { + inline_level_boxes = iter; + continue; + }, + None => break false, + }, + };{ + match &*inline_box.borrow() { + InlineLevelBox::TextRun(r) => break !r.text.ends_with(' '), + InlineLevelBox::Atomic { .. } => break false, + InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(_) | + InlineLevelBox::OutOfFlowFloatBox(_) => {}, + InlineLevelBox::InlineBox(b) => { stack.push(inline_level_boxes); inline_level_boxes = b.children.iter().rev() }, - None => { - if let Some(iter) = stack.pop() { - inline_level_boxes = iter - } else { - break false; // Paragraph start - } - }, - } + };} + () }; let text = text.trim_start_matches(|c: char| c.is_ascii_whitespace()); (preserved, text) @@ -384,7 +383,7 @@ where style: &Arc<ComputedValues>, display_inside: DisplayInside, contents: Contents, - ) -> Arc<InlineLevelBox> { + ) -> ArcRefCell<InlineLevelBox> { 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 @@ -410,9 +409,9 @@ where .pop() .expect("no ongoing inline level box found"); inline_box.last_fragment = true; - Arc::new(InlineLevelBox::InlineBox(inline_box)) + ArcRefCell::new(InlineLevelBox::InlineBox(inline_box)) } else { - Arc::new(InlineLevelBox::Atomic( + ArcRefCell::new(InlineLevelBox::Atomic( IndependentFormattingContext::construct( self.context, node, @@ -466,13 +465,13 @@ where for mut fragmented_parent_inline_box in fragmented_inline_boxes { fragmented_parent_inline_box .children - .push(Arc::new(fragmented_inline)); + .push(ArcRefCell::new(fragmented_inline)); fragmented_inline = InlineLevelBox::InlineBox(fragmented_parent_inline_box); } self.ongoing_inline_formatting_context .inline_level_boxes - .push(Arc::new(fragmented_inline)); + .push(ArcRefCell::new(fragmented_inline)); } // We found a block level element, so the ongoing inline formatting @@ -525,7 +524,7 @@ where kind, }); } else { - let box_ = Arc::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( + let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( AbsolutelyPositionedBox::construct( self.context, node, @@ -561,7 +560,7 @@ where kind, }); } else { - let box_ = Arc::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct( + let box_ = ArcRefCell::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox::construct( self.context, node, style, @@ -610,7 +609,7 @@ where }); } - fn current_inline_level_boxes(&mut self) -> &mut Vec<Arc<InlineLevelBox>> { + fn current_inline_level_boxes(&mut self) -> &mut Vec<ArcRefCell<InlineLevelBox>> { match self.ongoing_inline_boxes_stack.last_mut() { Some(last) => &mut last.children, None => &mut self.ongoing_inline_formatting_context.inline_level_boxes, @@ -634,7 +633,7 @@ where self, context: &LayoutContext, max_assign_in_flow_outer_content_sizes_to: Option<&mut ContentSizes>, - ) -> (Arc<BlockLevelBox>, ContainsFloats) { + ) -> (ArcRefCell<BlockLevelBox>, ContainsFloats) { let node = self.node; let style = self.style; let (block_level_box, contains_floats) = match self.kind { @@ -651,7 +650,7 @@ where if let Some(to) = max_assign_in_flow_outer_content_sizes_to { to.max_assign(&box_content_sizes.outer_inline(&style)) } - let block_level_box = Arc::new(BlockLevelBox::SameFormattingContextBlock { + let block_level_box = ArcRefCell::new(BlockLevelBox::SameFormattingContextBlock { tag: node.as_opaque(), contents, style, @@ -678,7 +677,7 @@ where to.max_assign(&contents.content_sizes.outer_inline(&contents.style)) } ( - Arc::new(BlockLevelBox::Independent(contents)), + ArcRefCell::new(BlockLevelBox::Independent(contents)), ContainsFloats::No, ) }, @@ -686,22 +685,23 @@ where display_inside, contents, } => { - let block_level_box = Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( - Arc::new(AbsolutelyPositionedBox::construct( - context, - node, - style, - display_inside, - contents, - )), - )); + let block_level_box = + ArcRefCell::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( + AbsolutelyPositionedBox::construct( + context, + node, + style, + display_inside, + contents, + ), + ))); (block_level_box, ContainsFloats::No) }, BlockLevelCreator::OutOfFlowFloatBox { display_inside, contents, } => { - let block_level_box = Arc::new(BlockLevelBox::OutOfFlowFloatBox( + let block_level_box = ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox( FloatBox::construct(context, node, style, display_inside, contents), )); (block_level_box, ContainsFloats::Yes) diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 8e1587568c0..0d1f2199597 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::flow::float::FloatBox; use crate::flow::FlowLayout; @@ -27,7 +28,7 @@ use webrender_api::FontInstanceKey; #[derive(Debug, Default, Serialize)] pub(crate) struct InlineFormattingContext { - pub(super) inline_level_boxes: Vec<Arc<InlineLevelBox>>, + pub(super) inline_level_boxes: Vec<ArcRefCell<InlineLevelBox>>, } #[derive(Debug, Serialize)] @@ -46,7 +47,7 @@ pub(crate) struct InlineBox { pub style: Arc<ComputedValues>, pub first_fragment: bool, pub last_fragment: bool, - pub children: Vec<Arc<InlineLevelBox>>, + pub children: Vec<ArcRefCell<InlineLevelBox>>, } /// https://www.w3.org/TR/css-display-3/#css-text-run @@ -59,7 +60,7 @@ pub(crate) struct TextRun { } struct InlineNestingLevelState<'box_tree> { - remaining_boxes: std::slice::Iter<'box_tree, Arc<InlineLevelBox>>, + remaining_boxes: std::slice::Iter<'box_tree, ArcRefCell<InlineLevelBox>>, fragments_so_far: Vec<Fragment>, inline_start: Length, max_block_size_of_fragments_so_far: Length, @@ -105,10 +106,10 @@ impl InlineFormattingContext { fn traverse( &mut self, layout_context: &LayoutContext, - inline_level_boxes: &[Arc<InlineLevelBox>], + inline_level_boxes: &[ArcRefCell<InlineLevelBox>], ) { for inline_level_box in inline_level_boxes { - match &**inline_level_box { + match &*inline_level_box.borrow() { InlineLevelBox::InlineBox(inline_box) => { let padding = inline_box.style.padding(); let border = inline_box.style.border_width(); @@ -229,7 +230,7 @@ impl InlineFormattingContext { }; loop { if let Some(child) = ifc.current_nesting_level.remaining_boxes.next() { - match &**child { + match &*child.borrow() { InlineLevelBox::InlineBox(inline) => { let partial = inline.start_layout(&mut ifc); ifc.partial_inline_boxes_stack.push(partial) diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 1f6d6db49df..fa0ed0b7c00 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -4,6 +4,7 @@ //! Flow layout, also known as block-and-inline layout. +use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::inline::InlineFormattingContext; @@ -38,7 +39,7 @@ pub(crate) struct BlockFormattingContext { #[derive(Debug, Serialize)] pub(crate) enum BlockContainer { - BlockLevelBoxes(Vec<Arc<BlockLevelBox>>), + BlockLevelBoxes(Vec<ArcRefCell<BlockLevelBox>>), InlineFormattingContext(InlineFormattingContext), } @@ -133,7 +134,7 @@ impl BlockContainer { fn layout_block_level_children( layout_context: &LayoutContext, positioning_context: &mut PositioningContext, - child_boxes: &[Arc<BlockLevelBox>], + child_boxes: &[ArcRefCell<BlockLevelBox>], containing_block: &ContainingBlock, tree_rank: usize, mut float_context: Option<&mut FloatContext>, @@ -204,7 +205,7 @@ fn layout_block_level_children( .iter() .enumerate() .map(|(tree_rank, box_)| { - let mut fragment = box_.layout( + let mut fragment = box_.borrow().layout( layout_context, positioning_context, containing_block, @@ -224,7 +225,7 @@ fn layout_block_level_children( .mapfold_reduce_into( positioning_context, |positioning_context, (tree_rank, box_)| { - box_.layout( + box_.borrow().layout( layout_context, positioning_context, containing_block, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 63ca58ead1d..6a8be578630 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ +use crate::cell::ArcRefCell; use crate::context::LayoutContext; use crate::display_list::stacking_context::{ ContainingBlock, ContainingBlockInfo, StackingContext, StackingContextBuildMode, @@ -62,7 +63,7 @@ impl BoxTreeRoot { fn construct_for_root_element<'dom>( context: &LayoutContext, root_element: impl NodeExt<'dom>, -) -> (ContainsFloats, Vec<Arc<BlockLevelBox>>) { +) -> (ContainsFloats, Vec<ArcRefCell<BlockLevelBox>>) { let style = root_element.style(context); let replaced = ReplacedContent::for_element(root_element); let box_style = style.get_box(); @@ -83,27 +84,29 @@ fn construct_for_root_element<'dom>( if box_style.position.is_absolutely_positioned() { ( ContainsFloats::No, - vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( - Arc::new(AbsolutelyPositionedBox::construct( - context, - root_element, - style, - display_inside, - contents, + vec![ArcRefCell::new( + BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(Arc::new( + AbsolutelyPositionedBox::construct( + context, + root_element, + style, + display_inside, + contents, + ), )), - ))], + )], ) } else if box_style.float.is_floating() { ( ContainsFloats::Yes, - vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox( + vec![ArcRefCell::new(BlockLevelBox::OutOfFlowFloatBox( FloatBox::construct(context, root_element, style, display_inside, contents), ))], ) } else { ( ContainsFloats::No, - vec![Arc::new(BlockLevelBox::Independent( + vec![ArcRefCell::new(BlockLevelBox::Independent( IndependentFormattingContext::construct( context, root_element, |