Merge pull request #3420 from glennw/table-debug

Adds support for table layout trace and updates viewer for tables.
This commit is contained in:
Patrick Walton 2014-09-19 19:50:47 -07:00
commit ccda8f204a
9 changed files with 118 additions and 10 deletions

View file

@ -1481,7 +1481,7 @@ impl Flow for BlockFlow {
///
/// TODO(pcwalton): Inline blocks.
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("bubble_inline_sizes {:s}", self.base.debug_id());
let _scope = layout_debug_scope!("block::bubble_inline_sizes {:s}", self.base.debug_id());
let mut flags = self.base.flags;
flags.set_has_left_floated_descendants(false);

View file

@ -103,11 +103,22 @@ pub trait Flow: fmt::Show + ToString + Share {
fail!("called as_table_wrapper() on a non-tablewrapper flow")
}
/// If this is a table wrapper flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_table_wrapper<'a>(&'a self) -> &'a TableWrapperFlow {
fail!("called as_immutable_table_wrapper() on a non-tablewrapper flow")
}
/// If this is a table flow, returns the underlying object. Fails otherwise.
fn as_table<'a>(&'a mut self) -> &'a mut TableFlow {
fail!("called as_table() on a non-table flow")
}
/// If this is a table flow, returns the underlying object, borrowed immutably. Fails otherwise.
fn as_immutable_table<'a>(&'a self) -> &'a TableFlow {
fail!("called as_table() on a non-table flow")
}
/// If this is a table colgroup flow, returns the underlying object. Fails otherwise.
fn as_table_colgroup<'a>(&'a mut self) -> &'a mut TableColGroupFlow {
fail!("called as_table_colgroup() on a non-tablecolgroup flow")
@ -118,11 +129,23 @@ pub trait Flow: fmt::Show + ToString + Share {
fail!("called as_table_rowgroup() on a non-tablerowgroup flow")
}
/// If this is a table rowgroup flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_table_rowgroup<'a>(&'a self) -> &'a TableRowGroupFlow {
fail!("called as_table_rowgroup() on a non-tablerowgroup flow")
}
/// If this is a table row flow, returns the underlying object. Fails otherwise.
fn as_table_row<'a>(&'a mut self) -> &'a mut TableRowFlow {
fail!("called as_table_row() on a non-tablerow flow")
}
/// If this is a table row flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_table_row<'a>(&'a self) -> &'a TableRowFlow {
fail!("called as_table_row() on a non-tablerow flow")
}
/// If this is a table cell flow, returns the underlying object. Fails otherwise.
fn as_table_caption<'a>(&'a mut self) -> &'a mut TableCaptionFlow {
fail!("called as_table_caption() on a non-tablecaption flow")
@ -133,6 +156,12 @@ pub trait Flow: fmt::Show + ToString + Share {
fail!("called as_table_cell() on a non-tablecell flow")
}
/// If this is a table cell flow, returns the underlying object, borrowed immutably. Fails
/// otherwise.
fn as_immutable_table_cell<'a>(&'a self) -> &'a TableCellFlow {
fail!("called as_table_cell() on a non-tablecell flow")
}
/// If this is a table row or table rowgroup or table flow, returns column inline-sizes.
/// Fails otherwise.
fn col_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<Au> {
@ -289,7 +318,12 @@ impl<'a, E, S: Encoder<E>> Encodable<S, E> for &'a Flow {
match self.class() {
BlockFlowClass => self.as_immutable_block().encode(e),
InlineFlowClass => self.as_immutable_inline().encode(e),
_ => { Ok(()) } // TODO: Support tables
TableFlowClass => self.as_immutable_table().encode(e),
TableWrapperFlowClass => self.as_immutable_table_wrapper().encode(e),
TableRowGroupFlowClass => self.as_immutable_table_rowgroup().encode(e),
TableRowFlowClass => self.as_immutable_table_row().encode(e),
TableCellFlowClass => self.as_immutable_table_cell().encode(e),
_ => { Ok(()) } // TODO: Support captions
}
})
})

View file

