Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(896)

Unified Diff: third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc

Issue 2749013003: [LayoutNG] Fix whitespace collapsing when a node is a newline (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
index 1954a5bc8b587a6365425c63065f3d3fb5d267a0..d0785764e780e61ef94319ab6a75a17070b18502 100644
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc
@@ -22,7 +22,7 @@ String NGLayoutInlineItemsBuilder::ToString() {
// [1] https://drafts.csswg.org/css-text-3/#line-break-transform
// [2] https://drafts.csswg.org/css-text-3/#white-space-phase-2
unsigned next_start_offset = text_.length();
- RemoveTrailingCollapsibleSpace(&next_start_offset);
+ RemoveTrailingCollapsibleSpaceIfExists(&next_start_offset);
return text_.toString();
}
@@ -55,8 +55,9 @@ static bool ShouldRemoveNewlineSlow(const StringBuilder& before,
const ComputedStyle* after_style) {
// Remove if either before/after the newline is zeroWidthSpaceCharacter.
UChar32 last = 0;
- if (!before.isEmpty()) {
- last = before[before.length() - 1];
+ DCHECK(!before.isEmpty() && before[before.length() - 1] == ' ');
+ if (before.length() >= 2) {
+ last = before[before.length() - 2];
if (last == zeroWidthSpaceCharacter)
return true;
}
@@ -111,15 +112,17 @@ static void AppendItem(Vector<NGLayoutInlineItem>* items,
items->push_back(NGLayoutInlineItem(start, end, style, layout_object));
}
+static inline bool IsCollapsibleSpace(UChar c, bool preserve_newline) {
+ return c == spaceCharacter || c == tabulationCharacter ||
+ (!preserve_newline && c == newlineCharacter);
+}
+
void NGLayoutInlineItemsBuilder::Append(const String& string,
const ComputedStyle* style,
LayoutObject* layout_object) {
if (string.isEmpty())
return;
- if (has_pending_newline_)
- ProcessPendingNewline(string, style);
-
EWhiteSpace whitespace = style->whiteSpace();
bool preserve_newline =
ComputedStyle::preserveNewline(whitespace) && !is_svgtext_;
@@ -128,38 +131,49 @@ void NGLayoutInlineItemsBuilder::Append(const String& string,
if (!collapse_whitespace) {
text_.append(string);
- is_last_collapsible_space_ = false;
+ last_collapsible_space_ = CollapsibleSpace::None;
} else {
text_.reserveCapacity(string.length());
- for (unsigned i = 0; i < string.length(); i++) {
+ for (unsigned i = 0; i < string.length();) {
UChar c = string[i];
- bool is_collapsible_space;
if (c == newlineCharacter) {
- RemoveTrailingCollapsibleSpace(&start_offset);
if (preserve_newline) {
+ RemoveTrailingCollapsibleSpaceIfExists(&start_offset);
text_.append(c);
// Remove collapsible spaces immediately following a newline.
- is_last_collapsible_space_ = true;
+ last_collapsible_space_ = CollapsibleSpace::Space;
+ i++;
continue;
}
- if (i + 1 == string.length()) {
- // If at the end of string, process this newline on the next Append.
- has_pending_newline_ = true;
- break;
+
+ if (last_collapsible_space_ == CollapsibleSpace::None)
+ text_.append(spaceCharacter);
+ last_collapsible_space_ = CollapsibleSpace::Newline;
+ i++;
+ continue;
+ }
+
+ if (c == spaceCharacter || c == tabulationCharacter) {
+ if (last_collapsible_space_ == CollapsibleSpace::None) {
+ text_.append(spaceCharacter);
+ last_collapsible_space_ = CollapsibleSpace::Space;
}
- if (ShouldRemoveNewline(text_, style, string, i + 1, style))
- continue;
- is_collapsible_space = true;
- } else {
- is_collapsible_space = c == spaceCharacter || c == tabulationCharacter;
+ i++;
+ continue;
+ }
+
+ if (last_collapsible_space_ == CollapsibleSpace::Newline) {
+ RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i,
+ style);
}
- if (!is_collapsible_space) {
- text_.append(c);
- is_last_collapsible_space_ = false;
- } else if (!is_last_collapsible_space_) {
- text_.append(spaceCharacter);
- is_last_collapsible_space_ = true;
+
+ unsigned start_of_non_space = i;
+ for (i++; i < string.length(); i++) {
+ if (IsCollapsibleSpace(string[i], false))
+ break;
}
+ text_.append(string, start_of_non_space, i - start_of_non_space);
+ last_collapsible_space_ = CollapsibleSpace::None;
}
}
@@ -172,49 +186,49 @@ void NGLayoutInlineItemsBuilder::Append(UChar character,
LayoutObject* layout_object) {
DCHECK(character != spaceCharacter && character != tabulationCharacter &&
character != newlineCharacter && character != zeroWidthSpaceCharacter);
- if (has_pending_newline_)
- ProcessPendingNewline(emptyString, nullptr);
text_.append(character);
unsigned end_offset = text_.length();
AppendItem(items_, end_offset - 1, end_offset, style, layout_object);
- is_last_collapsible_space_ = false;
+ last_collapsible_space_ = CollapsibleSpace::None;
}
-void NGLayoutInlineItemsBuilder::AppendAsOpaqueToSpaceCollapsing(
- UChar character) {
- if (has_pending_newline_)
- ProcessPendingNewline(emptyString, nullptr);
+void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleNewlineIfNeeded(
+ unsigned* next_start_offset,
+ const String& after,
+ unsigned after_index,
+ const ComputedStyle* after_style) {
+ DCHECK_EQ(last_collapsible_space_, CollapsibleSpace::Newline);
- text_.append(character);
- unsigned end_offset = text_.length();
- AppendItem(items_, end_offset - 1, end_offset, nullptr);
-}
+ if (text_.isEmpty() || text_[text_.length() - 1] != spaceCharacter)
+ return;
-void NGLayoutInlineItemsBuilder::ProcessPendingNewline(
- const String& string,
- const ComputedStyle* style) {
- DCHECK(has_pending_newline_);
+ const ComputedStyle* before_style = after_style;
if (!items_->isEmpty()) {
NGLayoutInlineItem& item = items_->back();
- if (!ShouldRemoveNewline(text_, item.Style(), string, 0, style)) {
- text_.append(spaceCharacter);
- item.SetEndOffset(text_.length());
- }
+ if (text_.length() < item.EndOffset() + 2)
+ before_style = item.Style();
}
- // Remove spaces following a newline even when the newline was removed.
- is_last_collapsible_space_ = true;
- has_pending_newline_ = false;
+
+ if (ShouldRemoveNewline(text_, before_style, after, after_index, after_style))
+ RemoveTrailingCollapsibleSpace(next_start_offset);
+}
+
+void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleSpaceIfExists(
+ unsigned* next_start_offset) {
+ if (last_collapsible_space_ != CollapsibleSpace::None && !text_.isEmpty() &&
+ text_[text_.length() - 1] == spaceCharacter)
+ RemoveTrailingCollapsibleSpace(next_start_offset);
}
void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleSpace(
unsigned* next_start_offset) {
- if (!is_last_collapsible_space_ || text_.isEmpty())
- return;
- DCHECK_EQ(spaceCharacter, text_[text_.length() - 1]);
+ DCHECK_NE(last_collapsible_space_, CollapsibleSpace::None);
+ DCHECK(!text_.isEmpty() && text_[text_.length() - 1] == spaceCharacter);
+
unsigned new_size = text_.length() - 1;
text_.resize(new_size);
- is_last_collapsible_space_ = false;
+ last_collapsible_space_ = CollapsibleSpace::None;
// Adjust the last item if the removed space is already appended.
if (*next_start_offset > new_size) {
@@ -233,8 +247,7 @@ void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleSpace(
void NGLayoutInlineItemsBuilder::AppendBidiControl(const ComputedStyle* style,
UChar ltr,
UChar rtl) {
- AppendAsOpaqueToSpaceCollapsing(
- style->direction() == TextDirection::kRtl ? rtl : ltr);
+ Append(style->direction() == TextDirection::kRtl ? rtl : ltr);
}
void NGLayoutInlineItemsBuilder::EnterBlock(const ComputedStyle* style) {
@@ -273,11 +286,11 @@ void NGLayoutInlineItemsBuilder::EnterInline(LayoutObject* node) {
Enter(node, popDirectionalIsolateCharacter);
break;
case UnicodeBidi::kPlaintext:
- AppendAsOpaqueToSpaceCollapsing(firstStrongIsolateCharacter);
+ Append(firstStrongIsolateCharacter);
Enter(node, popDirectionalIsolateCharacter);
break;
case UnicodeBidi::kIsolateOverride:
- AppendAsOpaqueToSpaceCollapsing(firstStrongIsolateCharacter);
+ Append(firstStrongIsolateCharacter);
AppendBidiControl(style, leftToRightOverrideCharacter,
rightToLeftOverrideCharacter);
Enter(node, popDirectionalIsolateCharacter);
@@ -303,7 +316,7 @@ void NGLayoutInlineItemsBuilder::ExitInline(LayoutObject* node) {
void NGLayoutInlineItemsBuilder::Exit(LayoutObject* node) {
while (!exits_.isEmpty() && exits_.back().node == node) {
- AppendAsOpaqueToSpaceCollapsing(exits_.back().character);
+ Append(exits_.back().character);
exits_.pop_back();
}
}

Powered by Google App Engine
This is Rietveld 408576698