diff options
author | Oriol Brufau <obrufau@igalia.com> | 2024-12-12 13:53:44 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-12 12:53:44 +0000 |
commit | acf0074f8af540eb1f9c6513970753be0f6f6b49 (patch) | |
tree | 0ac9880e48f4ebbfa6eb89c6e571a3dbe037bc56 /components | |
parent | 0ffa5fa27792a53847e3d07320e9768de9f44d60 (diff) | |
download | servo-acf0074f8af540eb1f9c6513970753be0f6f6b49.tar.gz servo-acf0074f8af540eb1f9c6513970753be0f6f6b49.zip |
Share more code for non-replaced float-avoiding blocks (#34585)
Block-level elements that establish an independent formatting context
(or are replaced) need to avoid overlapping floats.
In the non-replaced case, we have two different subcases, depending on
whether the inline size of the element is known. This patch makes them
share more logic.
Then `solve_clearance_and_inline_margins_avoiding_floats()` would only
be used in the replaced case, so it's removed, inlining its logic.
Signed-off-by: Oriol Brufau <obrufau@igalia.com>
Diffstat (limited to 'components')
-rw-r--r-- | components/layout_2020/flow/float.rs | 7 | ||||
-rw-r--r-- | components/layout_2020/flow/mod.rs | 125 |
2 files changed, 46 insertions, 86 deletions
diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index d84b3f3393b..d4ad8ac78c1 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -1103,11 +1103,8 @@ impl SequentialLayoutState { let placement_rect = placement.place(); let position = &placement_rect.start_corner; let has_clearance = clear_position.is_some() || position.block > ceiling; - let clearance = if has_clearance { - Some(position.block - self.position_with_zero_clearance(block_start_margin)) - } else { - None - }; + let clearance = has_clearance + .then(|| position.block - self.position_with_zero_clearance(block_start_margin)); (clearance, placement_rect) } diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index d8f7a5f570c..aa85857a350 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -1121,9 +1121,6 @@ impl IndependentNonReplacedContents { .clamp_between_extremums(content_min_box_size.block, content_max_box_size.block) }); - let margin_inline_start; - let margin_inline_end; - let effective_margin_inline_start; let (margin_block_start, margin_block_end) = solve_block_margins_for_in_flow_block_level(&pbm); let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start); @@ -1138,10 +1135,22 @@ impl IndependentNonReplacedContents { // sufficient space. They may even make the border box of said element narrower // than defined by section 10.3.3. CSS 2 does not define when a UA may put said // element next to the float or by how much said element may become narrower." - let clearance; let mut content_size; let mut layout; + let mut placement_rect; let style = &base.style; + + // First compute the clear position required by the 'clear' property. + // The code below may then add extra clearance when the element can't fit + // next to floats not covered by 'clear'. + let clear_position = sequential_layout_state.calculate_clear_position( + Clear::from_style_and_container_writing_mode(style, containing_block_writing_mode), + &collapsed_margin_block_start, + ); + let ceiling = clear_position.unwrap_or_else(|| { + sequential_layout_state.position_without_clearance(&collapsed_margin_block_start) + }); + if let AuOrAuto::LengthPercentage(ref inline_size) = content_box_size.inline { let inline_size = inline_size .clamp_between_extremums(content_min_box_size.inline, content_max_box_size.inline); @@ -1175,30 +1184,14 @@ impl IndependentNonReplacedContents { }; } - ( - clearance, - (margin_inline_start, margin_inline_end), - effective_margin_inline_start, - ) = solve_clearance_and_inline_margins_avoiding_floats( - sequential_layout_state, - &collapsed_margin_block_start, - containing_block, - &pbm, + let mut placement = PlacementAmongFloats::new( + &sequential_layout_state.floats, + ceiling, content_size + pbm.padding_border_sums, - style, + &pbm, ); + placement_rect = placement.place(); } else { - // First compute the clear position required by the 'clear' property. - // The code below may then add extra clearance when the element can't fit - // next to floats not covered by 'clear'. - let clear_position = sequential_layout_state.calculate_clear_position( - Clear::from_style_and_container_writing_mode(style, containing_block_writing_mode), - &collapsed_margin_block_start, - ); - let ceiling = clear_position.unwrap_or_else(|| { - sequential_layout_state.position_without_clearance(&collapsed_margin_block_start) - }); - // Create a PlacementAmongFloats using the minimum size in all dimensions as the object size. let minimum_size_of_block = LogicalVec2 { inline: content_min_box_size.inline, @@ -1210,7 +1203,6 @@ impl IndependentNonReplacedContents { minimum_size_of_block, &pbm, ); - let mut placement_rect; loop { // First try to place the block using the minimum size as the object size. @@ -1284,31 +1276,26 @@ impl IndependentNonReplacedContents { // attempt. positioning_context.truncate(&positioning_context_length); } + } - // Only set clearance if we would have cleared or the placement among floats moves - // the block further in the block direction. These two situations are the ones that - // prevent margin collapse. - clearance = if clear_position.is_some() || placement_rect.start_corner.block > ceiling { - Some( - placement_rect.start_corner.block - - sequential_layout_state - .position_with_zero_clearance(&collapsed_margin_block_start), - ) - } else { - None - }; + // Only set clearance if we would have cleared or the placement among floats moves + // the block further in the block direction. These two situations are the ones that + // prevent margin collapse. + let has_clearance = clear_position.is_some() || placement_rect.start_corner.block > ceiling; + let clearance = has_clearance.then(|| { + placement_rect.start_corner.block - + sequential_layout_state + .position_with_zero_clearance(&collapsed_margin_block_start) + }); - ( - (margin_inline_start, margin_inline_end), - effective_margin_inline_start, - ) = solve_inline_margins_avoiding_floats( + let ((margin_inline_start, margin_inline_end), effective_margin_inline_start) = + solve_inline_margins_avoiding_floats( sequential_layout_state, containing_block, &pbm, content_size.inline + pbm.padding_border_sums.inline, placement_rect, ); - } let margin = LogicalSides { inline_start: margin_inline_start, @@ -1409,17 +1396,26 @@ impl ReplacedContents { // element next to the float or by how much said element may become narrower." let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start); let size = content_size + pbm.padding_border_sums; + let placement_rect; + (clearance, placement_rect) = sequential_layout_state + .calculate_clearance_and_inline_adjustment( + Clear::from_style_and_container_writing_mode( + &base.style, + containing_block.style.writing_mode, + ), + &collapsed_margin_block_start, + pbm, + size, + ); ( - clearance, (margin_inline_start, margin_inline_end), effective_margin_inline_start, - ) = solve_clearance_and_inline_margins_avoiding_floats( + ) = solve_inline_margins_avoiding_floats( sequential_layout_state, - &collapsed_margin_block_start, containing_block, pbm, - size, - &base.style, + size.inline, + placement_rect, ); // Clearance prevents margin collapse between this block and previous ones, @@ -1738,39 +1734,6 @@ fn solve_inline_margins_avoiding_floats( (inline_margins, effective_margin_inline_start) } -/// A block-level element that establishes an independent formatting context (or is replaced) -/// must not overlap floats. -/// This can be achieved by adding clearance (to adjust the position in the block axis) -/// and/or modifying the margins in the inline axis. -/// This function takes care of calculating them. -fn solve_clearance_and_inline_margins_avoiding_floats( - sequential_layout_state: &SequentialLayoutState, - block_start_margin: &CollapsedMargin, - containing_block: &ContainingBlock, - pbm: &PaddingBorderMargin, - size: LogicalVec2<Au>, - style: &Arc<ComputedValues>, -) -> (Option<Au>, (Au, Au), Au) { - let (clearance, placement_rect) = sequential_layout_state - .calculate_clearance_and_inline_adjustment( - Clear::from_style_and_container_writing_mode( - style, - containing_block.style.writing_mode, - ), - block_start_margin, - pbm, - size, - ); - let (inline_margins, effective_margin_inline_start) = solve_inline_margins_avoiding_floats( - sequential_layout_state, - containing_block, - pbm, - size.inline, - placement_rect, - ); - (clearance, inline_margins, effective_margin_inline_start) -} - /// State that we maintain when placing blocks. /// /// In parallel mode, this placement is done after all child blocks are laid out. In |