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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/layout/ng/inline/ng_inline_items_builder.h" 5 #include "core/layout/ng/inline/ng_inline_items_builder.h"
6 6
7 #include "core/layout/LayoutObject.h" 7 #include "core/layout/LayoutObject.h"
8 #include "core/layout/ng/inline/ng_inline_node.h" 8 #include "core/layout/ng/inline/ng_inline_node.h"
9 #include "core/style/ComputedStyle.h" 9 #include "core/style/ComputedStyle.h"
10 10
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 static void AppendItem(Vector<NGInlineItem>* items, 106 static void AppendItem(Vector<NGInlineItem>* items,
107 NGInlineItem::NGInlineItemType type, 107 NGInlineItem::NGInlineItemType type,
108 unsigned start, 108 unsigned start,
109 unsigned end, 109 unsigned end,
110 const ComputedStyle* style = nullptr, 110 const ComputedStyle* style = nullptr,
111 LayoutObject* layout_object = nullptr) { 111 LayoutObject* layout_object = nullptr) {
112 DCHECK(items->IsEmpty() || items->back().EndOffset() == start); 112 DCHECK(items->IsEmpty() || items->back().EndOffset() == start);
113 items->push_back(NGInlineItem(type, start, end, style, layout_object)); 113 items->push_back(NGInlineItem(type, start, end, style, layout_object));
114 } 114 }
115 115
116 static inline bool IsCollapsibleSpace(UChar c, bool preserve_newline) { 116 static inline bool IsCollapsibleSpace(UChar c) {
117 return c == kSpaceCharacter || c == kTabulationCharacter || 117 return c == kSpaceCharacter || c == kTabulationCharacter ||
118 (!preserve_newline && c == kNewlineCharacter); 118 c == kNewlineCharacter;
119 }
120
121 // Characters needing a separate control item than other text items.
122 // It makes the line breaker easier to handle.
123 static inline bool IsControlItemCharacter(UChar c) {
124 return c == kTabulationCharacter || c == kNewlineCharacter;
119 } 125 }
120 126
121 void NGInlineItemsBuilder::Append(const String& string, 127 void NGInlineItemsBuilder::Append(const String& string,
122 const ComputedStyle* style, 128 const ComputedStyle* style,
123 LayoutObject* layout_object) { 129 LayoutObject* layout_object) {
124 if (string.IsEmpty()) 130 if (string.IsEmpty())
125 return; 131 return;
132 text_.ReserveCapacity(string.length());
126 133
127 EWhiteSpace whitespace = style->WhiteSpace(); 134 EWhiteSpace whitespace = style->WhiteSpace();
128 bool preserve_newline = 135 if (!ComputedStyle::CollapseWhiteSpace(whitespace))
129 ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_; 136 return AppendWithoutWhiteSpaceCollapsing(string, style, layout_object);
130 bool collapse_whitespace = ComputedStyle::CollapseWhiteSpace(whitespace); 137 if (ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_)
138 return AppendWithPreservingNewlines(string, style, layout_object);
139
140 AppendWithWhiteSpaceCollapsing(string, 0, string.length(), style,
141 layout_object);
142 }
143
144 void NGInlineItemsBuilder::AppendWithWhiteSpaceCollapsing(
145 const String& string,
146 unsigned start,
147 unsigned end,
148 const ComputedStyle* style,
149 LayoutObject* layout_object) {
131 unsigned start_offset = text_.length(); 150 unsigned start_offset = text_.length();
132 151 for (unsigned i = start; i < end;) {
133 if (!collapse_whitespace) { 152 UChar c = string[i];
134 text_.Append(string); 153 if (c == kNewlineCharacter) {
135 last_collapsible_space_ = CollapsibleSpace::kNone; 154 // LayoutBR does not set preserve_newline, but should be preserved.
136 } else { 155 if (!i && end == 1 && layout_object && layout_object->IsBR()) {
137 text_.ReserveCapacity(string.length()); 156 AppendForcedBreak(style, layout_object);
138 for (unsigned i = 0; i < string.length();) { 157 return;
139 UChar c = string[i];
140 if (c == kNewlineCharacter) {
141 if (preserve_newline) {
142 RemoveTrailingCollapsibleSpaceIfExists(&start_offset);
143 text_.Append(c);
144 // Remove collapsible spaces immediately following a newline.
145 last_collapsible_space_ = CollapsibleSpace::kSpace;
146 i++;
147 continue;
148 }
149
150 if (last_collapsible_space_ == CollapsibleSpace::kNone)
151 text_.Append(kSpaceCharacter);
152 last_collapsible_space_ = CollapsibleSpace::kNewline;
153 i++;
154 continue;
155 } 158 }
156 159
157 if (c == kSpaceCharacter || c == kTabulationCharacter) { 160 if (last_collapsible_space_ == CollapsibleSpace::kNone)
158 if (last_collapsible_space_ == CollapsibleSpace::kNone) { 161 text_.Append(kSpaceCharacter);
159 text_.Append(kSpaceCharacter); 162 last_collapsible_space_ = CollapsibleSpace::kNewline;
160 last_collapsible_space_ = CollapsibleSpace::kSpace; 163 i++;
161 } 164 continue;
162 i++; 165 }
163 continue; 166
167 if (c == kSpaceCharacter || c == kTabulationCharacter) {
168 if (last_collapsible_space_ == CollapsibleSpace::kNone) {
169 text_.Append(kSpaceCharacter);
170 last_collapsible_space_ = CollapsibleSpace::kSpace;
164 } 171 }
172 i++;
173 continue;
174 }
165 175
166 if (last_collapsible_space_ == CollapsibleSpace::kNewline) { 176 if (last_collapsible_space_ == CollapsibleSpace::kNewline) {
167 RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i, 177 RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i, style);
168 style); 178 }
169 }
170 179
171 unsigned start_of_non_space = i; 180 size_t end_of_non_space = string.Find(IsCollapsibleSpace, i + 1);
172 for (i++; i < string.length(); i++) { 181 if (end_of_non_space == kNotFound)
173 if (IsCollapsibleSpace(string[i], false)) 182 end_of_non_space = string.length();
174 break; 183 text_.Append(string, i, end_of_non_space - i);
175 } 184 i = end_of_non_space;
176 text_.Append(string, start_of_non_space, i - start_of_non_space); 185 last_collapsible_space_ = CollapsibleSpace::kNone;
177 last_collapsible_space_ = CollapsibleSpace::kNone;
178 }
179 } 186 }
180 187
181 if (text_.length() > start_offset) { 188 if (text_.length() > start_offset) {
182 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, 189 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style,
183 layout_object); 190 layout_object);
184 } 191 }
185 } 192 }
186 193
194 // Even when without whitespace collapsing, control characters (newlines and
195 // tabs) are in their own control items to make the line breaker easier.
196 void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing(
197 const String& string,
198 const ComputedStyle* style,
199 LayoutObject* layout_object) {
200 for (unsigned start = 0; start < string.length();) {
201 UChar c = string[start];
202 if (IsControlItemCharacter(c)) {
203 Append(NGInlineItem::kControl, c, style, layout_object);
204 start++;
205 continue;
206 }
207
208 size_t end = string.Find(IsControlItemCharacter, start + 1);
209 if (end == kNotFound)
210 end = string.length();
211 unsigned start_offset = text_.length();
212 text_.Append(string, start, end - start);
213 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style,
214 layout_object);
215 start = end;
216 }
217
218 last_collapsible_space_ = CollapsibleSpace::kNone;
219 }
220
221 void NGInlineItemsBuilder::AppendWithPreservingNewlines(
222 const String& string,
223 const ComputedStyle* style,
224 LayoutObject* layout_object) {
225 for (unsigned start = 0; start < string.length();) {
226 if (string[start] == kNewlineCharacter) {
227 AppendForcedBreak(style, layout_object);
228 start++;
229 continue;
230 }
231
232 size_t end = string.find(kNewlineCharacter, start + 1);
233 if (end == kNotFound)
234 end = string.length();
235 AppendWithWhiteSpaceCollapsing(string, start, end, style, layout_object);
236 start = end;
237 }
238 }
239
240 void NGInlineItemsBuilder::AppendForcedBreak(const ComputedStyle* style,
241 LayoutObject* layout_object) {
242 // Remove collapsible spaces immediately before a preserved newline.
243 unsigned start_offset = text_.length();
244 RemoveTrailingCollapsibleSpaceIfExists(&start_offset);
245
246 Append(NGInlineItem::kControl, kNewlineCharacter, style, layout_object);
247
248 // Remove collapsible spaces immediately after a preserved newline.
249 last_collapsible_space_ = CollapsibleSpace::kSpace;
250 }
251
187 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, 252 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type,
188 UChar character, 253 UChar character,
189 const ComputedStyle* style, 254 const ComputedStyle* style,
190 LayoutObject* layout_object) { 255 LayoutObject* layout_object) {
191 DCHECK_NE(character, kSpaceCharacter); 256 DCHECK_NE(character, kSpaceCharacter);
192 DCHECK_NE(character, kTabulationCharacter);
193 DCHECK_NE(character, kNewlineCharacter);
194 DCHECK_NE(character, kZeroWidthSpaceCharacter); 257 DCHECK_NE(character, kZeroWidthSpaceCharacter);
195 258
196 text_.Append(character); 259 text_.Append(character);
197 unsigned end_offset = text_.length(); 260 unsigned end_offset = text_.length();
198 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); 261 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object);
199 last_collapsible_space_ = CollapsibleSpace::kNone; 262 last_collapsible_space_ = CollapsibleSpace::kNone;
200 } 263 }
201 264
202 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, 265 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type,
203 const ComputedStyle* style, 266 const ComputedStyle* style,
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 } 422 }
360 423
361 void NGInlineItemsBuilder::Exit(LayoutObject* node) { 424 void NGInlineItemsBuilder::Exit(LayoutObject* node) {
362 while (!exits_.IsEmpty() && exits_.back().node == node) { 425 while (!exits_.IsEmpty() && exits_.back().node == node) {
363 Append(NGInlineItem::kBidiControl, exits_.back().character); 426 Append(NGInlineItem::kBidiControl, exits_.back().character);
364 exits_.pop_back(); 427 exits_.pop_back();
365 } 428 }
366 } 429 }
367 430
368 } // namespace blink 431 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698