diff options
-rw-r--r-- | components/layout_2020/display_list/stacking_context.rs | 126 | ||||
-rw-r--r-- | components/layout_2020/flow/root.rs | 61 | ||||
-rw-r--r-- | components/layout_2020/fragments.rs | 53 | ||||
-rw-r--r-- | components/layout_2020/positioned.rs | 7 |
4 files changed, 133 insertions, 114 deletions
diff --git a/components/layout_2020/display_list/stacking_context.rs b/components/layout_2020/display_list/stacking_context.rs index 87a170f499e..c86031df888 100644 --- a/components/layout_2020/display_list/stacking_context.rs +++ b/components/layout_2020/display_list/stacking_context.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::display_list::conversions::ToWebRender; use crate::display_list::DisplayListBuilder; use crate::fragments::{ @@ -13,12 +14,14 @@ use crate::style_ext::ComputedValuesExt; use euclid::default::Rect; use fnv::FnvHashMap; use gfx_traits::{combine_id_with_fragment_type, FragmentType}; +use servo_arc::Arc as ServoArc; use std::cmp::Ordering; use std::mem; use style::computed_values::float::T as ComputedFloat; use style::computed_values::mix_blend_mode::T as ComputedMixBlendMode; use style::computed_values::overflow_x::T as ComputedOverflow; use style::computed_values::position::T as ComputedPosition; +use style::properties::ComputedValues; use style::values::computed::Length; use style::values::generics::box_::Perspective; use style::values::generics::transform; @@ -27,7 +30,7 @@ use webrender_api as wr; use webrender_api::units::{LayoutPoint, LayoutTransform, LayoutVector2D}; #[derive(Clone)] -pub(crate) struct ContainingBlock<'a> { +pub(crate) struct ContainingBlock { /// The SpaceAndClipInfo that contains the children of the fragment that /// established this containing block. space_and_clip: wr::SpaceAndClipInfo, @@ -38,19 +41,19 @@ pub(crate) struct ContainingBlock<'a> { /// Fragments for positioned descendants (including direct children) that were /// hoisted into this containing block. They have hashed based on the /// HoistedFragmentId that is generated during hoisting. - hoisted_children: FnvHashMap<HoistedFragmentId, &'a Fragment>, + hoisted_children: FnvHashMap<HoistedFragmentId, ArcRefCell<Fragment>>, } -impl<'a> ContainingBlock<'a> { +impl ContainingBlock { pub(crate) fn new( rect: &PhysicalRect<Length>, space_and_clip: wr::SpaceAndClipInfo, - children: &'a Vec<Fragment>, + children: &[ArcRefCell<Fragment>], ) -> Self { let mut hoisted_children = FnvHashMap::default(); for child in children { - if let Some(hoisted_fragment_id) = child.hoisted_fragment_id() { - hoisted_children.insert(*hoisted_fragment_id, child); + if let Some(hoisted_fragment_id) = child.borrow().hoisted_fragment_id() { + hoisted_children.insert(*hoisted_fragment_id, child.clone()); } } @@ -63,19 +66,19 @@ impl<'a> ContainingBlock<'a> { } #[derive(Clone)] -pub(crate) struct ContainingBlockInfo<'a> { +pub(crate) struct ContainingBlockInfo { /// The positioning rectangle established by the parent. This is sometimes /// called the "containing block" in layout_2020. pub rect: PhysicalRect<Length>, /// The nearest real containing block at this point in the construction of /// the stacking context tree. - pub nearest_containing_block: Option<ContainingBlock<'a>>, + pub nearest_containing_block: Option<ContainingBlock>, /// The nearest containing block for all descendants at this point in the /// stacking context tree. This containing blocks contains fixed position /// elements. - pub containing_block_for_all_descendants: ContainingBlock<'a>, + pub containing_block_for_all_descendants: ContainingBlock, } pub(crate) struct StackingContextBuilder<'a> { @@ -117,17 +120,18 @@ pub(crate) enum StackingContextSection { Content, } -pub(crate) struct StackingContextFragment<'a> { +pub(crate) struct StackingContextFragment { space_and_clip: wr::SpaceAndClipInfo, section: StackingContextSection, containing_block: PhysicalRect<Length>, - fragment: &'a Fragment, + fragment: ArcRefCell<Fragment>, } -impl<'a> StackingContextFragment<'a> { +impl StackingContextFragment { fn build_display_list(&self, builder: &mut DisplayListBuilder) { builder.current_space_and_clip = self.space_and_clip; self.fragment + .borrow() .build_display_list(builder, &self.containing_block); } } @@ -140,31 +144,31 @@ pub(crate) enum StackingContextType { PseudoAtomicInline, } -pub(crate) struct StackingContext<'a> { +pub(crate) struct StackingContext { /// The fragment that established this stacking context. - initializing_fragment: Option<&'a BoxFragment>, + initializing_fragment_style: Option<ServoArc<ComputedValues>>, /// The type of this StackingContext. Used for collecting and sorting. context_type: StackingContextType, /// Fragments that make up the content of this stacking context. - fragments: Vec<StackingContextFragment<'a>>, + fragments: Vec<StackingContextFragment>, /// All non-float stacking context and pseudo stacking context children /// of this stacking context. - stacking_contexts: Vec<StackingContext<'a>>, + stacking_contexts: Vec<StackingContext>, /// All float pseudo stacking context children of this stacking context. - float_stacking_contexts: Vec<StackingContext<'a>>, + float_stacking_contexts: Vec<StackingContext>, } -impl<'a> StackingContext<'a> { +impl StackingContext { pub(crate) fn new( - initializing_fragment: &'a BoxFragment, + initializing_fragment_style: ServoArc<ComputedValues>, context_type: StackingContextType, ) -> Self { Self { - initializing_fragment: Some(initializing_fragment), + initializing_fragment_style: Some(initializing_fragment_style), context_type, fragments: vec![], stacking_contexts: vec![], @@ -174,7 +178,7 @@ impl<'a> StackingContext<'a> { pub(crate) fn create_root() -> Self { Self { - initializing_fragment: None, + initializing_fragment_style: None, context_type: StackingContextType::Real, fragments: vec![], stacking_contexts: vec![], @@ -183,10 +187,9 @@ impl<'a> StackingContext<'a> { } fn z_index(&self) -> i32 { - match self.initializing_fragment { - Some(fragment) => fragment.style.effective_z_index(), - None => 0, - } + self.initializing_fragment_style + .as_ref() + .map_or(0, |style| style.effective_z_index()) } pub(crate) fn sort(&mut self) { @@ -210,18 +213,17 @@ impl<'a> StackingContext<'a> { }); } - fn push_webrender_stacking_context_if_necessary( + fn push_webrender_stacking_context_if_necessary<'a>( &self, builder: &'a mut DisplayListBuilder, ) -> bool { - let fragment = match self.initializing_fragment { - Some(fragment) => fragment, + let effects = match self.initializing_fragment_style.as_ref() { + Some(style) => style.get_effects(), None => return false, }; // WebRender only uses the stacking context to apply certain effects. If we don't // actually need to create a stacking context, just avoid creating one. - let effects = fragment.style.get_effects(); if effects.filter.0.is_empty() && effects.opacity == 1.0 && effects.mix_blend_mode == ComputedMixBlendMode::Normal @@ -261,7 +263,7 @@ impl<'a> StackingContext<'a> { true } - pub(crate) fn build_display_list(&'a self, builder: &'a mut DisplayListBuilder) { + pub(crate) fn build_display_list<'a>(&self, builder: &'a mut DisplayListBuilder) { let pushed_context = self.push_webrender_stacking_context_if_necessary(builder); // Properly order display items that make up a stacking context. "Steps" here @@ -323,11 +325,12 @@ pub(crate) enum StackingContextBuildMode { } impl Fragment { - pub(crate) fn build_stacking_context_tree<'a>( - &'a self, + pub(crate) fn build_stacking_context_tree( + &self, + fragment_ref: &ArcRefCell<Fragment>, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, - stacking_context: &mut StackingContext<'a>, + containing_block_info: &ContainingBlockInfo, + stacking_context: &mut StackingContext, mode: StackingContextBuildMode, ) { if mode == StackingContextBuildMode::SkipHoisted && self.is_hoisted() { @@ -337,7 +340,7 @@ impl Fragment { match self { Fragment::Box(fragment) => { fragment.build_stacking_context_tree( - self, + fragment_ref, builder, containing_block_info, stacking_context, @@ -362,7 +365,7 @@ impl Fragment { section: StackingContextSection::Content, space_and_clip: builder.current_space_and_clip, containing_block: containing_block_info.rect, - fragment: self, + fragment: fragment_ref.clone(), }); }, } @@ -407,7 +410,7 @@ impl BoxFragment { &'a self, builder: &mut StackingContextBuilder, padding_rect: &PhysicalRect<Length>, - containing_block_info: &mut ContainingBlockInfo<'a>, + containing_block_info: &mut ContainingBlockInfo, ) { if !self.style.establishes_containing_block() { return; @@ -427,12 +430,12 @@ impl BoxFragment { } } - fn build_stacking_context_tree<'a>( - &'a self, - fragment: &'a Fragment, + fn build_stacking_context_tree( + &self, + fragment: &ArcRefCell<Fragment>, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, - stacking_context: &mut StackingContext<'a>, + containing_block_info: &ContainingBlockInfo, + stacking_context: &mut StackingContext, ) { builder.clipping_and_scrolling_scope(|builder| { self.adjust_spatial_id_for_positioning(builder); @@ -450,7 +453,7 @@ impl BoxFragment { }, }; - let mut child_stacking_context = StackingContext::new(self, context_type); + let mut child_stacking_context = StackingContext::new(self.style.clone(), context_type); self.build_stacking_context_tree_for_children( fragment, builder, @@ -478,10 +481,10 @@ impl BoxFragment { fn build_stacking_context_tree_for_children<'a>( &'a self, - fragment: &'a Fragment, + fragment: &ArcRefCell<Fragment>, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, - stacking_context: &mut StackingContext<'a>, + containing_block_info: &ContainingBlockInfo, + stacking_context: &mut StackingContext, ) { let relative_border_rect = self .border_rect() @@ -506,7 +509,7 @@ impl BoxFragment { space_and_clip: builder.current_space_and_clip, section: self.get_stacking_context_section(), containing_block: new_containing_block_info.rect, - fragment, + fragment: fragment.clone(), }); // We want to build the scroll frame after the background and border, because @@ -528,7 +531,8 @@ impl BoxFragment { self.build_containing_block(builder, &padding_rect, &mut new_containing_block_info); for child in &self.children { - child.build_stacking_context_tree( + child.borrow().build_stacking_context_tree( + child, builder, &new_containing_block_info, stacking_context, @@ -551,7 +555,7 @@ impl BoxFragment { fn build_scroll_frame_if_necessary<'a>( &self, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, + containing_block_info: &ContainingBlockInfo, ) { let overflow_x = self.style.get_box().overflow_x; let overflow_y = self.style.get_box().overflow_y; @@ -715,11 +719,11 @@ impl BoxFragment { } impl AnonymousFragment { - fn build_stacking_context_tree<'a>( - &'a self, + fn build_stacking_context_tree( + &self, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, - stacking_context: &mut StackingContext<'a>, + containing_block_info: &ContainingBlockInfo, + stacking_context: &mut StackingContext, ) { let mut new_containing_block_info = containing_block_info.clone(); new_containing_block_info.rect = self @@ -727,7 +731,8 @@ impl AnonymousFragment { .to_physical(self.mode, &containing_block_info.rect) .translate(containing_block_info.rect.origin.to_vector()); for child in &self.children { - child.build_stacking_context_tree( + child.borrow().build_stacking_context_tree( + child, builder, &new_containing_block_info, stacking_context, @@ -738,13 +743,13 @@ impl AnonymousFragment { } impl AbsoluteOrFixedPositionedFragment { - fn build_stacking_context_tree<'a>( - &'a self, + fn build_stacking_context_tree( + &self, builder: &mut StackingContextBuilder, - containing_block_info: &ContainingBlockInfo<'a>, - stacking_context: &mut StackingContext<'a>, + containing_block_info: &ContainingBlockInfo, + stacking_context: &mut StackingContext, ) { - let mut build_for_containing_block = |containing_block: &ContainingBlock<'a>| { + let mut build_for_containing_block = |containing_block: &ContainingBlock| { let hoisted_child = match containing_block.hoisted_children.get(&self.0) { Some(hoisted_child) => hoisted_child, None => return false, @@ -754,7 +759,8 @@ impl AbsoluteOrFixedPositionedFragment { let mut new_containing_block_info = containing_block_info.clone(); new_containing_block_info.rect = containing_block.rect; builder.current_space_and_clip = containing_block.space_and_clip; - hoisted_child.build_stacking_context_tree( + hoisted_child.borrow().build_stacking_context_tree( + hoisted_child, builder, &new_containing_block_info, stacking_context, diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 6a8be578630..46db5d4b7d8 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -38,7 +38,7 @@ pub struct BoxTreeRoot(BlockFormattingContext); #[derive(Serialize)] pub struct FragmentTreeRoot { /// The children of the root of the fragment tree. - children: Vec<Fragment>, + children: Vec<ArcRefCell<Fragment>>, /// The scrollable overflow of the root of the fragment tree. scrollable_overflow: PhysicalRect<Length>, @@ -182,7 +182,11 @@ impl BoxTreeRoot { }); FragmentTreeRoot { - children: independent_layout.fragments, + children: independent_layout + .fragments + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)) + .collect(), scrollable_overflow, initial_containing_block: physical_containing_block, } @@ -205,7 +209,8 @@ impl FragmentTreeRoot { }; for fragment in &self.children { - fragment.build_stacking_context_tree( + fragment.borrow().build_stacking_context_tree( + fragment, &mut stacking_context_builder, &containing_block_info, &mut stacking_context, @@ -221,7 +226,7 @@ impl FragmentTreeRoot { pub fn print(&self) { let mut print_tree = PrintTree::new("Fragment Tree".to_string()); for fragment in &self.children { - fragment.print(&mut print_tree); + fragment.borrow().print(&mut print_tree); } } @@ -236,49 +241,11 @@ impl FragmentTreeRoot { &self, mut process_func: impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>, ) -> Option<T> { - fn recur<T>( - fragments: &[Fragment], - containing_block: &PhysicalRect<Length>, - process_func: &mut impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>, - ) -> Option<T> { - for fragment in fragments { - if let Some(result) = process_func(fragment, containing_block) { - return Some(result); - } - - match fragment { - Fragment::Box(fragment) => { - let new_containing_block = fragment - .content_rect - .to_physical(fragment.style.writing_mode, containing_block) - .translate(containing_block.origin.to_vector()); - if let Some(result) = - recur(&fragment.children, &new_containing_block, process_func) - { - return Some(result); - } - }, - Fragment::Anonymous(fragment) => { - let new_containing_block = fragment - .rect - .to_physical(fragment.mode, containing_block) - .translate(containing_block.origin.to_vector()); - if let Some(result) = - recur(&fragment.children, &new_containing_block, process_func) - { - return Some(result); - } - }, - _ => {}, - } - } - None - } - recur( - &self.children, - &self.initial_containing_block, - &mut process_func, - ) + self.children.iter().find_map(|child| { + child + .borrow() + .find(&self.initial_containing_block, &mut process_func) + }) } pub fn get_content_box_for_node(&self, requested_node: OpaqueNode) -> Rect<Au> { diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 3be702bbf84..921b532c396 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.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::geom::flow_relative::{Rect, Sides}; use crate::geom::{PhysicalPoint, PhysicalRect}; #[cfg(debug_assertions)] @@ -39,7 +40,7 @@ pub(crate) struct BoxFragment { pub debug_id: DebugId, #[serde(skip_serializing)] pub style: ServoArc<ComputedValues>, - pub children: Vec<Fragment>, + pub children: Vec<ArcRefCell<Fragment>>, /// From the containing block’s start corner…? /// This might be broken when the containing block is in a different writing mode: @@ -79,7 +80,7 @@ pub(crate) struct CollapsedMargin { pub(crate) struct AnonymousFragment { pub debug_id: DebugId, pub rect: Rect<Length>, - pub children: Vec<Fragment>, + pub children: Vec<ArcRefCell<Fragment>>, pub mode: WritingMode, /// The scrollable overflow of this anonymous fragment's children. @@ -162,6 +163,40 @@ impl Fragment { _ => None, } } + + pub(crate) fn find<T>( + &self, + containing_block: &PhysicalRect<Length>, + process_func: &mut impl FnMut(&Fragment, &PhysicalRect<Length>) -> Option<T>, + ) -> Option<T> { + if let Some(result) = process_func(self, containing_block) { + return Some(result); + } + + match self { + Fragment::Box(fragment) => { + let new_containing_block = fragment + .content_rect + .to_physical(fragment.style.writing_mode, containing_block) + .translate(containing_block.origin.to_vector()); + fragment + .children + .iter() + .find_map(|child| child.borrow().find(&new_containing_block, process_func)) + }, + Fragment::Anonymous(fragment) => { + let new_containing_block = fragment + .rect + .to_physical(fragment.mode, containing_block) + .translate(containing_block.origin.to_vector()); + fragment + .children + .iter() + .find_map(|child| child.borrow().find(&new_containing_block, process_func)) + }, + _ => None, + } + } } impl AbsoluteOrFixedPositionedFragment { @@ -193,7 +228,10 @@ impl AnonymousFragment { AnonymousFragment { debug_id: DebugId::new(), rect, - children, + children: children + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)) + .collect(), mode, scrollable_overflow, } @@ -208,7 +246,7 @@ impl AnonymousFragment { )); for child in &self.children { - child.print(tree); + child.borrow().print(tree); } tree.end_level(); } @@ -234,7 +272,10 @@ impl BoxFragment { tag, debug_id: DebugId::new(), style, - children, + children: children + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)) + .collect(), content_rect, padding, border, @@ -292,7 +333,7 @@ impl BoxFragment { )); for child in &self.children { - child.print(tree); + child.borrow().print(tree); } tree.end_level(); } diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs index a0216ec296c..058173cb88a 100644 --- a/components/layout_2020/positioned.rs +++ b/components/layout_2020/positioned.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::{Contents, NodeExt}; use crate::formatting_contexts::IndependentFormattingContext; @@ -282,7 +283,11 @@ impl PositioningContext { hoisted_boxes = take_hoisted_boxes_pending_layout(self); } - new_fragment.children.extend(laid_out_child_fragments); + new_fragment.children.extend( + laid_out_child_fragments + .into_iter() + .map(|fragment| ArcRefCell::new(fragment)), + ); } pub(crate) fn push(&mut self, box_: HoistedAbsolutelyPositionedBox) { |