From 39f660f520a4aa0f3fad95f02fec5beb2dfc9d07 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Fri, 15 Mar 2024 17:12:41 +0100 Subject: [PATCH] Allow pre-wrap whitespace to hang at the end of the line (#31681) * Allow pre-wrap whitespace to hang at the end of the line * Use bitflags --- components/layout_2020/flow/inline.rs | 72 ++++++++++++++----- .../hyphens/hyphens-auto-002.html.ini | 2 - .../white-space/control-chars-00D.html.ini | 2 - .../white-space/eol-spaces-bidi-002.html.ini | 2 - .../white-space/pre-wrap-001.html.ini | 2 - .../white-space/pre-wrap-002.html.ini | 2 - .../white-space/pre-wrap-003.html.ini | 2 - .../white-space/pre-wrap-004.html.ini | 2 - .../white-space/pre-wrap-005.html.ini | 2 - .../white-space/pre-wrap-006.html.ini | 2 - .../white-space/pre-wrap-007.html.ini | 2 - .../white-space/pre-wrap-015.html.ini | 2 - .../pre-wrap-align-left-001.html.ini | 2 - .../pre-wrap-align-start-001.html.ini | 2 - .../pre-wrap-leading-spaces-012.html.ini | 2 - .../white-space/pre-wrap-tab-001.html.ini | 2 - .../textarea-pre-wrap-001.html.ini | 2 - .../textarea-pre-wrap-002.html.ini | 2 - .../textarea-pre-wrap-003.html.ini | 2 - .../textarea-pre-wrap-004.html.ini | 2 - .../textarea-pre-wrap-005.html.ini | 2 - .../textarea-pre-wrap-006.html.ini | 2 - .../textarea-pre-wrap-007.html.ini | 2 - .../meta/css/white-space-pre-wrap.htm.ini | 2 - 24 files changed, 54 insertions(+), 64 deletions(-) delete mode 100644 tests/wpt/meta/css/css-text/hyphens/hyphens-auto-002.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/control-chars-00D.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/eol-spaces-bidi-002.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-001.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-002.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-003.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-004.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-005.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-006.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-007.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-015.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-align-left-001.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-align-start-001.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-leading-spaces-012.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/pre-wrap-tab-001.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-001.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-002.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-003.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-004.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-005.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-006.html.ini delete mode 100644 tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-007.html.ini delete mode 100644 tests/wpt/mozilla/meta/css/white-space-pre-wrap.htm.ini diff --git a/components/layout_2020/flow/inline.rs b/components/layout_2020/flow/inline.rs index 47f6f87558e..843838ad33a 100644 --- a/components/layout_2020/flow/inline.rs +++ b/components/layout_2020/flow/inline.rs @@ -72,6 +72,7 @@ use std::cell::OnceCell; use std::mem; use app_units::Au; +use bitflags::bitflags; use gfx::font::FontMetrics; use gfx::text::glyph::GlyphStore; use serde::Serialize; @@ -1215,7 +1216,11 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { .current_inline_container_state() .strut_block_sizes .clone(); - self.update_unbreakable_segment_for_new_content(&strut_size, Length::zero(), false); + self.update_unbreakable_segment_for_new_content( + &strut_size, + Length::zero(), + SegmentContentFlags::empty(), + ); } self.had_inflow_content = true; @@ -1243,12 +1248,11 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { font_index: usize, ) { let inline_advance = Length::from(glyph_store.total_advance()); - let preserve_spaces = text_run - .parent_style - .get_inherited_text() - .white_space - .preserve_spaces(); - let is_collapsible_whitespace = glyph_store.is_whitespace() && !preserve_spaces; + let flags = if glyph_store.is_whitespace() { + SegmentContentFlags::from(text_run.parent_style.get_inherited_text().white_space) + } else { + SegmentContentFlags::empty() + }; // If the metrics of this font don't match the default font, we are likely using a fallback // font and need to adjust the line size to account for a potentially different font. @@ -1270,7 +1274,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { container_state.get_block_size_contribution(vertical_align, &font_metrics); block_size.adjust_for_baseline_offset(container_state.baseline_offset); block_size - } else if quirks_mode && !is_collapsible_whitespace { + } else if quirks_mode && !flags.is_collapsible_whitespace() { // Normally, the strut is incorporated into the nested block size. In quirks mode though // if we find any text that isn't collapsed whitespace, we need to incorporate the strut. // TODO(mrobinson): This isn't quite right for situations where collapsible white space @@ -1281,11 +1285,7 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { } else { LineBlockSizes::zero() }; - self.update_unbreakable_segment_for_new_content( - &strut_size, - inline_advance, - is_collapsible_whitespace, - ); + self.update_unbreakable_segment_for_new_content(&strut_size, inline_advance, flags); match self.current_line_segment.line_items.last_mut() { Some(LineItem::TextRun(line_item)) if ifc_font_info.key == line_item.font_key => { @@ -1309,14 +1309,16 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { &mut self, block_sizes_of_content: &LineBlockSizes, inline_size: Length, - is_collapsible_whitespace: bool, + flags: SegmentContentFlags, ) { - if !is_collapsible_whitespace { + if flags.is_collapsible_whitespace() || flags.is_wrappable_whitespace() { + self.current_line_segment.trailing_whitespace_size = inline_size; + } else { self.current_line_segment.trailing_whitespace_size = Length::zero(); + } + if !flags.is_collapsible_whitespace() { self.current_line_segment.has_content = true; self.had_inflow_content = true; - } else { - self.current_line_segment.trailing_whitespace_size = inline_size; } // This may or may not include the size of the strut depending on the quirks mode setting. @@ -1442,6 +1444,36 @@ impl<'a, 'b> InlineFormattingContextState<'a, 'b> { } } +bitflags! { + pub struct SegmentContentFlags: u8 { + const COLLAPSIBLE_WHITESPACE = 0b00000001; + const WRAPPABLE_WHITESPACE = 0b00000010; + } +} + +impl SegmentContentFlags { + fn is_collapsible_whitespace(&self) -> bool { + self.contains(Self::COLLAPSIBLE_WHITESPACE) + } + + fn is_wrappable_whitespace(&self) -> bool { + self.contains(Self::WRAPPABLE_WHITESPACE) + } +} + +impl From for SegmentContentFlags { + fn from(white_space: WhiteSpace) -> Self { + let mut flags = Self::empty(); + if !white_space.preserve_spaces() { + flags.insert(Self::COLLAPSIBLE_WHITESPACE); + } + if white_space.allow_wrap() { + flags.insert(Self::WRAPPABLE_WHITESPACE); + } + flags + } +} + enum InlineFormattingContextIterItem<'a> { Item(&'a mut InlineLevelBox), EndInlineBox, @@ -2088,7 +2120,11 @@ impl IndependentFormattingContext { let (block_sizes, baseline_offset_in_parent) = self.get_block_sizes_and_baseline_offset(ifc, size.block, baseline_offset); - ifc.update_unbreakable_segment_for_new_content(&block_sizes, size.inline, false); + ifc.update_unbreakable_segment_for_new_content( + &block_sizes, + size.inline, + SegmentContentFlags::empty(), + ); ifc.push_line_item_to_unbreakable_segment(LineItem::Atomic(AtomicLineItem { fragment, size, diff --git a/tests/wpt/meta/css/css-text/hyphens/hyphens-auto-002.html.ini b/tests/wpt/meta/css/css-text/hyphens/hyphens-auto-002.html.ini deleted file mode 100644 index 8d731c13b0c..00000000000 --- a/tests/wpt/meta/css/css-text/hyphens/hyphens-auto-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[hyphens-auto-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/control-chars-00D.html.ini b/tests/wpt/meta/css/css-text/white-space/control-chars-00D.html.ini deleted file mode 100644 index c1b4dc8af5d..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/control-chars-00D.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[control-chars-00D.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/eol-spaces-bidi-002.html.ini b/tests/wpt/meta/css/css-text/white-space/eol-spaces-bidi-002.html.ini deleted file mode 100644 index f66d7ce5370..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/eol-spaces-bidi-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[eol-spaces-bidi-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-001.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-001.html.ini deleted file mode 100644 index bbd66f9b4bf..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-002.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-002.html.ini deleted file mode 100644 index f1c90a7727c..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-003.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-003.html.ini deleted file mode 100644 index d37dfc68a45..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-003.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-004.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-004.html.ini deleted file mode 100644 index 9fb1c924859..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-004.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-004.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-005.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-005.html.ini deleted file mode 100644 index 3610344cfe9..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-005.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-005.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-006.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-006.html.ini deleted file mode 100644 index 832e5dfd79e..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-006.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-006.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-007.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-007.html.ini deleted file mode 100644 index db1e5be184f..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-007.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-007.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-015.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-015.html.ini deleted file mode 100644 index 1e110cf2423..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-015.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-015.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-left-001.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-left-001.html.ini deleted file mode 100644 index 32c493a3e57..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-left-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-align-left-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-start-001.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-start-001.html.ini deleted file mode 100644 index f91bba47f01..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-align-start-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-align-start-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-leading-spaces-012.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-leading-spaces-012.html.ini deleted file mode 100644 index 3b734712ee3..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-leading-spaces-012.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-leading-spaces-012.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/pre-wrap-tab-001.html.ini b/tests/wpt/meta/css/css-text/white-space/pre-wrap-tab-001.html.ini deleted file mode 100644 index f40b22a19fb..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/pre-wrap-tab-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[pre-wrap-tab-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-001.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-001.html.ini deleted file mode 100644 index 25425534015..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-001.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-002.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-002.html.ini deleted file mode 100644 index 1a9f7544ed6..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-002.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-002.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-003.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-003.html.ini deleted file mode 100644 index 3a8addee39b..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-003.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-003.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-004.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-004.html.ini deleted file mode 100644 index ad7ac442d7b..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-004.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-004.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-005.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-005.html.ini deleted file mode 100644 index 5f96bb43a6c..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-005.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-005.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-006.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-006.html.ini deleted file mode 100644 index 2a7940d6673..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-006.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-006.html] - expected: FAIL diff --git a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-007.html.ini b/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-007.html.ini deleted file mode 100644 index dd9d05f1b76..00000000000 --- a/tests/wpt/meta/css/css-text/white-space/textarea-pre-wrap-007.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[textarea-pre-wrap-007.html] - expected: FAIL diff --git a/tests/wpt/mozilla/meta/css/white-space-pre-wrap.htm.ini b/tests/wpt/mozilla/meta/css/white-space-pre-wrap.htm.ini deleted file mode 100644 index 521c793832b..00000000000 --- a/tests/wpt/mozilla/meta/css/white-space-pre-wrap.htm.ini +++ /dev/null @@ -1,2 +0,0 @@ -[white-space-pre-wrap.htm] - expected: FAIL