diff options
Diffstat (limited to 'components/layout_2020')
-rw-r--r-- | components/layout_2020/dom_traversal.rs | 24 | ||||
-rw-r--r-- | components/layout_2020/flow/construct.rs | 27 | ||||
-rw-r--r-- | components/layout_2020/flow/float.rs | 3 | ||||
-rw-r--r-- | components/layout_2020/flow/inline.rs | 16 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 82 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 31 | ||||
-rw-r--r-- | components/layout_2020/formatting_contexts.rs | 114 | ||||
-rw-r--r-- | components/layout_2020/lib.rs | 100 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 16 |
9 files changed, 223 insertions, 190 deletions
diff --git a/components/layout_2020/dom_traversal.rs b/components/layout_2020/dom_traversal.rs index ce57f4c8100..732dc1afdc9 100644 --- a/components/layout_2020/dom_traversal.rs +++ b/components/layout_2020/dom_traversal.rs @@ -8,7 +8,7 @@ use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside, DisplayOuts use crate::wrapper::GetRawData; use atomic_refcell::{AtomicRefCell, AtomicRefMut}; use script_layout_interface::wrapper_traits::{LayoutNode, ThreadSafeLayoutNode}; -use servo_arc::Arc; +use servo_arc::Arc as ServoArc; use std::convert::TryInto; use std::marker::PhantomData as marker; use style::context::SharedStyleContext; @@ -30,7 +30,7 @@ pub(super) enum Contents<Node> { /// <https://drafts.csswg.org/css2/conform.html#replaced-element> Replaced(ReplacedContent), - /// Content of a `::before` or `::after` pseudo-element this is being generated. + /// Content of a `::before` or `::after` pseudo-element that is being generated. /// <https://drafts.csswg.org/css2/generate.html#content> OfPseudoElement(Vec<PseudoElementContentItem>), } @@ -49,12 +49,12 @@ pub(super) trait TraversalHandler<'dom, Node> where Node: 'dom, { - fn handle_text(&mut self, text: String, parent_style: &Arc<ComputedValues>); + fn handle_text(&mut self, text: String, parent_style: &ServoArc<ComputedValues>); /// Or pseudo-element fn handle_element( &mut self, - style: &Arc<ComputedValues>, + style: &ServoArc<ComputedValues>, display: DisplayGeneratingBox, contents: Contents<Node>, box_slot: BoxSlot<'dom>, @@ -144,7 +144,7 @@ fn traverse_pseudo_element<'dom, Node>( } fn traverse_pseudo_element_contents<'dom, Node>( - pseudo_element_style: &Arc<ComputedValues>, + pseudo_element_style: &ServoArc<ComputedValues>, context: &SharedStyleContext, handler: &mut impl TraversalHandler<'dom, Node>, items: Vec<PseudoElementContentItem>, @@ -213,7 +213,7 @@ where { pub(crate) fn traverse( self, - inherited_style: &Arc<ComputedValues>, + inherited_style: &ServoArc<ComputedValues>, context: &SharedStyleContext, handler: &mut impl TraversalHandler<'dom, Node>, ) { @@ -230,7 +230,7 @@ fn pseudo_element_style<'dom, Node>( _which: WhichPseudoElement, _element: Node, _context: &SharedStyleContext, -) -> Option<Arc<ComputedValues>> +) -> Option<ServoArc<ComputedValues>> where Node: NodeExt<'dom>, { @@ -253,12 +253,12 @@ where } pub struct BoxSlot<'dom> { - slot: Option<Arc<AtomicRefCell<Option<LayoutBox>>>>, + slot: Option<ServoArc<AtomicRefCell<Option<LayoutBox>>>>, marker: marker<&'dom ()>, } impl BoxSlot<'_> { - pub(crate) fn new(slot: Arc<AtomicRefCell<Option<LayoutBox>>>) -> Self { + pub(crate) fn new(slot: ServoArc<AtomicRefCell<Option<LayoutBox>>>) -> Self { *slot.borrow_mut() = None; let slot = Some(slot); Self { slot, marker } @@ -284,13 +284,13 @@ impl Drop for BoxSlot<'_> { } } -pub trait NodeExt<'dom>: 'dom + Copy + LayoutNode + Send + Sync { +pub(crate) trait NodeExt<'dom>: 'dom + Copy + LayoutNode + Send + Sync { fn is_element(self) -> bool; fn as_text(self) -> Option<String>; fn first_child(self) -> Option<Self>; fn next_sibling(self) -> Option<Self>; fn parent_node(self) -> Option<Self>; - fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues>; + fn style(self, context: &SharedStyleContext) -> ServoArc<ComputedValues>; fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement>; fn element_box_slot(&self) -> BoxSlot<'dom>; @@ -327,7 +327,7 @@ where TNode::parent_node(&self) } - fn style(self, context: &SharedStyleContext) -> Arc<ComputedValues> { + fn style(self, context: &SharedStyleContext) -> ServoArc<ComputedValues> { self.to_threadsafe().style(context) } diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index f3afabf15fc..57d7bf9dd31 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -7,9 +7,9 @@ use crate::element_data::LayoutBox; use crate::flow::float::FloatBox; use crate::flow::inline::{InlineBox, InlineFormattingContext, InlineLevelBox, TextRun}; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; +use crate::formatting_contexts::IndependentFormattingContext; use crate::positioned::AbsolutelyPositionedBox; use crate::style_ext::{DisplayGeneratingBox, DisplayInside, DisplayOutside}; -use crate::{take, IndependentFormattingContext}; use rayon::iter::{IntoParallelIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; @@ -380,7 +380,7 @@ where // The fragmented boxes before the block level element // are obviously not the last fragment. last_fragment: false, - children: take(&mut ongoing.children), + children: std::mem::take(&mut ongoing.children), }; ongoing.first_fragment = false; fragmented @@ -450,11 +450,10 @@ where AbsolutelyPositionedBox { contents: IndependentFormattingContext::construct( unimplemented!(), - &style, + style, display_inside, contents, ), - style, }, )); self.current_inline_level_boxes().push(box_.clone()); @@ -482,11 +481,10 @@ where let box_ = Arc::new(InlineLevelBox::OutOfFlowFloatBox(FloatBox { contents: IndependentFormattingContext::construct( self.context, - &style, + style, display_inside, contents, ), - style, })); self.current_inline_level_boxes().push(box_.clone()); box_slot.set(LayoutBox::InlineLevel(box_)) @@ -517,7 +515,7 @@ where let box_ = IntermediateBlockLevelBox::SameFormattingContextBlock { style: anonymous_style.clone(), - contents: IntermediateBlockContainer::InlineFormattingContext(take( + contents: IntermediateBlockContainer::InlineFormattingContext(std::mem::take( &mut self.ongoing_inline_formatting_context, )), }; @@ -562,12 +560,12 @@ where } => { let contents = IndependentFormattingContext::construct( context, - &style, + style, display_inside, contents, ); ( - Arc::new(BlockLevelBox::Independent { style, contents }), + Arc::new(BlockLevelBox::Independent(contents)), ContainsFloats::No, ) }, @@ -580,11 +578,10 @@ where AbsolutelyPositionedBox { contents: IndependentFormattingContext::construct( context, - &style, + style, display_inside, contents, ), - style: style, }, )); (block_level_box, ContainsFloats::No) @@ -596,14 +593,12 @@ where } => { let contents = IndependentFormattingContext::construct( context, - &style, + style, display_inside, contents, ); - let block_level_box = Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox { - contents, - style, - })); + let block_level_box = + Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox { contents })); (block_level_box, ContainsFloats::Yes) }, } diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index 31fec0b79c0..4698e9d2f1c 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -2,13 +2,12 @@ * 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::IndependentFormattingContext; +use crate::formatting_contexts::IndependentFormattingContext; use servo_arc::Arc; use style::properties::ComputedValues; #[derive(Debug)] pub(crate) struct FloatBox { - pub style: Arc<ComputedValues>, pub contents: IndependentFormattingContext, } diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index e410fa269ec..5a48ac9a2ee 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -4,7 +4,7 @@ use crate::context::LayoutContext; use crate::flow::float::FloatBox; -use crate::flow::FlowChildren; +use crate::flow::FlowLayout; use crate::fragments::{ AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment, TextFragment, }; @@ -12,7 +12,7 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::{AbsolutelyPositionedBox, AbsolutelyPositionedFragment}; use crate::replaced::ReplacedContent; use crate::style_ext::{ComputedValuesExt, Display, DisplayGeneratingBox, DisplayOutside}; -use crate::{relative_adjustement, take, ContainingBlock}; +use crate::{relative_adjustement, ContainingBlock}; use servo_arc::Arc; use style::properties::ComputedValues; use style::values::computed::Length; @@ -88,7 +88,7 @@ impl InlineFormattingContext { containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, - ) -> FlowChildren { + ) -> FlowLayout { let mut ifc = InlineFormattingContextState { containing_block, partial_inline_boxes_stack: Vec::new(), @@ -118,7 +118,7 @@ impl InlineFormattingContext { }, InlineLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => { let initial_start_corner = - match Display::from(box_.style.get_box().original_display) { + match Display::from(box_.contents.style.get_box().original_display) { Display::GeneratingBox(DisplayGeneratingBox::OutsideInside { outside, inside: _, @@ -156,9 +156,9 @@ impl InlineFormattingContext { } else { ifc.line_boxes .finish_line(&mut ifc.current_nesting_level, containing_block); - return FlowChildren { + return FlowLayout { fragments: ifc.line_boxes.boxes, - block_size: ifc.line_boxes.next_line_block_position, + content_block_size: ifc.line_boxes.next_line_block_position, collapsible_margins_in_children: CollapsedBlockMargins::zero(), }; } @@ -185,7 +185,7 @@ impl LinesBoxes { }; self.next_line_block_position += size.block; self.boxes.push(Fragment::Anonymous(AnonymousFragment { - children: take(&mut top_nesting_level.fragments_so_far), + children: std::mem::take(&mut top_nesting_level.fragments_so_far), rect: Rect { start_corner, size }, mode: containing_block.mode, })) @@ -250,7 +250,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> { ) { let mut fragment = BoxFragment { style: self.style.clone(), - children: take(&mut nesting_level.fragments_so_far), + children: std::mem::take(&mut nesting_level.fragments_so_far), content_rect: Rect { size: Vec2 { inline: *inline_position - self.start_corner.inline, diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index b690e447cd7..9281c135760 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -7,15 +7,16 @@ use crate::context::LayoutContext; use crate::flow::float::{FloatBox, FloatContext}; use crate::flow::inline::InlineFormattingContext; +use crate::formatting_contexts::{IndependentFormattingContext, IndependentLayout}; use crate::fragments::{ AnonymousFragment, BoxFragment, CollapsedBlockMargins, CollapsedMargin, Fragment, }; -use crate::geom::flow_relative::{Rect, Vec2}; +use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::positioned::{ adjust_static_positions, AbsolutelyPositionedBox, AbsolutelyPositionedFragment, }; use crate::style_ext::{ComputedValuesExt, Position}; -use crate::{relative_adjustement, ContainingBlock, IndependentFormattingContext}; +use crate::{relative_adjustement, ContainingBlock}; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; @@ -50,15 +51,12 @@ pub(crate) enum BlockLevelBox { }, OutOfFlowAbsolutelyPositionedBox(AbsolutelyPositionedBox), OutOfFlowFloatBox(FloatBox), - Independent { - style: Arc<ComputedValues>, - contents: IndependentFormattingContext, - }, + Independent(IndependentFormattingContext), } -pub(super) struct FlowChildren { +struct FlowLayout { pub fragments: Vec<Fragment>, - pub block_size: Length, + pub content_block_size: Length, pub collapsible_margins_in_children: CollapsedBlockMargins, } @@ -72,7 +70,7 @@ impl BlockFormattingContext { containing_block: &ContainingBlock, tree_rank: usize, absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, - ) -> FlowChildren { + ) -> IndependentLayout { let mut float_context; let float_context = if self.contains_floats { float_context = FloatContext::new(); @@ -80,7 +78,7 @@ impl BlockFormattingContext { } else { None }; - let mut flow_children = self.contents.layout( + let flow_layout = self.contents.layout( layout_context, containing_block, tree_rank, @@ -88,12 +86,16 @@ impl BlockFormattingContext { float_context, CollapsibleWithParentStartMargin(false), ); - flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve(); - flow_children - .collapsible_margins_in_children - .collapsed_through = false; - flow_children.collapsible_margins_in_children.end = CollapsedMargin::zero(); - flow_children + assert!( + !flow_layout + .collapsible_margins_in_children + .collapsed_through + ); + IndependentLayout { + fragments: flow_layout.fragments, + content_block_size: flow_layout.content_block_size + + flow_layout.collapsible_margins_in_children.end.solve(), + } } } @@ -106,7 +108,7 @@ impl BlockContainer { absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, float_context: Option<&mut FloatContext>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, - ) -> FlowChildren { + ) -> FlowLayout { match self { BlockContainer::BlockLevelBoxes(child_boxes) => layout_block_level_children( layout_context, @@ -135,7 +137,7 @@ fn layout_block_level_children<'a>( absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, float_context: Option<&mut FloatContext>, collapsible_with_parent_start_margin: CollapsibleWithParentStartMargin, -) -> FlowChildren { +) -> FlowLayout { fn place_block_level_fragment(fragment: &mut Fragment, placement_state: &mut PlacementState) { match fragment { Fragment::Box(fragment) => { @@ -251,9 +253,9 @@ fn layout_block_level_children<'a>( tree_rank, ); - FlowChildren { + FlowLayout { fragments, - block_size: placement_state.current_block_direction_position, + content_block_size: placement_state.current_block_direction_position, collapsible_margins_in_children: CollapsedBlockMargins { collapsed_through: placement_state .next_in_flow_margin_collapses_with_parent_start_margin, @@ -292,19 +294,29 @@ impl BlockLevelBox { }, )) }, - BlockLevelBox::Independent { style, contents } => match contents.as_replaced() { + BlockLevelBox::Independent(contents) => match contents.as_replaced() { Ok(replaced) => { // FIXME match *replaced {} }, - Err(contents) => Fragment::Box(layout_in_flow_non_replaced_block_level( + Err(non_replaced) => Fragment::Box(layout_in_flow_non_replaced_block_level( layout_context, containing_block, absolutely_positioned_fragments, - style, + &contents.style, BlockLevelKind::EstablishesAnIndependentFormattingContext, |containing_block, nested_abspos, _| { - contents.layout(layout_context, containing_block, tree_rank, nested_abspos) + let independent_layout = non_replaced.layout( + layout_context, + containing_block, + tree_rank, + nested_abspos, + ); + FlowLayout { + fragments: independent_layout.fragments, + content_block_size: independent_layout.content_block_size, + collapsible_margins_in_children: CollapsedBlockMargins::zero(), + } }, )), }, @@ -338,7 +350,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( &ContainingBlock, &mut Vec<AbsolutelyPositionedFragment<'a>>, CollapsibleWithParentStartMargin, - ) -> FlowChildren, + ) -> FlowLayout, ) -> BoxFragment { let cbis = containing_block.inline_size; let padding = style.padding().percentages_relative_to(cbis); @@ -397,7 +409,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( LengthOrAuto::Auto, ); let mut nested_abspos = vec![]; - let mut flow_children = layout_contents( + let mut flow_layout = layout_contents( &containing_block_for_children, if style.get_box().position == Position::Relative { &mut nested_abspos @@ -409,15 +421,15 @@ fn layout_in_flow_non_replaced_block_level<'a>( if this_start_margin_can_collapse_with_children.0 { block_margins_collapsed_with_children .start - .adjoin_assign(&flow_children.collapsible_margins_in_children.start); - if flow_children + .adjoin_assign(&flow_layout.collapsible_margins_in_children.start); + if flow_layout .collapsible_margins_in_children .collapsed_through { block_margins_collapsed_with_children .start .adjoin_assign(&std::mem::replace( - &mut flow_children.collapsible_margins_in_children.end, + &mut flow_layout.collapsible_margins_in_children.end, CollapsedMargin::zero(), )); } @@ -425,18 +437,18 @@ fn layout_in_flow_non_replaced_block_level<'a>( if this_end_margin_can_collapse_with_children { block_margins_collapsed_with_children .end - .adjoin_assign(&flow_children.collapsible_margins_in_children.end); + .adjoin_assign(&flow_layout.collapsible_margins_in_children.end); } else { - flow_children.block_size += flow_children.collapsible_margins_in_children.end.solve(); + flow_layout.content_block_size += flow_layout.collapsible_margins_in_children.end.solve(); } block_margins_collapsed_with_children.collapsed_through = this_start_margin_can_collapse_with_children.0 && this_end_margin_can_collapse_with_children && - flow_children + flow_layout .collapsible_margins_in_children .collapsed_through; let relative_adjustement = relative_adjustement(style, inline_size, block_size); - let block_size = block_size.auto_is(|| flow_children.block_size); + let block_size = block_size.auto_is(|| flow_layout.content_block_size); let content_rect = Rect { start_corner: Vec2 { block: pb.block_start + relative_adjustement.block, @@ -451,7 +463,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( AbsolutelyPositionedFragment::in_positioned_containing_block( layout_context, &nested_abspos, - &mut flow_children.fragments, + &mut flow_layout.fragments, &content_rect.size, &padding, containing_block_for_children.mode, @@ -459,7 +471,7 @@ fn layout_in_flow_non_replaced_block_level<'a>( } BoxFragment { style: style.clone(), - children: flow_children.fragments, + children: flow_layout.fragments, content_rect, padding, border, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index a1831c6433a..8df332b90d6 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -8,6 +8,7 @@ use crate::dom_traversal::{Contents, NodeExt}; use crate::flow::construct::ContainsFloats; use crate::flow::float::FloatBox; use crate::flow::{BlockContainer, BlockFormattingContext, BlockLevelBox}; +use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::Fragment; use crate::geom; use crate::geom::flow_relative::Vec2; @@ -16,8 +17,9 @@ use crate::replaced::ReplacedContent; use crate::style_ext::{ Direction, Display, DisplayGeneratingBox, DisplayInside, DisplayOutside, WritingMode, }; -use crate::{ContainingBlock, DefiniteContainingBlock, IndependentFormattingContext}; +use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelExtend, ParallelIterator}; +use script_layout_interface::wrapper_traits::LayoutNode; use servo_arc::Arc; use style::context::SharedStyleContext; use style::properties::ComputedValues; @@ -29,10 +31,10 @@ pub struct BoxTreeRoot(BlockFormattingContext); pub struct FragmentTreeRoot(Vec<Fragment>); impl BoxTreeRoot { - pub fn construct<'dom>( - context: &SharedStyleContext<'_>, - root_element: impl NodeExt<'dom>, - ) -> Self { + pub fn construct<'dom, Node>(context: &SharedStyleContext<'_>, root_element: Node) -> Self + where + Node: 'dom + Copy + LayoutNode + Send + Sync, + { let (contains_floats, boxes) = construct_for_root_element(&context, root_element); Self(BlockFormattingContext { contains_floats: contains_floats == ContainsFloats::Yes, @@ -69,31 +71,32 @@ fn construct_for_root_element<'dom>( } } + let position = box_style.position; + let float = box_style.float; let contents = IndependentFormattingContext::construct( context, - &style, + style, display_inside, Contents::OfElement(root_element), ); - if box_style.position.is_absolutely_positioned() { + if position.is_absolutely_positioned() { ( ContainsFloats::No, vec![Arc::new(BlockLevelBox::OutOfFlowAbsolutelyPositionedBox( - AbsolutelyPositionedBox { style, contents }, + AbsolutelyPositionedBox { contents }, ))], ) - } else if box_style.float.is_floating() { + } else if float.is_floating() { ( ContainsFloats::Yes, vec![Arc::new(BlockLevelBox::OutOfFlowFloatBox(FloatBox { contents, - style, }))], ) } else { ( ContainsFloats::No, - vec![Arc::new(BlockLevelBox::Independent { style, contents })], + vec![Arc::new(BlockLevelBox::Independent(contents))], ) } } @@ -118,7 +121,7 @@ impl BoxTreeRoot { }; let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; - let mut flow_children = self.0.layout( + let mut independent_layout = self.0.layout( layout_context, &initial_containing_block, dummy_tree_rank, @@ -129,12 +132,12 @@ impl BoxTreeRoot { size: initial_containing_block_size, mode: initial_containing_block.mode, }; - flow_children.fragments.par_extend( + independent_layout.fragments.par_extend( absolutely_positioned_fragments .par_iter() .map(|a| a.layout(layout_context, &initial_containing_block)), ); - FragmentTreeRoot(flow_children.fragments) + FragmentTreeRoot(independent_layout.fragments) } } diff --git a/components/layout_2020/formatting_contexts.rs b/components/layout_2020/formatting_contexts.rs new file mode 100644 index 00000000000..96294947720 --- /dev/null +++ b/components/layout_2020/formatting_contexts.rs @@ -0,0 +1,114 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * 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::context::LayoutContext; +use crate::dom_traversal::{Contents, NodeExt}; +use crate::flow::BlockFormattingContext; +use crate::fragments::Fragment; +use crate::geom::flow_relative::Vec2; +use crate::positioned::AbsolutelyPositionedFragment; +use crate::replaced::ReplacedContent; +use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, Position, WritingMode}; +use crate::ContainingBlock; +use servo_arc::Arc; +use std::convert::TryInto; +use style::context::SharedStyleContext; +use style::properties::ComputedValues; +use style::values::computed::Length; + +/// https://drafts.csswg.org/css-display/#independent-formatting-context +#[derive(Debug)] +pub(crate) struct IndependentFormattingContext { + pub style: Arc<ComputedValues>, + contents: IndependentFormattingContextContents, +} + +pub(crate) struct IndependentLayout { + pub fragments: Vec<Fragment>, + pub content_block_size: Length, +} + +// Private so that code outside of this module cannot match variants. +// It should got through methods instead. +#[derive(Debug)] +enum IndependentFormattingContextContents { + Flow(BlockFormattingContext), + + // 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), +} + +impl IndependentFormattingContext { + pub fn construct<'dom, 'style>( + context: &SharedStyleContext<'style>, + style: Arc<ComputedValues>, + display_inside: DisplayInside, + contents: Contents<impl NodeExt<'dom>>, + ) -> Self { + use self::IndependentFormattingContextContents as Contents; + let contents = match contents.try_into() { + Ok(non_replaced) => match display_inside { + DisplayInside::Flow | DisplayInside::FlowRoot => Contents::Flow( + BlockFormattingContext::construct(context, &style, non_replaced), + ), + }, + Err(replaced) => Contents::Replaced(replaced), + }; + Self { style, contents } + } + + pub fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> { + use self::IndependentFormattingContextContents as Contents; + use self::NonReplacedIFC as NR; + use self::NonReplacedIFCKind as Kind; + match &self.contents { + Contents::Replaced(r) => Ok(r), + Contents::Flow(f) => Err(NR(Kind::Flow(f))), + } + } + + pub fn layout<'a>( + &'a self, + layout_context: &LayoutContext, + containing_block: &ContainingBlock, + tree_rank: usize, + absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, + ) -> IndependentLayout { + match self.as_replaced() { + Ok(replaced) => match *replaced {}, + Err(ifc) => ifc.layout( + layout_context, + containing_block, + tree_rank, + absolutely_positioned_fragments, + ), + } + } +} + +impl<'a> NonReplacedIFC<'a> { + pub fn layout( + &self, + layout_context: &LayoutContext, + containing_block: &ContainingBlock, + tree_rank: usize, + absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, + ) -> IndependentLayout { + match &self.0 { + NonReplacedIFCKind::Flow(bfc) => bfc.layout( + layout_context, + containing_block, + tree_rank, + absolutely_positioned_fragments, + ), + } + } +} diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index c0892553f35..07956417087 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -12,16 +12,13 @@ #[macro_use] extern crate serde; -use style::properties::ComputedValues; -use style::values::computed::{Length, LengthOrAuto}; -use style::Zero; - pub mod context; pub mod data; pub mod display_list; mod dom_traversal; mod element_data; mod flow; +mod formatting_contexts; mod fragments; mod geom; mod opaque_node; @@ -36,94 +33,16 @@ pub use flow::{BoxTreeRoot, FragmentTreeRoot}; use crate::context::LayoutContext; use crate::dom_traversal::{Contents, NodeExt}; -use crate::flow::{BlockFormattingContext, FlowChildren}; +use crate::flow::BlockFormattingContext; use crate::geom::flow_relative::Vec2; use crate::positioned::AbsolutelyPositionedFragment; use crate::replaced::ReplacedContent; use crate::style_ext::{ComputedValuesExt, Direction, DisplayInside, Position, WritingMode}; use servo_arc::Arc; use std::convert::TryInto; -use style::context::SharedStyleContext; - -/// https://drafts.csswg.org/css-display/#independent-formatting-context -#[derive(Debug)] -enum IndependentFormattingContext { - Flow(BlockFormattingContext), - - // Not called FC in specs, but behaves close enough - Replaced(ReplacedContent), - // Other layout modes go here -} - -enum NonReplacedIFC<'a> { - Flow(&'a BlockFormattingContext), -} - -impl IndependentFormattingContext { - fn construct<'dom, 'style>( - context: &SharedStyleContext<'style>, - style: &Arc<ComputedValues>, - display_inside: DisplayInside, - contents: Contents<impl NodeExt<'dom>>, - ) -> Self { - match contents.try_into() { - Ok(non_replaced) => match display_inside { - DisplayInside::Flow | DisplayInside::FlowRoot => { - IndependentFormattingContext::Flow(BlockFormattingContext::construct( - context, - style, - non_replaced, - )) - }, - }, - Err(replaced) => IndependentFormattingContext::Replaced(replaced), - } - } - - fn as_replaced(&self) -> Result<&ReplacedContent, NonReplacedIFC> { - match self { - IndependentFormattingContext::Replaced(r) => Ok(r), - IndependentFormattingContext::Flow(f) => Err(NonReplacedIFC::Flow(f)), - } - } - - fn layout<'a>( - &'a self, - layout_context: &LayoutContext, - containing_block: &ContainingBlock, - tree_rank: usize, - absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, - ) -> FlowChildren { - match self.as_replaced() { - Ok(replaced) => match *replaced {}, - Err(ifc) => ifc.layout( - layout_context, - containing_block, - tree_rank, - absolutely_positioned_fragments, - ), - } - } -} - -impl<'a> NonReplacedIFC<'a> { - fn layout( - &self, - layout_context: &LayoutContext, - containing_block: &ContainingBlock, - tree_rank: usize, - absolutely_positioned_fragments: &mut Vec<AbsolutelyPositionedFragment<'a>>, - ) -> FlowChildren { - match self { - NonReplacedIFC::Flow(bfc) => bfc.layout( - layout_context, - containing_block, - tree_rank, - absolutely_positioned_fragments, - ), - } - } -} +use style::properties::ComputedValues; +use style::values::computed::{Length, LengthOrAuto}; +use style::Zero; struct ContainingBlock { inline_size: Length, @@ -162,12 +81,3 @@ fn relative_adjustement( block: adjust(box_offsets.block_start, box_offsets.block_end), } } - -// FIXME: use std::mem::take when it’s stable. -// https://github.com/rust-lang/rust/issues/61129 -fn take<T>(x: &mut T) -> T -where - T: Default, -{ - std::mem::replace(x, Default::default()) -} diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index b37a5ed4a70..92bd4c8a4d5 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.rs @@ -3,10 +3,11 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use crate::context::LayoutContext; +use crate::formatting_contexts::IndependentFormattingContext; use crate::fragments::{AnonymousFragment, BoxFragment, CollapsedBlockMargins, Fragment}; use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::style_ext::{ComputedValuesExt, Direction, WritingMode}; -use crate::{ContainingBlock, DefiniteContainingBlock, IndependentFormattingContext}; +use crate::{ContainingBlock, DefiniteContainingBlock}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use servo_arc::Arc; use style::properties::ComputedValues; @@ -15,7 +16,6 @@ use style::Zero; #[derive(Debug)] pub(crate) struct AbsolutelyPositionedBox { - pub style: Arc<ComputedValues>, pub contents: IndependentFormattingContext, } @@ -49,7 +49,7 @@ impl AbsolutelyPositionedBox { initial_start_corner: Vec2<Length>, tree_rank: usize, ) -> AbsolutelyPositionedFragment { - let style = &self.style; + let style = &self.contents.style; let box_offsets = style.box_offsets(); let box_size = style.box_size(); @@ -130,7 +130,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { layout_context: &LayoutContext, containing_block: &DefiniteContainingBlock, ) -> Fragment { - let style = &self.absolutely_positioned_box.style; + let style = &self.absolutely_positioned_box.contents.style; let cbis = containing_block.size.inline; let cbbs = containing_block.size.block; @@ -274,7 +274,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { ); let dummy_tree_rank = 0; let mut absolutely_positioned_fragments = vec![]; - let mut flow_children = self.absolutely_positioned_box.contents.layout( + let mut independent_layout = self.absolutely_positioned_box.contents.layout( layout_context, &containing_block_for_children, dummy_tree_rank, @@ -286,7 +286,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { Anchor::End(end) => cbbs - end - pb.inline_end - margin.inline_end - inline_size, }; - let block_size = block_size.auto_is(|| flow_children.block_size); + let block_size = block_size.auto_is(|| independent_layout.content_block_size); let block_start = match block_anchor { Anchor::Start(start) => start + pb.block_start + margin.block_start, Anchor::End(end) => cbbs - end - pb.block_end - margin.block_end - block_size, @@ -306,7 +306,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { AbsolutelyPositionedFragment::in_positioned_containing_block( layout_context, &absolutely_positioned_fragments, - &mut flow_children.fragments, + &mut independent_layout.fragments, &content_rect.size, &padding, containing_block_for_children.mode, @@ -314,7 +314,7 @@ impl<'a> AbsolutelyPositionedFragment<'a> { Fragment::Box(BoxFragment { style: style.clone(), - children: flow_children.fragments, + children: independent_layout.fragments, content_rect, padding, border, |