Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp

Issue 2883163002: Un-insanify first-letter handling in TextIterator (to some degree) (Closed)
Patch Set: Tue May 16 16:31:00 PDT 2017 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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.

Powered by Google App Engine
This is Rietveld 408576698