OLD | NEW |
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 |
11 namespace blink { | 11 namespace blink { |
12 | 12 |
13 NGInlineItemsBuilder::~NGInlineItemsBuilder() { | 13 template <typename OffsetMappingBuilder> |
| 14 NGInlineItemsBuilderTemplate< |
| 15 OffsetMappingBuilder>::~NGInlineItemsBuilderTemplate() { |
14 DCHECK_EQ(0u, exits_.size()); | 16 DCHECK_EQ(0u, exits_.size()); |
15 DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); | 17 DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); |
16 } | 18 } |
17 | 19 |
18 String NGInlineItemsBuilder::ToString() { | 20 template <typename OffsetMappingBuilder> |
| 21 String NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ToString() { |
19 // Segment Break Transformation Rules[1] defines to keep trailing new lines, | 22 // Segment Break Transformation Rules[1] defines to keep trailing new lines, |
20 // but it will be removed in Phase II[2]. We prefer not to add trailing new | 23 // but it will be removed in Phase II[2]. We prefer not to add trailing new |
21 // lines and collapsible spaces in Phase I. | 24 // lines and collapsible spaces in Phase I. |
22 // [1] https://drafts.csswg.org/css-text-3/#line-break-transform | 25 // [1] https://drafts.csswg.org/css-text-3/#line-break-transform |
23 // [2] https://drafts.csswg.org/css-text-3/#white-space-phase-2 | 26 // [2] https://drafts.csswg.org/css-text-3/#white-space-phase-2 |
24 RemoveTrailingCollapsibleSpaceIfExists(); | 27 RemoveTrailingCollapsibleSpaceIfExists(); |
25 | 28 |
26 return text_.ToString(); | 29 return text_.ToString(); |
27 } | 30 } |
28 | 31 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 return c == kSpaceCharacter || c == kTabulationCharacter || | 119 return c == kSpaceCharacter || c == kTabulationCharacter || |
117 c == kNewlineCharacter; | 120 c == kNewlineCharacter; |
118 } | 121 } |
119 | 122 |
120 // Characters needing a separate control item than other text items. | 123 // Characters needing a separate control item than other text items. |
121 // It makes the line breaker easier to handle. | 124 // It makes the line breaker easier to handle. |
122 static inline bool IsControlItemCharacter(UChar c) { | 125 static inline bool IsControlItemCharacter(UChar c) { |
123 return c == kTabulationCharacter || c == kNewlineCharacter; | 126 return c == kTabulationCharacter || c == kNewlineCharacter; |
124 } | 127 } |
125 | 128 |
126 void NGInlineItemsBuilder::Append(const String& string, | 129 template <typename OffsetMappingBuilder> |
127 const ComputedStyle* style, | 130 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append( |
128 LayoutObject* layout_object) { | 131 const String& string, |
| 132 const ComputedStyle* style, |
| 133 LayoutObject* layout_object) { |
129 if (string.IsEmpty()) | 134 if (string.IsEmpty()) |
130 return; | 135 return; |
131 text_.ReserveCapacity(string.length()); | 136 text_.ReserveCapacity(string.length()); |
132 | 137 |
133 EWhiteSpace whitespace = style->WhiteSpace(); | 138 EWhiteSpace whitespace = style->WhiteSpace(); |
134 if (!ComputedStyle::CollapseWhiteSpace(whitespace)) | 139 if (!ComputedStyle::CollapseWhiteSpace(whitespace)) |
135 return AppendWithoutWhiteSpaceCollapsing(string, style, layout_object); | 140 return AppendWithoutWhiteSpaceCollapsing(string, style, layout_object); |
136 if (ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_) | 141 if (ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_) |
137 return AppendWithPreservingNewlines(string, style, layout_object); | 142 return AppendWithPreservingNewlines(string, style, layout_object); |
138 | 143 |
139 AppendWithWhiteSpaceCollapsing(string, 0, string.length(), style, | 144 AppendWithWhiteSpaceCollapsing(string, 0, string.length(), style, |
140 layout_object); | 145 layout_object); |
141 } | 146 } |
142 | 147 |
143 void NGInlineItemsBuilder::AppendWithWhiteSpaceCollapsing( | 148 template <typename OffsetMappingBuilder> |
144 const String& string, | 149 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: |
145 unsigned start, | 150 AppendWithWhiteSpaceCollapsing(const String& string, |
146 unsigned end, | 151 unsigned start, |
147 const ComputedStyle* style, | 152 unsigned end, |
148 LayoutObject* layout_object) { | 153 const ComputedStyle* style, |
| 154 LayoutObject* layout_object) { |
149 unsigned start_offset = text_.length(); | 155 unsigned start_offset = text_.length(); |
150 for (unsigned i = start; i < end;) { | 156 for (unsigned i = start; i < end;) { |
151 UChar c = string[i]; | 157 UChar c = string[i]; |
152 if (c == kNewlineCharacter) { | 158 if (c == kNewlineCharacter) { |
153 // LayoutBR does not set preserve_newline, but should be preserved. | 159 // LayoutBR does not set preserve_newline, but should be preserved. |
154 if (!i && end == 1 && layout_object && layout_object->IsBR()) { | 160 if (!i && end == 1 && layout_object && layout_object->IsBR()) { |
155 AppendForcedBreak(style, layout_object); | 161 AppendForcedBreak(style, layout_object); |
156 return; | 162 return; |
157 } | 163 } |
158 | 164 |
(...skipping 27 matching lines...) Expand all Loading... |
186 } | 192 } |
187 | 193 |
188 if (text_.length() > start_offset) { | 194 if (text_.length() > start_offset) { |
189 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, | 195 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, |
190 layout_object); | 196 layout_object); |
191 } | 197 } |
192 } | 198 } |
193 | 199 |
194 // Even when without whitespace collapsing, control characters (newlines and | 200 // Even when without whitespace collapsing, control characters (newlines and |
195 // tabs) are in their own control items to make the line breaker easier. | 201 // tabs) are in their own control items to make the line breaker easier. |
196 void NGInlineItemsBuilder::AppendWithoutWhiteSpaceCollapsing( | 202 template <typename OffsetMappingBuilder> |
197 const String& string, | 203 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: |
198 const ComputedStyle* style, | 204 AppendWithoutWhiteSpaceCollapsing(const String& string, |
199 LayoutObject* layout_object) { | 205 const ComputedStyle* style, |
| 206 LayoutObject* layout_object) { |
200 for (unsigned start = 0; start < string.length();) { | 207 for (unsigned start = 0; start < string.length();) { |
201 UChar c = string[start]; | 208 UChar c = string[start]; |
202 if (IsControlItemCharacter(c)) { | 209 if (IsControlItemCharacter(c)) { |
203 Append(NGInlineItem::kControl, c, style, layout_object); | 210 Append(NGInlineItem::kControl, c, style, layout_object); |
204 start++; | 211 start++; |
205 continue; | 212 continue; |
206 } | 213 } |
207 | 214 |
208 size_t end = string.Find(IsControlItemCharacter, start + 1); | 215 size_t end = string.Find(IsControlItemCharacter, start + 1); |
209 if (end == kNotFound) | 216 if (end == kNotFound) |
210 end = string.length(); | 217 end = string.length(); |
211 unsigned start_offset = text_.length(); | 218 unsigned start_offset = text_.length(); |
212 text_.Append(string, start, end - start); | 219 text_.Append(string, start, end - start); |
213 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, | 220 AppendItem(items_, NGInlineItem::kText, start_offset, text_.length(), style, |
214 layout_object); | 221 layout_object); |
215 start = end; | 222 start = end; |
216 } | 223 } |
217 | 224 |
218 last_collapsible_space_ = CollapsibleSpace::kNone; | 225 last_collapsible_space_ = CollapsibleSpace::kNone; |
219 } | 226 } |
220 | 227 |
221 void NGInlineItemsBuilder::AppendWithPreservingNewlines( | 228 template <typename OffsetMappingBuilder> |
222 const String& string, | 229 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: |
223 const ComputedStyle* style, | 230 AppendWithPreservingNewlines(const String& string, |
224 LayoutObject* layout_object) { | 231 const ComputedStyle* style, |
| 232 LayoutObject* layout_object) { |
225 for (unsigned start = 0; start < string.length();) { | 233 for (unsigned start = 0; start < string.length();) { |
226 if (string[start] == kNewlineCharacter) { | 234 if (string[start] == kNewlineCharacter) { |
227 AppendForcedBreak(style, layout_object); | 235 AppendForcedBreak(style, layout_object); |
228 start++; | 236 start++; |
229 continue; | 237 continue; |
230 } | 238 } |
231 | 239 |
232 size_t end = string.find(kNewlineCharacter, start + 1); | 240 size_t end = string.find(kNewlineCharacter, start + 1); |
233 if (end == kNotFound) | 241 if (end == kNotFound) |
234 end = string.length(); | 242 end = string.length(); |
235 AppendWithWhiteSpaceCollapsing(string, start, end, style, layout_object); | 243 AppendWithWhiteSpaceCollapsing(string, start, end, style, layout_object); |
236 start = end; | 244 start = end; |
237 } | 245 } |
238 } | 246 } |
239 | 247 |
240 void NGInlineItemsBuilder::AppendForcedBreak(const ComputedStyle* style, | 248 template <typename OffsetMappingBuilder> |
241 LayoutObject* layout_object) { | 249 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendForcedBreak( |
| 250 const ComputedStyle* style, |
| 251 LayoutObject* layout_object) { |
242 // Remove collapsible spaces immediately before a preserved newline. | 252 // Remove collapsible spaces immediately before a preserved newline. |
243 RemoveTrailingCollapsibleSpaceIfExists(); | 253 RemoveTrailingCollapsibleSpaceIfExists(); |
244 | 254 |
245 Append(NGInlineItem::kControl, kNewlineCharacter, style, layout_object); | 255 Append(NGInlineItem::kControl, kNewlineCharacter, style, layout_object); |
246 | 256 |
247 // Remove collapsible spaces immediately after a preserved newline. | 257 // Remove collapsible spaces immediately after a preserved newline. |
248 last_collapsible_space_ = CollapsibleSpace::kSpace; | 258 last_collapsible_space_ = CollapsibleSpace::kSpace; |
249 } | 259 } |
250 | 260 |
251 void NGInlineItemsBuilder::Append(NGInlineItem::NGInlineItemType type, | 261 template <typename OffsetMappingBuilder> |
252 UChar character, | 262 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Append( |
253 const ComputedStyle* style, | 263 NGInlineItem::NGInlineItemType type, |
254 LayoutObject* layout_object) { | 264 UChar character, |
| 265 const ComputedStyle* style, |
| 266 LayoutObject* layout_object) { |
255 DCHECK_NE(character, kSpaceCharacter); | 267 DCHECK_NE(character, kSpaceCharacter); |
256 DCHECK_NE(character, kZeroWidthSpaceCharacter); | 268 DCHECK_NE(character, kZeroWidthSpaceCharacter); |
257 | 269 |
258 text_.Append(character); | 270 text_.Append(character); |
259 unsigned end_offset = text_.length(); | 271 unsigned end_offset = text_.length(); |
260 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); | 272 AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); |
261 last_collapsible_space_ = CollapsibleSpace::kNone; | 273 last_collapsible_space_ = CollapsibleSpace::kNone; |
262 } | 274 } |
263 | 275 |
264 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 276 template <typename OffsetMappingBuilder> |
265 UChar character) { | 277 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque( |
| 278 NGInlineItem::NGInlineItemType type, |
| 279 UChar character) { |
266 text_.Append(character); | 280 text_.Append(character); |
267 unsigned end_offset = text_.length(); | 281 unsigned end_offset = text_.length(); |
268 AppendItem(items_, type, end_offset - 1, end_offset, nullptr, nullptr); | 282 AppendItem(items_, type, end_offset - 1, end_offset, nullptr, nullptr); |
269 } | 283 } |
270 | 284 |
271 void NGInlineItemsBuilder::AppendOpaque(NGInlineItem::NGInlineItemType type, | 285 template <typename OffsetMappingBuilder> |
272 const ComputedStyle* style, | 286 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendOpaque( |
273 LayoutObject* layout_object) { | 287 NGInlineItem::NGInlineItemType type, |
| 288 const ComputedStyle* style, |
| 289 LayoutObject* layout_object) { |
274 unsigned end_offset = text_.length(); | 290 unsigned end_offset = text_.length(); |
275 AppendItem(items_, type, end_offset, end_offset, style, layout_object); | 291 AppendItem(items_, type, end_offset, end_offset, style, layout_object); |
276 } | 292 } |
277 | 293 |
278 // Removes the collapsible newline at the end of |text_| if exists and the | 294 // Removes the collapsible newline at the end of |text_| if exists and the |
279 // removal conditions met. | 295 // removal conditions met. |
280 void NGInlineItemsBuilder::RemoveTrailingCollapsibleNewlineIfNeeded( | 296 template <typename OffsetMappingBuilder> |
281 const String& after, | 297 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>:: |
282 unsigned after_index, | 298 RemoveTrailingCollapsibleNewlineIfNeeded(const String& after, |
283 const ComputedStyle* after_style) { | 299 unsigned after_index, |
| 300 const ComputedStyle* after_style) { |
284 DCHECK_EQ(last_collapsible_space_, CollapsibleSpace::kNewline); | 301 DCHECK_EQ(last_collapsible_space_, CollapsibleSpace::kNewline); |
285 | 302 |
286 if (text_.IsEmpty() || text_[text_.length() - 1] != kSpaceCharacter) | 303 if (text_.IsEmpty() || text_[text_.length() - 1] != kSpaceCharacter) |
287 return; | 304 return; |
288 | 305 |
289 const ComputedStyle* before_style = after_style; | 306 const ComputedStyle* before_style = after_style; |
290 if (!items_->IsEmpty()) { | 307 if (!items_->IsEmpty()) { |
291 NGInlineItem& item = items_->back(); | 308 NGInlineItem& item = items_->back(); |
292 if (text_.length() < item.EndOffset() + 2) | 309 if (text_.length() < item.EndOffset() + 2) |
293 before_style = item.Style(); | 310 before_style = item.Style(); |
294 } | 311 } |
295 | 312 |
296 if (ShouldRemoveNewline(text_, before_style, after, after_index, after_style)) | 313 if (ShouldRemoveNewline(text_, before_style, after, after_index, after_style)) |
297 RemoveTrailingCollapsibleSpace(text_.length() - 1); | 314 RemoveTrailingCollapsibleSpace(text_.length() - 1); |
298 } | 315 } |
299 | 316 |
300 // Removes the collapsible space at the end of |text_| if exists. | 317 // Removes the collapsible space at the end of |text_| if exists. |
301 void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpaceIfExists() { | 318 template <typename OffsetMappingBuilder> |
| 319 void NGInlineItemsBuilderTemplate< |
| 320 OffsetMappingBuilder>::RemoveTrailingCollapsibleSpaceIfExists() { |
302 if (last_collapsible_space_ == CollapsibleSpace::kNone || text_.IsEmpty()) | 321 if (last_collapsible_space_ == CollapsibleSpace::kNone || text_.IsEmpty()) |
303 return; | 322 return; |
304 | 323 |
305 // Look for the last space character since characters that are opaque to | 324 // Look for the last space character since characters that are opaque to |
306 // whitespace collapsing may be appended. | 325 // whitespace collapsing may be appended. |
307 for (unsigned i = text_.length(); i;) { | 326 for (unsigned i = text_.length(); i;) { |
308 UChar ch = text_[--i]; | 327 UChar ch = text_[--i]; |
309 if (ch == kSpaceCharacter) { | 328 if (ch == kSpaceCharacter) { |
310 RemoveTrailingCollapsibleSpace(i); | 329 RemoveTrailingCollapsibleSpace(i); |
311 return; | 330 return; |
312 } | 331 } |
313 | 332 |
314 // AppendForcedBreak sets CollapsibleSpace::kSpace to ignore leading | 333 // AppendForcedBreak sets CollapsibleSpace::kSpace to ignore leading |
315 // spaces. In this case, the trailing collapsible space does not exist. | 334 // spaces. In this case, the trailing collapsible space does not exist. |
316 if (ch == kNewlineCharacter) | 335 if (ch == kNewlineCharacter) |
317 return; | 336 return; |
318 } | 337 } |
319 NOTREACHED(); | 338 NOTREACHED(); |
320 } | 339 } |
321 | 340 |
322 // Removes the collapsible space at the specified index. | 341 // Removes the collapsible space at the specified index. |
323 void NGInlineItemsBuilder::RemoveTrailingCollapsibleSpace(unsigned index) { | 342 template <typename OffsetMappingBuilder> |
| 343 void NGInlineItemsBuilderTemplate< |
| 344 OffsetMappingBuilder>::RemoveTrailingCollapsibleSpace(unsigned index) { |
324 DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); | 345 DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); |
325 DCHECK(!text_.IsEmpty()); | 346 DCHECK(!text_.IsEmpty()); |
326 DCHECK_EQ(text_[index], kSpaceCharacter); | 347 DCHECK_EQ(text_[index], kSpaceCharacter); |
327 | 348 |
328 text_.erase(index); | 349 text_.erase(index); |
329 last_collapsible_space_ = CollapsibleSpace::kNone; | 350 last_collapsible_space_ = CollapsibleSpace::kNone; |
330 | 351 |
331 // Adjust items if the removed space is already included. | 352 // Adjust items if the removed space is already included. |
332 for (unsigned i = items_->size(); i > 0;) { | 353 for (unsigned i = items_->size(); i > 0;) { |
333 NGInlineItem& item = (*items_)[--i]; | 354 NGInlineItem& item = (*items_)[--i]; |
334 if (index >= item.EndOffset()) | 355 if (index >= item.EndOffset()) |
335 return; | 356 return; |
336 if (item.StartOffset() <= index) { | 357 if (item.StartOffset() <= index) { |
337 if (item.Length() == 1) { | 358 if (item.Length() == 1) { |
338 DCHECK_EQ(item.StartOffset(), index); | 359 DCHECK_EQ(item.StartOffset(), index); |
339 DCHECK_EQ(item.Type(), NGInlineItem::kText); | 360 DCHECK_EQ(item.Type(), NGInlineItem::kText); |
340 items_->erase(i); | 361 items_->erase(i); |
341 } else { | 362 } else { |
342 item.SetEndOffset(item.EndOffset() - 1); | 363 item.SetEndOffset(item.EndOffset() - 1); |
343 } | 364 } |
344 return; | 365 return; |
345 } | 366 } |
346 | 367 |
347 // Trailing spaces can be removed across non-character items. | 368 // Trailing spaces can be removed across non-character items. |
348 // Adjust their offsets if after the removed index. | 369 // Adjust their offsets if after the removed index. |
349 item.SetOffset(item.StartOffset() - 1, item.EndOffset() - 1); | 370 item.SetOffset(item.StartOffset() - 1, item.EndOffset() - 1); |
350 } | 371 } |
351 } | 372 } |
352 | 373 |
353 void NGInlineItemsBuilder::AppendBidiControl(const ComputedStyle* style, | 374 template <typename OffsetMappingBuilder> |
354 UChar ltr, | 375 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::AppendBidiControl( |
355 UChar rtl) { | 376 const ComputedStyle* style, |
| 377 UChar ltr, |
| 378 UChar rtl) { |
356 AppendOpaque(NGInlineItem::kBidiControl, | 379 AppendOpaque(NGInlineItem::kBidiControl, |
357 IsLtr(style->Direction()) ? ltr : rtl); | 380 IsLtr(style->Direction()) ? ltr : rtl); |
358 } | 381 } |
359 | 382 |
360 void NGInlineItemsBuilder::EnterBlock(const ComputedStyle* style) { | 383 template <typename OffsetMappingBuilder> |
| 384 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterBlock( |
| 385 const ComputedStyle* style) { |
361 // Handle bidi-override on the block itself. | 386 // Handle bidi-override on the block itself. |
362 switch (style->GetUnicodeBidi()) { | 387 switch (style->GetUnicodeBidi()) { |
363 case UnicodeBidi::kNormal: | 388 case UnicodeBidi::kNormal: |
364 case UnicodeBidi::kEmbed: | 389 case UnicodeBidi::kEmbed: |
365 case UnicodeBidi::kIsolate: | 390 case UnicodeBidi::kIsolate: |
366 // Isolate and embed values are enforced by default and redundant on the | 391 // Isolate and embed values are enforced by default and redundant on the |
367 // block elements. | 392 // block elements. |
368 // Direction is handled as the paragraph level by | 393 // Direction is handled as the paragraph level by |
369 // NGBidiParagraph::SetParagraph(). | 394 // NGBidiParagraph::SetParagraph(). |
370 if (style->Direction() == TextDirection::kRtl) | 395 if (style->Direction() == TextDirection::kRtl) |
371 has_bidi_controls_ = true; | 396 has_bidi_controls_ = true; |
372 break; | 397 break; |
373 case UnicodeBidi::kBidiOverride: | 398 case UnicodeBidi::kBidiOverride: |
374 case UnicodeBidi::kIsolateOverride: | 399 case UnicodeBidi::kIsolateOverride: |
375 AppendBidiControl(style, kLeftToRightOverrideCharacter, | 400 AppendBidiControl(style, kLeftToRightOverrideCharacter, |
376 kRightToLeftOverrideCharacter); | 401 kRightToLeftOverrideCharacter); |
377 Enter(nullptr, kPopDirectionalFormattingCharacter); | 402 Enter(nullptr, kPopDirectionalFormattingCharacter); |
378 break; | 403 break; |
379 case UnicodeBidi::kPlaintext: | 404 case UnicodeBidi::kPlaintext: |
380 // Plaintext is handled as the paragraph level by | 405 // Plaintext is handled as the paragraph level by |
381 // NGBidiParagraph::SetParagraph(). | 406 // NGBidiParagraph::SetParagraph(). |
382 has_bidi_controls_ = true; | 407 has_bidi_controls_ = true; |
383 break; | 408 break; |
384 } | 409 } |
385 } | 410 } |
386 | 411 |
387 void NGInlineItemsBuilder::EnterInline(LayoutObject* node) { | 412 template <typename OffsetMappingBuilder> |
| 413 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::EnterInline( |
| 414 LayoutObject* node) { |
388 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table | 415 // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-
table |
389 const ComputedStyle* style = node->Style(); | 416 const ComputedStyle* style = node->Style(); |
390 switch (style->GetUnicodeBidi()) { | 417 switch (style->GetUnicodeBidi()) { |
391 case UnicodeBidi::kNormal: | 418 case UnicodeBidi::kNormal: |
392 break; | 419 break; |
393 case UnicodeBidi::kEmbed: | 420 case UnicodeBidi::kEmbed: |
394 AppendBidiControl(style, kLeftToRightEmbedCharacter, | 421 AppendBidiControl(style, kLeftToRightEmbedCharacter, |
395 kRightToLeftEmbedCharacter); | 422 kRightToLeftEmbedCharacter); |
396 Enter(node, kPopDirectionalFormattingCharacter); | 423 Enter(node, kPopDirectionalFormattingCharacter); |
397 break; | 424 break; |
(...skipping 16 matching lines...) Expand all Loading... |
414 AppendBidiControl(style, kLeftToRightOverrideCharacter, | 441 AppendBidiControl(style, kLeftToRightOverrideCharacter, |
415 kRightToLeftOverrideCharacter); | 442 kRightToLeftOverrideCharacter); |
416 Enter(node, kPopDirectionalIsolateCharacter); | 443 Enter(node, kPopDirectionalIsolateCharacter); |
417 Enter(node, kPopDirectionalFormattingCharacter); | 444 Enter(node, kPopDirectionalFormattingCharacter); |
418 break; | 445 break; |
419 } | 446 } |
420 | 447 |
421 AppendOpaque(NGInlineItem::kOpenTag, style, node); | 448 AppendOpaque(NGInlineItem::kOpenTag, style, node); |
422 } | 449 } |
423 | 450 |
424 void NGInlineItemsBuilder::Enter(LayoutObject* node, UChar character_to_exit) { | 451 template <typename OffsetMappingBuilder> |
| 452 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Enter( |
| 453 LayoutObject* node, |
| 454 UChar character_to_exit) { |
425 exits_.push_back(OnExitNode{node, character_to_exit}); | 455 exits_.push_back(OnExitNode{node, character_to_exit}); |
426 has_bidi_controls_ = true; | 456 has_bidi_controls_ = true; |
427 } | 457 } |
428 | 458 |
429 void NGInlineItemsBuilder::ExitBlock() { | 459 template <typename OffsetMappingBuilder> |
| 460 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ExitBlock() { |
430 Exit(nullptr); | 461 Exit(nullptr); |
431 } | 462 } |
432 | 463 |
433 void NGInlineItemsBuilder::ExitInline(LayoutObject* node) { | 464 template <typename OffsetMappingBuilder> |
| 465 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::ExitInline( |
| 466 LayoutObject* node) { |
434 DCHECK(node); | 467 DCHECK(node); |
435 | 468 |
436 AppendOpaque(NGInlineItem::kCloseTag, node->Style(), node); | 469 AppendOpaque(NGInlineItem::kCloseTag, node->Style(), node); |
437 | 470 |
438 Exit(node); | 471 Exit(node); |
439 } | 472 } |
440 | 473 |
441 void NGInlineItemsBuilder::Exit(LayoutObject* node) { | 474 template <typename OffsetMappingBuilder> |
| 475 void NGInlineItemsBuilderTemplate<OffsetMappingBuilder>::Exit( |
| 476 LayoutObject* node) { |
442 while (!exits_.IsEmpty() && exits_.back().node == node) { | 477 while (!exits_.IsEmpty() && exits_.back().node == node) { |
443 AppendOpaque(NGInlineItem::kBidiControl, exits_.back().character); | 478 AppendOpaque(NGInlineItem::kBidiControl, exits_.back().character); |
444 exits_.pop_back(); | 479 exits_.pop_back(); |
445 } | 480 } |
446 } | 481 } |
447 | 482 |
| 483 template class CORE_TEMPLATE_EXPORT |
| 484 NGInlineItemsBuilderTemplate<EmptyOffsetMappingBuilder>; |
| 485 |
448 } // namespace blink | 486 } // namespace blink |
OLD | NEW |