| 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 b27060717778fafd0e52a22919f9b5dbd58db38e..33346290aea92e5764b5bf7d96a8faa28fab0978 100644
|
| --- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| +++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp
|
| @@ -342,12 +342,8 @@ void TextIteratorAlgorithm<Strategy>::Advance() {
|
| return;
|
| }
|
|
|
| - if (!text_box_ && remaining_text_box_) {
|
| - text_box_ = remaining_text_box_;
|
| - remaining_text_box_ = 0;
|
| - first_letter_text_ = nullptr;
|
| - offset_ = 0;
|
| - }
|
| + if (ShouldProceedToRemainingText())
|
| + ProceedToRemainingText();
|
| // handle remembered text box
|
| if (text_box_) {
|
| HandleTextBox();
|
| @@ -561,6 +557,18 @@ static bool HasVisibleTextNode(LayoutText* layout_object) {
|
| EVisibility::kVisible;
|
| }
|
|
|
| +template <typename Strategy>
|
| +bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter(
|
| + const LayoutText& layout_text) const {
|
| + if (handled_first_letter_)
|
| + 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_;
|
| +}
|
| +
|
| template <typename Strategy>
|
| bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| if (ExcludesAutofilledValue()) {
|
| @@ -579,20 +587,19 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
|
|
| // handle pre-formatted text
|
| if (!layout_object->Style()->CollapseWhiteSpace()) {
|
| - int run_start = offset_;
|
| if (last_text_node_ended_with_collapsed_space_ &&
|
| HasVisibleTextNode(layout_object)) {
|
| if (behavior_.CollapseTrailingSpace()) {
|
| - if (run_start > 0 && str[run_start - 1] == ' ') {
|
| - SpliceBuffer(kSpaceCharacter, text_node, 0, run_start, run_start);
|
| + if (offset_ > 0 && str[offset_ - 1] == ' ') {
|
| + SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_);
|
| return false;
|
| }
|
| } else {
|
| - SpliceBuffer(kSpaceCharacter, text_node, 0, run_start, run_start);
|
| + SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_);
|
| return false;
|
| }
|
| }
|
| - if (!handled_first_letter_ && layout_object->IsTextFragment() && !offset_) {
|
| + if (ShouldHandleFirstLetter(*layout_object)) {
|
| HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
| if (first_letter_text_) {
|
| String first_letter = first_letter_text_->GetText();
|
| @@ -606,9 +613,10 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
|
| !IgnoresStyleVisibility())
|
| return false;
|
| - int str_length = str.length();
|
| - int end = (text_node == end_container_) ? end_offset_ : INT_MAX;
|
| - int run_end = std::min(str_length, end);
|
| + const unsigned run_start = offset_;
|
| + const unsigned str_length = str.length();
|
| + const unsigned end = (text_node == end_container_) ? end_offset_ : INT_MAX;
|
| + const unsigned run_end = std::min(str_length, end);
|
|
|
| if (run_start >= run_end)
|
| return true;
|
| @@ -620,8 +628,8 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
|
| if (layout_object->FirstTextBox())
|
| text_box_ = layout_object->FirstTextBox();
|
|
|
| - bool should_handle_first_letter =
|
| - !handled_first_letter_ && layout_object->IsTextFragment() && !offset_;
|
| + const bool should_handle_first_letter =
|
| + ShouldHandleFirstLetter(*layout_object);
|
| if (should_handle_first_letter)
|
| HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
|
|
|
| @@ -696,22 +704,22 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| text_box_ = nullptr;
|
| } else {
|
| String str = layout_object->GetText();
|
| - unsigned start = offset_;
|
| - unsigned end = (node_ == end_container_)
|
| - ? static_cast<unsigned>(end_offset_)
|
| - : INT_MAX;
|
| + const unsigned start = offset_;
|
| + const unsigned end = (node_ == end_container_)
|
| + ? static_cast<unsigned>(end_offset_)
|
| + : INT_MAX;
|
| while (text_box_) {
|
| - unsigned text_box_start = text_box_->Start();
|
| - unsigned run_start = std::max(text_box_start, start);
|
| + const unsigned text_box_start = text_box_->Start();
|
| + const unsigned run_start = std::max(text_box_start, start);
|
|
|
| // Check for collapsed space at the start of this run.
|
| InlineTextBox* first_text_box =
|
| layout_object->ContainsReversedText()
|
| ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0])
|
| : layout_object->FirstTextBox();
|
| - bool need_space = last_text_node_ended_with_collapsed_space_ ||
|
| - (text_box_ == first_text_box &&
|
| - text_box_start == run_start && run_start > 0);
|
| + const bool need_space = last_text_node_ended_with_collapsed_space_ ||
|
| + (text_box_ == first_text_box &&
|
| + text_box_start == run_start && run_start > 0);
|
| if (need_space &&
|
| !layout_object->Style()->IsCollapsibleWhiteSpace(
|
| text_state_.LastCharacter()) &&
|
| @@ -727,8 +735,8 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| }
|
| return;
|
| }
|
| - unsigned text_box_end = text_box_start + text_box_->Len();
|
| - unsigned run_end = std::min(text_box_end, end);
|
| + const unsigned text_box_end = text_box_start + text_box_->Len();
|
| + const unsigned run_end = std::min(text_box_end, end);
|
|
|
| // Determine what the next text box will be, but don't advance yet
|
| InlineTextBox* next_text_box = nullptr;
|
| @@ -795,7 +803,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| }
|
|
|
| // Advance and return
|
| - unsigned next_run_start =
|
| + const unsigned next_run_start =
|
| next_text_box ? next_text_box->Start() : str.length();
|
| if (next_run_start > run_end)
|
| last_text_node_ended_with_collapsed_space_ =
|
| @@ -813,15 +821,29 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
|
| }
|
| }
|
|
|
| - if (!text_box_ && remaining_text_box_) {
|
| - text_box_ = remaining_text_box_;
|
| - remaining_text_box_ = 0;
|
| - first_letter_text_ = nullptr;
|
| - offset_ = 0;
|
| + if (ShouldProceedToRemainingText()) {
|
| + ProceedToRemainingText();
|
| 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_;
|
| +}
|
| +
|
| +template <typename Strategy>
|
| +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;
|
| +}
|
| +
|
| template <typename Strategy>
|
| void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter(
|
| LayoutTextFragment* layout_object) {
|
|
|