Skip to content

Commit 7412e28

Browse files
authored
Auto merge of servo#29945 - Loirooriol:fix-float-placement-with-future-margins-2, r=mrobinson
Properly position floats when subsequent boxes collapse margins with containing block (2) PR servo#29939 tried to address this but missed various cases. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [X] These changes fix servo#29944 - [X] There are tests for these changes <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
2 parents 57d3460 + a435e02 commit 7412e28

File tree

7 files changed

+37
-57
lines changed

7 files changed

+37
-57
lines changed

components/layout_2020/flow/mod.rs

Lines changed: 35 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ pub(crate) enum BlockLevelBox {
6262
}
6363

6464
impl BlockLevelBox {
65-
fn find_block_margin_collapsing_with_parent_for_floats(
65+
fn find_block_margin_collapsing_with_parent(
6666
&self,
6767
collected_margin: &mut CollapsedMargin,
6868
containing_block_writing_mode: WritingMode,
@@ -80,16 +80,19 @@ impl BlockLevelBox {
8080
let border = style.border_width(containing_block_writing_mode);
8181
let padding = style.padding(containing_block_writing_mode);
8282

83+
// FIXME: This should only return false when 'clear' causes clearance.
8384
if style.get_box().clear != Clear::None {
8485
return false;
8586
}
8687

88+
// FIXME: Percentages should be resolved against the width of the containing block.
8789
let start_margin = margin
8890
.block_start
8991
.percentage_relative_to(CSSPixelLength::zero())
9092
.auto_is(CSSPixelLength::zero);
9193
collected_margin.adjoin_assign(&CollapsedMargin::new(start_margin));
9294

95+
// FIXME: Should resolve padding percentages.
9396
let start_padding_is_zero = padding.block_start.is_zero();
9497
let start_border_is_zero = border.block_start.is_zero();
9598
if !start_border_is_zero || !start_padding_is_zero {
@@ -102,7 +105,7 @@ impl BlockLevelBox {
102105
};
103106
match contents {
104107
BlockContainer::BlockLevelBoxes(boxes) => {
105-
if !Self::find_block_margin_collapsing_with_parent_for_floats_from_slice(
108+
if !Self::find_block_margin_collapsing_with_parent_from_slice(
106109
&boxes,
107110
collected_margin,
108111
style.writing_mode,
@@ -115,14 +118,18 @@ impl BlockLevelBox {
115118

116119
let block_size_zero =
117120
style.content_block_size().is_definitely_zero() || style.content_block_size().is_auto();
118-
if !style.min_block_size().is_definitely_zero() ||
121+
let min_block_size_zero =
122+
style.min_block_size().is_definitely_zero() || style.min_block_size().is_auto();
123+
// FIXME: Should resolve padding percentages.
124+
if !min_block_size_zero ||
119125
!block_size_zero ||
120126
!border.block_end.is_zero() ||
121127
!padding.block_end.is_zero()
122128
{
123129
return false;
124130
}
125131

132+
// FIXME: Percentages should be resolved against the width of the containing block.
126133
let end_margin = margin
127134
.block_end
128135
.percentage_relative_to(CSSPixelLength::zero())
@@ -132,15 +139,15 @@ impl BlockLevelBox {
132139
true
133140
}
134141

135-
fn find_block_margin_collapsing_with_parent_for_floats_from_slice(
142+
fn find_block_margin_collapsing_with_parent_from_slice(
136143
boxes: &[ArcRefCell<BlockLevelBox>],
137144
margin: &mut CollapsedMargin,
138145
writing_mode: WritingMode,
139146
) -> bool {
140147
boxes.iter().all(|block_level_box| {
141148
block_level_box
142149
.borrow()
143-
.find_block_margin_collapsing_with_parent_for_floats(margin, writing_mode)
150+
.find_block_margin_collapsing_with_parent(margin, writing_mode)
144151
})
145152
}
146153
}
@@ -421,8 +428,7 @@ fn layout_block_level_children_sequentially(
421428
// tracks every float encountered so far (again in tree order).
422429
let fragments = child_boxes
423430
.iter()
424-
.enumerate()
425-
.map(|(index, child_box)| {
431+
.map(|child_box| {
426432
let mut child_positioning_context =
427433
PositioningContext::new_for_subtree(collects_for_nearest_positioned_ancestor);
428434
let mut fragment = child_box.borrow_mut().layout(
@@ -432,11 +438,7 @@ fn layout_block_level_children_sequentially(
432438
Some(&mut *sequential_layout_state),
433439
);
434440

435-
let sequential_info = PlacementStateSequentialInfo {
436-
sequential_layout_state,
437-
following_boxes: &child_boxes[index..],
438-
};
439-
placement_state.place_fragment(&mut fragment, Some(sequential_info));
441+
placement_state.place_fragment(&mut fragment, Some(sequential_layout_state));
440442

441443
child_positioning_context.adjust_static_position_of_hoisted_fragments(&fragment);
442444
positioning_context.append(child_positioning_context);
@@ -656,7 +658,22 @@ fn layout_in_flow_non_replaced_block_level(
656658
None => parent_containing_block_position_info = None,
657659
Some(ref mut sequential_layout_state) => {
658660
sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_start));
659-
if !start_margin_can_collapse_with_children {
661+
if start_margin_can_collapse_with_children {
662+
if let NonReplacedContents::SameFormattingContextBlock(
663+
BlockContainer::BlockLevelBoxes(child_boxes),
664+
) = block_level_kind
665+
{
666+
// The block start margin may collapse with content margins,
667+
// compute the resulting one in order to place floats correctly.
668+
let mut future_margins = CollapsedMargin::zero();
669+
BlockLevelBox::find_block_margin_collapsing_with_parent_from_slice(
670+
child_boxes,
671+
&mut future_margins,
672+
WritingMode::empty(),
673+
);
674+
sequential_layout_state.adjoin_assign(&future_margins);
675+
}
676+
} else {
660677
sequential_layout_state.collapse_margins();
661678
}
662679

@@ -876,18 +893,6 @@ fn solve_inline_margins_for_in_flow_block_level(
876893
}
877894
}
878895

879-
/// Information passed to [PlacementState::place_fragment] when operating in sequential
880-
/// mode.
881-
struct PlacementStateSequentialInfo<'a> {
882-
/// The sequential layout state of the current layout.
883-
sequential_layout_state: &'a mut SequentialLayoutState,
884-
885-
/// The boxes that follow the one currently being placed. This is used to try
886-
/// to calculate margins after the current box that will collapse with the
887-
/// parent, if this current box is floating.
888-
following_boxes: &'a [ArcRefCell<BlockLevelBox>],
889-
}
890-
891896
/// State that we maintain when placing blocks.
892897
///
893898
/// In parallel mode, this placement is done after all child blocks are laid out. In
@@ -919,7 +924,7 @@ impl PlacementState {
919924
fn place_fragment(
920925
&mut self,
921926
fragment: &mut Fragment,
922-
sequential_info: Option<PlacementStateSequentialInfo>,
927+
sequential_layout_state: Option<&mut SequentialLayoutState>,
923928
) {
924929
match fragment {
925930
Fragment::Box(fragment) => {
@@ -983,30 +988,13 @@ impl PlacementState {
983988
fragment.borrow_mut().adjust_offsets(offset);
984989
},
985990
Fragment::Float(box_fragment) => {
986-
let info = sequential_info
987-
.expect("Tried to lay out a float with no sequential placement state!");
988-
989-
let mut margins_collapsing_with_parent_containing_block = self.start_margin;
990-
if self.next_in_flow_margin_collapses_with_parent_start_margin {
991-
// If block start margins are still collapsing from the parent, margins of elements
992-
// that follow this float in tree order might collapse, pushing this float down
993-
// and changing the offset of the containing block of the float. We try to look
994-
// ahead to determine which margins from future elements will collapse with the
995-
// parent.
996-
let mut future_margins = CollapsedMargin::zero();
997-
BlockLevelBox::find_block_margin_collapsing_with_parent_for_floats_from_slice(
998-
info.following_boxes,
999-
&mut future_margins,
1000-
WritingMode::empty(),
1001-
);
1002-
margins_collapsing_with_parent_containing_block.adjoin_assign(&future_margins)
1003-
}
1004-
991+
let sequential_layout_state = sequential_layout_state
992+
.expect("Found float fragment without SequentialLayoutState");
1005993
let block_offset_from_containing_block_top =
1006994
self.current_block_direction_position + self.current_margin.solve();
1007-
info.sequential_layout_state.place_float_fragment(
995+
sequential_layout_state.place_float_fragment(
1008996
box_fragment,
1009-
margins_collapsing_with_parent_containing_block,
997+
self.start_margin,
1010998
block_offset_from_containing_block_top,
1011999
);
10121000
},
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[adjoining-float-nested-forced-clearance-002.html]
2+
expected: FAIL

tests/wpt/meta/css/CSS2/floats-clear/clear-on-parent-with-margins-no-clearance.html.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/wpt/meta/css/CSS2/floats-clear/margin-collapse-157.xht.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/wpt/meta/css/CSS2/floats-clear/margin-collapse-clear-015.xht.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/wpt/meta/css/CSS2/margin-padding-clear/margin-collapse-039.xht.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

tests/wpt/meta/css/CSS2/margin-padding-clear/margin-collapse-041.xht.ini

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)