@ -13,6 +13,7 @@ use context::LayoutContext;
use floats::FloatKind;
use flow::{TableFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use fragment::Fragment;
use layout_debug;
use table_wrapper::{TableLayout, FixedLayout, AutoLayout};
use wrapper::ThreadSafeLayoutNode;
@ -25,6 +26,7 @@ use style::computed_values::table_layout;
/// A table flow corresponded to the table's internal table fragment under a table wrapper flow.
/// The properties `position`, `float`, and `margin-*` are used on the table wrapper fragment,
/// not table fragment per CSS 2.1 § 10.5.
#[deriving(Encodable)]
pub struct TableFlow {
pub block_flow: BlockFlow,
@ -145,6 +147,10 @@ impl Flow for TableFlow {
self
}
fn as_immutable_table<'a>(&'a self) -> &'a TableFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow
}
@ -166,6 +172,9 @@ impl Flow for TableFlow {
/// The maximum min/pref inline-sizes of each column are set from the rows for the automatic
/// table layout calculation.
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("table::bubble_inline_sizes {:s}",
self.block_flow.base.debug_id());
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
let mut did_first_row = false;
@ -241,6 +250,8 @@ impl Flow for TableFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table::assign_inline_sizes {:s}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table");
// The position was set to the containing block by the flow's parent.

View file

@ -11,6 +11,7 @@ use context::LayoutContext;
use flow::{TableCellFlowClass, FlowClass, Flow};
use fragment::Fragment;
use model::{MaybeAuto};
use layout_debug;
use table::InternalTable;
use wrapper::ThreadSafeLayoutNode;
@ -18,6 +19,7 @@ use servo_util::geometry::Au;
use std::fmt;
/// A table formatting context.
#[deriving(Encodable)]
pub struct TableCellFlow {
/// Data common to all flows.
pub block_flow: BlockFlow,
@ -64,12 +66,19 @@ impl Flow for TableCellFlow {
self
}
fn as_immutable_table_cell<'a>(&'a self) -> &'a TableCellFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow
}
/// Minimum/preferred inline-sizes set by this function are used in automatic table layout calculation.
fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_cell::bubble_inline_sizes {:s}",
self.block_flow.base.debug_id());
self.block_flow.bubble_inline_sizes(ctx);
let specified_inline_size = MaybeAuto::from_style(self.block_flow.fragment.style().content_inline_size(),
Au::new(0)).specified_or_zero();
@ -86,6 +95,8 @@ impl Flow for TableCellFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent table row.
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_cell::assign_inline_sizes {:s}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_cell");
// The position was set to the column inline-size by the parent flow, table row flow.

View file

