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

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

Issue 2870413005: [LayoutNG] Add "Control" NGInlineItemType for newlines and tabs (Closed)
Patch Set: Created 3 years, 7 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/inline/ng_inline_items_builder.cc
diff --git a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc
index 2aec0936902d03f51dcafc4d9a3dd54523d28f61..1038485901038a4a211dbd51b71fa06440c5c91e 100644
--- a/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc
+++ b/third_party/WebKit/Source/core/layout/ng/inline/ng_inline_items_builder.cc
@@ -113,9 +113,15 @@ static void AppendItem(Vector<NGInlineItem>* items,
items->push_back(NGInlineItem(type, start, end, style, layout_object));
}
-static inline bool IsCollapsibleSpace(UChar c, bool preserve_newline) {
+static inline bool IsCollapsibleSpace(UChar c) {
return c == kSpaceCharacter || c == kTabulationCharacter ||
- (!preserve_newline && c == kNewlineCharacter);
+ c == kNewlineCharacter;
+}
+
+// Characters needing a separate control item than other text items.
+// It makes the line breaker easier to handle.
+static inline bool IsControlItemCharacter(UChar c) {
+ return c == kTabulationCharacter || c == kNewlineCharacter;
}
void NGInlineItemsBuilder::Append(const String& string,
@@ -123,59 +129,60 @@ void NGInlineItemsBuilder::Append(const String& string,
LayoutObject* layout_object) {
if (string.IsEmpty())
return;
+ text_.ReserveCapacity(string.length());
EWhiteSpace whitespace = style->WhiteSpace();
- bool preserve_newline =
- ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_;
- bool collapse_whitespace = ComputedStyle::CollapseWhiteSpace(whitespace);
- unsigned start_offset = text_.length();
+ if (!ComputedStyle::CollapseWhiteSpace(whitespace))
+ return AppendWithoutWhiteSpaceCollapsing(string, style, layout_object);
+ if (ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_)
+ return AppendWithPreservingNewlines(string, style, layout_object);
- if (!collapse_whitespace) {
- text_.Append(string);
- last_collapsible_space_ = CollapsibleSpace::kNone;
- } else {
- text_.ReserveCapacity(string.length());
- for (unsigned i = 0; i < string.length();) {
- UChar c = string[i];
- if (c == kNewlineCharacter) {
- if (preserve_newline) {
- RemoveTrailingCollapsibleSpaceIfExists(&start_offset);
- text_.Append(c);
- // Remove collapsible spaces immediately following a newline.
- last_collapsible_space_ = CollapsibleSpace::kSpace;
- i++;
- continue;
- }
-
- if (last_collapsible_space_ == CollapsibleSpace::kNone)
- text_.Append(kSpaceCharacter);
- last_collapsible_space_ = CollapsibleSpace::kNewline;
- i++;
- continue;
- }
+ AppendWithWhiteSpaceCollapsing(string, 0, string.length(), style,
+ layout_object);
+}
- if (c == kSpaceCharacter || c == kTabulationCharacter) {
- if (last_collapsible_space_ == CollapsibleSpace::kNone) {
- text_.Append(kSpaceCharacter);
- last_collapsible_space_ = CollapsibleSpace::kSpace;
- }
- i++;
- continue;
+void NGInlineItemsBuilder::AppendWithWhiteSpaceCollapsing(
+ const String& string,
+ unsigned start,
+ unsigned end,
+ const ComputedStyle* style,
+ LayoutObject* layout_object) {
+ unsigned start_offset = text_.length();
+ for (unsigned i = start; i < end;) {
+ UChar c = string[i];
+ if (c == kNewlineCharacter) {
+ // LayoutBR does not set preserve_newline, but should be preserved.
+ if (!i && end == 1 && layout_object && layout_object->IsBR()) {
+ AppendForcedBreak(style, layout_object);
+ return;
}
- if (last_collapsible_space_ == CollapsibleSpace::kNewline) {
- RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i,
- style);
- }
+ if (last_collapsible_space_ == CollapsibleSpace::kNone)
+ text_.Append(kSpaceCharacter);
+ last_collapsible_space_ = CollapsibleSpace::kNewline;
+ i++;
+ continue;
+ }
- unsigned start_of_non_space = i;
- for (i++; i < string.length(); i++) {
- if (IsCollapsibleSpace(string[i], false))
- break;
+ if (c == kSpaceCharacter || c == kTabulationCharacter) {
+ if (last_collapsible_space_ == CollapsibleSpace::kNone) {
+ text_.Append(kSpaceCharacter);
+ last_collapsible_space_ = CollapsibleSpace::kSpace;
}
- text_.Append(string, start_of_non_space, i - start_of_non_space);
- last_collapsible_space_ = CollapsibleSpace::kNone;
+ i++;
+ continue;
}
+
+ if (last_collapsible_space_ == CollapsibleSpace::kNewline) {
+ RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i, style);
+ }
+
+ size_t end_of_non_space = string.Find(IsCollapsibleSpace, i + 1);
+ if (end_of_non_space == kNotFound)
+ end_of_non_space = string.length();
+ text_.Append(string, i, end_of_non_space - i);
+ i = end_of_non_space;
+ last_collapsible_space_ = CollapsibleSpace::kNone;
}
if (text_.length() > start_offset) {
@@ -184,13 +191,69 @@ void NGInlineItemsBuilder::Append(const String& string,
}
}
+// Even when without whitespace collapsing, control characters (newlines and
+// tabs) are in their own control items to make the line breaker easier.
+void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing(
+ const String& string,
+ const ComputedStyle* style,
+ LayoutObject* layout_object) {
+ for (unsigned start = 0; start < string.length();) {
+ UChar c = string[start];
+ if (IsControlItemCharacter(c)) {
+ Append(NGInlineItem::kControl, c, style, layout_object);
+ start++;
+ continue;
+ }
+
+ size_t end = string.Find(IsControlItemCharacter, start + 1);
+ if (end == kNotFound)
+ end = string.length();
+ unsigned start_offset = text_.length();
+ text_.Append(string, start, end - start);
+ AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style,
+ layout_object);
+ start = end;
+ }
+
+ last_collapsible_space_ = CollapsibleSpace::kNone;
+}
+
+void NGInlineItemsBuilder::AppendWithPreservingNewlines(
+ const String& string,
+ const ComputedStyle* style,
+ LayoutObject* layout_object) {
+ for (unsigned start = 0; start < string.length();) {
+ if (string[start] == kNewlineCharacter) {
+ AppendForcedBreak(style, layout_object);
+ start++;
+ continue;
+ }
+
+ size_t end = string.find(kNewlineCharacter, start + 1);
+ if (end == kNotFound)
+ end = string.length();
+ AppendWithWhiteSpaceCollapsing(string, start, end, style, layout_object);
+ start = end;
+ }
+}
+
+void NGInlineItemsBuilder::AppendForcedBreak(const ComputedStyle* style,
+ LayoutObject* layout_object) {
+ // Remove collapsible spaces immediately before a preserved newline.
+ unsigned start_offset = text_.length();
+ RemoveTrailingCollapsibleSpaceIfExists(&start_offset);
+
+ Append(NGInlineItem::kControl, kNewlineCharacter, style, layout_object);
+
+ // Remove collapsible spaces immediately after a preserved newline.
+ last_collapsible_space_ = CollapsibleSpace::kSpace;
+}
+
void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type,
UChar character,
const ComputedStyle* style,
LayoutObject* layout_object) {
DCHECK_NE(character, kSpaceCharacter);
- DCHECK_NE(character, kTabulationCharacter);
- DCHECK_NE(character, kNewlineCharacter);
DCHECK_NE(character, kZeroWidthSpaceCharacter);
text_.Append(character);

Powered by Google App Engine
This is Rietveld 408576698