From 4ec61c2cdc46d73a3047f4f7e2454465e022420c Mon Sep 17 00:00:00 2001 From: Martin Robinson Date: Wed, 17 Apr 2024 16:15:06 +0200 Subject: [PATCH] layout: Add support for `clear` on `
` elements (#32094) `
` elements are a bit "special" in the sense that they defer a linebreak, but can also have `clear` applied to them. The `clear` that they supply should be applie *after* the linebreak is processed. This change adds special processing for this situation. Fixes #15402. --- components/layout_2020/flow/inline.rs | 36 +++++++++++++++++-- .../floats-clear-multicol-000.html.ini | 2 -- .../floats-clear-multicol-001.html.ini | 2 -- ...oats-clear-multicol-balancing-000.html.ini | 2 -- ...oats-clear-multicol-balancing-001.html.ini | 2 -- 5 files changed, 34 insertions(+), 10 deletions(-) delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-000.html.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-001.html.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-000.html.ini delete mode 100644 tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-001.html.ini diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 247ae3542c4..8ab22124b2a 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -82,7 +82,7 @@ use style::computed_values::white_space::T as WhiteSpace; use style::context::QuirksMode; use style::logical_geometry::WritingMode; use style::properties::ComputedValues; -use style::values::computed::Length; +use style::values::computed::{Clear, Length}; use style::values::generics::box_::VerticalAlignKeyword; use style::values::generics::font::LineHeight; use style::values::specified::box_::BaselineSource; @@ -640,6 +640,11 @@ pub(super) struct InlineFormattingContextState<'a, 'b> { /// [`InlineFormattingContextState::finish_inline_box()`]. linebreak_before_new_content: bool, + /// When a `
` element has `clear`, this needs to be applied after the linebreak, + /// which will be processed *after* the `
` element is processed. This member + /// stores any deferred `clear` to apply after a linebreak. + deferred_br_clear: Clear, + /// Whether or not a soft wrap opportunity is queued. Soft wrap opportunities are /// queued after replaced content and they are processed when the next text content /// is encountered. @@ -733,6 +738,20 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { .into() } + // If we are starting a `
` element prepare to clear after its deferred linebreak has been + // processed. Note that a `
` is composed of the element itself and the inner pseudo-element + // with the actual linebreak. Both will have this `FragmentFlag`; that's why this code only + // sets `deferred_br_clear` if it isn't set yet. + if inline_box_state + .base_fragment_info + .flags + .contains(FragmentFlags::IS_BR_ELEMENT) + { + if self.deferred_br_clear == Clear::None { + self.deferred_br_clear = inline_box_state.base.style.clone_clear(); + } + } + let line_item = inline_box_state .layout_into_line_item(inline_box.is_first_fragment, inline_box.is_last_fragment); self.push_line_item_to_unbreakable_segment(LineItem::StartInlineBox(line_item)); @@ -817,12 +836,24 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { LineBlockSizes::zero() }; - let block_end_position = block_start_position + effective_block_advance.resolve().into(); + let resolved_block_advance = effective_block_advance.resolve().into(); + let mut block_end_position = block_start_position + resolved_block_advance; if let Some(sequential_layout_state) = self.sequential_layout_state.as_mut() { // This amount includes both the block size of the line and any extra space // added to move the line down in order to avoid overlapping floats. let increment = block_end_position - self.current_line.start_position.block.into(); sequential_layout_state.advance_block_position(increment); + + // This newline may have been triggered by a `
` with clearance, in which case we + // want to make sure that we make space not only for the current line, but any clearance + // from floats. + if let Some(clearance) = sequential_layout_state + .calculate_clearance(self.deferred_br_clear, &CollapsedMargin::zero()) + { + sequential_layout_state.advance_block_position(clearance); + block_end_position += clearance; + }; + self.deferred_br_clear = Clear::None; } let mut line_items = std::mem::take(&mut self.current_line.line_items); @@ -1624,6 +1655,7 @@ impl InlineFormattingContext { inline_box_state_stack: Vec::new(), current_line_segment: UnbreakableSegmentUnderConstruction::new(), linebreak_before_new_content: false, + deferred_br_clear: Clear::None, have_deferred_soft_wrap_opportunity: false, prevent_soft_wrap_opportunity_before_next_atomic: false, had_inflow_content: false, diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-000.html.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-000.html.ini deleted file mode 100644 index d91ccfb5690..00000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-000.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[floats-clear-multicol-000.html] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-001.html.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-001.html.ini deleted file mode 100644 index 4c9969190bb..00000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[floats-clear-multicol-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-000.html.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-000.html.ini deleted file mode 100644 index b748a3798b7..00000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-000.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[floats-clear-multicol-balancing-000.html] - expected: FAIL diff --git a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-001.html.ini b/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-001.html.ini deleted file mode 100644 index c0c1e8a7cbe..00000000000 --- a/tests/wpt/meta/css/CSS2/floats-clear/floats-clear-multicol-balancing-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[floats-clear-multicol-balancing-001.html] - expected: FAIL