| Index: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| index 33346290aea92e5764b5bf7d96a8faa28fab0978..93268ca933c6e499123fc8de91c7db5af7237252 100644
|
| --- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| @@ -62,8 +62,6 @@ using namespace HTMLNames;
|
|
|
| namespace {
|
|
|
| -const int kInvalidTextOffset = -1;
|
| -
|
| template <typename Strategy>
|
| TextIteratorBehavior AdjustBehaviorFlags(const TextIteratorBehavior&);
|
|
|
| @@ -175,8 +173,6 @@ TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(
|
| handled_first_letter_(false),
|
| should_stop_(false),
|
| handle_shadow_root_(false),
|
| - first_letter_start_offset_(kInvalidTextOffset),
|
| - remaining_text_start_offset_(kInvalidTextOffset),
|
| text_state_(behavior_) {
|
| DCHECK(start.IsNotNull());
|
| DCHECK(end.IsNotNull());
|
| @@ -199,44 +195,6 @@ TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(
|
| }
|
|
|
| template <typename Strategy>
|
| -bool TextIteratorAlgorithm<Strategy>::PrepareForFirstLetterInitialization() {
|
| - if (node_ != start_container_)
|
| - return false;
|
| -
|
| - if (node_->getNodeType() != Node::kTextNode)
|
| - return false;
|
| -
|
| - Text* text_node = ToText(node_);
|
| - LayoutText* layout_object = text_node->GetLayoutObject();
|
| - if (!layout_object || !layout_object->IsTextFragment())
|
| - return false;
|
| -
|
| - LayoutTextFragment* text_fragment = ToLayoutTextFragment(layout_object);
|
| - if (!text_fragment->IsRemainingTextLayoutObject())
|
| - return false;
|
| -
|
| - if (static_cast<unsigned>(start_offset_) >=
|
| - text_fragment->TextStartOffset()) {
|
| - remaining_text_start_offset_ =
|
| - start_offset_ - text_fragment->TextStartOffset();
|
| - } else {
|
| - first_letter_start_offset_ = start_offset_;
|
| - }
|
| - offset_ = 0;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -bool TextIteratorAlgorithm<Strategy>::HasNotAdvancedToStartPosition() {
|
| - if (AtEnd())
|
| - return false;
|
| - if (remaining_text_start_offset_ == kInvalidTextOffset)
|
| - return false;
|
| - return node_ == start_container_;
|
| -}
|
| -
|
| -template <typename Strategy>
|
| void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container,
|
| int start_offset,
|
| Node* end_container,
|
| @@ -270,8 +228,7 @@ void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container,
|
| return;
|
|
|
| fully_clipped_stack_.SetUpFullyClippedStack(node_);
|
| - if (!PrepareForFirstLetterInitialization())
|
| - offset_ = node_ == start_container_ ? start_offset_ : 0;
|
| + offset_ = node_ == start_container_ ? start_offset_ : 0;
|
| iteration_progress_ = kHandledNone;
|
|
|
| // Calculate first out of bounds node.
|
| @@ -281,16 +238,6 @@ void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container,
|
|
|
| // Identify the first run.
|
| Advance();
|
| -
|
| - // The current design cannot start in a text node with arbitrary offset, if
|
| - // the node has :first-letter. Instead, we start with offset 0, and have extra
|
| - // advance() calls until we have moved to/past the starting position.
|
| - while (HasNotAdvancedToStartPosition())
|
| - Advance();
|
| -
|
| - // Clear temporary data for initialization with :first-letter.
|
| - first_letter_start_offset_ = kInvalidTextOffset;
|
| - remaining_text_start_offset_ = kInvalidTextOffset;
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -564,9 +511,8 @@ bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter(
|
| return false;
|
| if (!layout_text.IsTextFragment())
|
| return false;
|
| - // TODO(xiaochengh): Handle the case where :first-letter has multiple chars,
|
| - // and eliminate the hack with first_letter/remaining_text_start_offset_.
|
| - return !offset_;
|
| + const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text);
|
| + return offset_ < static_cast<int>(text_fragment.TextStartOffset());
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -603,19 +549,29 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
| if (first_letter_text_) {
|
| String first_letter = first_letter_text_->GetText();
|
| - EmitText(text_node, first_letter_text_, offset_,
|
| - offset_ + first_letter.length());
|
| + const unsigned run_start = offset_;
|
| + const bool stops_in_first_letter =
|
| + text_node == end_container_ &&
|
| + end_offset_ <= static_cast<int>(first_letter.length());
|
| + const unsigned run_end =
|
| + stops_in_first_letter ? end_offset_ : first_letter.length();
|
| + EmitText(text_node, first_letter_text_, run_start, run_end);
|
| first_letter_text_ = nullptr;
|
| text_box_ = 0;
|
| - return false;
|
| + offset_ = run_end;
|
| + return stops_in_first_letter;
|
| }
|
| + // We are here only if the DOM and/or layout trees are broken.
|
| + NOTREACHED();
|
| }
|
| if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| !IgnoresStyleVisibility())
|
| return false;
|
| - const unsigned run_start = offset_;
|
| + const unsigned run_start = offset_ - layout_object->TextStartOffset();
|
| const unsigned str_length = str.length();
|
| - const unsigned end = (text_node == end_container_) ? end_offset_ : INT_MAX;
|
| + const unsigned end = (text_node == end_container_)
|
| + ? end_offset_ - layout_object->TextStartOffset()
|
| + : INT_MAX;
|
| const unsigned run_end = std::min(str_length, end);
|
|
|
| if (run_start >= run_end)
|
| @@ -698,16 +654,20 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| LayoutText* layout_object = first_letter_text_
|
| ? first_letter_text_
|
| : ToLayoutText(node_->GetLayoutObject());
|
| + const unsigned text_start_offset = layout_object->TextStartOffset();
|
|
|
| if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| !IgnoresStyleVisibility()) {
|
| text_box_ = nullptr;
|
| } else {
|
| String str = layout_object->GetText();
|
| - const unsigned start = offset_;
|
| - const unsigned end = (node_ == end_container_)
|
| - ? static_cast<unsigned>(end_offset_)
|
| - : INT_MAX;
|
| + // Start and end offsets in |str|, i.e., str[start..end - 1] should be
|
| + // emitted (after handling whitespace collapsing).
|
| + const unsigned start = offset_ - layout_object->TextStartOffset();
|
| + const unsigned end =
|
| + (node_ == end_container_)
|
| + ? static_cast<unsigned>(end_offset_) - text_start_offset
|
| + : INT_MAX;
|
| while (text_box_) {
|
| const unsigned text_box_start = text_box_->Start();
|
| const unsigned run_start = std::max(text_box_start, start);
|
| @@ -772,7 +732,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| SpliceBuffer('\n', node_, 0, run_start, run_start);
|
| else
|
| SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start + 1);
|
| - offset_ = run_start + 1;
|
| + offset_ = text_start_offset + run_start + 1;
|
| } else {
|
| size_t subrun_end = str.find('\n', run_start);
|
| if (subrun_end == kNotFound || subrun_end > run_end) {
|
| @@ -781,7 +741,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| RestoreCollapsedTrailingSpace(next_text_box, subrun_end);
|
| }
|
|
|
| - offset_ = subrun_end;
|
| + offset_ = text_start_offset + subrun_end;
|
| EmitText(node_, layout_object, run_start, subrun_end);
|
| }
|
|
|
| @@ -829,9 +789,11 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
|
|
| template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const {
|
| - // TODO(xiaochengh): Handle the case where the iterator should stop in
|
| - // :first-letter.
|
| - return !text_box_ && remaining_text_box_;
|
| + if (text_box_ || !remaining_text_box_)
|
| + return false;
|
| + if (node_ != end_container_)
|
| + return true;
|
| + return offset_ < end_offset_;
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -839,9 +801,7 @@ void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() {
|
| text_box_ = remaining_text_box_;
|
| remaining_text_box_ = 0;
|
| first_letter_text_ = nullptr;
|
| - // TODO(xiaochengh): |offset_| should be set to the starting offset of the
|
| - // remaining text;
|
| - offset_ = 0;
|
| + offset_ = ToLayoutText(node_->GetLayoutObject())->TextStartOffset();
|
| }
|
|
|
| template <typename Strategy>
|
| @@ -1230,57 +1190,10 @@ void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c,
|
| }
|
|
|
| template <typename Strategy>
|
| -int TextIteratorAlgorithm<Strategy>::AdjustedStartForFirstLetter(
|
| - const Node& text_node,
|
| - const LayoutText& layout_object,
|
| - int text_start_offset,
|
| - int text_end_offset) {
|
| - if (first_letter_start_offset_ == kInvalidTextOffset)
|
| - return text_start_offset;
|
| - if (text_node != start_container_)
|
| - return text_start_offset;
|
| - if (!layout_object.IsTextFragment())
|
| - return text_start_offset;
|
| - if (ToLayoutTextFragment(layout_object).IsRemainingTextLayoutObject())
|
| - return text_start_offset;
|
| - if (text_end_offset <= first_letter_start_offset_)
|
| - return text_start_offset;
|
| - int adjusted_offset = std::max(text_start_offset, first_letter_start_offset_);
|
| - first_letter_start_offset_ = kInvalidTextOffset;
|
| - return adjusted_offset;
|
| -}
|
| -
|
| -template <typename Strategy>
|
| -int TextIteratorAlgorithm<Strategy>::AdjustedStartForRemainingText(
|
| - const Node& text_node,
|
| - const LayoutText& layout_object,
|
| - int text_start_offset,
|
| - int text_end_offset) {
|
| - if (remaining_text_start_offset_ == kInvalidTextOffset)
|
| - return text_start_offset;
|
| - if (text_node != start_container_)
|
| - return text_start_offset;
|
| - if (!layout_object.IsTextFragment())
|
| - return text_start_offset;
|
| - if (!ToLayoutTextFragment(layout_object).IsRemainingTextLayoutObject())
|
| - return text_start_offset;
|
| - if (text_end_offset <= remaining_text_start_offset_)
|
| - return text_start_offset;
|
| - int adjusted_offset =
|
| - std::max(text_start_offset, remaining_text_start_offset_);
|
| - remaining_text_start_offset_ = kInvalidTextOffset;
|
| - return adjusted_offset;
|
| -}
|
| -
|
| -template <typename Strategy>
|
| void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node,
|
| LayoutText* layout_object,
|
| int text_start_offset,
|
| int text_end_offset) {
|
| - text_start_offset = AdjustedStartForFirstLetter(
|
| - *text_node, *layout_object, text_start_offset, text_end_offset);
|
| - text_start_offset = AdjustedStartForRemainingText(
|
| - *text_node, *layout_object, text_start_offset, text_end_offset);
|
| // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in
|
| // TextIterator, but is always reset when we call spliceBuffer, we
|
| // wrap TextIteratorTextState::spliceBuffer() with this function.
|
|
|