mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
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>
This commit is contained in:
parent
0ffa5fa277
commit
acf0074f8a
2 changed files with 46 additions and 86 deletions
|
@ -1103,11 +1103,8 @@ impl SequentialLayoutState {
|
||||||
let placement_rect = placement.place();
|
let placement_rect = placement.place();
|
||||||
let position = &placement_rect.start_corner;
|
let position = &placement_rect.start_corner;
|
||||||
let has_clearance = clear_position.is_some() || position.block > ceiling;
|
let has_clearance = clear_position.is_some() || position.block > ceiling;
|
||||||
let clearance = if has_clearance {
|
let clearance = has_clearance
|
||||||
Some(position.block - self.position_with_zero_clearance(block_start_margin))
|
.then(|| position.block - self.position_with_zero_clearance(block_start_margin));
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
(clearance, placement_rect)
|
(clearance, placement_rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1121,9 +1121,6 @@ impl IndependentNonReplacedContents {
|
||||||
.clamp_between_extremums(content_min_box_size.block, content_max_box_size.block)
|
.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) =
|
let (margin_block_start, margin_block_end) =
|
||||||
solve_block_margins_for_in_flow_block_level(&pbm);
|
solve_block_margins_for_in_flow_block_level(&pbm);
|
||||||
let collapsed_margin_block_start = CollapsedMargin::new(margin_block_start);
|
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
|
// 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
|
// 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."
|
// element next to the float or by how much said element may become narrower."
|
||||||
let clearance;
|
|
||||||
let mut content_size;
|
let mut content_size;
|
||||||
let mut layout;
|
let mut layout;
|
||||||
|
let mut placement_rect;
|
||||||
let style = &base.style;
|
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 {
|
if let AuOrAuto::LengthPercentage(ref inline_size) = content_box_size.inline {
|
||||||
let inline_size = inline_size
|
let inline_size = inline_size
|
||||||
.clamp_between_extremums(content_min_box_size.inline, content_max_box_size.inline);
|
.clamp_between_extremums(content_min_box_size.inline, content_max_box_size.inline);
|
||||||
|
@ -1175,30 +1184,14 @@ impl IndependentNonReplacedContents {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
(
|
let mut placement = PlacementAmongFloats::new(
|
||||||
clearance,
|
&sequential_layout_state.floats,
|
||||||
(margin_inline_start, margin_inline_end),
|
ceiling,
|
||||||
effective_margin_inline_start,
|
|
||||||
) = solve_clearance_and_inline_margins_avoiding_floats(
|
|
||||||
sequential_layout_state,
|
|
||||||
&collapsed_margin_block_start,
|
|
||||||
containing_block,
|
|
||||||
&pbm,
|
|
||||||
content_size + pbm.padding_border_sums,
|
content_size + pbm.padding_border_sums,
|
||||||
style,
|
&pbm,
|
||||||
);
|
);
|
||||||
|
placement_rect = placement.place();
|
||||||
} else {
|
} 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.
|
// Create a PlacementAmongFloats using the minimum size in all dimensions as the object size.
|
||||||
let minimum_size_of_block = LogicalVec2 {
|
let minimum_size_of_block = LogicalVec2 {
|
||||||
inline: content_min_box_size.inline,
|
inline: content_min_box_size.inline,
|
||||||
|
@ -1210,7 +1203,6 @@ impl IndependentNonReplacedContents {
|
||||||
minimum_size_of_block,
|
minimum_size_of_block,
|
||||||
&pbm,
|
&pbm,
|
||||||
);
|
);
|
||||||
let mut placement_rect;
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
// First try to place the block using the minimum size as the object size.
|
// First try to place the block using the minimum size as the object size.
|
||||||
|
@ -1284,31 +1276,26 @@ impl IndependentNonReplacedContents {
|
||||||
// attempt.
|
// attempt.
|
||||||
positioning_context.truncate(&positioning_context_length);
|
positioning_context.truncate(&positioning_context_length);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only set clearance if we would have cleared or the placement among floats moves
|
// 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
|
// the block further in the block direction. These two situations are the ones that
|
||||||
// prevent margin collapse.
|
// prevent margin collapse.
|
||||||
clearance = if clear_position.is_some() || placement_rect.start_corner.block > ceiling {
|
let has_clearance = clear_position.is_some() || placement_rect.start_corner.block > ceiling;
|
||||||
Some(
|
let clearance = has_clearance.then(|| {
|
||||||
placement_rect.start_corner.block -
|
placement_rect.start_corner.block -
|
||||||
sequential_layout_state
|
sequential_layout_state
|
||||||
.position_with_zero_clearance(&collapsed_margin_block_start),
|
.position_with_zero_clearance(&collapsed_margin_block_start)
|
||||||
)
|
});
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
(
|
let ((margin_inline_start, margin_inline_end), effective_margin_inline_start) =
|
||||||
(margin_inline_start, margin_inline_end),
|
solve_inline_margins_avoiding_floats(
|
||||||
effective_margin_inline_start,
|
|
||||||
) = solve_inline_margins_avoiding_floats(
|
|
||||||
sequential_layout_state,
|
sequential_layout_state,
|
||||||
containing_block,
|
containing_block,
|
||||||
&pbm,
|
&pbm,
|
||||||
content_size.inline + pbm.padding_border_sums.inline,
|
content_size.inline + pbm.padding_border_sums.inline,
|
||||||
placement_rect,
|
placement_rect,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
let margin = LogicalSides {
|
let margin = LogicalSides {
|
||||||
inline_start: margin_inline_start,
|
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."
|
// 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 collapsed_margin_block_start = CollapsedMargin::new(margin_block_start);
|
||||||
let size = content_size + pbm.padding_border_sums;
|
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),
|
(margin_inline_start, margin_inline_end),
|
||||||
effective_margin_inline_start,
|
effective_margin_inline_start,
|
||||||
) = solve_clearance_and_inline_margins_avoiding_floats(
|
) = solve_inline_margins_avoiding_floats(
|
||||||
sequential_layout_state,
|
sequential_layout_state,
|
||||||
&collapsed_margin_block_start,
|
|
||||||
containing_block,
|
containing_block,
|
||||||
pbm,
|
pbm,
|
||||||
size,
|
size.inline,
|
||||||
&base.style,
|
placement_rect,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Clearance prevents margin collapse between this block and previous ones,
|
// 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)
|
(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.
|
/// State that we maintain when placing blocks.
|
||||||
///
|
///
|
||||||
/// In parallel mode, this placement is done after all child blocks are laid out. In
|
/// In parallel mode, this placement is done after all child blocks are laid out. In
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue