aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorOriol Brufau <obrufau@igalia.com>2024-12-23 03:00:37 -0800
committerGitHub <noreply@github.com>2024-12-23 11:00:37 +0000
commit6be0a64939c04fdcd9b8a11a863f1a04f07e4c9c (patch)
tree4fd6e66b7097ed5532d80f96a60358f6bc74d595 /components
parent2ab66ce67870acfff7bf18087421013475411380 (diff)
downloadservo-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.rs104
-rw-r--r--components/layout_2020/style_ext.rs31
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>>,