layout: Enable parallel layout for tables (#32477)

This simply wraps row and column-based layout of table sells in a
`par_iter()` unconditionally enabling parallel layout for tables. In the
future we can choose to adjust the conditions under which layout is done
in parallel.
This commit is contained in:
Martin Robinson 2024-06-26 18:33:48 +02:00 committed by GitHub
parent f055964792
commit e16291f14e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -6,6 +6,7 @@ use std::ops::Range;
use app_units::{Au, MAX_AU}; use app_units::{Au, MAX_AU};
use log::warn; use log::warn;
use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator};
use servo_arc::Arc; use servo_arc::Arc;
use style::computed_values::border_collapse::T as BorderCollapse; use style::computed_values::border_collapse::T as BorderCollapse;
use style::computed_values::box_sizing::T as BoxSizing; use style::computed_values::box_sizing::T as BoxSizing;
@ -1004,7 +1005,12 @@ impl<'a> TableLayout<'a> {
containing_block_for_table: &ContainingBlock, containing_block_for_table: &ContainingBlock,
parent_positioning_context: &mut PositioningContext, parent_positioning_context: &mut PositioningContext,
) { ) {
for row_index in 0..self.table.slots.len() { self.cells_laid_out = self
.table
.slots
.par_iter()
.enumerate()
.map(|(row_index, row_slots)| {
// When building the PositioningContext for this cell, we want it to have the same // When building the PositioningContext for this cell, we want it to have the same
// configuration for whatever PositioningContext the contents are ultimately added to. // configuration for whatever PositioningContext the contents are ultimately added to.
let collect_for_nearest_positioned_ancestor = parent_positioning_context let collect_for_nearest_positioned_ancestor = parent_positioning_context
@ -1025,27 +1031,17 @@ impl<'a> TableLayout<'a> {
) )
}); });
let mut cells_laid_out_row = Vec::new(); row_slots
let slots = &self.table.slots[row_index]; .par_iter()
for (column_index, slot) in slots.iter().enumerate() { .enumerate()
let cell = match slot { .map(|(column_index, slot)| {
TableSlot::Cell(cell) => cell, let TableSlot::Cell(ref cell) = slot else {
_ => { return None;
cells_laid_out_row.push(None);
continue;
},
}; };
let mut total_width = Au::zero(); let coordinates = TableSlotCoordinates::new(column_index, row_index);
for width_index in column_index..column_index + cell.colspan {
total_width += self.distributed_column_widths[width_index];
}
let border: LogicalSides<Au> = self let border: LogicalSides<Au> = self
.get_collapsed_borders_for_cell( .get_collapsed_borders_for_cell(cell, coordinates)
cell,
TableSlotCoordinates::new(column_index, row_index),
)
.unwrap_or_else(|| { .unwrap_or_else(|| {
cell.style cell.style
.border_width(containing_block_for_table.style.writing_mode) .border_width(containing_block_for_table.style.writing_mode)
@ -1058,16 +1054,22 @@ impl<'a> TableLayout<'a> {
.percentages_relative_to(self.basis_for_cell_padding_percentage.into()) .percentages_relative_to(self.basis_for_cell_padding_percentage.into())
.into(); .into();
let inline_border_padding_sum = border.inline_sum() + padding.inline_sum(); let inline_border_padding_sum = border.inline_sum() + padding.inline_sum();
let total_width = (total_width - inline_border_padding_sum).max(Au::zero());
let mut total_cell_width: Au = (column_index..column_index + cell.colspan)
.map(|column_index| self.distributed_column_widths[column_index])
.sum::<Au>() -
inline_border_padding_sum;
total_cell_width = total_cell_width.max(Au::zero());
let containing_block_for_children = ContainingBlock { let containing_block_for_children = ContainingBlock {
inline_size: total_width, inline_size: total_cell_width,
block_size: AuOrAuto::Auto, block_size: AuOrAuto::Auto,
style: &cell.style, style: &cell.style,
}; };
let mut positioning_context = let mut positioning_context = PositioningContext::new_for_subtree(
PositioningContext::new_for_subtree(collect_for_nearest_positioned_ancestor); collect_for_nearest_positioned_ancestor,
);
let layout = cell.contents.layout( let layout = cell.contents.layout(
layout_context, layout_context,
@ -1075,23 +1077,34 @@ impl<'a> TableLayout<'a> {
&containing_block_for_children, &containing_block_for_children,
); );
Some(CellLayout {
layout,
padding: padding.clone(),
border: border.clone(),
positioning_context,
})
})
.collect()
})
.collect();
// Now go through all cells laid out and update the cell measure based on the size
// determined during layout.
for row_index in 0..self.table.size.height {
for column_index in 0..self.table.size.width {
let Some(layout) = &self.cells_laid_out[row_index][column_index] else {
continue;
};
let content_size_from_layout = ContentSizes { let content_size_from_layout = ContentSizes {
min_content: layout.content_block_size, min_content: layout.layout.content_block_size,
max_content: layout.content_block_size, max_content: layout.layout.content_block_size,
}; };
self.cell_measures[row_index][column_index] self.cell_measures[row_index][column_index]
.block .block
.content_sizes .content_sizes
.max_assign(content_size_from_layout); .max_assign(content_size_from_layout);
cells_laid_out_row.push(Some(CellLayout {
layout,
padding,
border,
positioning_context,
}));
} }
self.cells_laid_out.push(cells_laid_out_row);
} }
} }