Index: third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc |
diff --git a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc b/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc |
deleted file mode 100644 |
index c54bbb9d6204834f41f83ab2e8256eccdbb67f19..0000000000000000000000000000000000000000 |
--- a/third_party/WebKit/Source/core/layout/ng/ng_inline_node.cc |
+++ /dev/null |
@@ -1,378 +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_inline_node.h" |
- |
-#include "core/layout/LayoutBlockFlow.h" |
-#include "core/layout/LayoutObject.h" |
-#include "core/layout/LayoutText.h" |
-#include "core/layout/ng/ng_bidi_paragraph.h" |
-#include "core/layout/ng/ng_box_fragment.h" |
-#include "core/layout/ng/ng_constraint_space_builder.h" |
-#include "core/layout/ng/ng_fragment_builder.h" |
-#include "core/layout/ng/ng_inline_break_token.h" |
-#include "core/layout/ng/ng_inline_layout_algorithm.h" |
-#include "core/layout/ng/ng_layout_inline_items_builder.h" |
-#include "core/layout/ng/ng_physical_box_fragment.h" |
-#include "core/layout/ng/ng_physical_text_fragment.h" |
-#include "core/layout/ng/ng_text_fragment.h" |
-#include "core/style/ComputedStyle.h" |
-#include "platform/fonts/CharacterRange.h" |
-#include "platform/fonts/shaping/CachingWordShapeIterator.h" |
-#include "platform/fonts/shaping/CachingWordShaper.h" |
-#include "platform/fonts/shaping/HarfBuzzShaper.h" |
-#include "platform/fonts/shaping/ShapeResultBuffer.h" |
-#include "wtf/text/CharacterNames.h" |
- |
-namespace blink { |
- |
-NGInlineNode::NGInlineNode(LayoutObject* start_inline, LayoutBlockFlow* block) |
- : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyInline), |
- start_inline_(start_inline), |
- block_(block) { |
- DCHECK(start_inline); |
- DCHECK(block); |
-} |
- |
-NGInlineNode::NGInlineNode() |
- : NGLayoutInputNode(NGLayoutInputNodeType::kLegacyInline), |
- start_inline_(nullptr), |
- block_(nullptr) {} |
- |
-NGInlineNode::~NGInlineNode() {} |
- |
-NGLayoutInlineItemRange NGInlineNode::Items(unsigned start, unsigned end) { |
- return NGLayoutInlineItemRange(&items_, start, end); |
-} |
- |
-void NGInlineNode::InvalidatePrepareLayout() { |
- text_content_ = String(); |
- items_.Clear(); |
-} |
- |
-void NGInlineNode::PrepareLayout() { |
- // Scan list of siblings collecting all in-flow non-atomic inlines. A single |
- // NGInlineNode represent a collection of adjacent non-atomic inlines. |
- CollectInlines(start_inline_, block_); |
- if (is_bidi_enabled_) |
- SegmentText(); |
- ShapeText(); |
-} |
- |
-// Depth-first-scan of all LayoutInline and LayoutText nodes that make up this |
-// NGInlineNode object. Collects LayoutText items, merging them up into the |
-// parent LayoutInline where possible, and joining all text content in a single |
-// string to allow bidi resolution and shaping of the entire block. |
-void NGInlineNode::CollectInlines(LayoutObject* start, LayoutBlockFlow* block) { |
- DCHECK(text_content_.IsNull()); |
- DCHECK(items_.IsEmpty()); |
- NGLayoutInlineItemsBuilder builder(&items_); |
- builder.EnterBlock(block->Style()); |
- LayoutObject* next_sibling = CollectInlines(start, block, &builder); |
- builder.ExitBlock(); |
- |
- text_content_ = builder.ToString(); |
- DCHECK(!next_sibling || !next_sibling->IsInline()); |
- next_sibling_ = next_sibling ? new NGBlockNode(next_sibling) : nullptr; |
- is_bidi_enabled_ = !text_content_.IsEmpty() && |
- !(text_content_.Is8Bit() && !builder.HasBidiControls()); |
-} |
- |
-LayoutObject* NGInlineNode::CollectInlines( |
- LayoutObject* start, |
- LayoutBlockFlow* block, |
- NGLayoutInlineItemsBuilder* builder) { |
- LayoutObject* node = start; |
- while (node) { |
- if (node->IsText()) { |
- builder->SetIsSVGText(node->IsSVGInlineText()); |
- builder->Append(ToLayoutText(node)->GetText(), node->Style(), node); |
- node->ClearNeedsLayout(); |
- |
- } else if (node->IsFloating()) { |
- // Add floats and positioned objects in the same way as atomic inlines. |
- // Because these objects need positions, they will be handled in |
- // NGInlineLayoutAlgorithm. |
- builder->Append(NGLayoutInlineItem::kFloating, |
- kObjectReplacementCharacter, nullptr, node); |
- } else if (node->IsOutOfFlowPositioned()) { |
- builder->Append(NGLayoutInlineItem::kOutOfFlowPositioned, |
- kObjectReplacementCharacter, nullptr, node); |
- |
- } else if (!node->IsInline()) { |
- // A block box found. End inline and transit to block layout. |
- return node; |
- |
- } else { |
- builder->EnterInline(node); |
- |
- // For atomic inlines add a unicode "object replacement character" to |
- // signal the presence of a non-text object to the unicode bidi algorithm. |
- if (node->IsAtomicInlineLevel()) { |
- builder->Append(NGLayoutInlineItem::kAtomicInline, |
- kObjectReplacementCharacter, nullptr, node); |
- } |
- |
- // Otherwise traverse to children if they exist. |
- else if (LayoutObject* child = node->SlowFirstChild()) { |
- node = child; |
- continue; |
- |
- } else { |
- // An empty inline node. |
- node->ClearNeedsLayout(); |
- } |
- |
- builder->ExitInline(node); |
- } |
- |
- // Find the next sibling, or parent, until we reach |block|. |
- while (true) { |
- if (LayoutObject* next = node->NextSibling()) { |
- node = next; |
- break; |
- } |
- node = node->Parent(); |
- if (node == block) |
- return nullptr; |
- DCHECK(node->IsInline()); |
- builder->ExitInline(node); |
- node->ClearNeedsLayout(); |
- } |
- } |
- return nullptr; |
-} |
- |
-void NGInlineNode::SegmentText() { |
- // TODO(kojii): Move this to caller, this will be used again after line break. |
- NGBidiParagraph bidi; |
- text_content_.Ensure16Bit(); |
- if (!bidi.SetParagraph(text_content_, Style())) { |
- // On failure, give up bidi resolving and reordering. |
- is_bidi_enabled_ = false; |
- return; |
- } |
- if (bidi.Direction() == UBIDI_LTR) { |
- // All runs are LTR, no need to reorder. |
- is_bidi_enabled_ = false; |
- return; |
- } |
- |
- unsigned item_index = 0; |
- for (unsigned start = 0; start < text_content_.length();) { |
- UBiDiLevel level; |
- unsigned end = bidi.GetLogicalRun(start, &level); |
- DCHECK_EQ(items_[item_index].start_offset_, start); |
- item_index = |
- NGLayoutInlineItem::SetBidiLevel(items_, item_index, end, level); |
- start = end; |
- } |
- DCHECK_EQ(item_index, items_.size()); |
-} |
- |
-// Set bidi level to a list of NGLayoutInlineItem from |index| to the item that |
-// ends with |end_offset|. |
-// If |end_offset| is mid of an item, the item is split to ensure each item has |
-// one bidi level. |
-// @param items The list of NGLayoutInlineItem. |
-// @param index The first index of the list to set. |
-// @param end_offset The exclusive end offset to set. |
-// @param level The level to set. |
-// @return The index of the next item. |
-unsigned NGLayoutInlineItem::SetBidiLevel(Vector<NGLayoutInlineItem>& items, |
- unsigned index, |
- unsigned end_offset, |
- UBiDiLevel level) { |
- for (; items[index].end_offset_ < end_offset; index++) |
- items[index].bidi_level_ = level; |
- items[index].bidi_level_ = level; |
- |
- if (items[index].end_offset_ == end_offset) { |
- // Let close items have the same bidi-level as the previous item. |
- while (index + 1 < items.size() && |
- items[index + 1].Type() == NGLayoutInlineItem::kCloseTag) { |
- items[++index].bidi_level_ = level; |
- } |
- } else { |
- Split(items, index, end_offset); |
- } |
- |
- return index + 1; |
-} |
- |
-// Split |items[index]| to 2 items at |offset|. |
-// All properties other than offsets are copied to the new item and it is |
-// inserted at |items[index + 1]|. |
-// @param items The list of NGLayoutInlineItem. |
-// @param index The index to split. |
-// @param offset The offset to split at. |
-void NGLayoutInlineItem::Split(Vector<NGLayoutInlineItem>& items, |
- unsigned index, |
- unsigned offset) { |
- DCHECK_GT(offset, items[index].start_offset_); |
- DCHECK_LT(offset, items[index].end_offset_); |
- items.insert(index + 1, items[index]); |
- items[index].end_offset_ = offset; |
- items[index + 1].start_offset_ = offset; |
-} |
- |
-void NGLayoutInlineItem::SetOffset(unsigned start, unsigned end) { |
- DCHECK_GE(end, start); |
- start_offset_ = start; |
- end_offset_ = end; |
-} |
- |
-void NGLayoutInlineItem::SetEndOffset(unsigned end_offset) { |
- DCHECK_GE(end_offset, start_offset_); |
- end_offset_ = end_offset; |
-} |
- |
-LayoutUnit NGLayoutInlineItem::InlineSize() const { |
- if (Type() == NGLayoutInlineItem::kText) |
- return LayoutUnit(shape_result_->Width()); |
- |
- DCHECK_NE(Type(), NGLayoutInlineItem::kAtomicInline) |
- << "Use NGInlineLayoutAlgorithm::InlineSize"; |
- // Bidi controls and out-of-flow objects do not have in-flow widths. |
- return LayoutUnit(); |
-} |
- |
-LayoutUnit NGLayoutInlineItem::InlineSize(unsigned start, unsigned end) const { |
- DCHECK_GE(start, StartOffset()); |
- DCHECK_LE(start, end); |
- DCHECK_LE(end, EndOffset()); |
- |
- if (start == end) |
- return LayoutUnit(); |
- if (start == start_offset_ && end == end_offset_) |
- return InlineSize(); |
- |
- DCHECK_EQ(Type(), NGLayoutInlineItem::kText); |
- return LayoutUnit(ShapeResultBuffer::GetCharacterRange( |
- shape_result_, Direction(), shape_result_->Width(), |
- start - StartOffset(), end - StartOffset()) |
- .Width()); |
-} |
- |
-void NGLayoutInlineItem::GetFallbackFonts( |
- HashSet<const SimpleFontData*>* fallback_fonts, |
- unsigned start, |
- unsigned end) const { |
- DCHECK_GE(start, StartOffset()); |
- DCHECK_LE(start, end); |
- DCHECK_LE(end, EndOffset()); |
- |
- // TODO(kojii): Implement |start| and |end|. |
- shape_result_->FallbackFonts(fallback_fonts); |
-} |
- |
-void NGInlineNode::ShapeText() { |
- // TODO(eae): Add support for shaping latin-1 text? |
- text_content_.Ensure16Bit(); |
- |
- // Shape each item with the full context of the entire node. |
- HarfBuzzShaper shaper(text_content_.Characters16(), text_content_.length()); |
- for (auto& item : items_) { |
- if (item.Type() != NGLayoutInlineItem::kText) |
- continue; |
- |
- item.shape_result_ = |
- shaper.Shape(&item.Style()->GetFont(), item.Direction(), |
- item.StartOffset(), item.EndOffset()); |
- } |
-} |
- |
-RefPtr<NGLayoutResult> NGInlineNode::Layout(NGConstraintSpace* constraint_space, |
- NGBreakToken* break_token) { |
- // TODO(kojii): Invalidate PrepareLayout() more efficiently. |
- InvalidatePrepareLayout(); |
- PrepareLayout(); |
- |
- NGInlineLayoutAlgorithm algorithm(this, constraint_space, |
- ToNGInlineBreakToken(break_token)); |
- RefPtr<NGLayoutResult> result = algorithm.Layout(); |
- algorithm.CopyFragmentDataToLayoutBlockFlow(result.Get()); |
- return result; |
-} |
- |
-MinMaxContentSize NGInlineNode::ComputeMinMaxContentSize() { |
- if (!IsPrepareLayoutFinished()) |
- PrepareLayout(); |
- |
- // Compute the max of inline sizes of all line boxes with 0 available inline |
- // size. This gives the min-content, the width where lines wrap at every break |
- // opportunity. |
- NGWritingMode writing_mode = |
- FromPlatformWritingMode(Style().GetWritingMode()); |
- RefPtr<NGConstraintSpace> constraint_space = |
- NGConstraintSpaceBuilder(writing_mode) |
- .SetTextDirection(Style().Direction()) |
- .SetAvailableSize({LayoutUnit(), NGSizeIndefinite}) |
- .ToConstraintSpace(writing_mode); |
- NGInlineLayoutAlgorithm algorithm(this, constraint_space.Get()); |
- return algorithm.ComputeMinMaxContentSizeByLayout(); |
-} |
- |
-NGLayoutInputNode* NGInlineNode::NextSibling() { |
- if (!IsPrepareLayoutFinished()) |
- PrepareLayout(); |
- return next_sibling_; |
-} |
- |
-LayoutObject* NGInlineNode::GetLayoutObject() { |
- return GetLayoutBlockFlow(); |
-} |
- |
-// Compute the delta of text offsets between NGInlineNode and LayoutText. |
-// This map is needed to produce InlineTextBox since its offsets are to |
-// LayoutText. |
-// TODO(kojii): Since NGInlineNode has text after whitespace collapsed, the |
-// length may not match with LayoutText. This function updates LayoutText to |
-// match, but this needs more careful coding, if we keep copying to layoutobject |
-// tree. |
-void NGInlineNode::GetLayoutTextOffsets( |
- Vector<unsigned, 32>* text_offsets_out) { |
- LayoutText* current_text = nullptr; |
- unsigned current_offset = 0; |
- for (unsigned i = 0; i < items_.size(); i++) { |
- const NGLayoutInlineItem& item = items_[i]; |
- LayoutObject* next_object = item.GetLayoutObject(); |
- LayoutText* next_text = next_object && next_object->IsText() |
- ? ToLayoutText(next_object) |
- : nullptr; |
- if (next_text != current_text) { |
- if (current_text && |
- current_text->TextLength() != item.StartOffset() - current_offset) { |
- current_text->SetTextInternal( |
- Text(current_offset, item.StartOffset()).ToString().Impl()); |
- } |
- current_text = next_text; |
- current_offset = item.StartOffset(); |
- } |
- (*text_offsets_out)[i] = current_offset; |
- } |
- if (current_text && |
- current_text->TextLength() != text_content_.length() - current_offset) { |
- current_text->SetTextInternal( |
- Text(current_offset, text_content_.length()).ToString().Impl()); |
- } |
-} |
- |
-DEFINE_TRACE(NGInlineNode) { |
- visitor->Trace(next_sibling_); |
- NGLayoutInputNode::Trace(visitor); |
-} |
- |
-NGLayoutInlineItemRange::NGLayoutInlineItemRange( |
- Vector<NGLayoutInlineItem>* items, |
- unsigned start_index, |
- unsigned end_index) |
- : start_item_(&(*items)[start_index]), |
- size_(end_index - start_index), |
- start_index_(start_index) { |
- CHECK_LE(start_index, end_index); |
- CHECK_LE(end_index, items->size()); |
-} |
- |
-} // namespace blink |