aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2023-07-18 20:43:45 +0200
committerGitHub <noreply@github.com>2023-07-18 18:43:45 +0000
commitae3f33b9d03393eb25503fa3b30f05957119f9a7 (patch)
treef322860fff2605bb11143e52851bd04fd50c92c4
parent64adc98e64100647bc0245b48399a947520c59fc (diff)
downloadservo-ae3f33b9d03393eb25503fa3b30f05957119f9a7.tar.gz
servo-ae3f33b9d03393eb25503fa3b30f05957119f9a7.zip
Place replaced and non-auto inline size independent FCs next to floats (#29977)
* Place replaced and non-auto inline size independent FCs next to floats The CSS2 specification says that replaced content and independent formatting contexts should be placed next to floats. This change adds support for that, but punts on support for independent formatting contexts that have an auto inline size. With an auto inline size, we which requires a much more complex layout algorithm. Co-authored-by: Oriol Brufau <obrufau@igalia.com> * Fix issue with where last band was taken into account for inline size * adjustment_from_floats should prevent margin collapse * Properly handle elements with 0 height --------- Co-authored-by: Oriol Brufau <obrufau@igalia.com>
-rw-r--r--components/layout_2020/flow/float.rs133
-rw-r--r--components/layout_2020/flow/mod.rs387
-rw-r--r--tests/wpt/meta/css/CSS2/floats-clear/floats-039.xht.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-001.xht.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-002.xht.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats/new-fc-beside-adjoining-float-2.html.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats/new-fc-beside-float-with-margin.html.ini2
-rw-r--r--tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-001.html.ini3
-rw-r--r--tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-002.html.ini3
-rw-r--r--tests/wpt/meta/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini2
-rw-r--r--tests/wpt/meta/css/css-flexbox/flexbox-paint-ordering-001.xhtml.ini2
13 files changed, 417 insertions, 127 deletions
diff --git a/components/layout_2020/flow/float.rs b/components/layout_2020/flow/float.rs
index 031ff1883e4..841fc2e19b7 100644
--- a/components/layout_2020/flow/float.rs
+++ b/components/layout_2020/flow/float.rs
@@ -17,6 +17,7 @@ use crate::style_ext::{ComputedValuesExt, DisplayInside};
use crate::ContainingBlock;
use euclid::num::Zero;
use servo_arc::Arc;
+use std::collections::VecDeque;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::ops::Range;
use std::{f32, mem};
@@ -70,6 +71,113 @@ impl ContainingBlockPositionInfo {
}
}
+/// This data strucure is used to try to place non-floating content among float content.
+/// This is used primarily to place replaced content and independent formatting contexts
+/// next to floats, as the specifcation dictates.
+pub(crate) struct PlacementAmongFloats<'a> {
+ /// The [FloatContext] to use for this placement.
+ float_context: &'a FloatContext,
+ /// The current bands we are considering for this placement.
+ current_bands: VecDeque<FloatBand>,
+ /// The next band, needed to know the height of the last band in current_bands.
+ next_band: FloatBand,
+ /// The size of the object to place.
+ object_size: Vec2<Length>,
+ /// The minimum position in the block direction for the placement. Objects should not
+ /// be placed before this point.
+ ceiling: Length,
+}
+
+impl<'a> PlacementAmongFloats<'a> {
+ pub(crate) fn new(
+ float_context: &'a FloatContext,
+ ceiling: Length,
+ object_size: Vec2<Length>,
+ ) -> Self {
+ assert!(!ceiling.px().is_infinite());
+ let current_band = float_context.bands.find(ceiling).unwrap();
+ let current_bands = VecDeque::from([current_band]);
+ let next_band = float_context.bands.find_next(current_band.top).unwrap();
+ PlacementAmongFloats {
+ float_context,
+ current_bands,
+ next_band,
+ object_size,
+ ceiling,
+ }
+ }
+
+ fn top_of_placement_for_current_bands(&self) -> Length {
+ self.ceiling.max(self.current_bands.front().unwrap().top)
+ }
+
+ fn current_bands_height(&self) -> Length {
+ assert!(!self.current_bands.is_empty());
+ self.next_band.top - self.top_of_placement_for_current_bands()
+ }
+
+ fn accumulate_enough_bands_for_block_size(&mut self) {
+ while self.current_bands_height() < self.object_size.block {
+ assert!(!self.next_band.top.px().is_infinite());
+ self.current_bands.push_back(self.next_band);
+ self.next_band = self
+ .float_context
+ .bands
+ .find_next(self.next_band.top)
+ .unwrap();
+ }
+ }
+
+ fn calculate_viable_inline_space(&self) -> (Length, Length) {
+ let mut max_inline_start = self.float_context.containing_block_info.inline_start;
+ let mut min_inline_end = self.float_context.containing_block_info.inline_end;
+ assert!(!self.current_bands.is_empty());
+
+ for band in self.current_bands.iter() {
+ if let Some(left) = band.left {
+ max_inline_start = max_inline_start.max(left);
+ }
+ if let Some(right) = band.right {
+ min_inline_end = min_inline_end.min(right);
+ }
+ }
+ return (max_inline_start, min_inline_end);
+ }
+
+ pub(crate) fn try_place_once(&mut self) -> Option<Vec2<Length>> {
+ self.accumulate_enough_bands_for_block_size();
+ let (inline_start, inline_end) = self.calculate_viable_inline_space();
+ if inline_end - inline_start >= self.object_size.inline {
+ return Some(Vec2 {
+ inline: inline_start,
+ block: self.top_of_placement_for_current_bands(),
+ });
+ }
+
+ self.current_bands.pop_front();
+ None
+ }
+
+ /// Run the placement algorithm for this [PlacementAmongFloats].
+ pub(crate) fn place(&mut self) -> Vec2<Length> {
+ while self.current_bands.len() > 0 {
+ if let Some(result) = self.try_place_once() {
+ return result;
+ }
+ }
+
+ // We could not fit the object in among the floats, so we place it as if it
+ // cleared all floats.
+ return Vec2 {
+ inline: self.float_context.containing_block_info.inline_start,
+ block: self
+ .ceiling
+ .max(self.float_context.clear_left_position)
+ .max(self.float_context.clear_right_position),
+ };
+ }
+}
+
/// Data kept during layout about the floats in a given block formatting context.
///
/// This is a persistent data structure. Each float has its own private copy of the float context,
@@ -133,13 +241,12 @@ impl FloatContext {
///
/// This should be used for placing inline elements and block formatting contexts so that they
/// don't collide with floats.
- pub fn place_object(&self, object: &PlacementInfo) -> Vec2<Length> {
+ pub(crate) fn place_object(&self, object: &PlacementInfo, ceiling: Length) -> Vec2<Length> {
let ceiling = match object.clear {
- ClearSide::None => self.ceiling,
- ClearSide::Left => self.ceiling.max(self.clear_left_position),
- ClearSide::Right => self.ceiling.max(self.clear_right_position),
- ClearSide::Both => self
- .ceiling
+ ClearSide::None => ceiling,
+ ClearSide::Left => ceiling.max(self.clear_left_position),
+ ClearSide::Right => ceiling.max(self.clear_right_position),
+ ClearSide::Both => ceiling
.max(self.clear_left_position)
.max(self.clear_right_position),
};
@@ -163,7 +270,7 @@ impl FloatContext {
};
Vec2 {
inline: left_object_edge,
- block: first_band.top.max(self.ceiling),
+ block: first_band.top.max(ceiling),
}
},
FloatSide::Right => {
@@ -173,16 +280,16 @@ impl FloatContext {
};
Vec2 {
inline: right_object_edge - object.size.inline,
- block: first_band.top.max(self.ceiling),
+ block: first_band.top.max(ceiling),
}
},
}
}
/// 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) -> Vec2<Length> {
+ pub(crate) fn add_float(&mut self, new_float: &PlacementInfo) -> Vec2<Length> {
// Place the float.
- let new_float_origin = self.place_object(&new_float);
+ let new_float_origin = self.place_object(&new_float, self.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,
@@ -242,7 +349,7 @@ impl FloatContext {
/// Information needed to place an object so that it doesn't collide with existing floats.
#[derive(Clone, Debug)]
-pub struct PlacementInfo {
+pub(crate) struct PlacementInfo {
/// The *margin* box size of the object.
pub size: Vec2<Length>,
/// Whether the object is (logically) aligned to the left or right.
@@ -909,7 +1016,7 @@ impl SequentialLayoutState {
&mut self,
box_fragment: &mut BoxFragment,
margins_collapsing_with_parent_containing_block: CollapsedMargin,
- block_offset_from_containining_block_top: CSSPixelLength,
+ block_offset_from_containing_block_top: Length,
) {
let block_start_of_containing_block_in_bfc = self.floats.containing_block_info.block_start +
self.floats
@@ -919,7 +1026,7 @@ impl SequentialLayoutState {
.solve();
self.floats.lower_ceiling(
- block_start_of_containing_block_in_bfc + block_offset_from_containining_block_top,
+ block_start_of_containing_block_in_bfc + block_offset_from_containing_block_top,
);
let pbm_sums = &(&box_fragment.padding + &box_fragment.border) + &box_fragment.margin;
diff --git a/components/layout_2020/flow/mod.rs b/components/layout_2020/flow/mod.rs
index 00e6670343d..ca28f4318ff 100644
--- a/components/layout_2020/flow/mod.rs
+++ b/components/layout_2020/flow/mod.rs
@@ -4,6 +4,7 @@
//! Flow layout, also known as block-and-inline layout.
+use self::float::PlacementAmongFloats;
use crate::cell::ArcRefCell;
use crate::context::LayoutContext;
use crate::flow::float::{ClearSide, ContainingBlockPositionInfo, FloatBox, SequentialLayoutState};
@@ -521,13 +522,10 @@ impl BlockLevelBox {
containing_block,
&non_replaced.style,
|positioning_context| {
- layout_in_flow_non_replaced_block_level_independent_formatting_context(
+ non_replaced.layout_in_flow_block_level(
layout_context,
positioning_context,
containing_block,
- non_replaced.base_fragment_info,
- &non_replaced.style,
- non_replaced,
sequential_layout_state,
)
},
@@ -766,82 +764,230 @@ fn layout_in_flow_non_replaced_block_level_same_formatting_context(
)
}
-/// Lay out a normal flow non-replaced block that establishes and independent formatting
-/// context in its containing formatting context.
-///
-/// - https://drafts.csswg.org/css2/visudet.html#blockwidth
-/// - https://drafts.csswg.org/css2/visudet.html#normal-block
-fn layout_in_flow_non_replaced_block_level_independent_formatting_context(
- layout_context: &LayoutContext,
- positioning_context: &mut PositioningContext,
- containing_block: &ContainingBlock,
- base_fragment_info: BaseFragmentInfo,
- style: &Arc<ComputedValues>,
- independent_formatting_context: &NonReplacedFormattingContext,
- mut sequential_layout_state: Option<&mut SequentialLayoutState>,
-) -> BoxFragment {
- let ContainingBlockPaddingBorderAndMargin {
- containing_block: containing_block_for_children,
- pbm,
- min_box_size,
- max_box_size,
- margin,
- } = solve_containing_block_padding_border_and_margin_for_in_flow_box(containing_block, style);
+impl NonReplacedFormattingContext {
+ /// Lay out a normal in flow non-replaced block that establishes an independent
+ /// formatting context in its containing formatting context.
+ ///
+ /// - https://drafts.csswg.org/css2/visudet.html#blockwidth
+ /// - https://drafts.csswg.org/css2/visudet.html#normal-block
+ fn layout_in_flow_block_level(
+ &self,
+ layout_context: &LayoutContext,
+ positioning_context: &mut PositioningContext,
+ containing_block: &ContainingBlock,
+ sequential_layout_state: Option<&mut SequentialLayoutState>,
+ ) -> BoxFragment {
+ let ContainingBlockPaddingBorderAndMargin {
+ containing_block: containing_block_for_children,
+ pbm,
+ min_box_size,
+ max_box_size,
+ margin,
+ } = solve_containing_block_padding_border_and_margin_for_in_flow_box(
+ containing_block,
+ &self.style,
+ );
- let layout = independent_formatting_context.layout(
- layout_context,
- positioning_context,
- &containing_block_for_children,
- );
+ if let Some(sequential_layout_state) = sequential_layout_state {
+ return self.layout_in_flow_block_level_sequentially(
+ layout_context,
+ positioning_context,
+ containing_block,
+ sequential_layout_state,
+ );
+ }
- let content_block_size = layout.content_block_size;
- let block_size = containing_block_for_children.block_size.auto_is(|| {
- content_block_size.clamp_between_extremums(min_box_size.block, max_box_size.block)
- });
+ let layout = self.layout(
+ layout_context,
+ positioning_context,
+ &containing_block_for_children,
+ );
- let mut clearance = None;
- if let Some(ref mut sequential_layout_state) = sequential_layout_state {
- clearance = sequential_layout_state.calculate_clearance_and_adjoin_margin(
- style,
- &CollapsedMargin::new(margin.block_start),
+ let block_size = containing_block_for_children.block_size.auto_is(|| {
+ layout
+ .content_block_size
+ .clamp_between_extremums(min_box_size.block, max_box_size.block)
+ });
+
+ let content_rect = Rect {
+ start_corner: Vec2 {
+ block: pbm.padding.block_start + pbm.border.block_start,
+ inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
+ },
+ size: Vec2 {
+ block: block_size,
+ inline: containing_block_for_children.inline_size,
+ },
+ };
+
+ let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
+ BoxFragment::new(
+ self.base_fragment_info,
+ self.style.clone(),
+ layout.fragments,
+ content_rect,
+ pbm.padding,
+ pbm.border,
+ margin,
+ None, /* clearance */
+ block_margins_collapsed_with_children,
+ )
+ }
+
+ /// Lay out a normal in flow non-replaced block that establishes an independent
+ /// formatting context in its containing formatting context but handling sequential
+ /// layout concerns, such clearing and placing the content next to floats.
+ fn layout_in_flow_block_level_sequentially(
+ &self,
+ layout_context: &LayoutContext<'_>,
+ positioning_context: &mut PositioningContext,
+ containing_block: &ContainingBlock<'_>,
+ sequential_layout_state: &mut SequentialLayoutState,
+ ) -> BoxFragment {
+ let ContainingBlockPaddingBorderAndMargin {
+ containing_block: containing_block_for_children,
+ pbm,
+ min_box_size,
+ max_box_size,
+ margin,
+ } = solve_containing_block_padding_border_and_margin_for_in_flow_box(
+ containing_block,
+ &self.style,
);
- sequential_layout_state.collapse_margins();
- // 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).
- sequential_layout_state.advance_block_position(
- (block_size - content_block_size) + pbm.padding.block_sum() + pbm.border.block_sum(),
+ let block_start_margin = CollapsedMargin::new(margin.block_start);
+ let clearance = sequential_layout_state
+ .calculate_clearance(ClearSide::from_style(&self.style), &block_start_margin);
+
+ let layout = self.layout(
+ layout_context,
+ positioning_context,
+ &containing_block_for_children,
);
+ let block_size = containing_block_for_children.block_size.auto_is(|| {
+ layout
+ .content_block_size
+ .clamp_between_extremums(min_box_size.block, max_box_size.block)
+ });
- sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_end));
- }
+ // From https://drafts.csswg.org/css2/#floats:
+ // "The border box of a table, a block-level replaced element, or an element in
+ // the normal flow that establishes a new block formatting context (such as an
+ // element with overflow other than visible) must not overlap the margin box of
+ // any floats in the same block formatting context as the element itself. If
+ // necessary, implementations should clear the said element by placing it below
+ // any preceding floats, but may place it adjacent to such floats if there is
+ // 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 mut adjustment_from_floats = Vec2::zero();
+ adjustment_from_floats.block = clearance.unwrap_or_else(Length::zero);
+
+ let inline_size_is_auto = self
+ .style
+ .box_size(containing_block.style.writing_mode)
+ .inline
+ .is_auto();
+ if !inline_size_is_auto {
+ // We calculate a hypothetical value for `bfc_relative_block_position`,
+ // assuming that there was no adjustment from floats. The real value will
+ // depend on whether or not there was adjustment.
+ let hypothetical_bfc_relative_block_position = if clearance.is_some() {
+ sequential_layout_state.bfc_relative_block_position +
+ sequential_layout_state.current_margin.solve() +
+ block_start_margin.solve()
+ } else {
+ sequential_layout_state.bfc_relative_block_position +
+ sequential_layout_state
+ .current_margin
+ .adjoin(&block_start_margin)
+ .solve()
+ };
- let content_rect = Rect {
- start_corner: Vec2 {
- block: pbm.padding.block_start +
- pbm.border.block_start +
- clearance.unwrap_or_else(Length::zero),
- inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
- },
- size: Vec2 {
- block: block_size,
- inline: containing_block_for_children.inline_size,
- },
- };
+ let size = &Vec2 {
+ inline: containing_block_for_children.inline_size,
+ block: block_size,
+ } + &pbm.padding_border_sums;
+ let placement = PlacementAmongFloats::new(
+ &sequential_layout_state.floats,
+ hypothetical_bfc_relative_block_position + clearance.unwrap_or_else(Length::zero),
+ size.clone(),
+ )
+ .place();
+
+ // This placement is in the coordinates of the float-containing block formatting
+ // context, but we need to calculate an offset to use for placing this replaced
+ // element.
+ adjustment_from_floats = &placement -
+ &Vec2 {
+ inline: sequential_layout_state
+ .floats
+ .containing_block_info
+ .inline_start,
+ block: hypothetical_bfc_relative_block_position,
+ };
+ }
- let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
- BoxFragment::new(
- base_fragment_info,
- style.clone(),
- layout.fragments,
- content_rect,
- pbm.padding,
- pbm.border,
- margin,
- clearance,
- block_margins_collapsed_with_children,
- )
+ // Clearance and any adjustment from float should prevent margin collapse, so it's
+ // important to make sure that it is non-None even when it is zero. Yet, when we
+ // didn't have clearance or any adjustment from placing next to floats, we want the
+ // value of clearance on the Fragment to be None, so margin collapse still works
+ // properly.
+ let effective_clearance = if clearance.is_some() || !adjustment_from_floats.block.is_zero()
+ {
+ Some(adjustment_from_floats.block)
+ } else {
+ None
+ };
+
+ // If there was effective clearance, it prevent margins collapse between this
+ // block and previous ones, so in that case collapse margins before adjoining
+ // them below.
+ if effective_clearance.is_some() {
+ sequential_layout_state.collapse_margins();
+ }
+ sequential_layout_state.adjoin_assign(&block_start_margin);
+
+ // Margins can never collapse into independent formatting contexts.
+ sequential_layout_state.collapse_margins();
+ sequential_layout_state.advance_block_position(
+ pbm.padding_border_sums.block + adjustment_from_floats.block + block_size,
+ );
+ sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_end));
+
+ let block_size = containing_block_for_children.block_size.auto_is(|| {
+ layout
+ .content_block_size
+ .clamp_between_extremums(min_box_size.block, max_box_size.block)
+ });
+ let content_rect = Rect {
+ start_corner: Vec2 {
+ block: pbm.padding.block_start +
+ pbm.border.block_start +
+ adjustment_from_floats.block,
+ inline: pbm.padding.inline_start +
+ pbm.border.inline_start +
+ margin.inline_start +
+ adjustment_from_floats.inline,
+ },
+ size: Vec2 {
+ block: block_size,
+ inline: containing_block_for_children.inline_size,
+ },
+ };
+ let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
+ BoxFragment::new(
+ self.base_fragment_info,
+ self.style.clone(),
+ layout.fragments,
+ content_rect,
+ pbm.padding,
+ pbm.border,
+ margin,
+ effective_clearance,
+ block_margins_collapsed_with_children,
+ )
+ }
}
/// https://drafts.csswg.org/css2/visudet.html#block-replaced-width
@@ -867,33 +1013,94 @@ fn layout_in_flow_replaced_block_level<'a>(
};
let fragments = replaced.make_fragments(style, size.clone());
- let mut clearance = None;
+ let mut effective_clearance = None;
+ let mut adjustment_from_floats = Vec2::zero();
if let Some(ref mut sequential_layout_state) = sequential_layout_state {
- clearance = sequential_layout_state.calculate_clearance_and_adjoin_margin(
- style,
- &CollapsedMargin::new(margin.block_start),
- );
+ let block_start_margin = CollapsedMargin::new(margin.block_start);
+ let clearance = sequential_layout_state
+ .calculate_clearance(ClearSide::from_style(style), &block_start_margin);
+
+ // We calculate a hypothetical value for `bfc_relative_block_position`,
+ // assuming that there was no adjustment from floats. The real value will
+ // depend on whether or not there was adjustment.
+ let hypothetical_bfc_relative_block_position = if clearance.is_some() {
+ sequential_layout_state.bfc_relative_block_position +
+ sequential_layout_state.current_margin.solve() +
+ block_start_margin.solve()
+ } else {
+ sequential_layout_state.bfc_relative_block_position +
+ sequential_layout_state
+ .current_margin
+ .adjoin(&block_start_margin)
+ .solve()
+ };
+
+ // From https://drafts.csswg.org/css2/#floats:
+ // "The border box of a table, a block-level replaced element, or an element in
+ // the normal flow that establishes a new block formatting context (such as an
+ // element with overflow other than visible) must not overlap the margin box of
+ // any floats in the same block formatting context as the element itself. If
+ // necessary, implementations should clear the said element by placing it below
+ // any preceding floats, but may place it adjacent to such floats if there is
+ // 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 placement_among_floats = PlacementAmongFloats::new(
+ &sequential_layout_state.floats,
+ hypothetical_bfc_relative_block_position + clearance.unwrap_or_else(Length::zero),
+ &size + &pbm.padding_border_sums,
+ )
+ .place();
+
+ // This placement is in the coordinates of the float-containing block formatting
+ // context, but we need to calculate an offset to use for placing this replaced
+ // element.
+ adjustment_from_floats = &placement_among_floats -
+ &Vec2 {
+ inline: sequential_layout_state
+ .floats
+ .containing_block_info
+ .inline_start,
+ block: hypothetical_bfc_relative_block_position,
+ };
+
+ // Clearance and any adjustment from float should prevent margin collapse, so it's
+ // important to make sure that it is non-None even when it is zero. Yet, when we
+ // didn't have clearance or any adjustment from placing next to floats, we want the
+ // value of clearance on the Fragment to be None, so margin collapse still works
+ // properly.
+ effective_clearance = if clearance.is_some() || !adjustment_from_floats.block.is_zero() {
+ Some(adjustment_from_floats.block)
+ } else {
+ None
+ };
+
+ // If there was effective clearance, it prevent margins collapse between this
+ // block and previous ones, so in that case collapse margins before adjoining
+ // them below.
+ if effective_clearance.is_some() {
+ sequential_layout_state.collapse_margins();
+ }
+ sequential_layout_state.adjoin_assign(&block_start_margin);
+
+ // Margins can never collapse into replaced elements.
sequential_layout_state.collapse_margins();
sequential_layout_state.advance_block_position(
- pbm.border.block_sum() +
- pbm.padding.block_sum() +
- size.block +
- clearance.unwrap_or_else(Length::zero),
+ pbm.padding_border_sums.block + size.block + adjustment_from_floats.block,
);
sequential_layout_state.adjoin_assign(&CollapsedMargin::new(margin.block_end));
};
- let content_rect = Rect {
- start_corner: Vec2 {
- block: pbm.padding.block_start +
- pbm.border.block_start +
- clearance.unwrap_or_else(Length::zero),
- inline: pbm.padding.inline_start + pbm.border.inline_start + margin.inline_start,
- },
- size,
+ let start_corner = Vec2 {
+ block: pbm.padding.block_start + pbm.border.block_start + adjustment_from_floats.block,
+ inline: pbm.padding.inline_start +
+ pbm.border.inline_start +
+ margin.inline_start +
+ adjustment_from_floats.inline,
};
- let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
+ let content_rect = Rect { start_corner, size };
+ let block_margins_collapsed_with_children = CollapsedBlockMargins::from_margin(&margin);
BoxFragment::new(
base_fragment_info,
style.clone(),
@@ -902,7 +1109,7 @@ fn layout_in_flow_replaced_block_level<'a>(
pbm.padding,
pbm.border,
margin,
- clearance,
+ effective_clearance,
block_margins_collapsed_with_children,
)
}
diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-039.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-039.xht.ini
deleted file mode 100644
index d99141cd3b6..00000000000
--- a/tests/wpt/meta/css/CSS2/floats-clear/floats-039.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[floats-039.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-001.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-001.xht.ini
deleted file mode 100644
index fe8adde8fbd..00000000000
--- a/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-001.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[floats-bfc-001.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-002.xht.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-002.xht.ini
deleted file mode 100644
index 4c5d30ada12..00000000000
--- a/tests/wpt/meta/css/CSS2/floats-clear/floats-bfc-002.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[floats-bfc-002.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht.ini b/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht.ini
deleted file mode 100644
index 6932dd5c0d7..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-002r.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[floats-wrap-top-below-bfc-002r.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht.ini b/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht.ini
deleted file mode 100644
index c8d275af695..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/floats-wrap-top-below-bfc-003r.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[floats-wrap-top-below-bfc-003r.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/new-fc-beside-adjoining-float-2.html.ini b/tests/wpt/meta/css/CSS2/floats/new-fc-beside-adjoining-float-2.html.ini
deleted file mode 100644
index 068736c5062..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/new-fc-beside-adjoining-float-2.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[new-fc-beside-adjoining-float-2.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/new-fc-beside-float-with-margin.html.ini b/tests/wpt/meta/css/CSS2/floats/new-fc-beside-float-with-margin.html.ini
deleted file mode 100644
index bc826f00b21..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/new-fc-beside-float-with-margin.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[new-fc-beside-float-with-margin.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-001.html.ini b/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-001.html.ini
deleted file mode 100644
index 0cf8aeeef3e..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-001.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[zero-space-between-floats-001.html]
- [#container 1]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-002.html.ini b/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-002.html.ini
deleted file mode 100644
index 74be952f9ae..00000000000
--- a/tests/wpt/meta/css/CSS2/floats/zero-space-between-floats-002.html.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[zero-space-between-floats-002.html]
- [#container 1]
- expected: FAIL
diff --git a/tests/wpt/meta/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini b/tests/wpt/meta/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini
deleted file mode 100644
index 27d98f802fc..00000000000
--- a/tests/wpt/meta/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[block-formatting-contexts-015.xht]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-flexbox/flexbox-paint-ordering-001.xhtml.ini b/tests/wpt/meta/css/css-flexbox/flexbox-paint-ordering-001.xhtml.ini
deleted file mode 100644
index f940711d2e5..00000000000
--- a/tests/wpt/meta/css/css-flexbox/flexbox-paint-ordering-001.xhtml.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[flexbox-paint-ordering-001.xhtml]
- expected: FAIL