Skip to content

Commit

Permalink
Turn white-space into a shorthand
Browse files Browse the repository at this point in the history
Bumps Stylo to servo/stylo#37

`white-space` is split into `text-wrap-mode` and `white-space-collapse`:

| 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`.
  • Loading branch information
Loirooriol committed Apr 25, 2024
1 parent 7bb26a4 commit 5542a7f
Show file tree
Hide file tree
Showing 10 changed files with 178 additions and 151 deletions.
26 changes: 13 additions & 13 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 9 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ keyboard-types = "0.6"
lazy_static = "1.4"
libc = "0.2"
log = "0.4"
malloc_size_of = { git = "https://github.com/servo/stylo", branch = "2024-04-16", features = ["servo"] }
malloc_size_of = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head", features = ["servo"] }
malloc_size_of_derive = "0.1"
mime = "0.3.13"
mime_guess = "2.0.3"
Expand All @@ -87,31 +87,31 @@ rustls = { version = "0.21.11", features = ["dangerous_configuration"] }
rustls-pemfile = "1.0.4"
script_layout_interface = { path = "components/shared/script_layout" }
script_traits = { path = "components/shared/script" }
selectors = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
selectors = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
serde = "1.0.198"
serde_bytes = "0.11"
serde_json = "1.0"
servo-media = { git = "https://github.com/servo/media" }
servo-media-dummy = { git = "https://github.com/servo/media" }
servo-media-gstreamer = { git = "https://github.com/servo/media" }
servo_arc = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
servo_atoms = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
size_of_test = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
servo_arc = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
servo_atoms = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
size_of_test = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
smallbitvec = "2.5.3"
smallvec = "1.13"
sparkle = "0.1.26"
string_cache = "0.8"
string_cache_codegen = "0.5"
style = { git = "https://github.com/servo/stylo", branch = "2024-04-16", features = ["servo"] }
style_config = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
style_traits = { git = "https://github.com/servo/stylo", branch = "2024-04-16", features = ["servo"] }
style = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head", features = ["servo"] }
style_config = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
style_traits = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head", features = ["servo"] }
# NOTE: the sm-angle feature only 2024-03-01rms!
surfman = { version = "0.9", features = ["chains", "sm-angle", "sm-angle-default"] }
syn = { version = "2", default-features = false, features = ["clone-impls", "derive", "parsing"] }
synstructure = "0.13"
thin-vec = "0.2.13"
time = "0.1.41"
to_shmem = { git = "https://github.com/servo/stylo", branch = "2024-04-16" }
to_shmem = { git = "https://github.com/servo/stylo", rev = "refs/pull/37/head" }
tokio = "1"
tokio-rustls = "0.24"
tungstenite = "0.20"
Expand Down
24 changes: 15 additions & 9 deletions components/layout/fragment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}

Expand Down
102 changes: 57 additions & 45 deletions components/layout/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
}
};

Expand Down Expand Up @@ -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 {
Expand All @@ -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"
);
Expand Down Expand Up @@ -1494,53 +1495,64 @@ 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 => {
intrinsic_sizes_for_nonbroken_run
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment);

// Flush the intrinsic sizes we've been gathering up in order to handle the
// line break, if necessary.
if fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
let style_text = fragment.style.get_inherited_text();
match style_text.white_space_collapse {
WhiteSpaceCollapse::Collapse => match style_text.text_wrap_mode {
TextWrapMode::Nowrap => intrinsic_sizes_for_nonbroken_run
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment),
TextWrapMode::Wrap => {
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
// necessary.
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();
intrinsic_sizes_for_flow
.union_block(&intrinsic_sizes_for_inline_run.finish());
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
}

intrinsic_sizes_for_nonbroken_run
.union_inline(&intrinsic_sizes_for_fragment);
},
},
WhiteSpace::PreWrap | WhiteSpace::PreLine => {
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
// necessary.
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();

intrinsic_sizes_for_nonbroken_run.union_inline(&intrinsic_sizes_for_fragment);

// Flush the intrinsic sizes we've been gathering up in order to handle the
// line break, if necessary.
if fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();
intrinsic_sizes_for_flow
.union_block(&intrinsic_sizes_for_inline_run.finish());
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
WhiteSpaceCollapse::Preserve | WhiteSpaceCollapse::PreserveBreaks => {
match style_text.text_wrap_mode {
TextWrapMode::Nowrap => {
intrinsic_sizes_for_nonbroken_run
.union_nonbreaking_inline(&intrinsic_sizes_for_fragment);

// Flush the intrinsic sizes we've been gathering up in order to handle the
// line break, if necessary.
if fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run =
IntrinsicISizesContribution::new();
intrinsic_sizes_for_flow
.union_block(&intrinsic_sizes_for_inline_run.finish());
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
}
},
TextWrapMode::Wrap => {
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
// necessary.
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();

intrinsic_sizes_for_nonbroken_run
.union_inline(&intrinsic_sizes_for_fragment);

// Flush the intrinsic sizes we've been gathering up in order to handle the
// line break, if necessary.
if fragment.requires_line_break_afterward_if_wrapping_on_newlines() {
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run =
IntrinsicISizesContribution::new();
intrinsic_sizes_for_flow
.union_block(&intrinsic_sizes_for_inline_run.finish());
intrinsic_sizes_for_inline_run = IntrinsicISizesContribution::new();
}
},
}
},
WhiteSpace::Normal => {
// Flush the intrinsic sizes we were gathering up for the nonbroken run, if
// necessary.
intrinsic_sizes_for_inline_run
.union_inline(&intrinsic_sizes_for_nonbroken_run.finish());
intrinsic_sizes_for_nonbroken_run = IntrinsicISizesContribution::new();

intrinsic_sizes_for_nonbroken_run.union_inline(&intrinsic_sizes_for_fragment);
},
}

fragment
Expand Down

0 comments on commit 5542a7f

Please sign in to comment.