aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/block.rs101
-rw-r--r--components/layout/table.rs25
-rw-r--r--components/layout/table_cell.rs8
-rw-r--r--components/layout/table_row.rs8
-rw-r--r--components/layout/table_rowgroup.rs7
-rw-r--r--components/layout/table_wrapper.rs203
-rw-r--r--tests/ref/basic.list1
-rw-r--r--tests/ref/table_margin_auto_a.html20
-rw-r--r--tests/ref/table_margin_auto_ref.html21
9 files changed, 279 insertions, 115 deletions
diff --git a/components/layout/block.rs b/components/layout/block.rs
index 3879c627d88..10bb2a055aa 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -622,51 +622,44 @@ impl BlockFlow {
/// Compute the actual inline size and position for this block.
pub fn compute_used_inline_size(&mut self,
layout_context: &LayoutContext,
- containing_block_inline_size: Au,
- border_collapse: border_collapse::T) {
+ containing_block_inline_size: Au) {
let block_type = self.block_type();
match block_type {
BlockType::AbsoluteReplaced => {
let inline_size_computer = AbsoluteReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
BlockType::AbsoluteNonReplaced => {
let inline_size_computer = AbsoluteNonReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
BlockType::FloatReplaced => {
let inline_size_computer = FloatReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
BlockType::FloatNonReplaced => {
let inline_size_computer = FloatNonReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
BlockType::Replaced => {
let inline_size_computer = BlockReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
BlockType::NonReplaced => {
let inline_size_computer = BlockNonReplaced;
inline_size_computer.compute_used_inline_size(self,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
}
}
}
@@ -1201,13 +1194,9 @@ impl BlockFlow {
/// Compute inline size based using the `block_container_inline_size` set by the parent flow.
///
/// This is run in the `AssignISizes` traversal.
- fn propagate_and_compute_used_inline_size(&mut self,
- layout_context: &LayoutContext,
- border_collapse: border_collapse::T) {
+ fn propagate_and_compute_used_inline_size(&mut self, layout_context: &LayoutContext) {
let containing_block_inline_size = self.base.block_container_inline_size;
- self.compute_used_inline_size(layout_context,
- containing_block_inline_size,
- border_collapse);
+ self.compute_used_inline_size(layout_context, containing_block_inline_size);
if self.base.flags.is_float() {
self.float.as_mut().unwrap().containing_inline_size = containing_block_inline_size
}
@@ -1589,8 +1578,7 @@ impl Flow for BlockFlow {
// Our inline-size was set to the inline-size of the containing block by the flow's parent.
// Now compute the real value.
- let border_collapse = self.fragment.style.get_inheritedtable().border_collapse;
- self.propagate_and_compute_used_inline_size(layout_context, border_collapse);
+ self.propagate_and_compute_used_inline_size(layout_context);
// Formatting contexts are never impacted by floats.
match self.formatting_context_type() {
@@ -2041,6 +2029,12 @@ impl ISizeConstraintSolution {
//
// CSS Section 10.3
pub trait ISizeAndMarginsComputer {
+ /// Instructs the fragment to compute its border and padding.
+ fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) {
+ block.fragment.compute_border_and_padding(containing_block_inline_size,
+ border_collapse::T::separate);
+ }
+
/// Compute the inputs for the ISize constraint equation.
///
/// This is called only once to compute the initial inputs. For calculations involving
@@ -2048,20 +2042,18 @@ pub trait ISizeAndMarginsComputer {
fn compute_inline_size_constraint_inputs(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- layout_context: &LayoutContext,
- border_collapse: border_collapse::T)
+ layout_context: &LayoutContext)
-> ISizeConstraintInput {
let containing_block_inline_size =
self.containing_block_inline_size(block, parent_flow_inline_size, layout_context);
block.fragment.compute_block_direction_margins(containing_block_inline_size);
block.fragment.compute_inline_direction_margins(containing_block_inline_size);
- block.fragment.compute_border_and_padding(containing_block_inline_size, border_collapse);
+ self.compute_border_and_padding(block, containing_block_inline_size);
let mut computed_inline_size = self.initial_computed_inline_size(block,
parent_flow_inline_size,
layout_context);
-
let style = block.fragment.style();
match (computed_inline_size, style.get_box().box_sizing) {
(MaybeAuto::Specified(size), box_sizing::T::border_box) => {
@@ -2161,12 +2153,12 @@ pub trait ISizeAndMarginsComputer {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- ctx: &LayoutContext)
+ layout_context: &LayoutContext)
-> MaybeAuto {
MaybeAuto::from_style(block.fragment().style().content_inline_size(),
self.containing_block_inline_size(block,
parent_flow_inline_size,
- ctx))
+ layout_context))
}
fn containing_block_inline_size(&self,
@@ -2183,12 +2175,10 @@ pub trait ISizeAndMarginsComputer {
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
layout_context: &LayoutContext,
- parent_flow_inline_size: Au,
- border_collapse: border_collapse::T) {
+ parent_flow_inline_size: Au) {
let mut input = self.compute_inline_size_constraint_inputs(block,
parent_flow_inline_size,
- layout_context,
- border_collapse);
+ layout_context);
let containing_block_inline_size =
self.containing_block_inline_size(block, parent_flow_inline_size, layout_context);
@@ -2268,32 +2258,49 @@ pub trait ISizeAndMarginsComputer {
match (inline_start_margin, computed_inline_size, inline_end_margin) {
// If all have a computed value other than 'auto', the system is
// over-constrained so we discard the end margin.
- (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(inline_size), MaybeAuto::Specified(margin_end)) => {
+ (MaybeAuto::Specified(margin_start),
+ MaybeAuto::Specified(inline_size),
+ MaybeAuto::Specified(margin_end)) => {
if parent_has_same_direction {
(margin_start, inline_size, available_inline_size -
(margin_start + inline_size))
} else {
- (available_inline_size - (margin_end + inline_size), inline_size, margin_end)
+ (available_inline_size - (margin_end + inline_size),
+ inline_size,
+ margin_end)
}
}
// If exactly one value is 'auto', solve for it
- (MaybeAuto::Auto, MaybeAuto::Specified(inline_size), MaybeAuto::Specified(margin_end)) =>
+ (MaybeAuto::Auto,
+ MaybeAuto::Specified(inline_size),
+ MaybeAuto::Specified(margin_end)) =>
(available_inline_size - (inline_size + margin_end), inline_size, margin_end),
- (MaybeAuto::Specified(margin_start), MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) =>
- (margin_start, available_inline_size - (margin_start + margin_end),
- margin_end),
- (MaybeAuto::Specified(margin_start), MaybeAuto::Specified(inline_size), MaybeAuto::Auto) =>
- (margin_start, inline_size, available_inline_size -
- (margin_start + inline_size)),
+ (MaybeAuto::Specified(margin_start),
+ MaybeAuto::Auto,
+ MaybeAuto::Specified(margin_end)) => {
+ (margin_start,
+ available_inline_size - (margin_start + margin_end),
+ margin_end)
+ }
+ (MaybeAuto::Specified(margin_start),
+ MaybeAuto::Specified(inline_size),
+ MaybeAuto::Auto) => {
+ (margin_start,
+ inline_size,
+ available_inline_size - (margin_start + inline_size))
+ }
// If inline-size is set to 'auto', any other 'auto' value becomes '0',
// and inline-size is solved for
- (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) =>
- (Au::new(0), available_inline_size - margin_end, margin_end),
- (MaybeAuto::Specified(margin_start), MaybeAuto::Auto, MaybeAuto::Auto) =>
- (margin_start, available_inline_size - margin_start, Au::new(0)),
- (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) =>
- (Au::new(0), available_inline_size, Au::new(0)),
+ (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
+ (Au(0), available_inline_size - margin_end, margin_end)
+ }
+ (MaybeAuto::Specified(margin_start), MaybeAuto::Auto, MaybeAuto::Auto) => {
+ (margin_start, available_inline_size - margin_start, Au(0))
+ }
+ (MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
+ (Au(0), available_inline_size, Au(0))
+ }
// If inline-start and inline-end margins are auto, they become equal
(MaybeAuto::Auto, MaybeAuto::Specified(inline_size), MaybeAuto::Auto) => {
diff --git a/components/layout/table.rs b/components/layout/table.rs
index 1733706a95c..25d17d04b8f 100644
--- a/components/layout/table.rs
+++ b/components/layout/table.rs
@@ -424,12 +424,12 @@ impl Flow for TableFlow {
}
}
- let inline_size_computer = InternalTable;
- let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
+ let inline_size_computer = InternalTable {
+ border_collapse: self.block_flow.fragment.style.get_inheritedtable().border_collapse,
+ };
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
let inline_start_content_edge = self.block_flow.fragment.border_padding.inline_start;
let inline_end_content_edge = self.block_flow.fragment.border_padding.inline_end;
@@ -581,21 +581,26 @@ impl fmt::Debug for TableFlow {
/// Table, TableRowGroup, TableRow, TableCell types.
/// Their inline-sizes are calculated in the same way and do not have margins.
-pub struct InternalTable;
+pub struct InternalTable {
+ pub border_collapse: border_collapse::T,
+}
impl ISizeAndMarginsComputer for InternalTable {
+ fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) {
+ block.fragment.compute_border_and_padding(containing_block_inline_size,
+ self.border_collapse)
+ }
+
/// Compute the used value of inline-size, taking care of min-inline-size and max-inline-size.
///
/// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
layout_context: &LayoutContext,
- parent_flow_inline_size: Au,
- border_collapse: border_collapse::T) {
+ parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs(block,
parent_flow_inline_size,
- layout_context,
- border_collapse);
+ layout_context);
let solution = self.solve_inline_size_constraints(block, &input);
self.set_inline_size_constraint_solutions(block, solution);
@@ -603,7 +608,7 @@ impl ISizeAndMarginsComputer for InternalTable {
/// Solve the inline-size and margins constraints for this block flow.
fn solve_inline_size_constraints(&self, _: &mut BlockFlow, input: &ISizeConstraintInput)
- -> ISizeConstraintSolution {
+ -> ISizeConstraintSolution {
ISizeConstraintSolution::new(input.available_inline_size, Au(0), Au(0))
}
}
diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs
index 00823aa89f8..6744fbc2106 100644
--- a/components/layout/table_cell.rs
+++ b/components/layout/table_cell.rs
@@ -135,12 +135,12 @@ impl Flow for TableCellFlow {
// The position was set to the column inline-size by the parent flow, table row flow.
let containing_block_inline_size = self.block_flow.base.block_container_inline_size;
- let inline_size_computer = InternalTable;
- let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
+ let inline_size_computer = InternalTable {
+ border_collapse: self.block_flow.fragment.style.get_inheritedtable().border_collapse,
+ };
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
let inline_start_content_edge =
self.block_flow.fragment.border_box.start.i +
diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs
index 9170fe8fb9e..ef3f70f5d6f 100644
--- a/components/layout/table_row.rs
+++ b/components/layout/table_row.rs
@@ -311,12 +311,12 @@ impl Flow for TableRowFlow {
let inline_start_content_edge = Au(0);
let inline_end_content_edge = Au(0);
- let inline_size_computer = InternalTable;
- let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
+ let inline_size_computer = InternalTable {
+ border_collapse: self.block_flow.fragment.style.get_inheritedtable().border_collapse,
+ };
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
// Spread out the completed inline sizes among columns with spans > 1.
let mut computed_inline_size_for_cells = Vec::new();
diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs
index 03e138200ae..e442f2b4c7b 100644
--- a/components/layout/table_rowgroup.rs
+++ b/components/layout/table_rowgroup.rs
@@ -151,12 +151,13 @@ impl Flow for TableRowGroupFlow {
let (inline_start_content_edge, inline_end_content_edge) = (Au(0), Au(0));
let content_inline_size = containing_block_inline_size;
- let inline_size_computer = InternalTable;
let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
+ let inline_size_computer = InternalTable {
+ border_collapse: border_collapse,
+ };
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
layout_context,
- containing_block_inline_size,
- border_collapse);
+ containing_block_inline_size);
let column_computed_inline_sizes = &self.column_computed_inline_sizes;
let border_spacing = self.spacing;
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs
index 8e85604bb2c..5e321382e97 100644
--- a/components/layout/table_wrapper.rs
+++ b/components/layout/table_wrapper.rs
@@ -13,13 +13,14 @@
#![deny(unsafe_code)]
-use block::{BlockFlow, BlockNonReplaced, FloatNonReplaced, ISizeAndMarginsComputer};
-use block::{MarginsMayCollapseFlag};
+use block::{BlockFlow, FloatNonReplaced, ISizeAndMarginsComputer, ISizeConstraintInput};
+use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
use context::LayoutContext;
use floats::FloatKind;
use flow::{FlowClass, Flow, ImmutableFlowUtils};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use fragment::{Fragment, FragmentBorderBoxIterator};
+use model::MaybeAuto;
use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize};
use table_row;
use wrapper::ThreadSafeLayoutNode;
@@ -31,7 +32,7 @@ use std::cmp::{max, min};
use std::fmt;
use std::ops::Add;
use std::sync::Arc;
-use style::computed_values::table_layout;
+use style::computed_values::{border_collapse, table_layout};
use style::properties::ComputedValues;
use style::values::CSSFloat;
use style::values::computed::LengthOrPercentageOrAuto;
@@ -55,8 +56,7 @@ pub struct TableWrapperFlow {
}
impl TableWrapperFlow {
- pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
- fragment: Fragment)
+ pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment)
-> TableWrapperFlow {
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment);
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
@@ -90,6 +90,21 @@ impl TableWrapperFlow {
}
}
+ fn border_padding_and_spacing(&mut self) -> (Au, Au) {
+ let (mut table_border_padding, mut spacing) = (Au(0), Au(0));
+ for kid in self.block_flow.base.child_iter() {
+ if kid.is_table() {
+ let kid_table = kid.as_table();
+ let spacing_per_cell = kid_table.spacing().horizontal;
+ spacing = spacing_per_cell * (self.column_intrinsic_inline_sizes.len() as i32 + 1);
+ table_border_padding =
+ kid_table.block_flow.fragment.border_padding.inline_start_end();
+ break
+ }
+ }
+ (table_border_padding, spacing)
+ }
+
/// Calculates table column sizes for automatic layout per INTRINSIC § 4.3.
fn calculate_table_column_sizes_for_automatic_layout(
&mut self,
@@ -100,20 +115,13 @@ impl TableWrapperFlow {
// when normally the child computes it itself. But it has to be this way because the
// padding will affect where we place the child. This is an odd artifact of the way that
// tables are separated into table flows and table wrapper flows.
- //
- // FIXME(pcwalton): Handle `border-collapse` correctly.
- let mut available_inline_size = self.block_flow.fragment.border_box.size.inline;
- let (mut table_border_padding, mut spacing) = (Au(0), Au(0));
+ let available_inline_size = self.block_flow.fragment.border_box.size.inline;
for kid in self.block_flow.base.child_iter() {
if !kid.is_table() {
continue
}
let kid_table = kid.as_table();
- let spacing_per_cell = kid_table.spacing().horizontal;
- spacing = spacing_per_cell * (self.column_intrinsic_inline_sizes.len() as i32 + 1);
- available_inline_size = self.block_flow.fragment.border_box.size.inline;
-
let kid_block_flow = &mut kid_table.block_flow;
kid_block_flow.fragment
.compute_border_and_padding(available_inline_size,
@@ -124,10 +132,11 @@ impl TableWrapperFlow {
.border_collapse);
kid_block_flow.fragment.compute_block_direction_margins(available_inline_size);
kid_block_flow.fragment.compute_inline_direction_margins(available_inline_size);
- table_border_padding = kid_block_flow.fragment.border_padding.inline_start_end();
break
}
+ let (table_border_padding, spacing) = self.border_padding_and_spacing();
+
// FIXME(pcwalton, spec): INTRINSIC § 8 does not properly define how to compute this, but
// says "the basic idea is the same as the shrink-to-fit width that CSS2.1 defines". So we
// just use the shrink-to-fit inline size.
@@ -201,37 +210,55 @@ impl TableWrapperFlow {
table_border_padding + spacing + self.block_flow.fragment.margin.inline_start_end();
}
- fn compute_used_inline_size(&mut self,
- layout_context: &LayoutContext,
- parent_flow_inline_size: Au) {
- // Delegate to the appropriate inline size computer to find the constraint inputs.
+ fn compute_used_inline_size(
+ &mut self,
+ layout_context: &LayoutContext,
+ parent_flow_inline_size: Au,
+ intermediate_column_inline_sizes: &[IntermediateColumnInlineSize]) {
+ let (border_padding, spacing) = self.border_padding_and_spacing();
+ let minimum_width_of_all_columns =
+ intermediate_column_inline_sizes.iter()
+ .fold(border_padding + spacing,
+ |accumulator, intermediate_column_inline_sizes| {
+ accumulator + intermediate_column_inline_sizes.size
+ });
+
+ // Delegate to the appropriate inline size computer to find the constraint inputs and write
+ // the constraint solutions in.
let border_collapse = self.block_flow.fragment.style.get_inheritedtable().border_collapse;
- let input = if self.block_flow.base.flags.is_float() {
- FloatNonReplaced.compute_inline_size_constraint_inputs(&mut self.block_flow,
- parent_flow_inline_size,
- layout_context,
- border_collapse)
- } else {
- BlockNonReplaced.compute_inline_size_constraint_inputs(&mut self.block_flow,
- parent_flow_inline_size,
- layout_context,
- border_collapse)
- };
-
- // Delegate to the appropriate inline size computer to write the constraint solutions in.
if self.block_flow.base.flags.is_float() {
- let solution = FloatNonReplaced.solve_inline_size_constraints(&mut self.block_flow,
- &input);
- FloatNonReplaced.set_inline_size_constraint_solutions(&mut self.block_flow, solution);
- FloatNonReplaced.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
+ let inline_size_computer = FloatedTable {
+ minimum_width_of_all_columns: minimum_width_of_all_columns,
+ border_collapse: border_collapse,
+ };
+ let input =
+ inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow,
+ parent_flow_inline_size,
+ layout_context);
+
+ let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow,
+ &input);
+ inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow,
solution);
- } else {
- let solution = BlockNonReplaced.solve_inline_size_constraints(&mut self.block_flow,
+ inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
+ solution);
+ return
+ }
+
+ let inline_size_computer = Table {
+ minimum_width_of_all_columns: minimum_width_of_all_columns,
+ border_collapse: border_collapse,
+ };
+ let input =
+ inline_size_computer.compute_inline_size_constraint_inputs(&mut self.block_flow,
+ parent_flow_inline_size,
+ layout_context);
+
+ let solution = inline_size_computer.solve_inline_size_constraints(&mut self.block_flow,
&input);
- BlockNonReplaced.set_inline_size_constraint_solutions(&mut self.block_flow, solution);
- BlockNonReplaced.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
+ inline_size_computer.set_inline_size_constraint_solutions(&mut self.block_flow, solution);
+ inline_size_computer.set_inline_position_of_flow_if_necessary(&mut self.block_flow,
solution);
- }
}
}
@@ -294,14 +321,13 @@ impl Flow for TableWrapperFlow {
containing_block_inline_size;
}
- self.compute_used_inline_size(layout_context, containing_block_inline_size);
+ self.compute_used_inline_size(layout_context,
+ containing_block_inline_size,
+ intermediate_column_inline_sizes.as_slice());
- match self.table_layout {
- TableLayout::Fixed => {}
- TableLayout::Auto => {
- self.calculate_table_column_sizes_for_automatic_layout(
- &mut intermediate_column_inline_sizes)
- }
+ if let TableLayout::Auto = self.table_layout {
+ self.calculate_table_column_sizes_for_automatic_layout(
+ &mut intermediate_column_inline_sizes)
}
let inline_start_content_edge = self.block_flow.fragment.border_box.start.i;
@@ -679,3 +705,86 @@ struct IntermediateColumnInlineSize {
percentage: f64,
}
+fn initial_computed_inline_size(block: &mut BlockFlow,
+ containing_block_inline_size: Au,
+ minimum_width_of_all_columns: Au)
+ -> MaybeAuto {
+ let inline_size_from_style = MaybeAuto::from_style(block.fragment.style.content_inline_size(),
+ containing_block_inline_size);
+ match inline_size_from_style {
+ MaybeAuto::Auto => {
+ MaybeAuto::Specified(Au::max(containing_block_inline_size,
+ minimum_width_of_all_columns))
+ }
+ MaybeAuto::Specified(inline_size_from_style) => {
+ MaybeAuto::Specified(Au::max(inline_size_from_style, minimum_width_of_all_columns))
+ }
+ }
+}
+
+struct Table {
+ minimum_width_of_all_columns: Au,
+ border_collapse: border_collapse::T,
+}
+
+impl ISizeAndMarginsComputer for Table {
+ fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) {
+ block.fragment.compute_border_and_padding(containing_block_inline_size,
+ self.border_collapse)
+ }
+
+ fn initial_computed_inline_size(&self,
+ block: &mut BlockFlow,
+ parent_flow_inline_size: Au,
+ layout_context: &LayoutContext)
+ -> MaybeAuto {
+ let containing_block_inline_size =
+ self.containing_block_inline_size(block,
+ parent_flow_inline_size,
+ layout_context);
+ initial_computed_inline_size(block,
+ containing_block_inline_size,
+ self.minimum_width_of_all_columns)
+ }
+
+ fn solve_inline_size_constraints(&self,
+ block: &mut BlockFlow,
+ input: &ISizeConstraintInput)
+ -> ISizeConstraintSolution {
+ self.solve_block_inline_size_constraints(block, input)
+ }
+}
+
+struct FloatedTable {
+ minimum_width_of_all_columns: Au,
+ border_collapse: border_collapse::T,
+}
+
+impl ISizeAndMarginsComputer for FloatedTable {
+ fn compute_border_and_padding(&self, block: &mut BlockFlow, containing_block_inline_size: Au) {
+ block.fragment.compute_border_and_padding(containing_block_inline_size,
+ self.border_collapse)
+ }
+
+ fn initial_computed_inline_size(&self,
+ block: &mut BlockFlow,
+ parent_flow_inline_size: Au,
+ layout_context: &LayoutContext)
+ -> MaybeAuto {
+ let containing_block_inline_size =
+ self.containing_block_inline_size(block,
+ parent_flow_inline_size,
+ layout_context);
+ initial_computed_inline_size(block,
+ containing_block_inline_size,
+ self.minimum_width_of_all_columns)
+ }
+
+ fn solve_inline_size_constraints(&self,
+ block: &mut BlockFlow,
+ input: &ISizeConstraintInput)
+ -> ISizeConstraintSolution {
+ FloatNonReplaced.solve_inline_size_constraints(block, input)
+ }
+}
+
diff --git a/tests/ref/basic.list b/tests/ref/basic.list
index 2d49112b4b9..635d79798de 100644
--- a/tests/ref/basic.list
+++ b/tests/ref/basic.list
@@ -296,6 +296,7 @@ experimental == rtl_simple.html rtl_simple_ref.html
== table_expansion_to_fit_a.html table_expansion_to_fit_ref.html
== table_float_translation_a.html table_float_translation_ref.html
== table_intrinsic_style_specified_width_a.html table_intrinsic_style_specified_width_ref.html
+== table_margin_auto_a.html table_margin_auto_ref.html
== table_padding_a.html table_padding_ref.html
== table_percentage_capping_a.html table_percentage_capping_ref.html
== table_percentage_width_a.html table_percentage_width_ref.html
diff --git a/tests/ref/table_margin_auto_a.html b/tests/ref/table_margin_auto_a.html
new file mode 100644
index 00000000000..3a052e5f861
--- /dev/null
+++ b/tests/ref/table_margin_auto_a.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body, html {
+ margin: 0;
+}
+table {
+ margin: auto;
+ width: 0px;
+ border-spacing: 0;
+ border: none;
+}
+</style>
+</head>
+<body>
+<table><tr><td>Foooooooooooooooooooooooooooooo</td></tr></table>
+</body>
+</html>
+
diff --git a/tests/ref/table_margin_auto_ref.html b/tests/ref/table_margin_auto_ref.html
new file mode 100644
index 00000000000..c46e9a410e5
--- /dev/null
+++ b/tests/ref/table_margin_auto_ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body, html {
+ margin: 0;
+}
+body {
+ text-align: center;
+}
+div {
+ position: relative;
+ top: 1px;
+}
+</style>
+</head>
+<body>
+<div>Foooooooooooooooooooooooooooooo</div>
+</body>
+</html>
+