Auto merge of #16588 - KiChjang:fix-fixed-table-layout-column-width, r=mbrubeck

Fix fixed table layout column width distribution

Fixes #16324.

Replaces the incorrect [CSS3 "distributing excess width to columns" algorithm](https://drafts.csswg.org/css-tables-3/#distributing-width-to-columns) and implements the simpler [CSS2 fixed table layout algorithm](https://drafts.csswg.org/css2/tables.html#fixed-table-layout).

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16588)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-04-28 12:56:06 -05:00 committed by GitHub
commit bf32a7b9bd
9 changed files with 45 additions and 63 deletions

View file

@ -352,20 +352,16 @@ impl Flow for TableFlow {
let shared_context = layout_context.shared_context();
// The position was set to the containing block by the flow's parent.
// FIXME: The code for distributing column widths should really be placed under table_wrapper.rs.
let containing_block_inline_size = self.block_flow.base.block_container_inline_size;
let mut num_unspecified_inline_sizes = 0;
let mut num_percentage_inline_sizes = 0;
let mut total_column_inline_size = Au(0);
let mut total_column_percentage_size = 0.0;
for column_inline_size in &self.column_intrinsic_inline_sizes {
if column_inline_size.percentage != 0.0 {
total_column_percentage_size += column_inline_size.percentage;
num_percentage_inline_sizes += 1;
} else if column_inline_size.constrained {
total_column_inline_size += column_inline_size.minimum_length;
} else {
num_unspecified_inline_sizes += 1;
let mut constrained_column_inline_sizes_indices = vec![];
let mut unspecified_inline_sizes_indices = vec![];
for (idx, column_inline_size) in self.column_intrinsic_inline_sizes.iter().enumerate() {
if column_inline_size.constrained {
constrained_column_inline_sizes_indices.push(idx);
} else if column_inline_size.percentage == 0.0 {
unspecified_inline_sizes_indices.push(idx);
}
}
@ -383,43 +379,50 @@ impl Flow for TableFlow {
let total_horizontal_spacing = self.total_horizontal_spacing();
let content_inline_size = self.block_flow.fragment.border_box.size.inline -
padding_and_borders - total_horizontal_spacing;
let mut remaining_inline_size = content_inline_size;
match self.table_layout {
TableLayout::Fixed => {
// 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.
// See: https://drafts.csswg.org/css-tables-3/#distributing-width-to-columns
// (infobox)
self.column_computed_inline_sizes.clear();
if num_unspecified_inline_sizes != 0 {
let extra_column_inline_size = content_inline_size - total_column_inline_size;
for column_inline_size in &self.column_intrinsic_inline_sizes {
if !column_inline_size.constrained {
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,
});
}
}
} else if num_percentage_inline_sizes != 0 {
let extra_column_inline_size = content_inline_size - total_column_inline_size;
let ratio = content_inline_size.to_f32_px() /
total_column_percentage_size;
for column_inline_size in &self.column_intrinsic_inline_sizes {
// https://drafts.csswg.org/css2/tables.html#fixed-table-layout
for column_inline_size in &self.column_intrinsic_inline_sizes {
if column_inline_size.constrained {
self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
size: extra_column_inline_size.scale_by(ratio * column_inline_size.percentage),
size: column_inline_size.minimum_length,
});
remaining_inline_size -= column_inline_size.minimum_length;
} else if column_inline_size.percentage != 0.0 {
let size = remaining_inline_size.scale_by(column_inline_size.percentage);
self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
size: size,
});
remaining_inline_size -= size;
} else {
// Set the size to 0 now, distribute the remaining widths later
self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
size: Au(0),
});
}
}
// Distribute remaining content inline size
if unspecified_inline_sizes_indices.len() > 0 {
for &index in &unspecified_inline_sizes_indices {
self.column_computed_inline_sizes[index].size =
remaining_inline_size.scale_by(1.0 / unspecified_inline_sizes_indices.len() as f32);
}
} else {
let ratio = content_inline_size.to_f32_px() /
total_column_inline_size.to_f32_px();
for column_inline_size in &self.column_intrinsic_inline_sizes {
self.column_computed_inline_sizes.push(ColumnComputedInlineSize {
size: column_inline_size.minimum_length.scale_by(ratio),
});
let total_minimum_size = self.column_intrinsic_inline_sizes
.iter()
.filter(|size| size.constrained)
.map(|size| size.minimum_length.0 as f32)
.sum::<f32>();
for &index in &constrained_column_inline_sizes_indices {
self.column_computed_inline_sizes[index].size +=
remaining_inline_size.scale_by(
self.column_computed_inline_sizes[index].size.0 as f32 / total_minimum_size);
}
}
}

View file

@ -1,3 +0,0 @@
[float-applies-to-001a.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-002.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-003.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-004.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-004a.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-005.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +0,0 @@
[float-applies-to-006.htm]
type: reftest
expected: FAIL

View file

@ -1,3 +1,3 @@
[float-applies-to-001.htm]
[floats-149.htm]
type: reftest
expected: FAIL