mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Turn white-space into a shorthand (#32146)
Bumps Stylo to servo/stylo#37 `white-space` is split into `white-space-collapse` and `text-wrap-mode`: | white-space | white-space-collapse | text-wrap-mode | | ----------- | -------------------- | -------------- | | normal | collapse | wrap | | nowrap | collapse | nowrap | | pre-wrap | preserve | wrap | | pre | preserve | nowrap | | pre-line | preserve-breaks | wrap | | - | preserve-breaks | nowrap | Note this introduces a combination that wasn't previously possible, but I think the existing logic can handle it well enough. The old `allow_wrap()` is replaced by checking whether `text-wrap-mode` is set to `wrap`. The old `preserve_newlines()` is replaced by checking whether `white-space-collapse` is *not* set to `collapse`. The old `preserve_spaces()` is replaced by checking whether `white-space-collapse` is set to `preserve`.
This commit is contained in:
parent
a1f8c19355
commit
d490fdf83c
23 changed files with 141 additions and 454 deletions
|
@ -41,8 +41,9 @@ use style::computed_values::overflow_wrap::T as OverflowWrap;
|
|||
use style::computed_values::overflow_x::T as StyleOverflow;
|
||||
use style::computed_values::position::T as Position;
|
||||
use style::computed_values::text_decoration_line::T as TextDecorationLine;
|
||||
use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
||||
use style::computed_values::transform_style::T as TransformStyle;
|
||||
use style::computed_values::white_space::T as WhiteSpace;
|
||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||
use style::computed_values::word_break::T as WordBreak;
|
||||
use style::logical_geometry::{Direction, LogicalMargin, LogicalRect, LogicalSize, WritingMode};
|
||||
use style::properties::ComputedValues;
|
||||
|
@ -1539,8 +1540,12 @@ impl Fragment {
|
|||
&self.selected_style
|
||||
}
|
||||
|
||||
pub fn white_space(&self) -> WhiteSpace {
|
||||
self.style().get_inherited_text().white_space
|
||||
pub fn white_space_collapse(&self) -> WhiteSpaceCollapse {
|
||||
self.style().get_inherited_text().white_space_collapse
|
||||
}
|
||||
|
||||
pub fn text_wrap_mode(&self) -> TextWrapMode {
|
||||
self.style().get_inherited_text().text_wrap_mode
|
||||
}
|
||||
|
||||
pub fn color(&self) -> Color {
|
||||
|
@ -1586,7 +1591,7 @@ impl Fragment {
|
|||
/// Returns true if this element can be split. This is true for text fragments, unless
|
||||
/// `white-space: pre` or `white-space: nowrap` is set.
|
||||
pub fn can_split(&self) -> bool {
|
||||
self.is_scanned_text_fragment() && self.white_space().allow_wrap()
|
||||
self.is_scanned_text_fragment() && self.text_wrap_mode() == TextWrapMode::Wrap
|
||||
}
|
||||
|
||||
/// Returns true if and only if this fragment is a generated content fragment.
|
||||
|
@ -1703,7 +1708,7 @@ impl Fragment {
|
|||
.metrics_for_range(range)
|
||||
.advance_width;
|
||||
|
||||
let min_line_inline_size = if self_.white_space().allow_wrap() {
|
||||
let min_line_inline_size = if self_.text_wrap_mode() == TextWrapMode::Wrap {
|
||||
text_fragment_info.run.min_width_for_range(range)
|
||||
} else {
|
||||
max_line_inline_size
|
||||
|
@ -1968,7 +1973,7 @@ impl Fragment {
|
|||
// see if we're going to overflow the line. If so, perform a best-effort split.
|
||||
let mut remaining_range = slice.text_run_range();
|
||||
let split_is_empty = inline_start_range.is_empty() &&
|
||||
(self.white_space().allow_wrap() ||
|
||||
(self.text_wrap_mode() == TextWrapMode::Wrap ||
|
||||
!self.requires_line_break_afterward_if_wrapping_on_newlines());
|
||||
if split_is_empty {
|
||||
// We're going to overflow the line.
|
||||
|
@ -2520,7 +2525,8 @@ impl Fragment {
|
|||
// FIXME: Should probably use a whitelist of styles that can safely differ (#3165)
|
||||
if self.style().get_font() != other.style().get_font() ||
|
||||
self.text_decoration_line() != other.text_decoration_line() ||
|
||||
self.white_space() != other.white_space() ||
|
||||
self.white_space_collapse() != other.white_space_collapse() ||
|
||||
self.text_wrap_mode() != other.text_wrap_mode() ||
|
||||
self.color() != other.color()
|
||||
{
|
||||
return false;
|
||||
|
@ -2893,7 +2899,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
pub fn strip_leading_whitespace_if_necessary(&mut self) -> WhitespaceStrippingResult {
|
||||
if self.white_space().preserve_spaces() {
|
||||
if self.white_space_collapse() == WhiteSpaceCollapse::Preserve {
|
||||
return WhitespaceStrippingResult::RetainFragment;
|
||||
}
|
||||
|
||||
|
@ -2963,7 +2969,7 @@ impl Fragment {
|
|||
|
||||
/// Returns true if the entire fragment was stripped.
|
||||
pub fn strip_trailing_whitespace_if_necessary(&mut self) -> WhitespaceStrippingResult {
|
||||
if self.white_space().preserve_spaces() {
|
||||
if self.white_space_collapse() == WhiteSpaceCollapse::Preserve {
|
||||
return WhitespaceStrippingResult::RetainFragment;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,8 @@ use style::computed_values::overflow_x::T as StyleOverflow;
|
|||
use style::computed_values::position::T as Position;
|
||||
use style::computed_values::text_align::T as TextAlign;
|
||||
use style::computed_values::text_justify::T as TextJustify;
|
||||
use style::computed_values::white_space::T as WhiteSpace;
|
||||
use style::computed_values::text_wrap_mode::T as TextWrapMode;
|
||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||
use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||
use style::properties::ComputedValues;
|
||||
use style::servo::restyle_damage::ServoRestyleDamage;
|
||||
|
@ -622,7 +623,7 @@ impl LineBreaker {
|
|||
if fragment.suppress_line_break_before() || !fragment.is_on_glyph_run_boundary() {
|
||||
false
|
||||
} else {
|
||||
fragment.white_space().allow_wrap()
|
||||
fragment.text_wrap_mode() == TextWrapMode::Wrap
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -663,7 +664,7 @@ impl LineBreaker {
|
|||
|
||||
// If we must flush the line after finishing this fragment due to `white-space: pre`,
|
||||
// detect that.
|
||||
let line_flush_mode = if fragment.white_space().preserve_newlines() {
|
||||
let line_flush_mode = if fragment.white_space_collapse() != WhiteSpaceCollapse::Collapse {
|
||||
if fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
|
||||
LineFlushMode::Flush
|
||||
} else {
|
||||
|
@ -687,7 +688,7 @@ impl LineBreaker {
|
|||
|
||||
// If the wrapping mode prevents us from splitting, then back up and split at the last
|
||||
// known good split point.
|
||||
if !fragment.white_space().allow_wrap() {
|
||||
if fragment.text_wrap_mode() == TextWrapMode::Nowrap {
|
||||
debug!(
|
||||
"LineBreaker: fragment can't split; falling back to last known good split point"
|
||||
);
|
||||
|
@ -1494,10 +1495,16 @@ impl Flow for InlineFlow {
|
|||
let mut intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();
|
||||
for fragment in &mut self.fragments.fragments {
|
||||
let intrinsic_sizes_for_fragment = fragment.compute_intrinsic_inline_sizes().finish();
|
||||
match fragment.style.get_inherited_text().white_space {
|
||||
WhiteSpace::Nowrap => intrinsic_sizes_for_nonbroken_run
|
||||
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment),
|
||||
WhiteSpace::Pre => {
|
||||
let style_text = fragment.style.get_inherited_text();
|
||||
match (style_text.white_space_collapse, style_text.text_wrap_mode) {
|
||||
(WhiteSpaceCollapse::Collapse, TextWrapMode::Nowrap) => {
|
||||
intrinsic_sizes_for_nonbroken_run
|
||||
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment)
|
||||
},
|
||||
(
|
||||
WhiteSpaceCollapse::Preserve | WhiteSpaceCollapse::PreserveBreaks,
|
||||
TextWrapMode::Nowrap,
|
||||
) => {
|
||||
intrinsic_sizes_for_nonbroken_run
|
||||
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment);
|
||||
|
||||
|
@ -1512,7 +1519,10 @@ impl Flow for InlineFlow {
|
|||
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
|
||||
}
|
||||
},
|
||||
WhiteSpace::PreWrap | WhiteSpace::PreLine => {
|
||||
(
|
||||
WhiteSpaceCollapse::Preserve | WhiteSpaceCollapse::PreserveBreaks,
|
||||
TextWrapMode::Wrap,
|
||||
) => {
|
||||
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
|
||||
// necessary.
|
||||
intrinsic_sizes_for_inline_run
|
||||
|
@ -1532,7 +1542,7 @@ impl Flow for InlineFlow {
|
|||
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
|
||||
}
|
||||
},
|
||||
WhiteSpace::Normal => {
|
||||
(WhiteSpaceCollapse::Collapse, TextWrapMode::Wrap) => {
|
||||
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
|
||||
// necessary.
|
||||
intrinsic_sizes_for_inline_run
|
||||
|
|
|
@ -17,7 +17,7 @@ use gfx::text::util::{self, CompressionMode};
|
|||
use log::{debug, warn};
|
||||
use range::Range;
|
||||
use style::computed_values::text_rendering::T as TextRendering;
|
||||
use style::computed_values::white_space::T as WhiteSpace;
|
||||
use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse;
|
||||
use style::computed_values::word_break::T as WordBreak;
|
||||
use style::logical_geometry::{LogicalSize, WritingMode};
|
||||
use style::properties::style_structs::Font as FontStyleStruct;
|
||||
|
@ -46,7 +46,7 @@ fn text(fragments: &LinkedList<Fragment>) -> String {
|
|||
|
||||
for fragment in fragments {
|
||||
if let SpecificFragmentInfo::UnscannedText(ref info) = fragment.specific {
|
||||
if fragment.white_space().preserve_newlines() {
|
||||
if fragment.white_space_collapse() != WhiteSpaceCollapse::Collapse {
|
||||
text.push_str(&info.text);
|
||||
} else {
|
||||
text.push_str(&info.text.replace('\n', " "));
|
||||
|
@ -190,12 +190,10 @@ impl TextRunScanner {
|
|||
let font_style = in_fragment.style().clone_font();
|
||||
let inherited_text_style = in_fragment.style().get_inherited_text();
|
||||
font_group = font_context.font_group(font_style);
|
||||
compression = match in_fragment.white_space() {
|
||||
WhiteSpace::Normal | WhiteSpace::Nowrap => {
|
||||
CompressionMode::CompressWhitespaceNewline
|
||||
},
|
||||
WhiteSpace::Pre | WhiteSpace::PreWrap => CompressionMode::CompressNone,
|
||||
WhiteSpace::PreLine => CompressionMode::CompressWhitespace,
|
||||
compression = match in_fragment.white_space_collapse() {
|
||||
WhiteSpaceCollapse::Collapse => CompressionMode::CompressWhitespaceNewline,
|
||||
WhiteSpaceCollapse::Preserve => CompressionMode::CompressNone,
|
||||
WhiteSpaceCollapse::PreserveBreaks => CompressionMode::CompressWhitespace,
|
||||
};
|
||||
text_transform = inherited_text_style.text_transform;
|
||||
letter_spacing = inherited_text_style.letter_spacing;
|
||||
|
@ -568,7 +566,7 @@ fn split_first_fragment_at_newline_if_necessary(fragments: &mut LinkedList<Fragm
|
|||
let string_before;
|
||||
let selection_before;
|
||||
{
|
||||
if !first_fragment.white_space().preserve_newlines() {
|
||||
if first_fragment.white_space_collapse() == WhiteSpaceCollapse::Collapse {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue