diff options
author | Oriol Brufau <obrufau@igalia.com> | 2024-12-23 03:00:37 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-23 11:00:37 +0000 |
commit | 6be0a64939c04fdcd9b8a11a863f1a04f07e4c9c (patch) | |
tree | 4fd6e66b7097ed5532d80f96a60358f6bc74d595 /components | |
parent | 2ab66ce67870acfff7bf18087421013475411380 (diff) | |
download | servo-6be0a64939c04fdcd9b8a11a863f1a04f07e4c9c.tar.gz servo-6be0a64939c04fdcd9b8a11a863f1a04f07e4c9c.zip |
layout: Implement keyword sizes for block layout heuristics (#34695)
Block layout uses some heuristics to guess whether margins are separated
by clearance and then don't collapse. These heuristics now take the
min-content, max-content, fit-content and stretch sizing keywords into
account.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_2020/flow/mod.rs | 104 | ||||
-rw-r--r-- | components/layout_2020/style_ext.rs | 31 |
2 files changed, 72 insertions, 63 deletions
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 06e7b6a4093..62bb828374a 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -39,7 +39,7 @@ use crate::layout_box_base::LayoutBoxBase; use crate::positioned::{AbsolutelyPositionedBox, PositioningContext, PositioningContextLength}; use crate::replaced::ReplacedContents; use crate::sizing::{self, ComputeInlineContentSizes, ContentSizes, InlineContentSizesResult}; -use crate::style_ext::{Clamp, ComputedValuesExt, ContentBoxSizesAndPBM, PaddingBorderMargin}; +use crate::style_ext::{ComputedValuesExt, ContentBoxSizesAndPBM, PaddingBorderMargin}; use crate::{ ConstraintSpace, ContainingBlock, ContainingBlockSize, IndefiniteContainingBlock, SizeConstraint, @@ -102,6 +102,7 @@ impl BlockLevelBox { fn find_block_margin_collapsing_with_parent( &self, + layout_context: &LayoutContext, collected_margin: &mut CollapsedMargin, containing_block: &ContainingBlock, ) -> bool { @@ -122,9 +123,13 @@ impl BlockLevelBox { return false; } - let pbm = style.padding_border_margin(containing_block); - let start_margin = pbm.margin.block_start.auto_is(Au::zero); - collected_margin.adjoin_assign(&CollapsedMargin::new(start_margin)); + let ContentBoxSizesAndPBM { + content_box_sizes, + pbm, + .. + } = style.content_box_sizes_and_padding_border_margin(&containing_block.into()); + let margin = pbm.margin.auto_is(Au::zero); + collected_margin.adjoin_assign(&CollapsedMargin::new(margin.block_start)); let child_boxes = match self { BlockLevelBox::SameFormattingContextBlock { ref contents, .. } => match contents { @@ -138,35 +143,45 @@ impl BlockLevelBox { return false; } - let min_size = style - .content_min_box_size_deprecated(containing_block, &pbm) - .auto_is(Au::zero); - let max_size = style.content_max_box_size_deprecated(containing_block, &pbm); - let prefered_size = style.content_box_size_deprecated(containing_block, &pbm); - let inline_size = prefered_size - .inline - .auto_is(|| { - let margin_inline_start = pbm.margin.inline_start.auto_is(Au::zero); - let margin_inline_end = pbm.margin.inline_end.auto_is(Au::zero); - containing_block.size.inline - - pbm.padding_border_sums.inline - - margin_inline_start - - margin_inline_end - }) - .clamp_between_extremums(min_size.inline, max_size.inline); - let block_size = prefered_size - .block - .map(|size| size.clamp_between_extremums(min_size.block, max_size.block)); + // FIXME: For BlockLevelBox::Independent, this should take floats into account. + let available_inline_size = + containing_block.size.inline - pbm.padding_border_sums.inline - margin.inline_sum(); + let available_block_size = containing_block.size.block.non_auto().map(|block_size| { + Au::zero().max(block_size - pbm.padding_border_sums.block - margin.block_sum()) + }); + + let tentative_block_size = content_box_sizes.block.resolve_extrinsic( + Size::FitContent, + Au::zero(), + available_block_size, + ); + + let get_inline_content_sizes = || { + let constraint_space = ConstraintSpace::new( + tentative_block_size, + style.writing_mode, + None, /* TODO: support preferred aspect ratios on non-replaced boxes */ + ); + self.inline_content_sizes(layout_context, &constraint_space) + .sizes + }; + let inline_size = content_box_sizes.inline.resolve( + Size::Stretch, + Au::zero(), + available_inline_size, + get_inline_content_sizes, + ); let containing_block_for_children = ContainingBlock { size: ContainingBlockSize { inline: inline_size, - block: block_size, + block: tentative_block_size.to_auto_or(), }, style, }; if !Self::find_block_margin_collapsing_with_parent_from_slice( + layout_context, child_boxes, collected_margin, &containing_block_for_children, @@ -181,13 +196,13 @@ impl BlockLevelBox { return false; } - let end_margin = pbm.margin.block_end.auto_is(Au::zero); - collected_margin.adjoin_assign(&CollapsedMargin::new(end_margin)); + collected_margin.adjoin_assign(&CollapsedMargin::new(margin.block_end)); true } fn find_block_margin_collapsing_with_parent_from_slice( + layout_context: &LayoutContext, boxes: &[ArcRefCell<BlockLevelBox>], margin: &mut CollapsedMargin, containing_block: &ContainingBlock, @@ -195,7 +210,7 @@ impl BlockLevelBox { boxes.iter().all(|block_level_box| { block_level_box .borrow() - .find_block_margin_collapsing_with_parent(margin, containing_block) + .find_block_margin_collapsing_with_parent(layout_context, margin, containing_block) }) } } @@ -230,6 +245,15 @@ impl OutsideMarker { &self.base.style } + fn inline_content_sizes( + &self, + layout_context: &LayoutContext, + constraint_space: &ConstraintSpace, + ) -> InlineContentSizesResult { + self.base + .inline_content_sizes(layout_context, constraint_space, &self.block_container) + } + fn layout( &self, layout_context: &LayoutContext<'_>, @@ -242,11 +266,7 @@ impl OutsideMarker { &self.marker_style, None, /* TODO: support preferred aspect ratios on non-replaced boxes */ ); - let content_sizes = self.base.inline_content_sizes( - layout_context, - &constraint_space, - &self.block_container, - ); + let content_sizes = self.inline_content_sizes(layout_context, &constraint_space); let containing_block_for_children = ContainingBlock { size: ContainingBlockSize { inline: content_sizes.sizes.max_content, @@ -770,6 +790,25 @@ impl BlockLevelBox { ), } } + + fn inline_content_sizes( + &self, + layout_context: &LayoutContext, + constraint_space: &ConstraintSpace, + ) -> InlineContentSizesResult { + let independent_formatting_context = match self { + BlockLevelBox::Independent(independent) => independent, + BlockLevelBox::OutOfFlowAbsolutelyPositionedBox(box_) => &box_.borrow().context, + BlockLevelBox::OutOfFlowFloatBox(float_box) => &float_box.contents, + BlockLevelBox::OutsideMarker(outside_marker) => { + return outside_marker.inline_content_sizes(layout_context, constraint_space) + }, + BlockLevelBox::SameFormattingContextBlock { base, contents, .. } => { + return base.inline_content_sizes(layout_context, constraint_space, contents) + }, + }; + independent_formatting_context.inline_content_sizes(layout_context, constraint_space) + } } /// Lay out a normal flow non-replaced block that does not establish a new formatting @@ -844,6 +883,7 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context( if !collapsible_with_parent_start_margin && start_margin_can_collapse_with_children { if let BlockContainer::BlockLevelBoxes(child_boxes) = contents { BlockLevelBox::find_block_margin_collapsing_with_parent_from_slice( + layout_context, child_boxes, &mut block_start_margin, containing_block, diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs index e6733ac998e..04ad55ddaac 100644 --- a/components/layout_2020/style_ext.rs +++ b/components/layout_2020/style_ext.rs @@ -261,16 +261,6 @@ pub(crate) trait ComputedValuesExt { box_size: LogicalVec2<Size<Au>>, pbm: &PaddingBorderMargin, ) -> LogicalVec2<Size<Au>>; - fn content_max_box_size( - &self, - containing_block: &ContainingBlock, - pbm: &PaddingBorderMargin, - ) -> LogicalVec2<Size<Au>>; - fn content_max_box_size_deprecated( - &self, - containing_block: &ContainingBlock, - pbm: &PaddingBorderMargin, - ) -> LogicalVec2<Option<Au>>; fn content_max_box_size_for_max_size( &self, box_size: LogicalVec2<Size<Au>>, @@ -470,27 +460,6 @@ impl ComputedValuesExt for ComputedValues { } } - fn content_max_box_size( - &self, - containing_block: &ContainingBlock, - pbm: &PaddingBorderMargin, - ) -> LogicalVec2<Size<Au>> { - let max_box_size = self - .max_box_size(containing_block.style.writing_mode) - .percentages_relative_to(containing_block); - - self.content_max_box_size_for_max_size(max_box_size, pbm) - } - - fn content_max_box_size_deprecated( - &self, - containing_block: &ContainingBlock, - pbm: &PaddingBorderMargin, - ) -> LogicalVec2<Option<Au>> { - self.content_max_box_size(containing_block, pbm) - .map(Size::to_numeric) - } - fn content_max_box_size_for_max_size( &self, max_box_size: LogicalVec2<Size<Au>>, |