diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index eb4a03be62e..b7b04cbe3a6 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -29,7 +29,7 @@ mod float; pub mod inline; mod root; -pub use root::{BoxTreeRoot, FragmentTreeRoot}; +pub use root::{BoxTree, FragmentTree}; #[derive(Debug, Serialize)] pub(crate) struct BlockFormattingContext { diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 8076bb5c1d9..78efef5de3c 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -34,21 +34,33 @@ use style::values::computed::Length; use style_traits::CSSPixel; #[derive(Serialize)] -pub struct BoxTreeRoot(BlockFormattingContext); +pub struct BoxTree { + /// Contains typically exactly one block-level box, which was generated by the root element. + /// There may be zero if that element has `display: none`. + root: BlockFormattingContext, +} #[derive(Serialize)] -pub struct FragmentTreeRoot { - /// The children of the root of the fragment tree. - children: Vec>, +pub struct FragmentTree { + /// Fragments at the top-level of the tree. + /// + /// If the root element has `display: none`, there are zero fragments. + /// Otherwise, there is at least one: + /// + /// * The first fragment is generated by the root element. + /// * There may be additional fragments generated by positioned boxes + /// that have the initial containing block. + root_fragments: Vec>, - /// The scrollable overflow of the root of the fragment tree. + /// The scrollable overflow rectangle for the entire tree + /// https://drafts.csswg.org/css-overflow/#scrollable scrollable_overflow: PhysicalRect, /// The containing block used in the layout of this fragment tree. initial_containing_block: PhysicalRect, } -impl BoxTreeRoot { +impl BoxTree { pub fn construct<'dom, Node>(context: &LayoutContext, root_element: Node) -> Self where Node: 'dom + Copy + LayoutNode<'dom> + Send + Sync, @@ -58,10 +70,12 @@ impl BoxTreeRoot { // Zero box for `:root { display: none }`, one for the root element otherwise. assert!(boxes.len() <= 1); - Self(BlockFormattingContext { - contains_floats: contains_floats == ContainsFloats::Yes, - contents: BlockContainer::BlockLevelBoxes(boxes), - }) + Self { + root: BlockFormattingContext { + contains_floats: contains_floats == ContainsFloats::Yes, + contents: BlockContainer::BlockLevelBoxes(boxes), + }, + } } } @@ -135,12 +149,12 @@ fn construct_for_root_element<'dom>( (contains_floats, vec![root_box]) } -impl BoxTreeRoot { +impl BoxTree { pub fn layout( &self, layout_context: &LayoutContext, viewport: euclid::Size2D, - ) -> FragmentTreeRoot { + ) -> FragmentTree { let style = ComputedValues::initial_values(); // FIXME: use the document’s mode: @@ -160,21 +174,21 @@ impl BoxTreeRoot { let dummy_tree_rank = 0; let mut positioning_context = PositioningContext::new_for_containing_block_for_all_descendants(); - let independent_layout = self.0.layout( + let independent_layout = self.root.layout( layout_context, &mut positioning_context, &(&initial_containing_block).into(), dummy_tree_rank, ); - let mut children = independent_layout + let mut root_fragments = independent_layout .fragments .into_iter() .map(|fragment| ArcRefCell::new(fragment)) .collect::>(); // Zero box for `:root { display: none }`, one for the root element otherwise. - assert!(children.len() <= 1); + assert!(root_fragments.len() <= 1); // There may be more fragments at the top-level // (for positioned boxes whose containing is the initial containing block) @@ -182,39 +196,41 @@ impl BoxTreeRoot { positioning_context.layout_initial_containing_block_children( layout_context, &initial_containing_block, - &mut children, + &mut root_fragments, ); - let scrollable_overflow = children.iter().fold(PhysicalRect::zero(), |acc, child| { - let child_overflow = child - .borrow() - .scrollable_overflow(&physical_containing_block); + let scrollable_overflow = root_fragments + .iter() + .fold(PhysicalRect::zero(), |acc, child| { + let child_overflow = child + .borrow() + .scrollable_overflow(&physical_containing_block); - // https://drafts.csswg.org/css-overflow/#scrolling-direction - // We want to clip scrollable overflow on box-start and inline-start - // sides of the scroll container. - // - // FIXME(mrobinson, bug 25564): This should take into account writing - // mode. - let child_overflow = PhysicalRect::new( - euclid::Point2D::zero(), - euclid::Size2D::new( - child_overflow.size.width + child_overflow.origin.x, - child_overflow.size.height + child_overflow.origin.y, - ), - ); - acc.union(&child_overflow) - }); + // https://drafts.csswg.org/css-overflow/#scrolling-direction + // We want to clip scrollable overflow on box-start and inline-start + // sides of the scroll container. + // + // FIXME(mrobinson, bug 25564): This should take into account writing + // mode. + let child_overflow = PhysicalRect::new( + euclid::Point2D::zero(), + euclid::Size2D::new( + child_overflow.size.width + child_overflow.origin.x, + child_overflow.size.height + child_overflow.origin.y, + ), + ); + acc.union(&child_overflow) + }); - FragmentTreeRoot { - children, + FragmentTree { + root_fragments, scrollable_overflow, initial_containing_block: physical_containing_block, } } } -impl FragmentTreeRoot { +impl FragmentTree { pub fn build_display_list(&self, builder: &mut crate::display_list::DisplayListBuilder) { let mut stacking_context = StackingContext::create_root(&builder.wr); { @@ -228,7 +244,7 @@ impl FragmentTreeRoot { ), }; - for fragment in &self.children { + for fragment in &self.root_fragments { fragment.borrow().build_stacking_context_tree( fragment, &mut stacking_context_builder, @@ -245,7 +261,7 @@ impl FragmentTreeRoot { pub fn print(&self) { let mut print_tree = PrintTree::new("Fragment Tree".to_string()); - for fragment in &self.children { + for fragment in &self.root_fragments { fragment.borrow().print(&mut print_tree); } } @@ -261,7 +277,7 @@ impl FragmentTreeRoot { &self, mut process_func: impl FnMut(&Fragment, &PhysicalRect) -> Option, ) -> Option { - self.children.iter().find_map(|child| { + self.root_fragments.iter().find_map(|child| { child .borrow() .find(&self.initial_containing_block, &mut process_func) diff --git a/components/layout_2020/layout_debug.rs b/components/layout_2020/layout_debug.rs index 571aa28eee9..79762f8b757 100644 --- a/components/layout_2020/layout_debug.rs +++ b/components/layout_2020/layout_debug.rs @@ -5,7 +5,7 @@ //! Supports writing a trace file created during each layout scope //! that can be viewed by an external tool to make layout debugging easier. -use crate::flow::{BoxTreeRoot, FragmentTreeRoot}; +use crate::flow::{BoxTree, FragmentTree}; use serde_json::{to_string, to_value, Value}; use std::cell::RefCell; use std::fs; @@ -63,8 +63,8 @@ impl ScopeData { } struct State { - fragment_tree: Arc, - box_tree: Arc, + fragment_tree: Arc, + box_tree: Arc, scope_stack: Vec>, } @@ -109,7 +109,7 @@ pub fn generate_unique_debug_id() -> u16 { /// Begin a layout debug trace. If this has not been called, /// creating debug scopes has no effect. -pub fn begin_trace(box_tree: Arc, fragment_tree: Arc) { +pub fn begin_trace(box_tree: Arc, fragment_tree: Arc) { assert!(STATE_KEY.with(|ref r| r.borrow().is_none())); STATE_KEY.with(|ref r| { diff --git a/components/layout_2020/lib.rs b/components/layout_2020/lib.rs index ed9531bfc38..f4f3a81d065 100644 --- a/components/layout_2020/lib.rs +++ b/components/layout_2020/lib.rs @@ -30,7 +30,7 @@ mod style_ext; pub mod traversal; pub mod wrapper; -pub use flow::{BoxTreeRoot, FragmentTreeRoot}; +pub use flow::{BoxTree, FragmentTree}; use crate::geom::flow_relative::Vec2; use style::properties::ComputedValues; diff --git a/components/layout_2020/query.rs b/components/layout_2020/query.rs index 18090ffe0d1..bc904d88b24 100644 --- a/components/layout_2020/query.rs +++ b/components/layout_2020/query.rs @@ -4,7 +4,7 @@ //! Utilities for querying the layout, as needed by the layout thread. use crate::context::LayoutContext; -use crate::flow::FragmentTreeRoot; +use crate::flow::FragmentTree; use crate::fragments::Fragment; use app_units::Au; use euclid::default::{Point2D, Rect}; @@ -166,14 +166,9 @@ impl LayoutRPC for LayoutRPCImpl { pub fn process_content_box_request( requested_node: OpaqueNode, - fragment_tree_root: Option>, + fragment_tree: Option>, ) -> Option> { - let fragment_tree_root = match fragment_tree_root { - Some(fragment_tree_root) => fragment_tree_root, - None => return None, - }; - - Some(fragment_tree_root.get_content_box_for_node(requested_node)) + Some(fragment_tree?.get_content_box_for_node(requested_node)) } pub fn process_content_boxes_request(_requested_node: OpaqueNode) -> Vec> { @@ -182,14 +177,13 @@ pub fn process_content_boxes_request(_requested_node: OpaqueNode) -> Vec>, + fragment_tree: Option>, ) -> Rect { - let fragment_tree_root = match fragment_tree_root { - Some(fragment_tree_root) => fragment_tree_root, - None => return Rect::zero(), - }; - - fragment_tree_root.get_border_dimensions_for_node(requested_node) + if let Some(fragment_tree) = fragment_tree { + fragment_tree.get_border_dimensions_for_node(requested_node) + } else { + Rect::zero() + } } pub fn process_node_scroll_id_request<'dom>( @@ -212,7 +206,7 @@ pub fn process_resolved_style_request<'dom>( node: impl LayoutNode<'dom>, pseudo: &Option, property: &PropertyId, - fragment_tree_root: Option>, + fragment_tree: Option>, ) -> String { if !node.as_element().unwrap().has_data() { return process_resolved_style_request_for_unstyled_node(context, node, pseudo, property); @@ -286,11 +280,11 @@ pub fn process_resolved_style_request<'dom>( return computed_style(); } - let fragment_tree_root = match fragment_tree_root { - Some(fragment_tree_root) => fragment_tree_root, + let fragment_tree = match fragment_tree { + Some(fragment_tree) => fragment_tree, None => return computed_style(), }; - fragment_tree_root + fragment_tree .find(|fragment, containing_block| { let box_fragment = match fragment { Fragment::Box(ref box_fragment) if box_fragment.tag == node.opaque() => { diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 66fc5d53183..0ad917f3a18 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -45,7 +45,7 @@ use layout::query::{ process_offset_parent_query, process_resolved_style_request, process_text_index_request, }; use layout::traversal::RecalcStyle; -use layout::{BoxTreeRoot, FragmentTreeRoot}; +use layout::{BoxTree, FragmentTree}; use layout_traits::LayoutThreadFactory; use libc::c_void; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; @@ -160,11 +160,11 @@ pub struct LayoutThread { /// The number of Web fonts that have been requested but not yet loaded. outstanding_web_fonts: Arc, - /// The root of the box tree. - box_tree_root: RefCell>>, + /// The box tree. + box_tree: RefCell>>, - /// The root of the fragment tree. - fragment_tree_root: RefCell>>, + /// The fragment tree. + fragment_tree: RefCell>>, /// The document-specific shared lock used for author-origin stylesheets document_shared_lock: Option, @@ -513,8 +513,8 @@ impl LayoutThread { font_cache_sender: ipc_font_cache_sender, generation: Cell::new(0), outstanding_web_fonts: Arc::new(AtomicUsize::new(0)), - box_tree_root: Default::default(), - fragment_tree_root: Default::default(), + box_tree: Default::default(), + fragment_tree: Default::default(), document_shared_lock: None, // Epoch starts at 1 because of the initial display list for epoch 0 that we send to WR epoch: Cell::new(Epoch(1)), @@ -1078,7 +1078,7 @@ impl LayoutThread { driver::traverse_dom(&traversal, token, rayon_pool); let root_node = document.root_element().unwrap().as_node(); - let build_box_tree = || BoxTreeRoot::construct(traversal.context(), root_node); + let build_box_tree = || BoxTree::construct(traversal.context(), root_node); let box_tree = if let Some(pool) = rayon_pool { pool.install(build_box_tree) } else { @@ -1103,8 +1103,8 @@ impl LayoutThread { } else { run_layout() }); - *self.box_tree_root.borrow_mut() = Some(box_tree); - *self.fragment_tree_root.borrow_mut() = Some(fragment_tree); + *self.box_tree.borrow_mut() = Some(box_tree); + *self.fragment_tree.borrow_mut() = Some(fragment_tree); } for element in elements_with_snapshot { @@ -1130,7 +1130,7 @@ impl LayoutThread { layout_context.style_context.stylist.rule_tree().maybe_gc(); // Perform post-style recalculation layout passes. - if let Some(root) = &*self.fragment_tree_root.borrow() { + if let Some(root) = &*self.fragment_tree.borrow() { self.perform_post_style_recalc_layout_passes( root.clone(), &data.reflow_goal, @@ -1162,7 +1162,7 @@ impl LayoutThread { ReflowGoal::LayoutQuery(ref querymsg, _) => match querymsg { &QueryMsg::ContentBoxQuery(node) => { rw_data.content_box_response = - process_content_box_request(node, self.fragment_tree_root.borrow().clone()); + process_content_box_request(node, self.fragment_tree.borrow().clone()); }, &QueryMsg::ContentBoxesQuery(node) => { rw_data.content_boxes_response = process_content_boxes_request(node); @@ -1175,10 +1175,8 @@ impl LayoutThread { rw_data.text_index_response = process_text_index_request(node, point_in_node); }, &QueryMsg::ClientRectQuery(node) => { - rw_data.client_rect_response = process_node_geometry_request( - node, - self.fragment_tree_root.borrow().clone(), - ); + rw_data.client_rect_response = + process_node_geometry_request(node, self.fragment_tree.borrow().clone()); }, &QueryMsg::NodeScrollGeometryQuery(node) => { rw_data.scroll_area_response = process_node_scroll_area_request(node); @@ -1190,7 +1188,7 @@ impl LayoutThread { }, &QueryMsg::ResolvedStyleQuery(node, ref pseudo, ref property) => { let node = unsafe { ServoLayoutNode::new(&node) }; - let fragment_tree = self.fragment_tree_root.borrow().clone(); + let fragment_tree = self.fragment_tree.borrow().clone(); rw_data.resolved_style_response = process_resolved_style_request( context, node, @@ -1270,13 +1268,13 @@ impl LayoutThread { fn perform_post_style_recalc_layout_passes( &self, - fragment_tree: Arc, + fragment_tree: Arc, reflow_goal: &ReflowGoal, document: Option<&ServoLayoutDocument>, context: &mut LayoutContext, ) { if self.trace_layout { - if let Some(box_tree) = &*self.box_tree_root.borrow() { + if let Some(box_tree) = &*self.box_tree.borrow() { layout_debug::begin_trace(box_tree.clone(), fragment_tree.clone()); } }