Chromium Code Reviews| 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 6aa72debc7f9020c41d6d310b9f74cb807320a55..31c02e0b0f78267a31fc25acff5213941febf42e 100644 |
| --- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
| +++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
| @@ -152,29 +152,38 @@ bool IsRenderedAsTable(const Node* node) { |
| } // namespace |
| +TextNodeContentExtractor::TextNodeContentExtractor( |
| + const TextIteratorBehavior& behavior, |
| + TextIteratorTextState& text_state) |
| + : start_offset_(0), |
|
yosin_UTC9
2017/05/25 06:44:09
Initialization of member variables should be done
|
| + end_offset_(0), |
| + offset_(0), |
| + text_box_(nullptr), |
| + needs_handle_pre_formatted_text_node_(false), |
| + handled_first_letter_(false), |
| + remaining_text_box_(nullptr), |
| + first_letter_text_(nullptr), |
| + last_text_node_ended_with_collapsed_space_(false), |
| + sorted_text_boxes_position_(0), |
| + behavior_(behavior), |
| + text_state_(text_state) {} |
| + |
| template <typename Strategy> |
| TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm( |
| const PositionTemplate<Strategy>& start, |
| const PositionTemplate<Strategy>& end, |
| const TextIteratorBehavior& behavior) |
| - : offset_(0), |
| - start_container_(nullptr), |
| + : start_container_(nullptr), |
| start_offset_(0), |
| end_container_(nullptr), |
| end_offset_(0), |
| needs_another_newline_(false), |
| - text_box_(nullptr), |
| - remaining_text_box_(nullptr), |
| - first_letter_text_(nullptr), |
| last_text_node_(nullptr), |
| - last_text_node_ended_with_collapsed_space_(false), |
| - sorted_text_boxes_position_(0), |
| behavior_(AdjustBehaviorFlags<Strategy>(behavior)), |
| - needs_handle_pre_formatted_text_node_(false), |
| - handled_first_letter_(false), |
| should_stop_(false), |
| handle_shadow_root_(false), |
| - text_state_(behavior_) { |
| + text_state_(behavior_), |
| + text_extractor_(behavior_, text_state_) { |
| DCHECK(start.IsNotNull()); |
| DCHECK(end.IsNotNull()); |
| @@ -195,6 +204,16 @@ TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm( |
| end.ComputeContainerNode(), end.ComputeOffsetInContainerNode()); |
| } |
| +void TextNodeContentExtractor::SetBoundaries(Node* start_container, |
| + int start_offset, |
| + Node* end_container, |
| + int end_offset) { |
| + start_container_ = start_container; |
| + start_offset_ = start_offset; |
| + end_container_ = end_container; |
| + end_offset_ = end_offset; |
| +} |
| + |
| template <typename Strategy> |
| void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, |
| int start_offset, |
| @@ -203,6 +222,9 @@ void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, |
| DCHECK(start_container); |
| DCHECK(end_container); |
| + text_extractor_.SetBoundaries(start_container, start_offset, end_container, |
| + end_offset); |
| + |
| // Remember the range - this does not change. |
| start_container_ = start_container; |
| start_offset_ = start_offset; |
| @@ -264,8 +286,7 @@ bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const { |
| return layout_object && layout_object->IsAtomicInlineLevel(); |
| } |
| -template <typename Strategy> |
| -bool TextIteratorAlgorithm<Strategy>::HandleRemainingTextRuns() { |
| +bool TextNodeContentExtractor::HandleRemainingTextRuns() { |
| if (ShouldProceedToRemainingText()) |
| ProceedToRemainingText(); |
| // handle remembered text box |
| @@ -307,7 +328,7 @@ void TextIteratorAlgorithm<Strategy>::Advance() { |
| return; |
| } |
| - if (HandleRemainingTextRuns()) |
| + if (text_extractor_.HandleRemainingTextRuns()) |
| return; |
| while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) { |
| @@ -511,8 +532,7 @@ static bool HasVisibleTextNode(LayoutText* layout_object) { |
| EVisibility::kVisible; |
| } |
| -template <typename Strategy> |
| -bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter( |
| +bool TextNodeContentExtractor::ShouldHandleFirstLetter( |
| const LayoutText& layout_text) const { |
| if (handled_first_letter_) |
| return false; |
| @@ -522,8 +542,7 @@ bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter( |
| return offset_ < static_cast<int>(text_fragment.TextStartOffset()); |
| } |
| -template <typename Strategy> |
| -void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() { |
| +void TextNodeContentExtractor::HandlePreFormattedTextNode() { |
| // TODO(xiaochengh): Get rid of repeated computation of these fields. |
| LayoutText* const layout_object = text_node_->GetLayoutObject(); |
| const String str = layout_object->GetText(); |
| @@ -535,7 +554,8 @@ void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() { |
| if (HasVisibleTextNode(layout_object)) { |
| if (!behavior_.CollapseTrailingSpace() || |
| (offset_ > 0 && str[offset_ - 1] == ' ')) { |
| - SpliceBuffer(kSpaceCharacter, text_node_, 0, offset_, offset_); |
| + text_state_.SpliceBuffer(kSpaceCharacter, text_node_, 0, offset_, |
| + offset_); |
| needs_handle_pre_formatted_text_node_ = true; |
| return; |
| } |
| @@ -551,7 +571,7 @@ void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() { |
| 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); |
| + text_state_.EmitText(text_node_, first_letter_text_, run_start, run_end); |
| first_letter_text_ = nullptr; |
| text_box_ = 0; |
| offset_ = run_end; |
| @@ -578,7 +598,8 @@ void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() { |
| if (run_start >= run_end) |
| return; |
| - EmitText(text_node_, text_node_->GetLayoutObject(), run_start, run_end); |
| + text_state_.EmitText(text_node_, text_node_->GetLayoutObject(), run_start, |
| + run_end); |
| } |
| template <typename Strategy> |
| @@ -594,8 +615,11 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { |
| DCHECK_NE(last_text_node_, node_) |
| << "We should never call HandleTextNode on the same node twice"; |
| last_text_node_ = ToText(node_); |
| + return text_extractor_.HandleTextNode(ToText(node_)); |
| +} |
| - text_node_ = ToText(node_); |
| +bool TextNodeContentExtractor::HandleTextNode(Text* node) { |
| + text_node_ = node; |
| offset_ = text_node_ == start_container_ ? start_offset_ : 0; |
| handled_first_letter_ = false; |
| first_letter_text_ = nullptr; |
| @@ -648,8 +672,7 @@ bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { |
| } |
| // Restore the collapsed space for copy & paste. See http://crbug.com/318925 |
| -template <typename Strategy> |
| -size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace( |
| +size_t TextNodeContentExtractor::RestoreCollapsedTrailingSpace( |
| InlineTextBox* next_text_box, |
| size_t subrun_end) { |
| if (next_text_box || !text_box_->Root().NextRootBox() || |
| @@ -677,8 +700,7 @@ size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace( |
| return subrun_end; |
| } |
| -template <typename Strategy> |
| -void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
| +void TextNodeContentExtractor::HandleTextBox() { |
| LayoutText* layout_object = |
| first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject(); |
| const unsigned text_start_offset = layout_object->TextStartOffset(); |
| @@ -716,10 +738,11 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
| unsigned space_run_start = run_start - 1; |
| while (space_run_start > 0 && str[space_run_start - 1] == ' ') |
| --space_run_start; |
| - EmitText(text_node_, layout_object, space_run_start, |
| - space_run_start + 1); |
| + text_state_.EmitText(text_node_, layout_object, space_run_start, |
|
yosin_UTC9
2017/05/25 06:44:09
Let's introduce TextNodeContentExtract::EmitText()
Xiaocheng
2017/05/25 23:47:58
Done.
|
| + space_run_start + 1); |
| } else { |
| - SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start, run_start); |
| + text_state_.SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start, |
|
yosin_UTC9
2017/05/25 06:44:09
Let's introduce TextNodeContentExtract::SpliceBuff
Xiaocheng
2017/05/25 23:47:58
Done.
|
| + run_start); |
| } |
| return; |
| } |
| @@ -757,10 +780,10 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
| // We need to preserve new lines in case of PreLine. |
| // See bug crbug.com/317365. |
| if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine) { |
| - SpliceBuffer('\n', text_node_, 0, run_start, run_start); |
| + text_state_.SpliceBuffer('\n', text_node_, 0, run_start, run_start); |
| } else { |
| - SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start, |
| - run_start + 1); |
| + text_state_.SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start, |
| + run_start + 1); |
| } |
| offset_ = text_start_offset + run_start + 1; |
| } else { |
| @@ -772,7 +795,8 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
| } |
| offset_ = text_start_offset + subrun_end; |
| - EmitText(text_node_, layout_object, run_start, subrun_end); |
| + text_state_.EmitText(text_node_, layout_object, run_start, |
| + subrun_end); |
| } |
| // If we are doing a subrun that doesn't go to the end of the text box, |
| @@ -817,8 +841,7 @@ void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
| } |
| } |
| -template <typename Strategy> |
| -bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { |
| +bool TextNodeContentExtractor::ShouldProceedToRemainingText() const { |
| if (text_box_ || !remaining_text_box_) |
| return false; |
| if (text_node_ != end_container_) |
| @@ -826,16 +849,14 @@ bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { |
| return offset_ < end_offset_; |
| } |
| -template <typename Strategy> |
| -void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() { |
| +void TextNodeContentExtractor::ProceedToRemainingText() { |
| text_box_ = remaining_text_box_; |
| remaining_text_box_ = 0; |
| first_letter_text_ = nullptr; |
| offset_ = text_node_->GetLayoutObject()->TextStartOffset(); |
| } |
| -template <typename Strategy> |
| -void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( |
| +void TextNodeContentExtractor::HandleTextNodeFirstLetter( |
| LayoutTextFragment* layout_object) { |
| handled_first_letter_ = true; |
| @@ -876,21 +897,20 @@ bool TextIteratorAlgorithm<Strategy>::SupportsAltText(Node* node) { |
| return false; |
| } |
| -template <typename Strategy> |
| -bool TextIteratorAlgorithm<Strategy>::FixLeadingWhiteSpaceForReplacedElement( |
| +bool TextNodeContentExtractor::FixLeadingWhiteSpaceForReplacedElement( |
| Node* parent) { |
| if (!last_text_node_ended_with_collapsed_space_) |
| return false; |
| last_text_node_ended_with_collapsed_space_ = false; |
| if (!behavior_.CollapseTrailingSpace()) { |
| - SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); |
| + text_state_.SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); |
| return true; |
| } |
| if (text_node_) { |
| const String str = text_node_->GetLayoutObject()->GetText(); |
| if (offset_ > 0 && str[offset_ - 1] == ' ') { |
| - SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); |
| + text_state_.SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); |
| return true; |
| } |
| } |
| @@ -915,7 +935,7 @@ bool TextIteratorAlgorithm<Strategy>::HandleReplacedElement() { |
| } |
| if (last_text_node_) { |
| - if (FixLeadingWhiteSpaceForReplacedElement( |
| + if (text_extractor_.FixLeadingWhiteSpaceForReplacedElement( |
| Strategy::Parent(*last_text_node_))) |
| return false; |
| } |