diff --git a/components/layout/table.rs b/components/layout/table.rs index 4f70c334dc74..61ab49f59cdc 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -781,17 +781,54 @@ impl TableLikeFlow for BlockFlow { debug_assert!(self.fragment.style.get_inheritedtable().border_collapse == border_collapse::T::Separate || block_direction_spacing == Au(0)); + fn border_spacing_for_row(fragment: &Fragment, row: &TableRowFlow, + block_direction_spacing: Au) -> Au { + match fragment.style.get_inheritedtable().border_collapse { + border_collapse::T::Separate => block_direction_spacing, + border_collapse::T::Collapse => { + row.collapsed_border_spacing.block_start + } + } + } if self.base.restyle_damage.contains(ServoRestyleDamage::REFLOW) { - let mut sizes = vec![]; + // (size, cumulative_border_spacing) + let mut sizes = vec![(Au(0), Au(0))]; + // The amount of border spacing up to and including this row, + // but not including the spacing beneath it + let mut cumulative_border = Au(0); let mut incoming_rowspan_data = vec![]; + // First pass: Compute block-direction border spacings + // XXXManishearth this can be done in tandem with the second pass, + // provided we never hit any rowspan cases + for kid in self.base.child_iter_mut() + .filter(|k| k.is_table_row()) + .skip(1) { + cumulative_border += + border_spacing_for_row(&self.fragment, kid.as_table_row(), + block_direction_spacing); + // we haven't calculated sizes yet + sizes.push((Au(0), cumulative_border)); + } + + // Second pass: Compute row block sizes + // [expensive: iterates over cells] + let mut i = 0; for kid in self.base.child_iter_mut() { if kid.is_table_row() { - sizes.push(kid.as_mut_table_row() - .compute_block_size_table_row_base(layout_context, &mut incoming_rowspan_data)) + let size = kid.as_mut_table_row() + .compute_block_size_table_row_base(layout_context, + &mut incoming_rowspan_data, + &sizes, + i); + sizes[i].0 = size; + i += 1; } } + + // Third pass: Assign block sizes to rows and cells + // [expensive: iterates over cells] let mut effects_rows = 0; let mut i = 0; for kid in self.base.child_iter_mut() { @@ -811,11 +848,15 @@ impl TableLikeFlow for BlockFlow { i += 1; } } + // Our current border-box position. let block_start_border_padding = self.fragment.border_padding.block_start; let mut current_block_offset = block_start_border_padding; let mut has_rows = false; + // Fourth pass: Compute block positions + // XXXManishearth this can be merged with the third pass + // At this point, `current_block_offset` is at the content edge of our box. Now iterate // over children. for kid in self.base.child_iter_mut() { @@ -824,12 +865,8 @@ impl TableLikeFlow for BlockFlow { has_rows = true; let child_table_row = kid.as_table_row(); current_block_offset = current_block_offset + - match self.fragment.style.get_inheritedtable().border_collapse { - border_collapse::T::Separate => block_direction_spacing, - border_collapse::T::Collapse => { - child_table_row.collapsed_border_spacing.block_start - } - } + border_spacing_for_row(&self.fragment, child_table_row, + block_direction_spacing) } // At this point, `current_block_offset` is at the border edge of the child. @@ -874,6 +911,7 @@ impl TableLikeFlow for BlockFlow { self.fragment.border_box.start.b = Au(0); self.base.position.size.block = current_block_offset; + // Fifth pass: Assign absolute position info // Write in the size of the relative containing block for children. (This information // is also needed to handle RTL.) for kid in self.base.child_iter_mut() { diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index ec06a19be559..8d5da7130a07 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -114,7 +114,9 @@ impl TableRowFlow { /// methods #[inline(always)] pub fn compute_block_size_table_row_base<'a>(&'a mut self, layout_context: &LayoutContext, - incoming_rowspan_data: &mut Vec) -> Au { + incoming_rowspan_data: &mut Vec, + border_info: &[(Au, Au)], + row_index: usize) -> Au { // XXXManishearth skip this when the REFLOW flag is unset if it is not affected by other // rows fn include_sizes_from_previous_rows(col: &mut usize, @@ -185,16 +187,16 @@ impl TableRowFlow { block_size } - pub fn assign_block_size_to_self_and_children(&mut self, sizes: &[Au], index: usize, effects_rows: &mut u32) { + pub fn assign_block_size_to_self_and_children(&mut self, sizes: &[(Au, Au)], index: usize, effects_rows: &mut u32) { // Assign the block-size of kid fragments, which is the same value as own block-size. - let block_size = sizes[index]; + let block_size = sizes[index].0; for kid in self.block_flow.base.child_iter_mut() { let child_table_cell = kid.as_mut_table_cell(); let block_size = if child_table_cell.row_span > 1 { *effects_rows = max(*effects_rows, child_table_cell.row_span); // XXXManishearth support border spacing and such sizes[index..].iter().take(child_table_cell.row_span as usize) - .fold(Au(0), |accum, size| accum + *size) + .fold(Au(0), |accum, size| accum + size.0) } else { block_size };