mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
layout: Add support for clear
on <br>
elements (#32094)
`<br>` 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.
This commit is contained in:
parent
83dec920dd
commit
4ec61c2cdc
5 changed files with 34 additions and 10 deletions
|
@ -82,7 +82,7 @@ use style::computed_values::white_space::T as WhiteSpace;
|
||||||
use style::context::QuirksMode;
|
use style::context::QuirksMode;
|
||||||
use style::logical_geometry::WritingMode;
|
use style::logical_geometry::WritingMode;
|
||||||
use style::properties::ComputedValues;
|
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::box_::VerticalAlignKeyword;
|
||||||
use style::values::generics::font::LineHeight;
|
use style::values::generics::font::LineHeight;
|
||||||
use style::values::specified::box_::BaselineSource;
|
use style::values::specified::box_::BaselineSource;
|
||||||
|
@ -640,6 +640,11 @@ pub(super) struct InlineFormattingContextState<'a, 'b> {
|
||||||
/// [`InlineFormattingContextState::finish_inline_box()`].
|
/// [`InlineFormattingContextState::finish_inline_box()`].
|
||||||
linebreak_before_new_content: bool,
|
linebreak_before_new_content: bool,
|
||||||
|
|
||||||
|
/// When a `<br>` element has `clear`, this needs to be applied after the linebreak,
|
||||||
|
/// which will be processed *after* the `<br>` 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
|
/// 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
|
/// queued after replaced content and they are processed when the next text content
|
||||||
/// is encountered.
|
/// is encountered.
|
||||||
|
@ -733,6 +738,20 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we are starting a `<br>` element prepare to clear after its deferred linebreak has been
|
||||||
|
// processed. Note that a `<br>` 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
|
let line_item = inline_box_state
|
||||||
.layout_into_line_item(inline_box.is_first_fragment, inline_box.is_last_fragment);
|
.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));
|
self.push_line_item_to_unbreakable_segment(LineItem::StartInlineBox(line_item));
|
||||||
|
@ -817,12 +836,24 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> {
|
||||||
LineBlockSizes::zero()
|
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() {
|
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
|
// 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.
|
// added to move the line down in order to avoid overlapping floats.
|
||||||
let increment = block_end_position - self.current_line.start_position.block.into();
|
let increment = block_end_position - self.current_line.start_position.block.into();
|
||||||
sequential_layout_state.advance_block_position(increment);
|
sequential_layout_state.advance_block_position(increment);
|
||||||
|
|
||||||
|
// This newline may have been triggered by a `<br>` 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);
|
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(),
|
inline_box_state_stack: Vec::new(),
|
||||||
current_line_segment: UnbreakableSegmentUnderConstruction::new(),
|
current_line_segment: UnbreakableSegmentUnderConstruction::new(),
|
||||||
linebreak_before_new_content: false,
|
linebreak_before_new_content: false,
|
||||||
|
deferred_br_clear: Clear::None,
|
||||||
have_deferred_soft_wrap_opportunity: false,
|
have_deferred_soft_wrap_opportunity: false,
|
||||||
prevent_soft_wrap_opportunity_before_next_atomic: false,
|
prevent_soft_wrap_opportunity_before_next_atomic: false,
|
||||||
had_inflow_content: false,
|
had_inflow_content: false,
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
[floats-clear-multicol-000.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[floats-clear-multicol-001.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[floats-clear-multicol-balancing-000.html]
|
|
||||||
expected: FAIL
|
|
|
@ -1,2 +0,0 @@
|
||||||
[floats-clear-multicol-balancing-001.html]
|
|
||||||
expected: FAIL
|
|
Loading…
Add table
Add a link
Reference in a new issue