aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/block.rs26
-rw-r--r--components/layout/flow.rs16
-rw-r--r--components/layout/table.rs103
-rw-r--r--components/layout/table_cell.rs4
-rw-r--r--components/layout/table_row.rs39
-rw-r--r--components/layout/table_rowgroup.rs85
-rw-r--r--components/layout/table_wrapper.rs155
7 files changed, 243 insertions, 185 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 6b141b1e749..8e8920e4033 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -47,7 +47,7 @@ use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
use model::{Auto, IntrinsicISizes, MarginCollapseInfo, MarginsCollapse, MarginsCollapseThrough};
use model::{MaybeAuto, NoCollapsibleMargins, Specified, specified, specified_or_none};
-use table::ColumnInlineSize;
+use table::ColumnComputedInlineSize;
use wrapper::ThreadSafeLayoutNode;
use geom::Size2D;
@@ -1258,7 +1258,7 @@ impl BlockFlow {
&mut self,
inline_start_content_edge: Au,
content_inline_size: Au,
- optional_column_inline_sizes: Option<&[ColumnInlineSize]>) {
+ optional_column_computed_inline_sizes: Option<&[ColumnComputedInlineSize]>) {
// Keep track of whether floats could impact each child.
let mut inline_start_floats_impact_child =
self.base.flags.contains(IMPACTED_BY_LEFT_FLOATS);
@@ -1369,12 +1369,12 @@ impl BlockFlow {
}
// Handle tables.
- match optional_column_inline_sizes {
- Some(ref column_inline_sizes) => {
+ match optional_column_computed_inline_sizes {
+ Some(ref column_computed_inline_sizes) => {
propagate_column_inline_sizes_to_child(kid,
i,
content_inline_size,
- *column_inline_sizes,
+ *column_computed_inline_sizes,
&mut inline_start_margin_edge)
}
None => {}
@@ -2551,22 +2551,24 @@ impl ISizeAndMarginsComputer for FloatReplaced {
}
}
-fn propagate_column_inline_sizes_to_child(kid: &mut Flow,
- child_index: uint,
- content_inline_size: Au,
- column_inline_sizes: &[ColumnInlineSize],
- inline_start_margin_edge: &mut Au) {
+fn propagate_column_inline_sizes_to_child(
+ kid: &mut Flow,
+ child_index: uint,
+ content_inline_size: Au,
+ column_computed_inline_sizes: &[ColumnComputedInlineSize],
+ inline_start_margin_edge: &mut Au) {
// If kid is table_rowgroup or table_row, the column inline-sizes info should be copied from
// its parent.
//
// FIXME(pcwalton): This seems inefficient. Reference count it instead?
let inline_size = if kid.is_table() || kid.is_table_rowgroup() || kid.is_table_row() {
- *kid.column_inline_sizes() = column_inline_sizes.iter().map(|&x| x).collect();
+ *kid.column_computed_inline_sizes() =
+ column_computed_inline_sizes.iter().map(|&x| x).collect();
// ISize of kid flow is our content inline-size.
content_inline_size
} else if kid.is_table_cell() {
- column_inline_sizes[child_index].minimum_length
+ column_computed_inline_sizes[child_index].size
} else {
// ISize of kid flow is our content inline-size.
content_inline_size
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 598a8717cdb..5435cacbe67 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -38,7 +38,7 @@ use incremental::{RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use inline::InlineFlow;
use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo};
use parallel::FlowParallelInfo;
-use table::{ColumnInlineSize, TableFlow};
+use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, TableFlow};
use table_caption::TableCaptionFlow;
use table_cell::TableCellFlow;
use table_colgroup::TableColGroupFlow;
@@ -163,10 +163,16 @@ pub trait Flow: fmt::Show + ToString + Sync {
panic!("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 column_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnInlineSize> {
- panic!("called column_inline_sizes() on non-table flow")
+ /// If this is a table row, table rowgroup, or table flow, returns column intrinsic
+ /// inline-sizes. Fails otherwise.
+ fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
+ panic!("called column_intrinsic_inline_sizes() on non-table flow")
+ }
+
+ /// If this is a table row, table rowgroup, or table flow, returns column computed
+ /// inline-sizes. Fails otherwise.
+ fn column_computed_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnComputedInlineSize> {
+ panic!("called column_intrinsic_inline_sizes() on non-table flow")
}
// Main methods
diff --git a/components/layout/table.rs b/components/layout/table.rs
index 20bc19c91fc..b65fa689919 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -34,8 +34,13 @@ use sync::Arc;
pub struct TableFlow {
pub block_flow: BlockFlow,
- /// Information about the inline-sizes of each column.
- pub column_inline_sizes: Vec<ColumnInlineSize>,
+ /// Information about the intrinsic inline-sizes of each column, computed bottom-up during
+ /// intrinsic inline-size bubbling.
+ pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
+
+ /// Information about the actual inline-sizes of each column, computed top-down during actual
+ /// inline-size bubbling.
+ pub column_computed_inline_sizes: Vec<ColumnComputedInlineSize>,
/// Table-layout property
pub table_layout: TableLayout,
@@ -54,7 +59,8 @@ impl TableFlow {
};
TableFlow {
block_flow: block_flow,
- column_inline_sizes: Vec::new(),
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
table_layout: table_layout
}
}
@@ -71,7 +77,8 @@ impl TableFlow {
};
TableFlow {
block_flow: block_flow,
- column_inline_sizes: Vec::new(),
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
table_layout: table_layout
}
}
@@ -89,7 +96,8 @@ impl TableFlow {
};
TableFlow {
block_flow: block_flow,
- column_inline_sizes: Vec::new(),
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
table_layout: table_layout
}
}
@@ -97,13 +105,13 @@ impl TableFlow {
/// Update the corresponding value of `self_inline_sizes` if a value of `kid_inline_sizes` has
/// a larger value than one of `self_inline_sizes`. Returns the minimum and preferred inline
/// sizes.
- pub fn update_column_inline_sizes(parent_inline_sizes: &mut Vec<ColumnInlineSize>,
- child_inline_sizes: &Vec<ColumnInlineSize>)
+ pub fn update_column_inline_sizes(parent_inline_sizes: &mut Vec<ColumnIntrinsicInlineSize>,
+ child_inline_sizes: &Vec<ColumnIntrinsicInlineSize>)
-> IntrinsicISizes {
let mut total_inline_sizes = IntrinsicISizes::new();
for (parent_sizes, child_sizes) in parent_inline_sizes.iter_mut()
.zip(child_inline_sizes.iter()) {
- *parent_sizes = ColumnInlineSize {
+ *parent_sizes = ColumnIntrinsicInlineSize {
minimum_length: max(parent_sizes.minimum_length, child_sizes.minimum_length),
percentage: parent_sizes.greatest_percentage(child_sizes),
preferred: max(parent_sizes.preferred, child_sizes.preferred),
@@ -147,8 +155,12 @@ impl Flow for TableFlow {
&mut self.block_flow
}
- fn column_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnInlineSize> {
- &mut self.column_inline_sizes
+ fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
+ &mut self.column_intrinsic_inline_sizes
+ }
+
+ fn column_computed_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnComputedInlineSize> {
+ &mut self.column_computed_inline_sizes
}
/// The specified column inline-sizes are set from column group and the first row for the fixed
@@ -165,7 +177,7 @@ impl Flow for TableFlow {
debug_assert!(kid.is_proper_table_child());
if kid.is_table_colgroup() {
for specified_inline_size in kid.as_table_colgroup().inline_sizes.iter() {
- self.column_inline_sizes.push(ColumnInlineSize {
+ self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize {
minimum_length: match *specified_inline_size {
LPA_Auto | LPA_Percentage(_) => Au(0),
LPA_Length(length) => length,
@@ -188,25 +200,26 @@ impl Flow for TableFlow {
// Fixed table layout only looks at the first row.
if !did_first_row {
did_first_row = true;
- for child_column_inline_size in kid.column_inline_sizes().iter() {
- self.column_inline_sizes.push(*child_column_inline_size);
+ for child_column_inline_size in kid.column_intrinsic_inline_sizes()
+ .iter() {
+ self.column_intrinsic_inline_sizes.push(*child_column_inline_size);
}
}
}
AutoLayout => {
- let child_column_inline_sizes = kid.column_inline_sizes();
- let mut child_intrinsic_sizes =
- TableFlow::update_column_inline_sizes(&mut self.column_inline_sizes,
- child_column_inline_sizes);
+ let child_column_inline_sizes = kid.column_intrinsic_inline_sizes();
+ let mut child_intrinsic_sizes = TableFlow::update_column_inline_sizes(
+ &mut self.column_intrinsic_inline_sizes,
+ child_column_inline_sizes);
// Add new columns if processing this row caused us to discover them.
let child_column_count = child_column_inline_sizes.len();
- let parent_column_count = self.column_inline_sizes.len();
+ let parent_column_count = self.column_intrinsic_inline_sizes.len();
debug!("table until the previous row has {} column(s) and this row has {} \
column(s)",
parent_column_count,
child_column_count);
- self.column_inline_sizes.reserve(child_column_count);
+ self.column_intrinsic_inline_sizes.reserve(child_column_count);
for i in range(parent_column_count, child_column_count) {
let inline_size_for_new_column = (*child_column_inline_sizes)[i];
child_intrinsic_sizes.minimum_inline_size =
@@ -215,7 +228,7 @@ impl Flow for TableFlow {
child_intrinsic_sizes.preferred_inline_size =
child_intrinsic_sizes.preferred_inline_size +
inline_size_for_new_column.preferred;
- self.column_inline_sizes.push(inline_size_for_new_column);
+ self.column_intrinsic_inline_sizes.push(inline_size_for_new_column);
}
computation.union_block(&child_intrinsic_sizes)
@@ -239,7 +252,7 @@ impl Flow for TableFlow {
let mut num_unspecified_inline_sizes = 0;
let mut total_column_inline_size = Au(0);
- for column_inline_size in self.column_inline_sizes.iter() {
+ for column_inline_size in self.column_intrinsic_inline_sizes.iter() {
let this_column_inline_size = column_inline_size.minimum_length;
if this_column_inline_size == Au(0) {
num_unspecified_inline_sizes += 1
@@ -263,28 +276,38 @@ impl Flow for TableFlow {
FixedLayout => {
// In fixed table layout, we distribute extra space among the unspecified columns
// if there are any, or among all the columns if all are specified.
+ self.column_computed_inline_sizes.clear();
if total_column_inline_size < content_inline_size &&
num_unspecified_inline_sizes == 0 {
- let ratio = content_inline_size.to_subpx() / total_column_inline_size.to_subpx();
- for column_inline_size in self.column_inline_sizes.iter_mut() {
- column_inline_size.minimum_length = column_inline_size.minimum_length.scale_by(ratio);
- column_inline_size.percentage = 0.0;
+ let ratio = content_inline_size.to_subpx() /
+ total_column_inline_size.to_subpx();
+ for column_inline_size in self.column_intrinsic_inline_sizes.iter() {
+ self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
+ size: column_inline_size.minimum_length.scale_by(ratio),
+ });
}
} else if num_unspecified_inline_sizes != 0 {
let extra_column_inline_size =
(content_inline_size - total_column_inline_size) /
num_unspecified_inline_sizes;
- for column_inline_size in self.column_inline_sizes.iter_mut() {
+ for column_inline_size in self.column_intrinsic_inline_sizes.iter() {
if column_inline_size.minimum_length == Au(0) &&
column_inline_size.percentage == 0.0 {
- column_inline_size.minimum_length = extra_column_inline_size /
- num_unspecified_inline_sizes
+ self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
+ size: extra_column_inline_size / num_unspecified_inline_sizes,
+ });
+ } else {
+ self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
+ size: column_inline_size.minimum_length,
+ });
}
- column_inline_size.percentage = 0.0;
}
}
}
- _ => {}
+ _ => {
+ // The table wrapper already computed the inline-sizes and propagated them down
+ // to us.
+ }
}
// As tables are always wrapped inside a table wrapper, they are never impacted by floats.
@@ -294,7 +317,7 @@ impl Flow for TableFlow {
self.block_flow.propagate_assigned_inline_size_to_children(
inline_start_content_edge,
content_inline_size,
- Some(self.column_inline_sizes.as_slice()));
+ Some(self.column_computed_inline_sizes.as_slice()));
}
fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
@@ -365,7 +388,7 @@ impl ISizeAndMarginsComputer for InternalTable {
}
}
-/// Information about the inline sizes of columns within a table.
+/// Information about the intrinsic inline sizes of columns within a table.
///
/// During table inline-size bubbling, we might need to store both a percentage constraint and a
/// specific width constraint. For instance, one cell might say that it wants to be 100 pixels wide
@@ -377,7 +400,7 @@ impl ISizeAndMarginsComputer for InternalTable {
/// potentially store both a specified width *and* a specified percentage, so that the inline-size
/// assignment phase of layout will know which one to pick.
#[deriving(Clone, Encodable, Show)]
-pub struct ColumnInlineSize {
+pub struct ColumnIntrinsicInlineSize {
/// The preferred intrinsic inline size.
pub preferred: Au,
/// The largest specified size of this column as a length.
@@ -388,7 +411,7 @@ pub struct ColumnInlineSize {
pub constrained: bool,
}
-impl ColumnInlineSize {
+impl ColumnIntrinsicInlineSize {
/// Returns the true minimum size of this column, given the containing block's inline size.
/// Beware that this is generally only correct for fixed table layout. (Compare CSS 2.1 §
/// 17.5.2.1 with the algorithm in INTRINSIC § 4.)
@@ -397,7 +420,7 @@ impl ColumnInlineSize {
}
/// Returns the higher of the two percentages specified in `self` and `other`.
- pub fn greatest_percentage(&self, other: &ColumnInlineSize) -> CSSFloat {
+ pub fn greatest_percentage(&self, other: &ColumnIntrinsicInlineSize) -> CSSFloat {
if self.percentage > other.percentage {
self.percentage
} else {
@@ -405,3 +428,13 @@ impl ColumnInlineSize {
}
}
}
+
+/// The actual inline size for each column.
+///
+/// TODO(pcwalton): There will probably be some `border-collapse`-related info in here too
+/// eventually.
+#[deriving(Encodable)]
+pub struct ColumnComputedInlineSize {
+ /// The computed size of this inline column.
+ pub size: Au,
+}
diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs
index 9fc6c17b52b..7dbfa3d678c 100644
--- a/components/layout/table_cell.rs
+++ b/components/layout/table_cell.rs
@@ -45,10 +45,8 @@ impl TableCellFlow {
/// Assign block-size for table-cell flow.
///
- /// TODO(#2015, pcwalton): This doesn't handle floats right.
- ///
/// inline(always) because this is only ever called by in-order or non-in-order top-level
- /// methods
+ /// methods.
#[inline(always)]
fn assign_block_size_table_cell_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse)
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index 4c12ef1ef87..5ecdac0b5b4 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -14,7 +14,7 @@ use flow::{TableRowFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use flow;
use fragment::{Fragment, FragmentBoundsIterator};
use layout_debug;
-use table::{ColumnInlineSize, InternalTable};
+use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable};
use model::{MaybeAuto, Specified, Auto};
use wrapper::ThreadSafeLayoutNode;
@@ -30,8 +30,11 @@ use sync::Arc;
pub struct TableRowFlow {
pub block_flow: BlockFlow,
- /// Information about the inline-sizes of each column.
- pub column_inline_sizes: Vec<ColumnInlineSize>,
+ /// Information about the intrinsic inline-sizes of each column.
+ pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
+
+ /// Information about the computed inline-sizes of each column.
+ pub column_computed_inline_sizes: Vec<ColumnComputedInlineSize>,
}
impl TableRowFlow {
@@ -40,7 +43,8 @@ impl TableRowFlow {
-> TableRowFlow {
TableRowFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
- column_inline_sizes: Vec::new()
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
}
}
@@ -49,7 +53,8 @@ impl TableRowFlow {
-> TableRowFlow {
TableRowFlow {
block_flow: BlockFlow::from_node(constructor, node),
- column_inline_sizes: Vec::new()
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
}
}
@@ -150,8 +155,12 @@ impl Flow for TableRowFlow {
&mut self.block_flow
}
- fn column_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnInlineSize> {
- &mut self.column_inline_sizes
+ fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
+ &mut self.column_intrinsic_inline_sizes
+ }
+
+ fn column_computed_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnComputedInlineSize> {
+ &mut self.column_computed_inline_sizes
}
/// Recursively (bottom-up) determines the context's preferred and minimum inline-sizes. When
@@ -180,7 +189,7 @@ impl Flow for TableRowFlow {
// Collect minimum and preferred inline-sizes of the cell for automatic table layout
// calculation.
let child_base = flow::mut_base(kid);
- let child_column_inline_size = ColumnInlineSize {
+ let child_column_inline_size = ColumnIntrinsicInlineSize {
minimum_length: match child_specified_inline_size {
LPA_Auto | LPA_Percentage(_) => {
child_base.intrinsic_inline_sizes.minimum_inline_size
@@ -199,7 +208,7 @@ impl Flow for TableRowFlow {
};
min_inline_size = min_inline_size + child_column_inline_size.minimum_length;
pref_inline_size = pref_inline_size + child_column_inline_size.preferred;
- self.column_inline_sizes.push(child_column_inline_size);
+ self.column_intrinsic_inline_sizes.push(child_column_inline_size);
}
self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size = min_inline_size;
self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size = max(min_inline_size,
@@ -208,7 +217,7 @@ 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) {
+ fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) {
let _scope = layout_debug_scope!("table_row::assign_inline_sizes {:x}",
self.block_flow.base.debug_id());
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row");
@@ -221,13 +230,13 @@ impl Flow for TableRowFlow {
let inline_size_computer = InternalTable;
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
- ctx,
+ layout_context,
containing_block_inline_size);
- self.block_flow
- .propagate_assigned_inline_size_to_children(inline_start_content_edge,
- containing_block_inline_size,
- Some(self.column_inline_sizes.as_slice()));
+ self.block_flow.propagate_assigned_inline_size_to_children(
+ inline_start_content_edge,
+ containing_block_inline_size,
+ Some(self.column_computed_inline_sizes.as_slice()));
}
fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs
index 865c0a3c081..0b9d37d1182 100644
--- a/components/layout/table_rowgroup.rs
+++ b/components/layout/table_rowgroup.rs
@@ -6,16 +6,14 @@
#![deny(unsafe_blocks)]
-use block::BlockFlow;
-use block::ISizeAndMarginsComputer;
+use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayNotCollapse};
use construct::FlowConstructor;
use context::LayoutContext;
use flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils};
-use flow;
use fragment::{Fragment, FragmentBoundsIterator};
use layout_debug;
use model::IntrinsicISizesContribution;
-use table::{ColumnInlineSize, InternalTable, TableFlow};
+use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize, InternalTable, TableFlow};
use wrapper::ThreadSafeLayoutNode;
use servo_util::geometry::Au;
@@ -28,26 +26,29 @@ use sync::Arc;
pub struct TableRowGroupFlow {
pub block_flow: BlockFlow,
- /// Information about the inline-sizes of each column.
- pub column_inline_sizes: Vec<ColumnInlineSize>,
+ /// Information about the intrinsic inline-sizes of each column.
+ pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
+
+ /// Information about the actual inline sizes of each column.
+ pub column_computed_inline_sizes: Vec<ColumnComputedInlineSize>,
}
impl TableRowGroupFlow {
- pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
- fragment: Fragment)
+ pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableRowGroupFlow {
TableRowGroupFlow {
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
- column_inline_sizes: Vec::new(),
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
}
}
- pub fn from_node(constructor: &mut FlowConstructor,
- node: &ThreadSafeLayoutNode)
+ pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode)
-> TableRowGroupFlow {
TableRowGroupFlow {
block_flow: BlockFlow::from_node(constructor, node),
- column_inline_sizes: Vec::new(),
+ column_intrinsic_inline_sizes: Vec::new(),
+ column_computed_inline_sizes: Vec::new(),
}
}
@@ -55,41 +56,13 @@ impl TableRowGroupFlow {
&self.block_flow.fragment
}
- fn initialize_offsets(&mut self) -> (Au, Au, Au) {
- // TODO: If border-collapse: collapse, block-start_offset, block-end_offset, and
- // inline-start_offset should be updated. Currently, they are set as Au(0).
- (Au(0), Au(0), Au(0))
- }
-
/// Assign block-size for table-rowgroup flow.
///
- /// FIXME(pcwalton): This doesn't handle floats right.
- ///
/// inline(always) because this is only ever called by in-order or non-in-order top-level
- /// methods
+ /// methods.
#[inline(always)]
fn assign_block_size_table_rowgroup_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
- let (block_start_offset, _, _) = self.initialize_offsets();
-
- let mut cur_y = block_start_offset;
-
- for kid in self.block_flow.base.child_iter() {
- kid.place_float_if_applicable(layout_context);
- if !flow::base(kid).flags.is_float() {
- kid.assign_block_size_for_inorder_child_if_necessary(layout_context);
- }
-
- let child_node = flow::mut_base(kid);
- child_node.position.start.b = cur_y;
- cur_y = cur_y + child_node.position.size.block;
- }
-
- let block_size = cur_y - block_start_offset;
-
- let mut position = self.block_flow.fragment.border_box;
- position.size.block = block_size;
- self.block_flow.fragment.border_box = position;
- self.block_flow.base.position.size.block = block_size;
+ self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse)
}
}
@@ -110,10 +83,15 @@ impl Flow for TableRowGroupFlow {
&mut self.block_flow
}
- fn column_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnInlineSize> {
- &mut self.column_inline_sizes
+ fn column_intrinsic_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnIntrinsicInlineSize> {
+ &mut self.column_intrinsic_inline_sizes
}
+ fn column_computed_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnComputedInlineSize> {
+ &mut self.column_computed_inline_sizes
+ }
+
+
/// Recursively (bottom-up) determines the context's preferred and minimum inline-sizes. When
/// called on this context, all child contexts have had their min/pref inline-sizes set. This
/// function must decide min/pref inline-sizes based on child context inline-sizes and
@@ -132,20 +110,19 @@ impl Flow for TableRowGroupFlow {
assert!(kid.is_table_row());
// Calculate minimum and preferred inline sizes for automatic table layout.
- if self.column_inline_sizes.is_empty() {
+ if self.column_intrinsic_inline_sizes.is_empty() {
// We're the first row.
- debug_assert!(self.column_inline_sizes.is_empty());
- self.column_inline_sizes = kid.column_inline_sizes().clone();
+ self.column_intrinsic_inline_sizes = kid.column_intrinsic_inline_sizes().clone();
} else {
let mut child_intrinsic_sizes =
- TableFlow::update_column_inline_sizes(&mut self.column_inline_sizes,
- kid.column_inline_sizes());
+ TableFlow::update_column_inline_sizes(&mut self.column_intrinsic_inline_sizes,
+ kid.column_intrinsic_inline_sizes());
// update the number of column inline-sizes from table-rows.
- let column_count = self.column_inline_sizes.len();
- let child_column_count = kid.column_inline_sizes().len();
+ let column_count = self.column_intrinsic_inline_sizes.len();
+ let child_column_count = kid.column_intrinsic_inline_sizes().len();
for i in range(column_count, child_column_count) {
- let this_column_inline_size = (*kid.column_inline_sizes())[i];
+ let this_column_inline_size = (*kid.column_intrinsic_inline_sizes())[i];
// FIXME(pcwalton): Ignoring the percentage here seems dubious.
child_intrinsic_sizes.minimum_inline_size =
@@ -154,7 +131,7 @@ impl Flow for TableRowGroupFlow {
child_intrinsic_sizes.preferred_inline_size =
child_intrinsic_sizes.preferred_inline_size +
this_column_inline_size.preferred;
- self.column_inline_sizes.push(this_column_inline_size);
+ self.column_intrinsic_inline_sizes.push(this_column_inline_size);
}
computation.union_block(&child_intrinsic_sizes)
@@ -186,7 +163,7 @@ impl Flow for TableRowGroupFlow {
self.block_flow.propagate_assigned_inline_size_to_children(
inline_start_content_edge,
content_inline_size,
- Some(self.column_inline_sizes.as_slice()));
+ Some(self.column_computed_inline_sizes.as_slice()));
}
fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index 7ec0ed874a4..5003dca66c1 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -21,7 +21,7 @@ use floats::FloatKind;
use flow::{TableWrapperFlowClass, FlowClass, Flow, ImmutableFlowUtils};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use fragment::{Fragment, FragmentBoundsIterator};
-use table::ColumnInlineSize;
+use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
use wrapper::ThreadSafeLayoutNode;
use servo_util::geometry::Au;
@@ -43,13 +43,7 @@ pub struct TableWrapperFlow {
pub block_flow: BlockFlow,
/// Intrinsic column inline sizes according to INTRINSIC § 4.1
- pub intrinsic_column_inline_sizes: Vec<ColumnInlineSize>,
-
- /// Computed inline-size for each column.
- ///
- /// FIXME: This should be a separate type that only contains computed inline
- /// sizes.
- pub column_inline_sizes: Vec<ColumnInlineSize>,
+ pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>,
/// Table-layout property
pub table_layout: TableLayout,
@@ -68,8 +62,7 @@ impl TableWrapperFlow {
};
TableWrapperFlow {
block_flow: block_flow,
- intrinsic_column_inline_sizes: vec!(),
- column_inline_sizes: vec!(),
+ column_intrinsic_inline_sizes: vec!(),
table_layout: table_layout
}
}
@@ -86,8 +79,7 @@ impl TableWrapperFlow {
};
TableWrapperFlow {
block_flow: block_flow,
- intrinsic_column_inline_sizes: vec!(),
- column_inline_sizes: vec!(),
+ column_intrinsic_inline_sizes: vec!(),
table_layout: table_layout
}
}
@@ -105,14 +97,15 @@ impl TableWrapperFlow {
};
TableWrapperFlow {
block_flow: block_flow,
- intrinsic_column_inline_sizes: vec!(),
- column_inline_sizes: vec!(),
+ column_intrinsic_inline_sizes: vec!(),
table_layout: table_layout
}
}
/// Calculates table column sizes for automatic layout per INTRINSIC § 4.3.
- fn calculate_table_column_sizes_for_automatic_layout(&mut self) {
+ fn calculate_table_column_sizes_for_automatic_layout(
+ &mut self,
+ intermediate_column_inline_sizes: &mut [IntermediateColumnInlineSize]) {
// Find the padding and border of our first child, which is the table itself.
//
// This is a little weird because we're computing border/padding/margins for our child,
@@ -141,9 +134,9 @@ impl TableWrapperFlow {
// Compute all the guesses for the column sizes, and sum them.
let mut total_guess = AutoLayoutCandidateGuess::new();
let guesses: Vec<AutoLayoutCandidateGuess> =
- self.column_inline_sizes.iter().map(|column_inline_size| {
- let guess = AutoLayoutCandidateGuess::from_column_inline_size(
- column_inline_size,
+ self.column_intrinsic_inline_sizes.iter().map(|column_intrinsic_inline_size| {
+ let guess = AutoLayoutCandidateGuess::from_column_intrinsic_inline_size(
+ column_intrinsic_inline_size,
available_inline_size);
total_guess = total_guess + guess;
guess
@@ -153,12 +146,11 @@ impl TableWrapperFlow {
let selection = SelectedAutoLayoutCandidateGuess::select(&total_guess,
available_inline_size);
let mut total_used_inline_size = Au(0);
- for (column_inline_size, guess) in self.column_inline_sizes
- .iter_mut()
- .zip(guesses.iter()) {
- column_inline_size.minimum_length = guess.calculate(selection);
- column_inline_size.percentage = 0.0;
- total_used_inline_size = total_used_inline_size + column_inline_size.minimum_length
+ for (intermediate_column_inline_size, guess) in
+ intermediate_column_inline_sizes.iter_mut().zip(guesses.iter()) {
+ intermediate_column_inline_size.size = guess.calculate(selection);
+ intermediate_column_inline_size.percentage = 0.0;
+ total_used_inline_size = total_used_inline_size + intermediate_column_inline_size.size
}
// Distribute excess inline-size if necessary per INTRINSIC § 4.4.
@@ -168,13 +160,17 @@ impl TableWrapperFlow {
if excess_inline_size > Au(0) &&
selection == UsePreferredGuessAndDistributeExcessInlineSize {
let mut info = ExcessInlineSizeDistributionInfo::new();
- for column_inline_size in self.column_inline_sizes.iter() {
- info.update(column_inline_size)
+ for column_intrinsic_inline_size in self.column_intrinsic_inline_sizes.iter() {
+ info.update(column_intrinsic_inline_size)
}
let mut total_distributed_excess_size = Au(0);
- for column_inline_size in self.column_inline_sizes.iter_mut() {
- info.distribute_excess_inline_size_to_column(column_inline_size,
+ for (intermediate_column_inline_size, column_intrinsic_inline_size) in
+ intermediate_column_inline_sizes.iter_mut()
+ .zip(self.column_intrinsic_inline_sizes
+ .iter()) {
+ info.distribute_excess_inline_size_to_column(intermediate_column_inline_size,
+ column_intrinsic_inline_size,
excess_inline_size,
&mut total_distributed_excess_size)
}
@@ -234,11 +230,11 @@ impl Flow for TableWrapperFlow {
}
fn bubble_inline_sizes(&mut self) {
- // Get the column inline-sizes info from the table flow.
+ // Get the intrinsic column inline-sizes info from the table flow.
for kid in self.block_flow.base.child_iter() {
debug_assert!(kid.is_table_caption() || kid.is_table());
if kid.is_table() {
- self.intrinsic_column_inline_sizes = kid.column_inline_sizes().clone()
+ self.column_intrinsic_inline_sizes = kid.column_intrinsic_inline_sizes().clone()
}
}
@@ -253,7 +249,14 @@ impl Flow for TableWrapperFlow {
"table_wrapper"
});
- self.column_inline_sizes = self.intrinsic_column_inline_sizes.clone();
+ let mut intermediate_column_inline_sizes = self.column_intrinsic_inline_sizes
+ .iter()
+ .map(|column_intrinsic_inline_size| {
+ IntermediateColumnInlineSize {
+ size: column_intrinsic_inline_size.minimum_length,
+ percentage: column_intrinsic_inline_size.percentage,
+ }
+ }).collect::<Vec<_>>();
// Table wrappers are essentially block formatting contexts and are therefore never
// impacted by floats.
@@ -273,7 +276,8 @@ impl Flow for TableWrapperFlow {
match self.table_layout {
FixedLayout => {}
AutoLayout => {
- self.calculate_table_column_sizes_for_automatic_layout()
+ self.calculate_table_column_sizes_for_automatic_layout(
+ intermediate_column_inline_sizes.as_mut_slice())
}
}
@@ -283,12 +287,29 @@ impl Flow for TableWrapperFlow {
// In case of fixed layout, column inline-sizes are calculated in table flow.
let assigned_column_inline_sizes = match self.table_layout {
FixedLayout => None,
- AutoLayout => Some(self.column_inline_sizes.as_slice())
+ AutoLayout => {
+ Some(intermediate_column_inline_sizes.iter().map(|sizes| {
+ ColumnComputedInlineSize {
+ size: sizes.size,
+ }
+ }).collect::<Vec<_>>())
+ }
};
- self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge,
- content_inline_size,
- assigned_column_inline_sizes);
+ match assigned_column_inline_sizes {
+ None => {
+ self.block_flow.propagate_assigned_inline_size_to_children(
+ inline_start_content_edge,
+ content_inline_size,
+ None)
+ }
+ Some(ref assigned_column_inline_sizes) => {
+ self.block_flow.propagate_assigned_inline_size_to_children(
+ inline_start_content_edge,
+ content_inline_size,
+ Some(assigned_column_inline_sizes.as_slice()));
+ }
+ }
}
@@ -395,27 +416,28 @@ impl AutoLayoutCandidateGuess {
}
/// Fills in the inline-size guesses for this column per INTRINSIC § 4.3.
- fn from_column_inline_size(column_inline_size: &ColumnInlineSize, assignable_inline_size: Au)
- -> AutoLayoutCandidateGuess {
+ fn from_column_intrinsic_inline_size(column_intrinsic_inline_size: &ColumnIntrinsicInlineSize,
+ assignable_inline_size: Au)
+ -> AutoLayoutCandidateGuess {
let minimum_percentage_guess =
- max(assignable_inline_size.scale_by(column_inline_size.percentage),
- column_inline_size.minimum_length);
+ max(assignable_inline_size.scale_by(column_intrinsic_inline_size.percentage),
+ column_intrinsic_inline_size.minimum_length);
AutoLayoutCandidateGuess {
- minimum_guess: column_inline_size.minimum_length,
+ minimum_guess: column_intrinsic_inline_size.minimum_length,
minimum_percentage_guess: minimum_percentage_guess,
// FIXME(pcwalton): We need the notion of *constrainedness* per INTRINSIC § 4 to
// implement this one correctly.
- minimum_specified_guess: if column_inline_size.percentage > 0.0 {
+ minimum_specified_guess: if column_intrinsic_inline_size.percentage > 0.0 {
minimum_percentage_guess
- } else if column_inline_size.constrained {
- column_inline_size.preferred
+ } else if column_intrinsic_inline_size.constrained {
+ column_intrinsic_inline_size.preferred
} else {
- column_inline_size.minimum_length
+ column_intrinsic_inline_size.minimum_length
},
- preferred_guess: if column_inline_size.percentage > 0.0 {
+ preferred_guess: if column_intrinsic_inline_size.percentage > 0.0 {
minimum_percentage_guess
} else {
- column_inline_size.preferred
+ column_intrinsic_inline_size.preferred
},
}
}
@@ -526,19 +548,21 @@ impl ExcessInlineSizeDistributionInfo {
}
}
- fn update(&mut self, column_inline_size: &ColumnInlineSize) {
- if !column_inline_size.constrained && column_inline_size.percentage == 0.0 {
+ fn update(&mut self, column_intrinsic_inline_size: &ColumnIntrinsicInlineSize) {
+ if !column_intrinsic_inline_size.constrained &&
+ column_intrinsic_inline_size.percentage == 0.0 {
self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage =
self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage +
- column_inline_size.preferred;
+ column_intrinsic_inline_size.preferred;
self.count_of_nonconstrained_columns_with_no_percentage += 1
}
- if column_inline_size.constrained && column_inline_size.percentage == 0.0 {
+ if column_intrinsic_inline_size.constrained &&
+ column_intrinsic_inline_size.percentage == 0.0 {
self.preferred_inline_size_of_constrained_columns_with_no_percentage =
self.preferred_inline_size_of_constrained_columns_with_no_percentage +
- column_inline_size.preferred
+ column_intrinsic_inline_size.preferred
}
- self.total_percentage += column_inline_size.percentage;
+ self.total_percentage += column_intrinsic_inline_size.percentage;
self.column_count += 1
}
@@ -547,23 +571,25 @@ impl ExcessInlineSizeDistributionInfo {
///
/// `#[inline]` so the compiler will hoist out the branch, which is loop-invariant.
#[inline]
- fn distribute_excess_inline_size_to_column(&self,
- column_inline_size: &mut ColumnInlineSize,
- excess_inline_size: Au,
- total_distributed_excess_size: &mut Au) {
+ fn distribute_excess_inline_size_to_column(
+ &self,
+ intermediate_column_inline_size: &mut IntermediateColumnInlineSize,
+ column_intrinsic_inline_size: &ColumnIntrinsicInlineSize,
+ excess_inline_size: Au,
+ total_distributed_excess_size: &mut Au) {
let proportion =
if self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage > Au(0) {
- column_inline_size.preferred.to_subpx() /
+ column_intrinsic_inline_size.preferred.to_subpx() /
self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage
.to_subpx()
} else if self.count_of_nonconstrained_columns_with_no_percentage > 0 {
1.0 / (self.count_of_nonconstrained_columns_with_no_percentage as CSSFloat)
} else if self.preferred_inline_size_of_constrained_columns_with_no_percentage >
Au(0) {
- column_inline_size.preferred.to_subpx() /
+ column_intrinsic_inline_size.preferred.to_subpx() /
self.preferred_inline_size_of_constrained_columns_with_no_percentage.to_subpx()
} else if self.total_percentage > 0.0 {
- column_inline_size.percentage / self.total_percentage
+ column_intrinsic_inline_size.percentage / self.total_percentage
} else {
1.0 / (self.column_count as CSSFloat)
};
@@ -573,7 +599,14 @@ impl ExcessInlineSizeDistributionInfo {
let amount_to_distribute = min(excess_inline_size.scale_by(proportion),
excess_inline_size - *total_distributed_excess_size);
*total_distributed_excess_size = *total_distributed_excess_size + amount_to_distribute;
- column_inline_size.minimum_length = column_inline_size.minimum_length +
+ intermediate_column_inline_size.size = intermediate_column_inline_size.size +
amount_to_distribute
}
}
+
+/// An intermediate column size assignment.
+struct IntermediateColumnInlineSize {
+ size: Au,
+ percentage: f64,
+}
+