@ -9,6 +9,7 @@
use context::LayoutContext;
use flow::{BaseFlow, TableColGroupFlowClass, FlowClass, Flow};
use fragment::{Fragment, TableColumnFragment};
use layout_debug;
use model::{MaybeAuto};
use wrapper::ThreadSafeLayoutNode;
@ -53,6 +54,9 @@ impl Flow for TableColGroupFlow {
}
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("table_colgroup::bubble_inline_sizes {:s}",
self.base.debug_id());
for fragment in self.cols.iter() {
// get the specified value from inline-size property
let inline_size = MaybeAuto::from_style(fragment.style().content_inline_size(),

View file

@ -13,6 +13,7 @@ use context::LayoutContext;
use flow::{TableRowFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use flow;
use fragment::Fragment;
use layout_debug;
use table::InternalTable;
use model::{MaybeAuto, Specified, Auto};
use wrapper::ThreadSafeLayoutNode;
@ -22,6 +23,7 @@ use std::cmp::max;
use std::fmt;
/// A table formatting context.
#[deriving(Encodable)]
pub struct TableRowFlow {
pub block_flow: BlockFlow,
@ -143,6 +145,10 @@ impl Flow for TableRowFlow {
self
}
fn as_immutable_table_row<'a>(&'a self) -> &'a TableRowFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow
}
@ -166,6 +172,9 @@ impl Flow for TableRowFlow {
/// Min/pref inline-sizes set by this function are used in automatic table layout calculation.
/// The specified column inline-sizes of children cells are used in fixed table layout calculation.
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("table_row::bubble_inline_sizes {:s}",
self.block_flow.base.debug_id());
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
/* find the specified inline_sizes from child table-cell contexts */
@ -195,6 +204,8 @@ impl Flow for TableRowFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When called
/// on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_row::assign_inline_sizes {:s}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row");
// The position was set to the containing block by the flow's parent.

View file

@ -13,6 +13,7 @@ use context::LayoutContext;
use flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use flow;
use fragment::Fragment;
use layout_debug;
use table::{InternalTable, TableFlow};
use wrapper::ThreadSafeLayoutNode;
@ -21,6 +22,7 @@ use std::cmp::max;
use std::fmt;
/// A table formatting context.
#[deriving(Encodable)]
pub struct TableRowGroupFlow {
pub block_flow: BlockFlow,
@ -110,6 +112,10 @@ impl Flow for TableRowGroupFlow {
self
}
fn as_immutable_table_rowgroup<'a>(&'a self) -> &'a TableRowGroupFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow
}
@ -134,6 +140,9 @@ impl Flow for TableRowGroupFlow {
/// Also, this function finds the specified column inline-sizes from the first row.
/// Those are used in fixed table layout calculation
fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let _scope = layout_debug_scope!("table_rowgroup::bubble_inline_sizes {:s}",
self.block_flow.base.debug_id());
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
@ -176,6 +185,8 @@ impl Flow for TableRowGroupFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent context.
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_rowgroup::assign_inline_sizes {:s}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_rowgroup");
// The position was set to the containing block by the flow's parent.

View file

@ -13,6 +13,7 @@ use context::LayoutContext;
use floats::FloatKind;
use flow::{TableWrapperFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use fragment::Fragment;
use layout_debug;
use model::{Specified, Auto, specified};
use wrapper::ThreadSafeLayoutNode;
@ -21,12 +22,14 @@ use std::cmp::max;
use std::fmt;
use style::computed_values::table_layout;
#[deriving(Encodable)]
pub enum TableLayout {
FixedLayout,
AutoLayout
}
/// A table wrapper flow based on a block formatting context.
#[deriving(Encodable)]
pub struct TableWrapperFlow {
pub block_flow: BlockFlow,
@ -119,6 +122,10 @@ impl Flow for TableWrapperFlow {
self
}
fn as_immutable_table_wrapper<'a>(&'a self) -> &'a TableWrapperFlow {
self
}
fn as_block<'a>(&'a mut self) -> &'a mut BlockFlow {
&mut self.block_flow
}
@ -130,6 +137,9 @@ impl Flow for TableWrapperFlow {
any fragments it is responsible for flowing. */
fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_wrapper::bubble_inline_sizes {:s}",
self.block_flow.base.debug_id());
// get column inline-sizes info from table flow
for kid in self.block_flow.base.child_iter() {
assert!(kid.is_table_caption() || kid.is_table());
@ -148,6 +158,8 @@ impl Flow for TableWrapperFlow {
/// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block)
/// contexts.
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
let _scope = layout_debug_scope!("table_wrapper::assign_inline_sizes {:s}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow",
if self.is_float() {
"floated table_wrapper"

View file

@ -89,16 +89,26 @@
<script src="js/formatters.min.js"></script>
<script>
function get_base(node) {
if (node.data.base !== undefined) {
return node.data.base;
}
if (node.data.block_flow.base !== undefined) {
return node.data.block_flow.base;
}
throw "Unknown node type";
}
function create_flow_tree(trace_node) {
var node = {
text: trace_node.class + " (" + trace_node.data.base.id + ")",
id: trace_node.data.base.id,
text: trace_node.class + " (" + get_base(trace_node).id + ")",
id: get_base(trace_node).id,
icon: "dummy",
};
var children = [];
for (var i=0 ; i < trace_node.data.base.children.length ; ++i) {
children.push(create_flow_tree(trace_node.data.base.children[i]));
for (var i=0 ; i < get_base(trace_node).children.length ; ++i) {
children.push(create_flow_tree(get_base(trace_node).children[i]));
}
if (children.length > 0) {
@ -109,13 +119,13 @@
}
function create_flow_hash(trace_node, flow_hash) {
flow_hash[trace_node.data.base.id] = trace_node;
flow_hash[get_base(trace_node).id] = trace_node;
for (var i=0 ; i < trace_node.data.base.children.length ; ++i) {
create_flow_hash(trace_node.data.base.children[i], flow_hash);
for (var i=0 ; i < get_base(trace_node).children.length ; ++i) {
create_flow_hash(get_base(trace_node).children[i], flow_hash);
}
delete trace_node.data.base.children;
delete get_base(trace_node).children;
}
function flatten_trace(trace_node) {
@ -182,6 +192,10 @@
if (obj.data !== undefined && obj.data.base !== undefined) {
return obj.data.base.id;
}
if (obj.data !== undefined && obj.data.block_flow !== undefined &&
obj.data.block_flow.base !== undefined) {
return obj.data.block_flow.base.id;
}
if (obj.id !== undefined) {
return obj.id;
}