mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Allow raising FloatContext ceiling after processing box with overflow (#30539)
When a box has overflow, any floats placed in that box will lower the float ceiling into the overflow. If no float is placed in the box though, the ceiling should be the block position where the overflow starts. We already know where this is, because we might be passing a negative value for the new block position after processing a box (content_size - actual_size would be negative). This negative value never raises the ceiling though since a maximum is used. In the case that there is overflow, this change allows raising the ceiling, but never passed the lowest float. This necessitates keeping two values for the ceiling: one for floats and one for non-floats. Fixes #30304.
This commit is contained in:
parent
59ea908294
commit
2c341d9e69
6 changed files with 35 additions and 25 deletions
|
@ -307,9 +307,13 @@ pub struct FloatContext {
|
|||
/// This tree is immutable; modification operations return the new tree, which may share nodes
|
||||
/// with previous versions of the tree.
|
||||
pub bands: FloatBandTree,
|
||||
/// The current (logically) vertical position. No new floats may be placed (logically) above
|
||||
/// this line.
|
||||
pub ceiling: Length,
|
||||
/// The block-direction "ceiling" defined by the placement of other floated content of
|
||||
/// this FloatContext. No new floats can be placed at a lower block start than this value.
|
||||
pub ceiling_from_floats: Length,
|
||||
/// The block-direction "ceiling" defined by the placement of non-floated content that
|
||||
/// precedes floated content in the document. Note that this may actually decrease as
|
||||
/// content is laid out in the case that content overflows its container.
|
||||
pub ceiling_from_non_floats: Length,
|
||||
/// Details about the position of the containing block relative to the
|
||||
/// independent block formatting context that contains all of the floats
|
||||
/// this `FloatContext` positions.
|
||||
|
@ -337,7 +341,8 @@ impl FloatContext {
|
|||
});
|
||||
FloatContext {
|
||||
bands,
|
||||
ceiling: Length::zero(),
|
||||
ceiling_from_floats: Length::zero(),
|
||||
ceiling_from_non_floats: Length::zero(),
|
||||
containing_block_info: ContainingBlockPositionInfo::new_with_inline_offsets(
|
||||
Length::zero(),
|
||||
max_inline_size,
|
||||
|
@ -350,8 +355,14 @@ impl FloatContext {
|
|||
/// (Logically) lowers the ceiling to at least `new_ceiling` units.
|
||||
///
|
||||
/// If the ceiling is already logically lower (i.e. larger) than this, does nothing.
|
||||
pub fn lower_ceiling(&mut self, new_ceiling: Length) {
|
||||
self.ceiling = self.ceiling.max(new_ceiling);
|
||||
pub fn set_ceiling_from_non_floats(&mut self, new_ceiling: Length) {
|
||||
self.ceiling_from_non_floats = new_ceiling;
|
||||
}
|
||||
|
||||
/// The "ceiling" used for float placement. This is the minimum block position value
|
||||
/// that should be used for placing any new float.
|
||||
fn ceiling(&mut self) -> Length {
|
||||
self.ceiling_from_floats.max(self.ceiling_from_non_floats)
|
||||
}
|
||||
|
||||
/// Determines where a float with the given placement would go, but leaves the float context
|
||||
|
@ -411,7 +422,8 @@ impl FloatContext {
|
|||
/// Places a new float and adds it to the list. Returns the start corner of its margin box.
|
||||
pub fn add_float(&mut self, new_float: &PlacementInfo) -> LogicalVec2<Length> {
|
||||
// Place the float.
|
||||
let new_float_origin = self.place_object(&new_float, self.ceiling);
|
||||
let ceiling = self.ceiling();
|
||||
let new_float_origin = self.place_object(&new_float, ceiling);
|
||||
let new_float_extent = match new_float.side {
|
||||
FloatSide::Left => new_float_origin.inline + new_float.size.inline,
|
||||
FloatSide::Right => new_float_origin.inline,
|
||||
|
@ -464,7 +476,8 @@ impl FloatContext {
|
|||
|
||||
// CSS 2.1 § 9.5.1 rule 6: The outer top of a floating box may not be higher than the outer
|
||||
// top of any block or floated box generated by an element earlier in the source document.
|
||||
self.ceiling = self.ceiling.max(new_float_rect.start_corner.block);
|
||||
self.ceiling_from_floats
|
||||
.max_assign(new_float_rect.start_corner.block);
|
||||
new_float_rect.start_corner
|
||||
}
|
||||
}
|
||||
|
@ -994,12 +1007,16 @@ impl SequentialLayoutState {
|
|||
}
|
||||
}
|
||||
|
||||
/// Moves the current block position (logically) down by `block_distance`.
|
||||
/// Moves the current block position (logically) down by `block_distance`. This may be
|
||||
/// a negative advancement in the case that that block content overflows its
|
||||
/// container, when the container is adjusting the block position of the
|
||||
/// [`SequentialLayoutState`] after processing its overflowing content.
|
||||
///
|
||||
/// Floats may not be placed higher than the current block position.
|
||||
pub(crate) fn advance_block_position(&mut self, block_distance: Length) {
|
||||
self.bfc_relative_block_position += block_distance;
|
||||
self.floats.lower_ceiling(self.bfc_relative_block_position);
|
||||
self.floats
|
||||
.set_ceiling_from_non_floats(self.bfc_relative_block_position);
|
||||
}
|
||||
|
||||
/// Replace the entire [ContainingBlockPositionInfo] data structure stored
|
||||
|
@ -1161,7 +1178,7 @@ impl SequentialLayoutState {
|
|||
.adjoin(&margins_collapsing_with_parent_containing_block)
|
||||
.solve();
|
||||
|
||||
self.floats.lower_ceiling(
|
||||
self.floats.set_ceiling_from_non_floats(
|
||||
block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top,
|
||||
);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue