aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorOriol Brufau <obrufau@igalia.com>2023-06-23 19:56:55 +0200
committerOriol Brufau <obrufau@igalia.com>2023-06-29 11:00:45 +0200
commit6b2bbdd02d88cc45d54e331537c10942b6cde990 (patch)
tree619ad528587e55ab1590f7afd9d129a00056bf70 /components
parenta725380db0b9fba31993409f7d0f4b2d11ca8f7d (diff)
downloadservo-6b2bbdd02d88cc45d54e331537c10942b6cde990.tar.gz
servo-6b2bbdd02d88cc45d54e331537c10942b6cde990.zip
Layout 2020: implement clearance as Option<Length>
Clearance was implemented as a Length, where zero meant no clearance. However, having a clearance of 0px should be different than having no clearance, since the former can still prevent margin collapse. This patch keeps the existing behavior, so it won't be possible to get a clearance of Some(Length::zero()), but it prepares the terrain for a follow-up to fix calculate_clearance to return the proper thing.
Diffstat (limited to 'components')
-rw-r--r--components/layout_2020/flexbox/layout.rs2
-rw-r--r--components/layout_2020/flow/float.rs11
-rw-r--r--components/layout_2020/flow/inline.rs6
-rw-r--r--components/layout_2020/flow/mod.rs33
-rw-r--r--components/layout_2020/fragment_tree/box_fragment.rs12
-rw-r--r--components/layout_2020/positioned.rs2
6 files changed, 42 insertions, 24 deletions
diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs
index 4e0ccc459e9..19619375b99 100644
--- a/components/layout_2020/flexbox/layout.rs
+++ b/components/layout_2020/flexbox/layout.rs
@@ -855,7 +855,7 @@ impl FlexLine<'_> {
flex_context.sides_to_flow_relative(item.padding),
flex_context.sides_to_flow_relative(item.border),
margin,
- Length::zero(),
+ None,
collapsed_margin,
),
item_result.positioning_context,
diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs
index 773c2cdaf7e..0383c23bad7 100644
--- a/components/layout_2020/flow/float.rs
+++ b/components/layout_2020/flow/float.rs
@@ -744,7 +744,7 @@ impl FloatBox {
margin,
// Clearance is handled internally by the float placement logic, so there's no need
// to store it explicitly in the fragment.
- Length::zero(), // clearance
+ None, // clearance
CollapsedBlockMargins::zero(),
)
},
@@ -826,9 +826,9 @@ impl SequentialLayoutState {
/// needs to have.
///
/// https://www.w3.org/TR/2011/REC-CSS2-20110607/visuren.html#flow-control
- pub(crate) fn calculate_clearance(&self, clear_side: ClearSide) -> Length {
+ pub(crate) fn calculate_clearance(&self, clear_side: ClearSide) -> Option<Length> {
if clear_side == ClearSide::None {
- return Length::zero();
+ return None;
}
let hypothetical_block_position = self.current_block_position_including_margins();
@@ -848,7 +848,10 @@ impl SequentialLayoutState {
.max(self.floats.clear_right_position)
.max(hypothetical_block_position),
};
- clear_position - hypothetical_block_position
+ if hypothetical_block_position >= clear_position {
+ return None;
+ }
+ Some(clear_position - hypothetical_block_position)
}
/// Adds a new adjoining margin.
diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs
index 58f8884473e..fdb795ea8b5 100644
--- a/components/layout_2020/flow/inline.rs
+++ b/components/layout_2020/flow/inline.rs
@@ -554,7 +554,7 @@ impl<'box_tree> PartialInlineBoxFragment<'box_tree> {
self.padding.clone(),
self.border.clone(),
self.margin.clone(),
- Length::zero(),
+ None,
CollapsedBlockMargins::zero(),
);
let last_fragment = self.last_box_tree_fragment && !at_line_break;
@@ -619,7 +619,7 @@ fn layout_atomic(
pbm.padding,
pbm.border,
margin,
- Length::zero(),
+ None,
CollapsedBlockMargins::zero(),
)
},
@@ -701,7 +701,7 @@ fn layout_atomic(
pbm.padding,
pbm.border,
margin,
- Length::zero(),
+ None,
CollapsedBlockMargins::zero(),
)
},
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs
index 7050913e98a..422ec11e887 100644
--- a/components/layout_2020/flow/mod.rs
+++ b/components/layout_2020/flow/mod.rs
@@ -183,7 +183,7 @@ impl BlockFormattingContext {
// The content height of a BFC root should include any float participating in that BFC
// (https://drafts.csswg.org/css2/#root-height), we implement this by imagining there is
// an element with `clear: both` after the actual contents.
- let clearance = sequential_layout_state.map_or(Length::zero(), |sequential_layout_state| {
+ let clearance = sequential_layout_state.and_then(|sequential_layout_state| {
sequential_layout_state.calculate_clearance(ClearSide::Both)
});
@@ -191,7 +191,7 @@ impl BlockFormattingContext {
fragments: flow_layout.fragments,
content_block_size: flow_layout.content_block_size +
flow_layout.collapsible_margins_in_children.end.solve() +
- clearance,
+ clearance.unwrap_or_else(Length::zero),
}
}
}
@@ -650,7 +650,7 @@ fn layout_in_flow_non_replaced_block_level(
pbm.border.block_end == Length::zero() &&
block_size == LengthOrAuto::Auto;
- let mut clearance = Length::zero();
+ let mut clearance = None;
let parent_containing_block_position_info;
match sequential_layout_state {
None => parent_containing_block_position_info = None,
@@ -667,7 +667,9 @@ fn layout_in_flow_non_replaced_block_level(
// NB: This will be a no-op if we're collapsing margins with our children since that
// can only happen if we have no block-start padding and border.
sequential_layout_state.advance_block_position(
- pbm.padding.block_start + pbm.border.block_start + clearance,
+ pbm.padding.block_start +
+ pbm.border.block_start +
+ clearance.unwrap_or_else(Length::zero),
);
// We are about to lay out children. Update the offset between the block formatting
@@ -776,7 +778,9 @@ fn layout_in_flow_non_replaced_block_level(
let content_rect = Rect {
start_corner: Vec2 {
- block: pbm.padding.block_start + pbm.border.block_start + clearance,
+ block: pbm.padding.block_start +
+ pbm.border.block_start +
+ clearance.unwrap_or_else(Length::zero),
inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
},
size: Vec2 {
@@ -821,20 +825,25 @@ fn layout_in_flow_replaced_block_level<'a>(
};
let fragments = replaced.make_fragments(style, size.clone());
- let mut clearance = Length::zero();
+ let mut clearance = None;
if let Some(ref mut sequential_layout_state) = sequential_layout_state {
sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_start));
sequential_layout_state.collapse_margins();
clearance = sequential_layout_state.calculate_clearance(ClearSide::from_style(style));
sequential_layout_state.advance_block_position(
- pbm.border.block_sum() + pbm.padding.block_sum() + size.block + clearance,
+ pbm.border.block_sum() +
+ pbm.padding.block_sum() +
+ size.block +
+ clearance.unwrap_or_else(Length::zero),
);
sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_end));
};
let content_rect = Rect {
start_corner: Vec2 {
- block: pbm.padding.block_start + pbm.border.block_start + clearance,
+ block: pbm.padding.block_start +
+ pbm.border.block_start +
+ clearance.unwrap_or_else(Length::zero),
inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
},
size,
@@ -915,8 +924,7 @@ impl PlacementState {
match fragment {
Fragment::Box(fragment) => {
let fragment_block_margins = &fragment.block_margins_collapsed_with_children;
- let fragment_block_size = fragment.clearance +
- fragment.padding.block_sum() +
+ let mut fragment_block_size = fragment.padding.block_sum() +
fragment.border.block_sum() +
fragment.content_rect.size.block;
// We use `last_in_flow_margin_collapses_with_parent_end_margin` to implement
@@ -924,7 +932,8 @@ impl PlacementState {
// > If the top and bottom margins of an element with clearance are adjoining,
// > its margins collapse with the adjoining margins of following siblings but that
// > resulting margin does not collapse with the bottom margin of the parent block.
- if fragment.clearance != Length::zero() {
+ if let Some(clearance) = fragment.clearance {
+ fragment_block_size += clearance;
// Margins can't be adjoining if they are separated by clearance.
// Setting `next_in_flow_margin_collapses_with_parent_start_margin` to false
// prevents collapsing with the start margin of the parent, and will set
@@ -957,7 +966,7 @@ impl PlacementState {
if fragment_block_margins.collapsed_through {
// `fragment_block_size` is typically zero when collapsing through,
// but we still need to consider it in case there is clearance.
- self.current_block_direction_position += fragment.clearance;
+ self.current_block_direction_position += fragment_block_size;
self.current_margin
.adjoin_assign(&fragment_block_margins.end);
} else {
diff --git a/components/layout_2020/fragment_tree/box_fragment.rs b/components/layout_2020/fragment_tree/box_fragment.rs
index 6f697ef23fd..9c06c212d33 100644
--- a/components/layout_2020/fragment_tree/box_fragment.rs
+++ b/components/layout_2020/fragment_tree/box_fragment.rs
@@ -31,7 +31,13 @@ pub(crate) struct BoxFragment {
pub border: Sides<Length>,
pub margin: Sides<Length>,
- pub clearance: Length,
+ /// When the `clear` property is not set to `none`, it may introduce clearance.
+ /// Clearance is some extra spacing that is added above the top margin,
+ /// so that the element doesn't overlap earlier floats in the same BFC.
+ /// The presence of clearance prevents the top margin from collapsing with
+ /// earlier margins or with the bottom margin of the parent block.
+ /// https://drafts.csswg.org/css2/#clearance
+ pub clearance: Option<Length>,
pub block_margins_collapsed_with_children: CollapsedBlockMargins,
@@ -51,7 +57,7 @@ impl BoxFragment {
padding: Sides<Length>,
border: Sides<Length>,
margin: Sides<Length>,
- clearance: Length,
+ clearance: Option<Length>,
block_margins_collapsed_with_children: CollapsedBlockMargins,
) -> BoxFragment {
let position = style.get_box().position;
@@ -85,7 +91,7 @@ impl BoxFragment {
padding: Sides<Length>,
border: Sides<Length>,
margin: Sides<Length>,
- clearance: Length,
+ clearance: Option<Length>,
block_margins_collapsed_with_children: CollapsedBlockMargins,
overconstrained: PhysicalSize<bool>,
) -> BoxFragment {
diff --git a/components/layout_2020/positioned.rs b/components/layout_2020/positioned.rs
index 493c5a1c714..666bd69c8af 100644
--- a/components/layout_2020/positioned.rs
+++ b/components/layout_2020/positioned.rs
@@ -620,7 +620,7 @@ impl HoistedAbsolutelyPositionedBox {
pbm.padding,
pbm.border,
margin,
- Length::zero(),
+ None,
CollapsedBlockMargins::zero(),
physical_overconstrained,
)