Allow dumping the fragment tree in layout_2020

This is done when the dump-flow-tree debug option is passed.
This commit is contained in:
Martin Robinson 2020-01-13 13:00:26 +01:00
parent c6192dc286
commit ea8c635344
4 changed files with 100 additions and 5 deletions

View file

@ -17,6 +17,7 @@ use crate::replaced::ReplacedContent;
use crate::sizing::ContentSizesRequest; use crate::sizing::ContentSizesRequest;
use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside}; use crate::style_ext::{Display, DisplayGeneratingBox, DisplayInside};
use crate::DefiniteContainingBlock; use crate::DefiniteContainingBlock;
use gfx_traits::print_tree::PrintTree;
use script_layout_interface::wrapper_traits::LayoutNode; use script_layout_interface::wrapper_traits::LayoutNode;
use servo_arc::Arc; use servo_arc::Arc;
use style::properties::ComputedValues; use style::properties::ComputedValues;
@ -154,4 +155,11 @@ impl FragmentTreeRoot {
fragment.build_display_list(builder, &containing_block) 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);
}
}
} }

View file

@ -4,6 +4,7 @@
use crate::geom::flow_relative::{Rect, Sides, Vec2}; use crate::geom::flow_relative::{Rect, Sides, Vec2};
use gfx::text::glyph::GlyphStore; use gfx::text::glyph::GlyphStore;
use gfx_traits::print_tree::PrintTree;
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
use std::sync::Arc; use std::sync::Arc;
use style::dom::OpaqueNode; use style::dom::OpaqueNode;
@ -80,6 +81,15 @@ impl Fragment {
Fragment::Image(f) => &mut f.rect.start_corner, 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 { impl AnonymousFragment {
@ -90,13 +100,67 @@ impl AnonymousFragment {
mode, 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 { impl BoxFragment {
pub fn padding_rect(&self) -> Rect<Length> {
self.content_rect.inflate(&self.padding)
}
pub fn border_rect(&self) -> Rect<Length> { pub fn border_rect(&self) -> Rect<Length> {
self.content_rect self.padding_rect().inflate(&self.border)
.inflate(&self.padding) }
.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::<isize>()
));
}
}
impl ImageFragment {
pub fn print(&self, tree: &mut PrintTree) {
tree.add_item(format!(
"Image\
\nrect={:?}",
self.rect
));
} }
} }

View file

@ -45,7 +45,7 @@ pub(crate) mod flow_relative {
pub block: T, pub block: T,
} }
#[derive(Clone, Debug)] #[derive(Clone)]
pub(crate) struct Rect<T> { pub(crate) struct Rect<T> {
pub start_corner: Vec2<T>, pub start_corner: Vec2<T>,
pub size: Vec2<T>, pub size: Vec2<T>,
@ -200,6 +200,19 @@ impl flow_relative::Rect<Length> {
} }
} }
impl fmt::Debug for flow_relative::Rect<Length> {
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<T: Clone> flow_relative::Vec2<T> { impl<T: Clone> flow_relative::Vec2<T> {
pub fn size_to_physical(&self, mode: WritingMode) -> physical::Vec2<T> { pub fn size_to_physical(&self, mode: WritingMode) -> physical::Vec2<T> {
// https://drafts.csswg.org/css-writing-modes/#logical-to-physical // https://drafts.csswg.org/css-writing-modes/#logical-to-physical

View file

@ -213,6 +213,9 @@ pub struct LayoutThread {
/// Emits notifications when there is a relayout. /// Emits notifications when there is a relayout.
relayout_event: bool, relayout_event: bool,
/// Dumps the fragment tree after a layout.
dump_fragment_tree: bool,
} }
impl LayoutThreadFactory for LayoutThread { impl LayoutThreadFactory for LayoutThread {
@ -246,7 +249,7 @@ impl LayoutThreadFactory for LayoutThread {
relayout_event: bool, relayout_event: bool,
_nonincremental_layout: bool, _nonincremental_layout: bool,
_trace_layout: bool, _trace_layout: bool,
_dump_flow_tree: bool, dump_flow_tree: bool,
) { ) {
thread::Builder::new() thread::Builder::new()
.name(format!("LayoutThread {:?}", id)) .name(format!("LayoutThread {:?}", id))
@ -287,6 +290,7 @@ impl LayoutThreadFactory for LayoutThread {
load_webfonts_synchronously, load_webfonts_synchronously,
window_size, window_size,
relayout_event, relayout_event,
dump_flow_tree,
); );
let reporter_name = format!("layout-reporter-{}", id); let reporter_name = format!("layout-reporter-{}", id);
@ -449,6 +453,7 @@ impl LayoutThread {
load_webfonts_synchronously: bool, load_webfonts_synchronously: bool,
window_size: WindowSizeData, window_size: WindowSizeData,
relayout_event: bool, relayout_event: bool,
dump_fragment_tree: bool,
) -> LayoutThread { ) -> LayoutThread {
// Let webrender know about this pipeline by sending an empty display list. // Let webrender know about this pipeline by sending an empty display list.
webrender_api_sender.send_initial_transaction(webrender_document, id.to_webrender()); webrender_api_sender.send_initial_transaction(webrender_document, id.to_webrender());
@ -527,6 +532,7 @@ impl LayoutThread {
busy, busy,
load_webfonts_synchronously, load_webfonts_synchronously,
relayout_event, relayout_event,
dump_fragment_tree,
} }
} }
@ -1292,6 +1298,10 @@ impl LayoutThread {
let mut display_list = DisplayListBuilder::new(self.id.to_webrender(), viewport_size); let mut display_list = DisplayListBuilder::new(self.id.to_webrender(), viewport_size);
fragment_tree.build_display_list(&mut display_list, viewport_size); fragment_tree.build_display_list(&mut display_list, viewport_size);
if self.dump_fragment_tree {
fragment_tree.print();
}
debug!("Layout done!"); debug!("Layout done!");
let mut epoch = self.epoch.get(); let mut epoch = self.epoch.get();