mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Account for rowspan in inline layout of table columns/cells
This commit is contained in:
parent
e982d6003f
commit
9700b0e8b3
6 changed files with 180 additions and 11 deletions
|
@ -45,6 +45,12 @@ pub struct TableRowFlow {
|
|||
/// Information about the computed inline-sizes of each column.
|
||||
pub column_computed_inline_sizes: Vec<ColumnComputedInlineSize>,
|
||||
|
||||
/// The number of remaining rows spanned by cells in previous rows, indexed by column.
|
||||
///
|
||||
/// Columns that are not included in this vector have the default rowspan of "1". If there are
|
||||
/// no cells with rowspan != 1 in previous rows, this vector may be empty.
|
||||
pub incoming_rowspan: Vec<u32>,
|
||||
|
||||
/// The spacing for this row, propagated down from the table during the inline-size assignment
|
||||
/// phase.
|
||||
pub spacing: border_spacing::T,
|
||||
|
@ -90,6 +96,7 @@ impl TableRowFlow {
|
|||
block_flow: BlockFlow::from_fragment(fragment),
|
||||
cell_intrinsic_inline_sizes: Vec::new(),
|
||||
column_computed_inline_sizes: Vec::new(),
|
||||
incoming_rowspan: Vec::new(),
|
||||
spacing: border_spacing::T {
|
||||
horizontal: Au(0),
|
||||
vertical: Au(0),
|
||||
|
@ -353,12 +360,23 @@ impl Flow for TableRowFlow {
|
|||
containing_block_inline_size);
|
||||
|
||||
// Spread out the completed inline sizes among columns with spans > 1.
|
||||
let mut computed_inline_size_for_cells = Vec::new();
|
||||
let mut column_computed_inline_size_iterator = self.column_computed_inline_sizes.iter();
|
||||
let num_columns = self.column_computed_inline_sizes.len();
|
||||
let mut computed_inline_size_for_cells = Vec::with_capacity(num_columns);
|
||||
let mut col = 0;
|
||||
|
||||
for cell_intrinsic_inline_size in &self.cell_intrinsic_inline_sizes {
|
||||
// Skip any column occupied by a cell from a previous row.
|
||||
while col < self.incoming_rowspan.len() && self.incoming_rowspan[col] != 1 {
|
||||
let size = match self.column_computed_inline_sizes.get(col) {
|
||||
Some(column_computed_inline_size) => *column_computed_inline_size,
|
||||
None => ColumnComputedInlineSize { size: Au(0) } // See FIXME below.
|
||||
};
|
||||
computed_inline_size_for_cells.push(size);
|
||||
col += 1;
|
||||
}
|
||||
// Start with the computed inline size for the first column in the span.
|
||||
let mut column_computed_inline_size =
|
||||
match column_computed_inline_size_iterator.next() {
|
||||
match self.column_computed_inline_sizes.get(col) {
|
||||
Some(column_computed_inline_size) => *column_computed_inline_size,
|
||||
None => {
|
||||
// We're in fixed layout mode and there are more cells in this row than
|
||||
|
@ -371,16 +389,18 @@ impl Flow for TableRowFlow {
|
|||
}
|
||||
}
|
||||
};
|
||||
col += 1;
|
||||
|
||||
// Add in computed inline sizes for any extra columns in the span.
|
||||
for _ in 1..cell_intrinsic_inline_size.column_span {
|
||||
let extra_column_computed_inline_size =
|
||||
match column_computed_inline_size_iterator.next() {
|
||||
match self.column_computed_inline_sizes.get(col) {
|
||||
Some(column_computed_inline_size) => column_computed_inline_size,
|
||||
None => break,
|
||||
};
|
||||
column_computed_inline_size.size = column_computed_inline_size.size +
|
||||
extra_column_computed_inline_size.size + self.spacing.horizontal;
|
||||
col += 1;
|
||||
}
|
||||
|
||||
computed_inline_size_for_cells.push(column_computed_inline_size)
|
||||
|
@ -402,6 +422,9 @@ impl Flow for TableRowFlow {
|
|||
let spacing = self.spacing;
|
||||
let row_writing_mode = self.block_flow.base.writing_mode;
|
||||
let table_writing_mode = self.table_writing_mode;
|
||||
let incoming_rowspan = &self.incoming_rowspan;
|
||||
let mut column_index = 0;
|
||||
|
||||
self.block_flow.propagate_assigned_inline_size_to_children(shared_context,
|
||||
inline_start_content_edge,
|
||||
inline_end_content_edge,
|
||||
|
@ -415,6 +438,8 @@ impl Flow for TableRowFlow {
|
|||
set_inline_position_of_child_flow(
|
||||
child_flow,
|
||||
child_index,
|
||||
&mut column_index,
|
||||
incoming_rowspan,
|
||||
row_writing_mode,
|
||||
table_writing_mode,
|
||||
&computed_inline_size_for_cells,
|
||||
|
@ -714,13 +739,14 @@ impl CollapsedBorder {
|
|||
}
|
||||
}
|
||||
|
||||
/// Pushes column inline size and border collapse info down to a child.
|
||||
/// Pushes column inline size, incoming rowspan, and border collapse info down to a child.
|
||||
pub fn propagate_column_inline_sizes_to_child(
|
||||
child_flow: &mut Flow,
|
||||
table_writing_mode: WritingMode,
|
||||
column_computed_inline_sizes: &[ColumnComputedInlineSize],
|
||||
border_spacing: &border_spacing::T) {
|
||||
// If the child is a row group or a row, the column inline-size info should be copied from its
|
||||
border_spacing: &border_spacing::T,
|
||||
incoming_rowspan: &mut Vec<u32>) {
|
||||
// If the child is a row group or a row, the column inline-size and rowspan info should be copied from its
|
||||
// parent.
|
||||
//
|
||||
// FIXME(pcwalton): This seems inefficient. Reference count it instead?
|
||||
|
@ -736,7 +762,8 @@ pub fn propagate_column_inline_sizes_to_child(
|
|||
propagate_column_inline_sizes_to_child(kid,
|
||||
table_writing_mode,
|
||||
column_computed_inline_sizes,
|
||||
border_spacing);
|
||||
border_spacing,
|
||||
incoming_rowspan);
|
||||
}
|
||||
}
|
||||
FlowClass::TableRow => {
|
||||
|
@ -745,6 +772,32 @@ pub fn propagate_column_inline_sizes_to_child(
|
|||
column_computed_inline_sizes.to_vec();
|
||||
child_table_row_flow.spacing = *border_spacing;
|
||||
child_table_row_flow.table_writing_mode = table_writing_mode;
|
||||
child_table_row_flow.incoming_rowspan = incoming_rowspan.clone();
|
||||
|
||||
// Update the incoming rowspan for the next row.
|
||||
let mut col = 0;
|
||||
for cell in &child_table_row_flow.cell_intrinsic_inline_sizes {
|
||||
// Skip any column occupied by a cell from a previous row.
|
||||
while col < incoming_rowspan.len() && incoming_rowspan[col] != 1 {
|
||||
if incoming_rowspan[col] > 1 {
|
||||
incoming_rowspan[col] -= 1;
|
||||
}
|
||||
col += 1;
|
||||
}
|
||||
for _ in 0..cell.column_span {
|
||||
if col < incoming_rowspan.len() && incoming_rowspan[col] > 1 {
|
||||
incoming_rowspan[col] -= 1;
|
||||
}
|
||||
// If this cell spans later rows, record its rowspan.
|
||||
if cell.row_span != 1 {
|
||||
if incoming_rowspan.len() < col + 1 {
|
||||
incoming_rowspan.resize(col + 1, 1);
|
||||
}
|
||||
incoming_rowspan[col] = max(cell.row_span, incoming_rowspan[col]);
|
||||
}
|
||||
col += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
c => warn!("unexpected flow in table {:?}", c)
|
||||
}
|
||||
|
@ -754,6 +807,8 @@ pub fn propagate_column_inline_sizes_to_child(
|
|||
fn set_inline_position_of_child_flow(
|
||||
child_flow: &mut Flow,
|
||||
child_index: usize,
|
||||
column_index: &mut usize,
|
||||
incoming_rowspan: &[u32],
|
||||
row_writing_mode: WritingMode,
|
||||
table_writing_mode: WritingMode,
|
||||
column_computed_inline_sizes: &[ColumnComputedInlineSize],
|
||||
|
@ -768,6 +823,21 @@ fn set_inline_position_of_child_flow(
|
|||
|
||||
let reverse_column_order = table_writing_mode.is_bidi_ltr() != row_writing_mode.is_bidi_ltr();
|
||||
|
||||
// Advance past any column occupied by a cell from a previous row.
|
||||
while *column_index < incoming_rowspan.len() && incoming_rowspan[*column_index] != 1 {
|
||||
let column_inline_size = column_computed_inline_sizes[*column_index].size;
|
||||
let border_inline_size = match *border_collapse_info {
|
||||
Some(_) => Au(0), // FIXME: Make collapsed borders account for colspan/rowspan.
|
||||
None => border_spacing.horizontal,
|
||||
};
|
||||
if reverse_column_order {
|
||||
*inline_end_margin_edge += column_inline_size + border_inline_size;
|
||||
} else {
|
||||
*inline_start_margin_edge += column_inline_size + border_inline_size;
|
||||
}
|
||||
*column_index += 1;
|
||||
}
|
||||
|
||||
// Handle border collapsing, if necessary.
|
||||
let child_table_cell = child_flow.as_mut_table_cell();
|
||||
match *border_collapse_info {
|
||||
|
@ -822,7 +892,9 @@ fn set_inline_position_of_child_flow(
|
|||
}
|
||||
}
|
||||
|
||||
let column_inline_size = column_computed_inline_sizes[child_index].size;
|
||||
let column_inline_size = column_computed_inline_sizes[*column_index].size;
|
||||
*column_index += 1;
|
||||
|
||||
let kid_base = &mut child_table_cell.block_flow.base;
|
||||
kid_base.block_container_inline_size = column_inline_size;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue