aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout_2020/flow/construct.rs
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2020-05-06 00:51:59 -0400
committerJosh Matthews <josh@joshmatthews.net>2020-07-27 20:06:53 -0400
commitd8b4dab4e38c2928f034248e158e8bf9b5ad60d6 (patch)
tree59f48ba368a55b7c37f147d9334ba525e7d2cb1e /components/layout_2020/flow/construct.rs
parentc7bdb1bcc0cd4985277579b7585d1abbbe489287 (diff)
downloadservo-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.rs51
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);
}