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 |
deleted file mode 100644 |
index d7f78ca6f4e4961f4bde12fdb52227d3d031489b..0000000000000000000000000000000000000000 |
--- a/third_party/WebKit/Source/core/layout/ng/ng_layout_inline_items_builder.cc |
+++ /dev/null |
@@ -1,371 +0,0 @@ |
-// Copyright 2016 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "core/layout/ng/ng_layout_inline_items_builder.h" |
- |
-#include "core/layout/LayoutObject.h" |
-#include "core/layout/ng/ng_inline_node.h" |
-#include "core/style/ComputedStyle.h" |
- |
-namespace blink { |
- |
-NGLayoutInlineItemsBuilder::~NGLayoutInlineItemsBuilder() { |
- DCHECK_EQ(0u, exits_.size()); |
- DCHECK_EQ(text_.length(), items_->IsEmpty() ? 0 : items_->back().EndOffset()); |
-} |
- |
-String NGLayoutInlineItemsBuilder::ToString() { |
- // Segment Break Transformation Rules[1] defines to keep trailing new lines, |
- // but it will be removed in Phase II[2]. We prefer not to add trailing new |
- // lines and collapsible spaces in Phase I. |
- // [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(); |
- RemoveTrailingCollapsibleSpaceIfExists(&next_start_offset); |
- |
- return text_.ToString(); |
-} |
- |
-// Determine "Ambiguous" East Asian Width is Wide or Narrow. |
-// Unicode East Asian Width |
-// http://unicode.org/reports/tr11/ |
-static bool IsAmbiguosEastAsianWidthWide(const ComputedStyle* style) { |
- UScriptCode script = style->GetFontDescription().Script(); |
- return script == USCRIPT_KATAKANA_OR_HIRAGANA || |
- script == USCRIPT_SIMPLIFIED_HAN || script == USCRIPT_TRADITIONAL_HAN; |
-} |
- |
-// Determine if a character has "Wide" East Asian Width. |
-static bool IsEastAsianWidthWide(UChar32 c, const ComputedStyle* style) { |
- UEastAsianWidth eaw = static_cast<UEastAsianWidth>( |
- u_getIntPropertyValue(c, UCHAR_EAST_ASIAN_WIDTH)); |
- return eaw == U_EA_WIDE || eaw == U_EA_FULLWIDTH || eaw == U_EA_HALFWIDTH || |
- (eaw == U_EA_AMBIGUOUS && style && |
- IsAmbiguosEastAsianWidthWide(style)); |
-} |
- |
-// Determine whether a newline should be removed or not. |
-// CSS Text, Segment Break Transformation Rules |
-// https://drafts.csswg.org/css-text-3/#line-break-transform |
-static bool ShouldRemoveNewlineSlow(const StringBuilder& before, |
- const ComputedStyle* before_style, |
- const String& after, |
- unsigned after_index, |
- const ComputedStyle* after_style) { |
- // Remove if either before/after the newline is zeroWidthSpaceCharacter. |
- UChar32 last = 0; |
- DCHECK(!before.IsEmpty()); |
- DCHECK_EQ(before[before.length() - 1], ' '); |
- if (before.length() >= 2) { |
- last = before[before.length() - 2]; |
- if (last == kZeroWidthSpaceCharacter) |
- return true; |
- } |
- UChar32 next = 0; |
- if (after_index < after.length()) { |
- next = after[after_index]; |
- if (next == kZeroWidthSpaceCharacter) |
- return true; |
- } |
- |
- // Logic below this point requires both before and after be 16 bits. |
- if (before.Is8Bit() || after.Is8Bit()) |
- return false; |
- |
- // Remove if East Asian Widths of both before/after the newline are Wide. |
- if (U16_IS_TRAIL(last) && before.length() >= 2) { |
- UChar last_last = before[before.length() - 2]; |
- if (U16_IS_LEAD(last_last)) |
- last = U16_GET_SUPPLEMENTARY(last_last, last); |
- } |
- if (IsEastAsianWidthWide(last, before_style)) { |
- if (U16_IS_LEAD(next) && after_index + 1 < after.length()) { |
- UChar next_next = after[after_index + 1]; |
- if (U16_IS_TRAIL(next_next)) |
- next = U16_GET_SUPPLEMENTARY(next, next_next); |
- } |
- if (IsEastAsianWidthWide(next, after_style)) |
- return true; |
- } |
- |
- return false; |
-} |
- |
-static bool ShouldRemoveNewline(const StringBuilder& before, |
- const ComputedStyle* before_style, |
- const String& after, |
- unsigned after_index, |
- const ComputedStyle* after_style) { |
- // All characters before/after removable newline are 16 bits. |
- return (!before.Is8Bit() || !after.Is8Bit()) && |
- ShouldRemoveNewlineSlow(before, before_style, after, after_index, |
- after_style); |
-} |
- |
-static void AppendItem(Vector<NGLayoutInlineItem>* items, |
- NGLayoutInlineItem::NGLayoutInlineItemType type, |
- unsigned start, |
- unsigned end, |
- const ComputedStyle* style = nullptr, |
- LayoutObject* layout_object = nullptr) { |
- DCHECK(items->IsEmpty() || items->back().EndOffset() == start); |
- items->push_back(NGLayoutInlineItem(type, start, end, style, layout_object)); |
-} |
- |
-static inline bool IsCollapsibleSpace(UChar c, bool preserve_newline) { |
- return c == kSpaceCharacter || c == kTabulationCharacter || |
- (!preserve_newline && c == kNewlineCharacter); |
-} |
- |
-void NGLayoutInlineItemsBuilder::Append(const String& string, |
- const ComputedStyle* style, |
- LayoutObject* layout_object) { |
- if (string.IsEmpty()) |
- return; |
- |
- EWhiteSpace whitespace = style->WhiteSpace(); |
- bool preserve_newline = |
- ComputedStyle::PreserveNewline(whitespace) && !is_svgtext_; |
- bool collapse_whitespace = ComputedStyle::CollapseWhiteSpace(whitespace); |
- unsigned start_offset = text_.length(); |
- |
- 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; |
- } |
- |
- if (c == kSpaceCharacter || c == kTabulationCharacter) { |
- if (last_collapsible_space_ == CollapsibleSpace::kNone) { |
- text_.Append(kSpaceCharacter); |
- last_collapsible_space_ = CollapsibleSpace::kSpace; |
- } |
- i++; |
- continue; |
- } |
- |
- if (last_collapsible_space_ == CollapsibleSpace::kNewline) { |
- RemoveTrailingCollapsibleNewlineIfNeeded(&start_offset, string, i, |
- style); |
- } |
- |
- 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::kNone; |
- } |
- } |
- |
- if (text_.length() > start_offset) { |
- AppendItem(items_, NGLayoutInlineItem::kText, start_offset, text_.length(), |
- style, layout_object); |
- } |
-} |
- |
-void NGLayoutInlineItemsBuilder::Append( |
- NGLayoutInlineItem::NGLayoutInlineItemType 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); |
- unsigned end_offset = text_.length(); |
- AppendItem(items_, type, end_offset - 1, end_offset, style, layout_object); |
- last_collapsible_space_ = CollapsibleSpace::kNone; |
-} |
- |
-void NGLayoutInlineItemsBuilder::Append( |
- NGLayoutInlineItem::NGLayoutInlineItemType type, |
- const ComputedStyle* style, |
- LayoutObject* layout_object) { |
- unsigned end_offset = text_.length(); |
- AppendItem(items_, type, end_offset, end_offset, style, layout_object); |
-} |
- |
-void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleNewlineIfNeeded( |
- unsigned* next_start_offset, |
- const String& after, |
- unsigned after_index, |
- const ComputedStyle* after_style) { |
- DCHECK_EQ(last_collapsible_space_, CollapsibleSpace::kNewline); |
- |
- if (text_.IsEmpty() || text_[text_.length() - 1] != kSpaceCharacter) |
- return; |
- |
- const ComputedStyle* before_style = after_style; |
- if (!items_->IsEmpty()) { |
- NGLayoutInlineItem& item = items_->back(); |
- if (text_.length() < item.EndOffset() + 2) |
- before_style = item.Style(); |
- } |
- |
- 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::kNone && !text_.IsEmpty() && |
- text_[text_.length() - 1] == kSpaceCharacter) |
- RemoveTrailingCollapsibleSpace(next_start_offset); |
-} |
- |
-void NGLayoutInlineItemsBuilder::RemoveTrailingCollapsibleSpace( |
- unsigned* next_start_offset) { |
- DCHECK_NE(last_collapsible_space_, CollapsibleSpace::kNone); |
- DCHECK(!text_.IsEmpty()); |
- DCHECK_EQ(text_[text_.length() - 1], kSpaceCharacter); |
- |
- unsigned new_size = text_.length() - 1; |
- text_.Resize(new_size); |
- last_collapsible_space_ = CollapsibleSpace::kNone; |
- |
- if (*next_start_offset <= new_size) |
- return; |
- *next_start_offset = new_size; |
- |
- // Adjust the last item if the removed space is already appended. |
- for (unsigned i = items_->size(); i > 0;) { |
- NGLayoutInlineItem& item = (*items_)[--i]; |
- DCHECK_EQ(item.EndOffset(), new_size + 1); |
- if (item.Type() == NGLayoutInlineItem::kText) { |
- DCHECK_GE(item.Length(), 1u); |
- if (item.Length() > 1) |
- item.SetEndOffset(new_size); |
- else |
- items_->erase(i); |
- break; |
- } |
- if (!item.Length()) { |
- // Trailing spaces can be removed across non-character items. |
- item.SetOffset(new_size, new_size); |
- continue; |
- } |
- NOTREACHED(); |
- break; |
- } |
-} |
- |
-void NGLayoutInlineItemsBuilder::AppendBidiControl(const ComputedStyle* style, |
- UChar ltr, |
- UChar rtl) { |
- Append(NGLayoutInlineItem::kBidiControl, |
- style->Direction() == TextDirection::kRtl ? rtl : ltr); |
-} |
- |
-void NGLayoutInlineItemsBuilder::EnterBlock(const ComputedStyle* style) { |
- // Handle bidi-override on the block itself. |
- switch (style->GetUnicodeBidi()) { |
- case UnicodeBidi::kNormal: |
- case UnicodeBidi::kEmbed: |
- case UnicodeBidi::kIsolate: |
- // Isolate and embed values are enforced by default and redundant on the |
- // block elements. |
- // Direction is handled as the paragraph level by |
- // NGBidiParagraph::SetParagraph(). |
- if (style->Direction() == TextDirection::kRtl) |
- has_bidi_controls_ = true; |
- break; |
- case UnicodeBidi::kBidiOverride: |
- case UnicodeBidi::kIsolateOverride: |
- AppendBidiControl(style, kLeftToRightOverrideCharacter, |
- kRightToLeftOverrideCharacter); |
- Enter(nullptr, kPopDirectionalFormattingCharacter); |
- break; |
- case UnicodeBidi::kPlaintext: |
- // Plaintext is handled as the paragraph level by |
- // NGBidiParagraph::SetParagraph(). |
- has_bidi_controls_ = true; |
- break; |
- } |
-} |
- |
-void NGLayoutInlineItemsBuilder::EnterInline(LayoutObject* node) { |
- // https://drafts.csswg.org/css-writing-modes-3/#bidi-control-codes-injection-table |
- const ComputedStyle* style = node->Style(); |
- switch (style->GetUnicodeBidi()) { |
- case UnicodeBidi::kNormal: |
- break; |
- case UnicodeBidi::kEmbed: |
- AppendBidiControl(style, kLeftToRightEmbedCharacter, |
- kRightToLeftEmbedCharacter); |
- Enter(node, kPopDirectionalFormattingCharacter); |
- break; |
- case UnicodeBidi::kBidiOverride: |
- AppendBidiControl(style, kLeftToRightOverrideCharacter, |
- kRightToLeftOverrideCharacter); |
- Enter(node, kPopDirectionalFormattingCharacter); |
- break; |
- case UnicodeBidi::kIsolate: |
- AppendBidiControl(style, kLeftToRightIsolateCharacter, |
- kRightToLeftIsolateCharacter); |
- Enter(node, kPopDirectionalIsolateCharacter); |
- break; |
- case UnicodeBidi::kPlaintext: |
- Append(NGLayoutInlineItem::kBidiControl, kFirstStrongIsolateCharacter); |
- Enter(node, kPopDirectionalIsolateCharacter); |
- break; |
- case UnicodeBidi::kIsolateOverride: |
- Append(NGLayoutInlineItem::kBidiControl, kFirstStrongIsolateCharacter); |
- AppendBidiControl(style, kLeftToRightOverrideCharacter, |
- kRightToLeftOverrideCharacter); |
- Enter(node, kPopDirectionalIsolateCharacter); |
- Enter(node, kPopDirectionalFormattingCharacter); |
- break; |
- } |
- |
- Append(NGLayoutInlineItem::kOpenTag, style, node); |
-} |
- |
-void NGLayoutInlineItemsBuilder::Enter(LayoutObject* node, |
- UChar character_to_exit) { |
- exits_.push_back(OnExitNode{node, character_to_exit}); |
- has_bidi_controls_ = true; |
-} |
- |
-void NGLayoutInlineItemsBuilder::ExitBlock() { |
- Exit(nullptr); |
-} |
- |
-void NGLayoutInlineItemsBuilder::ExitInline(LayoutObject* node) { |
- DCHECK(node); |
- |
- Append(NGLayoutInlineItem::kCloseTag, node->Style(), node); |
- |
- Exit(node); |
-} |
- |
-void NGLayoutInlineItemsBuilder::Exit(LayoutObject* node) { |
- while (!exits_.IsEmpty() && exits_.back().node == node) { |
- Append(NGLayoutInlineItem::kBidiControl, exits_.back().character); |
- exits_.pop_back(); |
- } |
-} |
- |
-} // namespace blink |