diff --git a/components/layout/construct_modern.rs b/components/layout/construct_modern.rs index 0514eea961a..1ac2bb44d99 100644 --- a/components/layout/construct_modern.rs +++ b/components/layout/construct_modern.rs @@ -44,6 +44,90 @@ enum ModernContainerJob<'dom> { TextRuns(Vec>), } +impl<'dom> ModernContainerJob<'dom> { + fn finish( + self, + builder: &ModernContainerBuilder, + anonymous_info: &LazyLock, impl FnOnce() -> NodeAndStyleInfo<'dom>>, + ) -> Option> { + match self { + ModernContainerJob::TextRuns(runs) => { + let mut inline_formatting_context_builder = + InlineFormattingContextBuilder::new(builder.info); + for flex_text_run in runs.into_iter() { + inline_formatting_context_builder + .push_text(flex_text_run.text, &flex_text_run.info); + } + + let inline_formatting_context = inline_formatting_context_builder.finish( + builder.context, + true, /* has_first_formatted_line */ + false, /* is_single_line_text_box */ + builder.info.style.to_bidi_level(), + )?; + + let block_formatting_context = BlockFormattingContext::from_block_container( + BlockContainer::InlineFormattingContext(inline_formatting_context), + ); + let info: &NodeAndStyleInfo = anonymous_info; + let formatting_context = IndependentFormattingContext { + base: LayoutBoxBase::new(info.into(), info.style.clone()), + contents: IndependentFormattingContextContents::NonReplaced( + IndependentNonReplacedContents::Flow(block_formatting_context), + ), + }; + + Some(ModernItem { + kind: ModernItemKind::InFlow, + order: 0, + box_slot: None, + formatting_context, + }) + }, + ModernContainerJob::ElementOrPseudoElement { + info, + display, + contents, + box_slot, + } => { + let is_abspos = info.style.get_box().position.is_absolutely_positioned(); + + // Text decorations are not propagated to any out-of-flow descendants. In addition, + // absolutes don't affect the size of ancestors so it is fine to allow descendent + // tables to resolve percentage columns. + let propagated_data = match is_abspos { + false => builder.propagated_data, + true => PropagatedBoxTreeData::default(), + }; + + let formatting_context = IndependentFormattingContext::construct( + builder.context, + &info, + display.display_inside(), + contents, + propagated_data, + ); + + if is_abspos { + Some(ModernItem { + kind: ModernItemKind::OutOfFlow, + order: 0, + box_slot: Some(box_slot), + formatting_context, + }) + } else { + Some(ModernItem { + kind: ModernItemKind::InFlow, + order: info.style.clone_order(), + box_slot: Some(box_slot), + formatting_context, + }) + } + }, + } + } +} + struct ModernContainerTextRun<'dom> { info: NodeAndStyleInfo<'dom>, text: Cow<'dom, str>, @@ -137,84 +221,17 @@ impl<'a, 'dom> ModernContainerBuilder<'a, 'dom> { .pseudo(self.context, PseudoElement::ServoAnonymousBox) .expect("Should always be able to construct info for anonymous boxes.") }); - let mut children: Vec = std::mem::take(&mut self.jobs) - .into_par_iter() - .filter_map(|job| match job { - ModernContainerJob::TextRuns(runs) => { - let mut inline_formatting_context_builder = - InlineFormattingContextBuilder::new(self.info); - for flex_text_run in runs.into_iter() { - inline_formatting_context_builder - .push_text(flex_text_run.text, &flex_text_run.info); - } - let inline_formatting_context = inline_formatting_context_builder.finish( - self.context, - true, /* has_first_formatted_line */ - false, /* is_single_line_text_box */ - self.info.style.to_bidi_level(), - )?; - - let block_formatting_context = BlockFormattingContext::from_block_container( - BlockContainer::InlineFormattingContext(inline_formatting_context), - ); - let info: &NodeAndStyleInfo = &anonymous_info; - let formatting_context = IndependentFormattingContext { - base: LayoutBoxBase::new(info.into(), info.style.clone()), - contents: IndependentFormattingContextContents::NonReplaced( - IndependentNonReplacedContents::Flow(block_formatting_context), - ), - }; - - Some(ModernItem { - kind: ModernItemKind::InFlow, - order: 0, - box_slot: None, - formatting_context, - }) - }, - ModernContainerJob::ElementOrPseudoElement { - info, - display, - contents, - box_slot, - } => { - let is_abspos = info.style.get_box().position.is_absolutely_positioned(); - - // Text decorations are not propagated to any out-of-flow descendants. In addition, - // absolutes don't affect the size of ancestors so it is fine to allow descendent - // tables to resolve percentage columns. - let propagated_data = match is_abspos { - false => self.propagated_data, - true => PropagatedBoxTreeData::default(), - }; - - let formatting_context = IndependentFormattingContext::construct( - self.context, - &info, - display.display_inside(), - contents, - propagated_data, - ); - - if is_abspos { - Some(ModernItem { - kind: ModernItemKind::OutOfFlow, - order: 0, - box_slot: Some(box_slot), - formatting_context, - }) - } else { - Some(ModernItem { - kind: ModernItemKind::InFlow, - order: info.style.clone_order(), - box_slot: Some(box_slot), - formatting_context, - }) - } - }, - }) - .collect::>(); + let jobs = std::mem::take(&mut self.jobs); + let mut children: Vec<_> = if self.context.use_rayon { + jobs.into_par_iter() + .filter_map(|job| job.finish(&self, &anonymous_info)) + .collect() + } else { + jobs.into_iter() + .filter_map(|job| job.finish(&self, &anonymous_info)) + .collect() + }; // https://drafts.csswg.org/css-flexbox/#order-modified-document-order children.sort_by_key(|child| child.order); diff --git a/components/layout/flexbox/layout.rs b/components/layout/flexbox/layout.rs index 6eff15421c3..7044583fa09 100644 --- a/components/layout/flexbox/layout.rs +++ b/components/layout/flexbox/layout.rs @@ -1221,14 +1221,25 @@ impl InitialFlexLineLayout<'_> { ); // https://drafts.csswg.org/css-flexbox/#algo-cross-item - let layout_results = items - .par_iter() - .zip(&item_used_main_sizes) - .map(|(item, used_main_size)| { - item.layout(*used_main_size, flex_context, None, None) - .unwrap() - }) - .collect::>(); + let layout_results: Vec<_> = if flex_context.layout_context.use_rayon { + items + .par_iter() + .zip(&item_used_main_sizes) + .map(|(item, used_main_size)| { + item.layout(*used_main_size, flex_context, None, None) + .unwrap() + }) + .collect() + } else { + items + .iter() + .zip(&item_used_main_sizes) + .map(|(item, used_main_size)| { + item.layout(*used_main_size, flex_context, None, None) + .unwrap() + }) + .collect() + }; let items: Vec<_> = izip!( items.into_iter(), diff --git a/components/layout/table/layout.rs b/components/layout/table/layout.rs index b9593ba4f7a..5748dccee81 100644 --- a/components/layout/table/layout.rs +++ b/components/layout/table/layout.rs @@ -1069,71 +1069,96 @@ impl<'a> TableLayout<'a> { layout_context: &LayoutContext, containing_block_for_table: &ContainingBlock, ) { - self.cells_laid_out = self - .table - .slots - .par_iter() - .enumerate() - .map(|(row_index, row_slots)| { - row_slots - .par_iter() - .enumerate() - .map(|(column_index, slot)| { - let TableSlot::Cell(cell) = slot else { - return None; - }; + let layout_table_slot = |coordinate: TableSlotCoordinates, slot: &TableSlot| { + let TableSlot::Cell(cell) = slot else { + return None; + }; - let cell = cell.borrow(); - let area = LogicalSides { - inline_start: column_index, - inline_end: column_index + cell.colspan, - block_start: row_index, - block_end: row_index + cell.rowspan, - }; - let layout_style = cell.layout_style(); - let border = self - .get_collapsed_border_widths_for_area(area) - .unwrap_or_else(|| { - layout_style - .border_width(containing_block_for_table.style.writing_mode) - }); - let padding: LogicalSides = layout_style - .padding(containing_block_for_table.style.writing_mode) - .percentages_relative_to(self.basis_for_cell_padding_percentage); - let inline_border_padding_sum = border.inline_sum() + padding.inline_sum(); + let cell = cell.borrow(); + let area = LogicalSides { + inline_start: coordinate.x, + inline_end: coordinate.x + cell.colspan, + block_start: coordinate.y, + block_end: coordinate.y + cell.rowspan, + }; + let layout_style = cell.layout_style(); + let border = self + .get_collapsed_border_widths_for_area(area) + .unwrap_or_else(|| { + layout_style.border_width(containing_block_for_table.style.writing_mode) + }); + let padding: LogicalSides = layout_style + .padding(containing_block_for_table.style.writing_mode) + .percentages_relative_to(self.basis_for_cell_padding_percentage); + let inline_border_padding_sum = border.inline_sum() + padding.inline_sum(); - let mut total_cell_width: Au = (column_index..column_index + cell.colspan) - .map(|column_index| self.distributed_column_widths[column_index]) - .sum::() - - inline_border_padding_sum; - total_cell_width = total_cell_width.max(Au::zero()); + let mut total_cell_width: Au = (coordinate.x..coordinate.x + cell.colspan) + .map(|column_index| self.distributed_column_widths[column_index]) + .sum::() - + inline_border_padding_sum; + total_cell_width = total_cell_width.max(Au::zero()); - let containing_block_for_children = ContainingBlock { - size: ContainingBlockSize { - inline: total_cell_width, - block: SizeConstraint::default(), - }, - style: &cell.base.style, - }; + let containing_block_for_children = ContainingBlock { + size: ContainingBlockSize { + inline: total_cell_width, + block: SizeConstraint::default(), + }, + style: &cell.base.style, + }; - let mut positioning_context = PositioningContext::default(); - let layout = cell.contents.layout( - layout_context, - &mut positioning_context, - &containing_block_for_children, - false, /* depends_on_block_constraints */ - ); + let mut positioning_context = PositioningContext::default(); + let layout = cell.contents.layout( + layout_context, + &mut positioning_context, + &containing_block_for_children, + false, /* depends_on_block_constraints */ + ); - Some(CellLayout { - layout, - padding, - border, - positioning_context, - }) - }) - .collect() + Some(CellLayout { + layout, + padding, + border, + positioning_context, }) - .collect(); + }; + + self.cells_laid_out = if layout_context.use_rayon { + self.table + .slots + .par_iter() + .enumerate() + .map(|(row_index, row_slots)| { + row_slots + .par_iter() + .enumerate() + .map(|(column_index, slot)| { + layout_table_slot( + TableSlotCoordinates::new(column_index, row_index), + slot, + ) + }) + .collect() + }) + .collect() + } else { + self.table + .slots + .iter() + .enumerate() + .map(|(row_index, row_slots)| { + row_slots + .iter() + .enumerate() + .map(|(column_index, slot)| { + layout_table_slot( + TableSlotCoordinates::new(column_index, row_index), + slot, + ) + }) + .collect() + }) + .collect() + }; // Now go through all cells laid out and update the cell measure based on the size // determined during layout.