diff options
author | Josh Matthews <josh@joshmatthews.net> | 2020-05-06 00:51:59 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2020-07-27 20:06:53 -0400 |
commit | d8b4dab4e38c2928f034248e158e8bf9b5ad60d6 (patch) | |
tree | 59f48ba368a55b7c37f147d9334ba525e7d2cb1e /components/layout_2020/flow/construct.rs | |
parent | c7bdb1bcc0cd4985277579b7585d1abbbe489287 (diff) | |
download | servo-d8b4dab4e38c2928f034248e158e8bf9b5ad60d6.tar.gz servo-d8b4dab4e38c2928f034248e158e8bf9b5ad60d6.zip |
Implement basic white-space: pre support for layout 2020.
Diffstat (limited to 'components/layout_2020/flow/construct.rs')
-rw-r--r-- | components/layout_2020/flow/construct.rs | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/components/layout_2020/flow/construct.rs b/components/layout_2020/flow/construct.rs index 00bcfdd2586..73aa0c151b5 100644 --- a/components/layout_2020/flow/construct.rs +++ b/components/layout_2020/flow/construct.rs @@ -20,6 +20,7 @@ use rayon_croissant::ParallelIteratorExt; use servo_arc::Arc; use std::borrow::Cow; use std::convert::{TryFrom, TryInto}; +use style::computed_values::white_space::T as WhiteSpace; use style::properties::longhands::list_style_position::computed_value::T as ListStylePosition; use style::properties::ComputedValues; use style::selector_parser::PseudoElement; @@ -293,7 +294,8 @@ where } fn handle_text(&mut self, info: &NodeAndStyleInfo<Node>, input: Cow<'dom, str>) { - let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input); + let white_space = info.style.get_inherited_text().white_space; + let (leading_whitespace, mut input) = self.handle_leading_whitespace(&input, white_space); if leading_whitespace || !input.is_empty() { // This text node should be pushed either to the next ongoing // inline level box with the parent style of that inline level box @@ -323,20 +325,37 @@ where if leading_whitespace { output.push(' ') } - loop { - if let Some(i) = input.bytes().position(|b| b.is_ascii_whitespace()) { - let (non_whitespace, rest) = input.split_at(i); - output.push_str(non_whitespace); - output.push(' '); - if let Some(i) = rest.bytes().position(|b| !b.is_ascii_whitespace()) { - input = &rest[i..]; + + match ( + white_space.preserve_spaces(), + white_space.preserve_newlines(), + ) { + (true, true) => { + output.push_str(input); + }, + + (true, false) => unreachable!(), + + (false, preserve_newlines) => loop { + if let Some(i) = input.bytes().position(|b| { + b.is_ascii_whitespace() && (!preserve_newlines || b != b'\n') + }) { + let (non_whitespace, rest) = input.split_at(i); + output.push_str(non_whitespace); + output.push(' '); + + if let Some(i) = rest.bytes().position(|b| { + !b.is_ascii_whitespace() || (preserve_newlines && b == b'\n') + }) { + input = &rest[i..]; + } else { + break; + } } else { + output.push_str(input); break; } - } else { - output.push_str(input); - break; - } + }, } } @@ -359,10 +378,14 @@ where /// /// * Whether this text run has preserved (non-collapsible) leading whitespace /// * The contents starting at the first non-whitespace character (or the empty string) - fn handle_leading_whitespace<'text>(&mut self, text: &'text str) -> (bool, &'text str) { + fn handle_leading_whitespace<'text>( + &mut self, + text: &'text str, + white_space: WhiteSpace, + ) -> (bool, &'text str) { // FIXME: this is only an approximation of // https://drafts.csswg.org/css2/text.html#white-space-model - if !text.starts_with(|c: char| c.is_ascii_whitespace()) { + if !text.starts_with(|c: char| c.is_ascii_whitespace()) || white_space.preserve_spaces() { return (false, text); } |