Fix fixed table layout column width distribution

This commit is contained in:
Keith Yeung 2017-04-24 03:31:40 -07:00
parent d8bcc0db1a
commit 2d5833d3af
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);
}
}
}