diff --git a/components/layout_2020/flow/root.rs b/components/layout_2020/flow/root.rs index 6d6a57594287..14b1081c84a1 100644 --- a/components/layout_2020/flow/root.rs +++ b/components/layout_2020/flow/root.rs @@ -17,6 +17,7 @@ use crate::replaced::ReplacedContent; use crate::sizing::ContentSizesRequest; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; use crate::DefiniteContainingBlock; +use gfx_traits::print_tree::PrintTree; use script_layout_interface::wrapper_traits::LayoutNode; use servo_arc::Arc; use style::properties::ComputedValues; @@ -154,4 +155,11 @@ impl FragmentTreeRoot { fragment.build_display_list(builder, &containing_block) } } + + pub fn print(&self) { + let mut print_tree = PrintTree::new("Fragment Tree".to_string()); + for fragment in &self.0 { + fragment.print(&mut print_tree); + } + } } diff --git a/components/layout_2020/fragments.rs b/components/layout_2020/fragments.rs index 730037a984b6..1bef85d16a78 100644 --- a/components/layout_2020/fragments.rs +++ b/components/layout_2020/fragments.rs @@ -4,6 +4,7 @@ use crate::geom::flow_relative::{Rect, Sides, Vec2}; use gfx::text::glyph::GlyphStore; +use gfx_traits::print_tree::PrintTree; use servo_arc::Arc as ServoArc; use std::sync::Arc; use style::dom::OpaqueNode; @@ -80,6 +81,15 @@ impl Fragment { Fragment::Image(f) => &mut f.rect.start_corner, } } + + pub fn print(&self, tree: &mut PrintTree) { + match self { + Fragment::Box(fragment) => fragment.print(tree), + Fragment::Anonymous(fragment) => fragment.print(tree), + Fragment::Text(fragment) => fragment.print(tree), + Fragment::Image(fragment) => fragment.print(tree), + } + } } impl AnonymousFragment { @@ -90,13 +100,67 @@ impl AnonymousFragment { mode, } } + + pub fn print(&self, tree: &mut PrintTree) { + tree.new_level(format!( + "Anonymous\ + \nrect={:?}", + self.rect + )); + + for child in &self.children { + child.print(tree); + } + tree.end_level(); + } } impl BoxFragment { + pub fn padding_rect(&self) -> Rect { + self.content_rect.inflate(&self.padding) + } + pub fn border_rect(&self) -> Rect { - self.content_rect - .inflate(&self.padding) - .inflate(&self.border) + self.padding_rect().inflate(&self.border) + } + + pub fn print(&self, tree: &mut PrintTree) { + tree.new_level(format!( + "Box\ + \ncontent={:?}\ + \npadding rect={:?}\ + \nborder rect={:?}", + self.content_rect, + self.padding_rect(), + self.border_rect() + )); + + for child in &self.children { + child.print(tree); + } + tree.end_level(); + } +} + +impl TextFragment { + pub fn print(&self, tree: &mut PrintTree) { + tree.add_item(format!( + "Text num_glyphs={}", + self.glyphs + .iter() + .map(|glyph_store| glyph_store.len().0) + .sum::() + )); + } +} + +impl ImageFragment { + pub fn print(&self, tree: &mut PrintTree) { + tree.add_item(format!( + "Image\ + \nrect={:?}", + self.rect + )); } } diff --git a/components/layout_2020/geom.rs b/components/layout_2020/geom.rs index 86e6faf45a72..166ba7a0494a 100644 --- a/components/layout_2020/geom.rs +++ b/components/layout_2020/geom.rs @@ -45,7 +45,7 @@ pub(crate) mod flow_relative { pub block: T, } - #[derive(Clone, Debug)] + #[derive(Clone)] pub(crate) struct Rect { pub start_corner: Vec2, pub size: Vec2, @@ -200,6 +200,19 @@ impl flow_relative::Rect { } } +impl fmt::Debug for flow_relative::Rect { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!( + f, + "Rect(i{}×b{} @ (i{},b{}))", + self.size.inline.px(), + self.size.block.px(), + self.start_corner.inline.px(), + self.start_corner.block.px(), + ) + } +} + impl flow_relative::Vec2 { pub fn size_to_physical(&self, mode: WritingMode) -> physical::Vec2 { // https://drafts.csswg.org/css-writing-modes/#logical-to-physical diff --git a/components/layout_thread_2020/lib.rs b/components/layout_thread_2020/lib.rs index 5df365e889bc..83f96b1c65f3 100644 --- a/components/layout_thread_2020/lib.rs +++ b/components/layout_thread_2020/lib.rs @@ -213,6 +213,9 @@ pub struct LayoutThread { /// Emits notifications when there is a relayout. relayout_event: bool, + + /// Dumps the fragment tree after a layout. + dump_fragment_tree: bool, } impl LayoutThreadFactory for LayoutThread { @@ -246,7 +249,7 @@ impl LayoutThreadFactory for LayoutThread { relayout_event: bool, _nonincremental_layout: bool, _trace_layout: bool, - _dump_flow_tree: bool, + dump_flow_tree: bool, ) { thread::Builder::new() .name(format!("LayoutThread {:?}", id)) @@ -287,6 +290,7 @@ impl LayoutThreadFactory for LayoutThread { load_webfonts_synchronously, window_size, relayout_event, + dump_flow_tree, ); let reporter_name = format!("layout-reporter-{}", id); @@ -449,6 +453,7 @@ impl LayoutThread { load_webfonts_synchronously: bool, window_size: WindowSizeData, relayout_event: bool, + dump_fragment_tree: bool, ) -> LayoutThread { // Let webrender know about this pipeline by sending an empty display list. webrender_api_sender.send_initial_transaction(webrender_document, id.to_webrender()); @@ -527,6 +532,7 @@ impl LayoutThread { busy, load_webfonts_synchronously, relayout_event, + dump_fragment_tree, } } @@ -1292,6 +1298,10 @@ impl LayoutThread { let mut display_list = DisplayListBuilder::new(self.id.to_webrender(), viewport_size); fragment_tree.build_display_list(&mut display_list, viewport_size); + if self.dump_fragment_tree { + fragment_tree.print(); + } + debug!("Layout done!"); let mut epoch = self.epoch.get();