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

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

Issue 2903693005: Introduce a wrapper class to handle text node in TextIterator (Closed)
Patch Set: Sun May 28 22:55:59 PDT 2017 Created 3 years, 6 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 unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/editing/iterators/TextIterator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All
3 * rights reserved. 3 * rights reserved.
4 * Copyright (C) 2005 Alexey Proskuryakov. 4 * Copyright (C) 2005 Alexey Proskuryakov.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 145
146 bool IsRenderedAsTable(const Node* node) { 146 bool IsRenderedAsTable(const Node* node) {
147 if (!node || !node->IsElementNode()) 147 if (!node || !node->IsElementNode())
148 return false; 148 return false;
149 LayoutObject* layout_object = node->GetLayoutObject(); 149 LayoutObject* layout_object = node->GetLayoutObject();
150 return layout_object && layout_object->IsTable(); 150 return layout_object && layout_object->IsTable();
151 } 151 }
152 152
153 } // namespace 153 } // namespace
154 154
155 TextIteratorTextNodeHandler::TextIteratorTextNodeHandler(
156 const TextIteratorBehavior& behavior,
157 TextIteratorTextState* text_state)
158 : behavior_(behavior), text_state_(*text_state) {}
159
155 template <typename Strategy> 160 template <typename Strategy>
156 TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm( 161 TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm(
157 const PositionTemplate<Strategy>& start, 162 const PositionTemplate<Strategy>& start,
158 const PositionTemplate<Strategy>& end, 163 const PositionTemplate<Strategy>& end,
159 const TextIteratorBehavior& behavior) 164 const TextIteratorBehavior& behavior)
160 : offset_(0), 165 : start_container_(nullptr),
161 start_container_(nullptr),
162 start_offset_(0), 166 start_offset_(0),
163 end_container_(nullptr), 167 end_container_(nullptr),
164 end_offset_(0), 168 end_offset_(0),
165 needs_another_newline_(false), 169 needs_another_newline_(false),
166 text_box_(nullptr),
167 remaining_text_box_(nullptr),
168 first_letter_text_(nullptr),
169 last_text_node_(nullptr), 170 last_text_node_(nullptr),
170 last_text_node_ended_with_collapsed_space_(false),
171 sorted_text_boxes_position_(0),
172 behavior_(AdjustBehaviorFlags<Strategy>(behavior)), 171 behavior_(AdjustBehaviorFlags<Strategy>(behavior)),
173 needs_handle_pre_formatted_text_node_(false),
174 handled_first_letter_(false),
175 should_stop_(false), 172 should_stop_(false),
176 handle_shadow_root_(false), 173 handle_shadow_root_(false),
177 text_state_(behavior_) { 174 text_state_(behavior_),
175 text_node_handler_(behavior_, &text_state_) {
178 DCHECK(start.IsNotNull()); 176 DCHECK(start.IsNotNull());
179 DCHECK(end.IsNotNull()); 177 DCHECK(end.IsNotNull());
180 178
181 // TODO(dglazkov): TextIterator should not be created for documents that don't 179 // TODO(dglazkov): TextIterator should not be created for documents that don't
182 // have a frame, but it currently still happens in some cases. See 180 // have a frame, but it currently still happens in some cases. See
183 // http://crbug.com/591877 for details. 181 // http://crbug.com/591877 for details.
184 DCHECK(!start.GetDocument()->View() || 182 DCHECK(!start.GetDocument()->View() ||
185 !start.GetDocument()->View()->NeedsLayout()); 183 !start.GetDocument()->View()->NeedsLayout());
186 DCHECK(!start.GetDocument()->NeedsLayoutTreeUpdate()); 184 DCHECK(!start.GetDocument()->NeedsLayoutTreeUpdate());
187 185
188 if (start.CompareTo(end) > 0) { 186 if (start.CompareTo(end) > 0) {
189 Initialize(end.ComputeContainerNode(), end.ComputeOffsetInContainerNode(), 187 Initialize(end.ComputeContainerNode(), end.ComputeOffsetInContainerNode(),
190 start.ComputeContainerNode(), 188 start.ComputeContainerNode(),
191 start.ComputeOffsetInContainerNode()); 189 start.ComputeOffsetInContainerNode());
192 return; 190 return;
193 } 191 }
194 Initialize(start.ComputeContainerNode(), start.ComputeOffsetInContainerNode(), 192 Initialize(start.ComputeContainerNode(), start.ComputeOffsetInContainerNode(),
195 end.ComputeContainerNode(), end.ComputeOffsetInContainerNode()); 193 end.ComputeContainerNode(), end.ComputeOffsetInContainerNode());
196 } 194 }
197 195
196 void TextIteratorTextNodeHandler::SetBoundaries(Node* start_container,
yosin_UTC9 2017/05/29 06:42:31 This function name can be misleading, e.g. we can
Xiaocheng 2017/05/29 07:01:37 This function is only called once. It copies the i
yosin_UTC9 2017/05/29 07:43:56 Could you add TODO about we'll remove this functio
Xiaocheng 2017/05/29 08:59:28 Renamed and added DCHECK.
197 int start_offset,
198 Node* end_container,
199 int end_offset) {
200 start_container_ = start_container;
201 start_offset_ = start_offset;
202 end_container_ = end_container;
203 end_offset_ = end_offset;
204 }
205
198 template <typename Strategy> 206 template <typename Strategy>
199 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, 207 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container,
200 int start_offset, 208 int start_offset,
201 Node* end_container, 209 Node* end_container,
202 int end_offset) { 210 int end_offset) {
203 DCHECK(start_container); 211 DCHECK(start_container);
204 DCHECK(end_container); 212 DCHECK(end_container);
205 213
214 // TODO(xiaochengh): There is no need to pass the entire range. Instead, we
215 // can pass the start and end offsets when calling HandleTextNode().
216 text_node_handler_.SetBoundaries(start_container, start_offset, end_container,
217 end_offset);
218
206 // Remember the range - this does not change. 219 // Remember the range - this does not change.
207 start_container_ = start_container; 220 start_container_ = start_container;
208 start_offset_ = start_offset; 221 start_offset_ = start_offset;
209 end_container_ = end_container; 222 end_container_ = end_container;
210 end_offset_ = end_offset; 223 end_offset_ = end_offset;
211 end_node_ = 224 end_node_ =
212 end_container && !end_container->IsCharacterDataNode() && end_offset > 0 225 end_container && !end_container->IsCharacterDataNode() && end_offset > 0
213 ? Strategy::ChildAt(*end_container, end_offset - 1) 226 ? Strategy::ChildAt(*end_container, end_offset - 1)
214 : nullptr; 227 : nullptr;
215 228
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 270
258 template <typename Strategy> 271 template <typename Strategy>
259 bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const { 272 bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const {
260 if (AtEnd() || length() != 1 || !node_) 273 if (AtEnd() || length() != 1 || !node_)
261 return false; 274 return false;
262 275
263 LayoutObject* layout_object = node_->GetLayoutObject(); 276 LayoutObject* layout_object = node_->GetLayoutObject();
264 return layout_object && layout_object->IsAtomicInlineLevel(); 277 return layout_object && layout_object->IsAtomicInlineLevel();
265 } 278 }
266 279
267 template <typename Strategy> 280 bool TextIteratorTextNodeHandler::HandleRemainingTextRuns() {
268 bool TextIteratorAlgorithm<Strategy>::HandleRemainingTextRuns() {
269 if (ShouldProceedToRemainingText()) 281 if (ShouldProceedToRemainingText())
270 ProceedToRemainingText(); 282 ProceedToRemainingText();
271 // Handle remembered text box 283 // Handle remembered text box
272 if (text_box_) { 284 if (text_box_) {
273 HandleTextBox(); 285 HandleTextBox();
274 return text_state_.PositionNode(); 286 return text_state_.PositionNode();
275 } 287 }
276 // Handle remembered pre-formatted text node. 288 // Handle remembered pre-formatted text node.
277 if (!needs_handle_pre_formatted_text_node_) 289 if (!needs_handle_pre_formatted_text_node_)
278 return false; 290 return false;
(...skipping 21 matching lines...) Expand all
300 // line break begins. 312 // line break begins.
301 // FIXME: It would be cleaner if we emitted two newlines during the last 313 // FIXME: It would be cleaner if we emitted two newlines during the last
302 // iteration, instead of using m_needsAnotherNewline. 314 // iteration, instead of using m_needsAnotherNewline.
303 Node* last_child = Strategy::LastChild(*node_); 315 Node* last_child = Strategy::LastChild(*node_);
304 Node* base_node = last_child ? last_child : node_.Get(); 316 Node* base_node = last_child ? last_child : node_.Get();
305 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1); 317 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1);
306 needs_another_newline_ = false; 318 needs_another_newline_ = false;
307 return; 319 return;
308 } 320 }
309 321
310 if (HandleRemainingTextRuns()) 322 if (text_node_handler_.HandleRemainingTextRuns())
311 return; 323 return;
312 324
313 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) { 325 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) {
314 if (!should_stop_ && StopsOnFormControls() && 326 if (!should_stop_ && StopsOnFormControls() &&
315 HTMLFormControlElement::EnclosingFormControlElement(node_)) 327 HTMLFormControlElement::EnclosingFormControlElement(node_))
316 should_stop_ = true; 328 should_stop_ = true;
317 329
318 // if the range ends at offset 0 of an element, represent the 330 // if the range ends at offset 0 of an element, represent the
319 // position, but not the content, of that element e.g. if the 331 // position, but not the content, of that element e.g. if the
320 // node is a blockflow element, emit a newline that 332 // node is a blockflow element, emit a newline that
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 return false; 516 return false;
505 517
506 DCHECK(fragment->GetFirstLetterPseudoElement()); 518 DCHECK(fragment->GetFirstLetterPseudoElement());
507 LayoutObject* pseudo_element_layout_object = 519 LayoutObject* pseudo_element_layout_object =
508 fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); 520 fragment->GetFirstLetterPseudoElement()->GetLayoutObject();
509 return pseudo_element_layout_object && 521 return pseudo_element_layout_object &&
510 pseudo_element_layout_object->Style()->Visibility() == 522 pseudo_element_layout_object->Style()->Visibility() ==
511 EVisibility::kVisible; 523 EVisibility::kVisible;
512 } 524 }
513 525
514 template <typename Strategy> 526 bool TextIteratorTextNodeHandler::ShouldHandleFirstLetter(
515 bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter(
516 const LayoutText& layout_text) const { 527 const LayoutText& layout_text) const {
517 if (handled_first_letter_) 528 if (handled_first_letter_)
518 return false; 529 return false;
519 if (!layout_text.IsTextFragment()) 530 if (!layout_text.IsTextFragment())
520 return false; 531 return false;
521 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text); 532 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text);
522 return offset_ < static_cast<int>(text_fragment.TextStartOffset()); 533 return offset_ < static_cast<int>(text_fragment.TextStartOffset());
523 } 534 }
524 535
525 template <typename Strategy> 536 void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
526 void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() {
527 // TODO(xiaochengh): Get rid of repeated computation of these fields. 537 // TODO(xiaochengh): Get rid of repeated computation of these fields.
528 LayoutText* const layout_object = text_node_->GetLayoutObject(); 538 LayoutText* const layout_object = text_node_->GetLayoutObject();
529 const String str = layout_object->GetText(); 539 const String str = layout_object->GetText();
530 540
531 needs_handle_pre_formatted_text_node_ = false; 541 needs_handle_pre_formatted_text_node_ = false;
532 542
533 if (last_text_node_ended_with_collapsed_space_ && 543 if (last_text_node_ended_with_collapsed_space_ &&
534 HasVisibleTextNode(layout_object)) { 544 HasVisibleTextNode(layout_object)) {
535 if (!behavior_.CollapseTrailingSpace() || 545 if (!behavior_.CollapseTrailingSpace() ||
536 (offset_ > 0 && str[offset_ - 1] == ' ')) { 546 (offset_ > 0 && str[offset_ - 1] == ' ')) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 TextControlElement* control = EnclosingTextControl(node_); 595 TextControlElement* control = EnclosingTextControl(node_);
586 // For security reason, we don't expose suggested value if it is 596 // For security reason, we don't expose suggested value if it is
587 // auto-filled. 597 // auto-filled.
588 if (control && control->IsAutofilled()) 598 if (control && control->IsAutofilled())
589 return true; 599 return true;
590 } 600 }
591 601
592 DCHECK_NE(last_text_node_, node_) 602 DCHECK_NE(last_text_node_, node_)
593 << "We should never call HandleTextNode on the same node twice"; 603 << "We should never call HandleTextNode on the same node twice";
594 last_text_node_ = ToText(node_); 604 last_text_node_ = ToText(node_);
605 return text_node_handler_.HandleTextNode(ToText(node_));
606 }
595 607
596 text_node_ = ToText(node_); 608 bool TextIteratorTextNodeHandler::HandleTextNode(Text* node) {
609 text_node_ = node;
597 offset_ = text_node_ == start_container_ ? start_offset_ : 0; 610 offset_ = text_node_ == start_container_ ? start_offset_ : 0;
598 handled_first_letter_ = false; 611 handled_first_letter_ = false;
599 first_letter_text_ = nullptr; 612 first_letter_text_ = nullptr;
600 613
601 LayoutText* layout_object = text_node_->GetLayoutObject(); 614 LayoutText* layout_object = text_node_->GetLayoutObject();
602 String str = layout_object->GetText(); 615 String str = layout_object->GetText();
603 616
604 // handle pre-formatted text 617 // handle pre-formatted text
605 if (!layout_object->Style()->CollapseWhiteSpace()) { 618 if (!layout_object->Style()->CollapseWhiteSpace()) {
606 HandlePreFormattedTextNode(); 619 HandlePreFormattedTextNode();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 InlineTextBox::CompareByStart); 652 InlineTextBox::CompareByStart);
640 sorted_text_boxes_position_ = 0; 653 sorted_text_boxes_position_ = 0;
641 text_box_ = sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]; 654 text_box_ = sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0];
642 } 655 }
643 656
644 HandleTextBox(); 657 HandleTextBox();
645 return true; 658 return true;
646 } 659 }
647 660
648 // Restore the collapsed space for copy & paste. See http://crbug.com/318925 661 // Restore the collapsed space for copy & paste. See http://crbug.com/318925
649 template <typename Strategy> 662 size_t TextIteratorTextNodeHandler::RestoreCollapsedTrailingSpace(
650 size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace(
651 InlineTextBox* next_text_box, 663 InlineTextBox* next_text_box,
652 size_t subrun_end) { 664 size_t subrun_end) {
653 if (next_text_box || !text_box_->Root().NextRootBox() || 665 if (next_text_box || !text_box_->Root().NextRootBox() ||
654 text_box_->Root().LastChild() != text_box_) 666 text_box_->Root().LastChild() != text_box_)
655 return subrun_end; 667 return subrun_end;
656 668
657 const String& text = text_node_->GetLayoutObject()->GetText(); 669 const String& text = text_node_->GetLayoutObject()->GetText();
658 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 || 670 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 ||
659 text[subrun_end - 1] == ' ') 671 text[subrun_end - 1] == ' ')
660 return subrun_end; 672 return subrun_end;
661 673
662 // If there is the leading space in the next line, we don't need to restore 674 // If there is the leading space in the next line, we don't need to restore
663 // the trailing space. 675 // the trailing space.
664 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div> 676 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div>
665 InlineBox* first_box_of_next_line = 677 InlineBox* first_box_of_next_line =
666 text_box_->Root().NextRootBox()->FirstChild(); 678 text_box_->Root().NextRootBox()->FirstChild();
667 if (!first_box_of_next_line) 679 if (!first_box_of_next_line)
668 return subrun_end + 1; 680 return subrun_end + 1;
669 Node* first_node_of_next_line = 681 Node* first_node_of_next_line =
670 first_box_of_next_line->GetLineLayoutItem().GetNode(); 682 first_box_of_next_line->GetLineLayoutItem().GetNode();
671 if (!first_node_of_next_line || 683 if (!first_node_of_next_line ||
672 first_node_of_next_line->nodeValue()[0] != ' ') 684 first_node_of_next_line->nodeValue()[0] != ' ')
673 return subrun_end + 1; 685 return subrun_end + 1;
674 686
675 return subrun_end; 687 return subrun_end;
676 } 688 }
677 689
678 template <typename Strategy> 690 void TextIteratorTextNodeHandler::HandleTextBox() {
679 void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
680 LayoutText* layout_object = 691 LayoutText* layout_object =
681 first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject(); 692 first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject();
682 const unsigned text_start_offset = layout_object->TextStartOffset(); 693 const unsigned text_start_offset = layout_object->TextStartOffset();
683 694
684 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 695 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
685 !IgnoresStyleVisibility()) { 696 !IgnoresStyleVisibility()) {
686 text_box_ = nullptr; 697 text_box_ = nullptr;
687 } else { 698 } else {
688 String str = layout_object->GetText(); 699 String str = layout_object->GetText();
689 // Start and end offsets in |str|, i.e., str[start..end - 1] should be 700 // Start and end offsets in |str|, i.e., str[start..end - 1] should be
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 ++sorted_text_boxes_position_; 818 ++sorted_text_boxes_position_;
808 } 819 }
809 } 820 }
810 821
811 if (ShouldProceedToRemainingText()) { 822 if (ShouldProceedToRemainingText()) {
812 ProceedToRemainingText(); 823 ProceedToRemainingText();
813 HandleTextBox(); 824 HandleTextBox();
814 } 825 }
815 } 826 }
816 827
817 template <typename Strategy> 828 bool TextIteratorTextNodeHandler::ShouldProceedToRemainingText() const {
818 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const {
819 if (text_box_ || !remaining_text_box_) 829 if (text_box_ || !remaining_text_box_)
820 return false; 830 return false;
821 if (text_node_ != end_container_) 831 if (text_node_ != end_container_)
822 return true; 832 return true;
823 return offset_ < end_offset_; 833 return offset_ < end_offset_;
824 } 834 }
825 835
826 template <typename Strategy> 836 void TextIteratorTextNodeHandler::ProceedToRemainingText() {
827 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() {
828 text_box_ = remaining_text_box_; 837 text_box_ = remaining_text_box_;
829 remaining_text_box_ = 0; 838 remaining_text_box_ = 0;
830 first_letter_text_ = nullptr; 839 first_letter_text_ = nullptr;
831 offset_ = text_node_->GetLayoutObject()->TextStartOffset(); 840 offset_ = text_node_->GetLayoutObject()->TextStartOffset();
832 } 841 }
833 842
834 template <typename Strategy> 843 void TextIteratorTextNodeHandler::HandleTextNodeFirstLetter(
835 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter(
836 LayoutTextFragment* layout_object) { 844 LayoutTextFragment* layout_object) {
837 handled_first_letter_ = true; 845 handled_first_letter_ = true;
838 846
839 if (!layout_object->IsRemainingTextLayoutObject()) 847 if (!layout_object->IsRemainingTextLayoutObject())
840 return; 848 return;
841 849
842 FirstLetterPseudoElement* first_letter_element = 850 FirstLetterPseudoElement* first_letter_element =
843 layout_object->GetFirstLetterPseudoElement(); 851 layout_object->GetFirstLetterPseudoElement();
844 if (!first_letter_element) 852 if (!first_letter_element)
845 return; 853 return;
(...skipping 20 matching lines...) Expand all
866 874
867 // FIXME: Add isSVGImageElement. 875 // FIXME: Add isSVGImageElement.
868 if (isHTMLImageElement(element)) 876 if (isHTMLImageElement(element))
869 return true; 877 return true;
870 if (isHTMLInputElement(ToHTMLElement(*node)) && 878 if (isHTMLInputElement(ToHTMLElement(*node)) &&
871 toHTMLInputElement(*node).type() == InputTypeNames::image) 879 toHTMLInputElement(*node).type() == InputTypeNames::image)
872 return true; 880 return true;
873 return false; 881 return false;
874 } 882 }
875 883
876 template <typename Strategy> 884 bool TextIteratorTextNodeHandler::FixLeadingWhiteSpaceForReplacedElement(
877 bool TextIteratorAlgorithm<Strategy>::FixLeadingWhiteSpaceForReplacedElement(
878 Node* parent) { 885 Node* parent) {
879 // This is a hacky way for white space fixup in legacy layout. With LayoutNG, 886 // This is a hacky way for white space fixup in legacy layout. With LayoutNG,
880 // we can get rid of this function. 887 // we can get rid of this function.
881 888
882 if (behavior_.CollapseTrailingSpace()) { 889 if (behavior_.CollapseTrailingSpace()) {
883 if (text_node_) { 890 if (text_node_) {
884 String str = text_node_->GetLayoutObject()->GetText(); 891 String str = text_node_->GetLayoutObject()->GetText();
885 if (last_text_node_ended_with_collapsed_space_ && offset_ > 0 && 892 if (last_text_node_ended_with_collapsed_space_ && offset_ > 0 &&
886 str[offset_ - 1] == ' ') { 893 str[offset_ - 1] == ' ') {
887 SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); 894 SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1);
(...skipping 17 matching lines...) Expand all
905 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 912 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
906 !IgnoresStyleVisibility()) 913 !IgnoresStyleVisibility())
907 return false; 914 return false;
908 915
909 if (EmitsObjectReplacementCharacter()) { 916 if (EmitsObjectReplacementCharacter()) {
910 SpliceBuffer(kObjectReplacementCharacter, Strategy::Parent(*node_), node_, 917 SpliceBuffer(kObjectReplacementCharacter, Strategy::Parent(*node_), node_,
911 0, 1); 918 0, 1);
912 return true; 919 return true;
913 } 920 }
914 921
915 DCHECK_EQ(last_text_node_, text_node_); 922 DCHECK_EQ(last_text_node_, text_node_handler_.GetNode());
916 if (last_text_node_) { 923 if (last_text_node_) {
917 if (FixLeadingWhiteSpaceForReplacedElement( 924 if (text_node_handler_.FixLeadingWhiteSpaceForReplacedElement(
918 Strategy::Parent(*last_text_node_))) 925 Strategy::Parent(*last_text_node_)))
919 return false; 926 return false;
920 } 927 }
921 928
922 if (EntersTextControls() && layout_object->IsTextControl()) { 929 if (EntersTextControls() && layout_object->IsTextControl()) {
923 // The shadow tree should be already visited. 930 // The shadow tree should be already visited.
924 return true; 931 return true;
925 } 932 }
926 933
927 if (EmitsCharactersBetweenAllVisiblePositions()) { 934 if (EmitsCharactersBetweenAllVisiblePositions()) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 1, 1); 1216 1, 1);
1210 } 1217 }
1211 } 1218 }
1212 1219
1213 // If nothing was emitted, see if we need to emit a space. 1220 // If nothing was emitted, see if we need to emit a space.
1214 if (!text_state_.PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_)) 1221 if (!text_state_.PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_))
1215 SpliceBuffer(kSpaceCharacter, Strategy::Parent(*base_node), base_node, 1, 1222 SpliceBuffer(kSpaceCharacter, Strategy::Parent(*base_node), base_node, 1,
1216 1); 1223 1);
1217 } 1224 }
1218 1225
1219 template <typename Strategy> 1226 void TextIteratorTextNodeHandler::ResetCollapsedWhiteSpaceFixup() {
1220 void TextIteratorAlgorithm<Strategy>::ResetCollapsedWhiteSpaceFixup() {
1221 // This is a hacky way for white space fixup in legacy layout. With LayoutNG, 1227 // This is a hacky way for white space fixup in legacy layout. With LayoutNG,
1222 // we can get rid of this function. 1228 // we can get rid of this function.
1223 last_text_node_ended_with_collapsed_space_ = false; 1229 last_text_node_ended_with_collapsed_space_ = false;
1224 } 1230 }
1225 1231
1226 template <typename Strategy> 1232 template <typename Strategy>
1227 void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c, 1233 void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c,
1228 Node* text_node, 1234 Node* text_node,
1229 Node* offset_base_node, 1235 Node* offset_base_node,
1230 int text_start_offset, 1236 int text_start_offset,
1231 int text_end_offset) { 1237 int text_end_offset) {
1232 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset, 1238 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
1233 text_end_offset); 1239 text_end_offset);
1240 text_node_handler_.ResetCollapsedWhiteSpaceFixup();
1241 }
1242
1243 void TextIteratorTextNodeHandler::SpliceBuffer(UChar c,
1244 Node* text_node,
1245 Node* offset_base_node,
1246 int text_start_offset,
1247 int text_end_offset) {
1248 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
1249 text_end_offset);
1234 ResetCollapsedWhiteSpaceFixup(); 1250 ResetCollapsedWhiteSpaceFixup();
1235 } 1251 }
1236 1252
1237 template <typename Strategy> 1253 void TextIteratorTextNodeHandler::EmitText(Node* text_node,
1238 void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node, 1254 LayoutText* layout_object,
1239 LayoutText* layout_object, 1255 int text_start_offset,
1240 int text_start_offset, 1256 int text_end_offset) {
1241 int text_end_offset) {
1242 text_state_.EmitText(text_node, layout_object, text_start_offset, 1257 text_state_.EmitText(text_node, layout_object, text_start_offset,
1243 text_end_offset); 1258 text_end_offset);
1244 ResetCollapsedWhiteSpaceFixup(); 1259 ResetCollapsedWhiteSpaceFixup();
1245 } 1260 }
1246 1261
1247 template <typename Strategy> 1262 template <typename Strategy>
1248 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range() 1263 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range()
1249 const { 1264 const {
1250 // use the current run information, if we have it 1265 // use the current run information, if we have it
1251 if (text_state_.PositionNode()) { 1266 if (text_state_.PositionNode()) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 String PlainText(const EphemeralRangeInFlatTree& range, 1437 String PlainText(const EphemeralRangeInFlatTree& range,
1423 const TextIteratorBehavior& behavior) { 1438 const TextIteratorBehavior& behavior) {
1424 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); 1439 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior);
1425 } 1440 }
1426 1441
1427 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; 1442 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>;
1428 template class CORE_TEMPLATE_EXPORT 1443 template class CORE_TEMPLATE_EXPORT
1429 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; 1444 TextIteratorAlgorithm<EditingInFlatTreeStrategy>;
1430 1445
1431 } // namespace blink 1446 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/editing/iterators/TextIterator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698