diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs index 218833f4634..9253e856ce6 100644 --- a/components/layout_2020/flow/float.rs +++ b/components/layout_2020/flow/float.rs @@ -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 { // 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, ); diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs index 85db59478f1..8b18bc5cdbd 100644 --- a/components/layout_2020/flow/mod.rs +++ b/components/layout_2020/flow/mod.rs @@ -761,6 +761,12 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context( // Account for padding and border. We also might have to readjust the // `bfc_relative_block_position` if it was different from the content size (i.e. was // non-`auto` and/or was affected by min/max block size). + // + // If this adjustment is positive, that means that a block size was specified, but + // the content inside had a smaller block size. If this adjustment is negative, a + // block size was specified, but the content inside overflowed this container in + // the block direction. In that case, the ceiling for floats is effectively raised + // as long as no floats in the overflowing content lowered it. sequential_layout_state.advance_block_position( (block_size - content_block_size) + pbm.padding.block_end + pbm.border.block_end, ); diff --git a/components/layout_2020/tests/floats.rs b/components/layout_2020/tests/floats.rs index 6226c774b44..b5187e7c4ef 100644 --- a/components/layout_2020/tests/floats.rs +++ b/components/layout_2020/tests/floats.rs @@ -467,7 +467,7 @@ impl FloatPlacement { let mut placed_floats = vec![]; for float in floats { let ceiling = Length::new(float.ceiling as f32); - float_context.lower_ceiling(ceiling); + float_context.set_ceiling_from_non_floats(ceiling); float_context.containing_block_info = float.containing_block_info; placed_floats.push(PlacedFloat { origin: float_context.add_float(&float.info), diff --git a/tests/wpt/meta/css/CSS2/margin-padding-clear/margin-collapse-104.xht.ini b/tests/wpt/meta/css/CSS2/margin-padding-clear/margin-collapse-104.xht.ini deleted file mode 100644 index 05240ac99c1..00000000000 --- a/tests/wpt/meta/css/CSS2/margin-padding-clear/margin-collapse-104.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[margin-collapse-104.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/zorder/z-index-020.xht.ini b/tests/wpt/meta/css/CSS2/zorder/z-index-020.xht.ini deleted file mode 100644 index e896f829816..00000000000 --- a/tests/wpt/meta/css/CSS2/zorder/z-index-020.xht.ini +++ /dev/null @@ -1,2 +0,0 @@ -[z-index-020.xht] - expected: FAIL diff --git a/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini b/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini index a4b894bcee4..5334b943293 100644 --- a/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini +++ b/tests/wpt/meta/css/cssom-view/elementsFromPoint-simple.html.ini @@ -1,12 +1,3 @@ [elementsFromPoint-simple.html] - [elementsFromPoint for each corner of a simple div] - expected: FAIL - - [elementsFromPoint for each corner of a div that is between another div and its pseudo-element] - expected: FAIL - - [elementsFromPoint for each corner of a div that has a margin] - expected: FAIL - [elementsFromPoint for each corner of a div with a 3d transform] expected: FAIL