| Index: third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
|
| index e4bf6aeffaf43c2e7c4fd68178a07ba42be38811..d786b02ab5eebd5ae8879c4176be1b47d3fc8830 100644
|
| --- a/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/iterators/TextIteratorTextNodeHandler.cpp
|
| @@ -6,10 +6,13 @@
|
|
|
| #include <algorithm>
|
| #include "core/dom/FirstLetterPseudoElement.h"
|
| +#include "core/editing/VisibleUnits.h"
|
| #include "core/editing/iterators/TextIteratorTextState.h"
|
| #include "core/layout/LayoutTextFragment.h"
|
| #include "core/layout/line/InlineTextBox.h"
|
| #include "core/layout/line/RootInlineBox.h"
|
| +#include "core/layout/ng/inline/ng_inline_node.h"
|
| +#include "core/layout/ng/layout_ng_block_flow.h"
|
|
|
| namespace blink {
|
|
|
| @@ -24,6 +27,11 @@ DEFINE_TRACE(TextIteratorTextNodeHandler) {
|
| }
|
|
|
| bool TextIteratorTextNodeHandler::HandleRemainingTextRuns() {
|
| + if (ng_block_flow_) {
|
| + HandleTextNodeInNGBlockFlow(*ng_block_flow_);
|
| + return text_state_->PositionNode();
|
| + }
|
| +
|
| if (ShouldProceedToRemainingText())
|
| ProceedToRemainingText();
|
| // Handle remembered text box
|
| @@ -120,18 +128,62 @@ void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
|
| EmitText(text_node_, text_node_->GetLayoutObject(), run_start, run_end);
|
| }
|
|
|
| +void TextIteratorTextNodeHandler::HandleTextNodeInNGBlockFlow(
|
| + const LayoutNGBlockFlow& block) {
|
| + if (block != ng_block_flow_) {
|
| + mapping_result_ = NGInlineNode(const_cast<LayoutNGBlockFlow*>(&block))
|
| + .BuildOffsetMapping();
|
| + ng_block_flow_ = █
|
| + }
|
| +
|
| + const LayoutObject* layout_object =
|
| + AssociatedLayoutObjectOf(*text_node_, offset_);
|
| +
|
| + // Skip invisible content.
|
| + if (layout_object->Style()->Display() == EDisplay::kNone ||
|
| + (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| + !IgnoresStyleVisibility())) {
|
| + offset_ = end_offset_;
|
| + return;
|
| + }
|
| +
|
| + while (offset_ < end_offset_ && !text_state_->PositionNode()) {
|
| + const NGOffsetMappingUnit* unit =
|
| + mapping_result_.GetMappingUnitForDOMOffset(*text_node_, offset_);
|
| + // No more text on this node to emit.
|
| + if (!unit || static_cast<unsigned>(offset_) == unit->dom_end) {
|
| + offset_ = end_offset_;
|
| + return;
|
| + }
|
| +
|
| + const unsigned run_end =
|
| + std::min(static_cast<unsigned>(end_offset_), unit->dom_end);
|
| + if (unit->type == NGOffsetMappingUnitType::kCollapsed) {
|
| + offset_ = run_end;
|
| + continue;
|
| + }
|
| +
|
| + // TODO(xiaochengh): Handle EmitsOriginalText.
|
| +
|
| + String string =
|
| + NGInlineNode(const_cast<LayoutNGBlockFlow*>(ng_block_flow_)).Text();
|
| + if (behavior_.EmitsSpaceForNbsp())
|
| + string.Replace(kNoBreakSpaceCharacter, kSpaceCharacter);
|
| + const unsigned text_content_start = unit->DOMToTextContentOffset(offset_);
|
| + const unsigned text_content_end = unit->DOMToTextContentOffset(run_end);
|
| + text_state_->EmitText(text_node_, offset_, run_end, string,
|
| + text_content_start, text_content_end);
|
| + offset_ = run_end;
|
| + return;
|
| + }
|
| +}
|
| +
|
| void TextIteratorTextNodeHandler::HandleTextNodeInRange(Text* node,
|
| int start_offset,
|
| int end_offset) {
|
| DCHECK(node);
|
| DCHECK_GE(start_offset, 0);
|
| -
|
| - // TODO(editing-dev): Add the following DCHECK once we stop assuming equal
|
| - // number of code units in DOM string and LayoutText::GetText(). Currently
|
| - // violated by
|
| - // - external/wpt/innerText/getter.html
|
| - // - fast/css/case-transform.html
|
| - // DCHECK_LE(end_offset, static_cast<int>(node->data().length()));
|
| + DCHECK_LE(end_offset, static_cast<int>(node->data().length()));
|
|
|
| // TODO(editing-dev): Stop passing in |start_offset == end_offset|.
|
| DCHECK_LE(start_offset, end_offset);
|
| @@ -143,6 +195,13 @@ void TextIteratorTextNodeHandler::HandleTextNodeInRange(Text* node,
|
| first_letter_text_ = nullptr;
|
|
|
| LayoutText* layout_object = text_node_->GetLayoutObject();
|
| + const LayoutBox* enclosing_box = layout_object->EnclosingBox();
|
| + if (enclosing_box && enclosing_box->IsLayoutNGBlockFlow()) {
|
| + HandleTextNodeInNGBlockFlow(ToLayoutNGBlockFlow(*enclosing_box));
|
| + return;
|
| + }
|
| + ng_block_flow_ = nullptr;
|
| +
|
| String str = layout_object->GetText();
|
|
|
| // handle pre-formatted text
|
| @@ -189,9 +248,7 @@ void TextIteratorTextNodeHandler::HandleTextNodeInRange(Text* node,
|
|
|
| void TextIteratorTextNodeHandler::HandleTextNodeStartFrom(Text* node,
|
| int start_offset) {
|
| - HandleTextNodeInRange(node, start_offset,
|
| - node->GetLayoutObject()->TextStartOffset() +
|
| - node->GetLayoutObject()->GetText().length());
|
| + HandleTextNodeInRange(node, start_offset, node->data().length());
|
| }
|
|
|
| void TextIteratorTextNodeHandler::HandleTextNodeEndAt(Text* node,
|
| @@ -411,6 +468,8 @@ bool TextIteratorTextNodeHandler::FixLeadingWhiteSpaceForReplacedElement(
|
| Node* parent) {
|
| // This is a hacky way for white space fixup in legacy layout. With LayoutNG,
|
| // we can get rid of this function.
|
| + if (ng_block_flow_)
|
| + return false;
|
|
|
| if (behavior_.CollapseTrailingSpace()) {
|
| if (text_node_) {
|
|
|