mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
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
This commit is contained in:
parent
ac24cd6139
commit
39f660f520
24 changed files with 54 additions and 64 deletions
|
@ -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<WhiteSpace> 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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue