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

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: Mon May 29 01:57:14 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::Initialize(Node* start_container,
197 int start_offset,
198 Node* end_container,
199 int end_offset) {
200 // This function should be called only once.
201 DCHECK(!start_container_);
yosin_UTC9 2017/05/29 09:12:59 nit: Please add DCHECK(start_container) and DCHECK
Xiaocheng 2017/05/30 03:01:49 This has been DCHECKed in TI::Initialize.
202 DCHECK_EQ(start_offset_, 0);
203 DCHECK(!end_container_);
204 DCHECK_EQ(end_offset_, 0);
205
206 start_container_ = start_container;
207 start_offset_ = start_offset;
208 end_container_ = end_container;
209 end_offset_ = end_offset;
210 }
211
198 template <typename Strategy> 212 template <typename Strategy>
199 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, 213 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container,
200 int start_offset, 214 int start_offset,
201 Node* end_container, 215 Node* end_container,
202 int end_offset) { 216 int end_offset) {
203 DCHECK(start_container); 217 DCHECK(start_container);
204 DCHECK(end_container); 218 DCHECK(end_container);
205 219
220 text_node_handler_.Initialize(start_container, start_offset, end_container,
221 end_offset);
222
206 // Remember the range - this does not change. 223 // Remember the range - this does not change.
207 start_container_ = start_container; 224 start_container_ = start_container;
208 start_offset_ = start_offset; 225 start_offset_ = start_offset;
209 end_container_ = end_container; 226 end_container_ = end_container;
210 end_offset_ = end_offset; 227 end_offset_ = end_offset;
211 end_node_ = 228 end_node_ =
212 end_container && !end_container->IsCharacterDataNode() && end_offset > 0 229 end_container && !end_container->IsCharacterDataNode() && end_offset > 0
213 ? Strategy::ChildAt(*end_container, end_offset - 1) 230 ? Strategy::ChildAt(*end_container, end_offset - 1)
214 : nullptr; 231 : nullptr;
215 232
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 274
258 template <typename Strategy> 275 template <typename Strategy>
259 bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const { 276 bool TextIteratorAlgorithm<Strategy>::IsInsideAtomicInlineElement() const {
260 if (AtEnd() || length() != 1 || !node_) 277 if (AtEnd() || length() != 1 || !node_)
261 return false; 278 return false;
262 279
263 LayoutObject* layout_object = node_->GetLayoutObject(); 280 LayoutObject* layout_object = node_->GetLayoutObject();
264 return layout_object && layout_object->IsAtomicInlineLevel(); 281 return layout_object && layout_object->IsAtomicInlineLevel();
265 } 282 }
266 283
267 template <typename Strategy> 284 bool TextIteratorTextNodeHandler::HandleRemainingTextRuns() {
268 bool TextIteratorAlgorithm<Strategy>::HandleRemainingTextRuns() {
269 if (ShouldProceedToRemainingText()) 285 if (ShouldProceedToRemainingText())
270 ProceedToRemainingText(); 286 ProceedToRemainingText();
271 // Handle remembered text box 287 // Handle remembered text box
272 if (text_box_) { 288 if (text_box_) {
273 HandleTextBox(); 289 HandleTextBox();
274 return text_state_.PositionNode(); 290 return text_state_.PositionNode();
275 } 291 }
276 // Handle remembered pre-formatted text node. 292 // Handle remembered pre-formatted text node.
277 if (!needs_handle_pre_formatted_text_node_) 293 if (!needs_handle_pre_formatted_text_node_)
278 return false; 294 return false;
(...skipping 21 matching lines...) Expand all
300 // line break begins. 316 // line break begins.
301 // FIXME: It would be cleaner if we emitted two newlines during the last 317 // FIXME: It would be cleaner if we emitted two newlines during the last
302 // iteration, instead of using m_needsAnotherNewline. 318 // iteration, instead of using m_needsAnotherNewline.
303 Node* last_child = Strategy::LastChild(*node_); 319 Node* last_child = Strategy::LastChild(*node_);
304 Node* base_node = last_child ? last_child : node_.Get(); 320 Node* base_node = last_child ? last_child : node_.Get();
305 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1); 321 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1);
306 needs_another_newline_ = false; 322 needs_another_newline_ = false;
307 return; 323 return;
308 } 324 }
309 325
310 if (HandleRemainingTextRuns()) 326 if (text_node_handler_.HandleRemainingTextRuns())
311 return; 327 return;
312 328
313 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) { 329 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) {
314 if (!should_stop_ && StopsOnFormControls() && 330 if (!should_stop_ && StopsOnFormControls() &&
315 HTMLFormControlElement::EnclosingFormControlElement(node_)) 331 HTMLFormControlElement::EnclosingFormControlElement(node_))
316 should_stop_ = true; 332 should_stop_ = true;
317 333
318 // if the range ends at offset 0 of an element, represent the 334 // 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 335 // position, but not the content, of that element e.g. if the
320 // node is a blockflow element, emit a newline that 336 // node is a blockflow element, emit a newline that
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 return false; 520 return false;
505 521
506 DCHECK(fragment->GetFirstLetterPseudoElement()); 522 DCHECK(fragment->GetFirstLetterPseudoElement());
507 LayoutObject* pseudo_element_layout_object = 523 LayoutObject* pseudo_element_layout_object =
508 fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); 524 fragment->GetFirstLetterPseudoElement()->GetLayoutObject();
509 return pseudo_element_layout_object && 525 return pseudo_element_layout_object &&
510 pseudo_element_layout_object->Style()->Visibility() == 526 pseudo_element_layout_object->Style()->Visibility() ==
511 EVisibility::kVisible; 527 EVisibility::kVisible;
512 } 528 }
513 529
514 template <typename Strategy> 530 bool TextIteratorTextNodeHandler::ShouldHandleFirstLetter(
515 bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter(
516 const LayoutText& layout_text) const { 531 const LayoutText& layout_text) const {
517 if (handled_first_letter_) 532 if (handled_first_letter_)
518 return false; 533 return false;
519 if (!layout_text.IsTextFragment()) 534 if (!layout_text.IsTextFragment())
520 return false; 535 return false;
521 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text); 536 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text);
522 return offset_ < static_cast<int>(text_fragment.TextStartOffset()); 537 return offset_ < static_cast<int>(text_fragment.TextStartOffset());
523 } 538 }
524 539
525 template <typename Strategy> 540 void TextIteratorTextNodeHandler::HandlePreFormattedTextNode() {
526 void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() {
527 // TODO(xiaochengh): Get rid of repeated computation of these fields. 541 // TODO(xiaochengh): Get rid of repeated computation of these fields.
528 LayoutText* const layout_object = text_node_->GetLayoutObject(); 542 LayoutText* const layout_object = text_node_->GetLayoutObject();
529 const String str = layout_object->GetText(); 543 const String str = layout_object->GetText();
530 544
531 needs_handle_pre_formatted_text_node_ = false; 545 needs_handle_pre_formatted_text_node_ = false;
532 546
533 if (last_text_node_ended_with_collapsed_space_ && 547 if (last_text_node_ended_with_collapsed_space_ &&
534 HasVisibleTextNode(layout_object)) { 548 HasVisibleTextNode(layout_object)) {
535 if (!behavior_.CollapseTrailingSpace() || 549 if (!behavior_.CollapseTrailingSpace() ||
536 (offset_ > 0 && str[offset_ - 1] == ' ')) { 550 (offset_ > 0 && str[offset_ - 1] == ' ')) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 TextControlElement* control = EnclosingTextControl(node_); 599 TextControlElement* control = EnclosingTextControl(node_);
586 // For security reason, we don't expose suggested value if it is 600 // For security reason, we don't expose suggested value if it is
587 // auto-filled. 601 // auto-filled.
588 if (control && control->IsAutofilled()) 602 if (control && control->IsAutofilled())
589 return true; 603 return true;
590 } 604 }
591 605
592 DCHECK_NE(last_text_node_, node_) 606 DCHECK_NE(last_text_node_, node_)
593 << "We should never call HandleTextNode on the same node twice"; 607 << "We should never call HandleTextNode on the same node twice";
594 last_text_node_ = ToText(node_); 608 last_text_node_ = ToText(node_);
609 return text_node_handler_.HandleTextNode(ToText(node_));
610 }
595 611
596 text_node_ = ToText(node_); 612 bool TextIteratorTextNodeHandler::HandleTextNode(Text* node) {
613 text_node_ = node;
597 offset_ = text_node_ == start_container_ ? start_offset_ : 0; 614 offset_ = text_node_ == start_container_ ? start_offset_ : 0;
598 handled_first_letter_ = false; 615 handled_first_letter_ = false;
599 first_letter_text_ = nullptr; 616 first_letter_text_ = nullptr;
600 617
601 LayoutText* layout_object = text_node_->GetLayoutObject(); 618 LayoutText* layout_object = text_node_->GetLayoutObject();
602 String str = layout_object->GetText(); 619 String str = layout_object->GetText();
603 620
604 // handle pre-formatted text 621 // handle pre-formatted text
605 if (!layout_object->Style()->CollapseWhiteSpace()) { 622 if (!layout_object->Style()->CollapseWhiteSpace()) {
606 HandlePreFormattedTextNode(); 623 HandlePreFormattedTextNode();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 InlineTextBox::CompareByStart); 656 InlineTextBox::CompareByStart);
640 sorted_text_boxes_position_ = 0; 657 sorted_text_boxes_position_ = 0;
641 text_box_ = sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]; 658 text_box_ = sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0];
642 } 659 }
643 660
644 HandleTextBox(); 661 HandleTextBox();
645 return true; 662 return true;
646 } 663 }
647 664
648 // Restore the collapsed space for copy & paste. See http://crbug.com/318925 665 // Restore the collapsed space for copy & paste. See http://crbug.com/318925
649 template <typename Strategy> 666 size_t TextIteratorTextNodeHandler::RestoreCollapsedTrailingSpace(
650 size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace(
651 InlineTextBox* next_text_box, 667 InlineTextBox* next_text_box,
652 size_t subrun_end) { 668 size_t subrun_end) {
653 if (next_text_box || !text_box_->Root().NextRootBox() || 669 if (next_text_box || !text_box_->Root().NextRootBox() ||
654 text_box_->Root().LastChild() != text_box_) 670 text_box_->Root().LastChild() != text_box_)
655 return subrun_end; 671 return subrun_end;
656 672
657 const String& text = text_node_->GetLayoutObject()->GetText(); 673 const String& text = text_node_->GetLayoutObject()->GetText();
658 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 || 674 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 ||
659 text[subrun_end - 1] == ' ') 675 text[subrun_end - 1] == ' ')
660 return subrun_end; 676 return subrun_end;
661 677
662 // If there is the leading space in the next line, we don't need to restore 678 // If there is the leading space in the next line, we don't need to restore
663 // the trailing space. 679 // the trailing space.
664 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div> 680 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div>
665 InlineBox* first_box_of_next_line = 681 InlineBox* first_box_of_next_line =
666 text_box_->Root().NextRootBox()->FirstChild(); 682 text_box_->Root().NextRootBox()->FirstChild();
667 if (!first_box_of_next_line) 683 if (!first_box_of_next_line)
668 return subrun_end + 1; 684 return subrun_end + 1;
669 Node* first_node_of_next_line = 685 Node* first_node_of_next_line =
670 first_box_of_next_line->GetLineLayoutItem().GetNode(); 686 first_box_of_next_line->GetLineLayoutItem().GetNode();
671 if (!first_node_of_next_line || 687 if (!first_node_of_next_line ||
672 first_node_of_next_line->nodeValue()[0] != ' ') 688 first_node_of_next_line->nodeValue()[0] != ' ')
673 return subrun_end + 1; 689 return subrun_end + 1;
674 690
675 return subrun_end; 691 return subrun_end;
676 } 692 }
677 693
678 template <typename Strategy> 694 void TextIteratorTextNodeHandler::HandleTextBox() {
679 void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
680 LayoutText* layout_object = 695 LayoutText* layout_object =
681 first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject(); 696 first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject();
682 const unsigned text_start_offset = layout_object->TextStartOffset(); 697 const unsigned text_start_offset = layout_object->TextStartOffset();
683 698
684 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 699 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
685 !IgnoresStyleVisibility()) { 700 !IgnoresStyleVisibility()) {
686 text_box_ = nullptr; 701 text_box_ = nullptr;
687 } else { 702 } else {
688 String str = layout_object->GetText(); 703 String str = layout_object->GetText();
689 // Start and end offsets in |str|, i.e., str[start..end - 1] should be 704 // 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_; 822 ++sorted_text_boxes_position_;
808 } 823 }
809 } 824 }
810 825
811 if (ShouldProceedToRemainingText()) { 826 if (ShouldProceedToRemainingText()) {
812 ProceedToRemainingText(); 827 ProceedToRemainingText();
813 HandleTextBox(); 828 HandleTextBox();
814 } 829 }
815 } 830 }
816 831
817 template <typename Strategy> 832 bool TextIteratorTextNodeHandler::ShouldProceedToRemainingText() const {
818 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const {
819 if (text_box_ || !remaining_text_box_) 833 if (text_box_ || !remaining_text_box_)
820 return false; 834 return false;
821 if (text_node_ != end_container_) 835 if (text_node_ != end_container_)
822 return true; 836 return true;
823 return offset_ < end_offset_; 837 return offset_ < end_offset_;
824 } 838 }
825 839
826 template <typename Strategy> 840 void TextIteratorTextNodeHandler::ProceedToRemainingText() {
827 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() {
828 text_box_ = remaining_text_box_; 841 text_box_ = remaining_text_box_;
829 remaining_text_box_ = 0; 842 remaining_text_box_ = 0;
830 first_letter_text_ = nullptr; 843 first_letter_text_ = nullptr;
831 offset_ = text_node_->GetLayoutObject()->TextStartOffset(); 844 offset_ = text_node_->GetLayoutObject()->TextStartOffset();
832 } 845 }
833 846
834 template <typename Strategy> 847 void TextIteratorTextNodeHandler::HandleTextNodeFirstLetter(
835 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter(
836 LayoutTextFragment* layout_object) { 848 LayoutTextFragment* layout_object) {
837 handled_first_letter_ = true; 849 handled_first_letter_ = true;
838 850
839 if (!layout_object->IsRemainingTextLayoutObject()) 851 if (!layout_object->IsRemainingTextLayoutObject())
840 return; 852 return;
841 853
842 FirstLetterPseudoElement* first_letter_element = 854 FirstLetterPseudoElement* first_letter_element =
843 layout_object->GetFirstLetterPseudoElement(); 855 layout_object->GetFirstLetterPseudoElement();
844 if (!first_letter_element) 856 if (!first_letter_element)
845 return; 857 return;
(...skipping 20 matching lines...) Expand all
866 878
867 // FIXME: Add isSVGImageElement. 879 // FIXME: Add isSVGImageElement.
868 if (isHTMLImageElement(element)) 880 if (isHTMLImageElement(element))
869 return true; 881 return true;
870 if (isHTMLInputElement(ToHTMLElement(*node)) && 882 if (isHTMLInputElement(ToHTMLElement(*node)) &&
871 toHTMLInputElement(*node).type() == InputTypeNames::image) 883 toHTMLInputElement(*node).type() == InputTypeNames::image)
872 return true; 884 return true;
873 return false; 885 return false;
874 } 886 }
875 887
876 template <typename Strategy> 888 bool TextIteratorTextNodeHandler::FixLeadingWhiteSpaceForReplacedElement(
877 bool TextIteratorAlgorithm<Strategy>::FixLeadingWhiteSpaceForReplacedElement(
878 Node* parent) { 889 Node* parent) {
879 // This is a hacky way for white space fixup in legacy layout. With LayoutNG, 890 // This is a hacky way for white space fixup in legacy layout. With LayoutNG,
880 // we can get rid of this function. 891 // we can get rid of this function.
881 892
882 if (behavior_.CollapseTrailingSpace()) { 893 if (behavior_.CollapseTrailingSpace()) {
883 if (text_node_) { 894 if (text_node_) {
884 String str = text_node_->GetLayoutObject()->GetText(); 895 String str = text_node_->GetLayoutObject()->GetText();
885 if (last_text_node_ended_with_collapsed_space_ && offset_ > 0 && 896 if (last_text_node_ended_with_collapsed_space_ && offset_ > 0 &&
886 str[offset_ - 1] == ' ') { 897 str[offset_ - 1] == ' ') {
887 SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1); 898 SpliceBuffer(kSpaceCharacter, parent, text_node_, 1, 1);
(...skipping 17 matching lines...) Expand all
905 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 916 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
906 !IgnoresStyleVisibility()) 917 !IgnoresStyleVisibility())
907 return false; 918 return false;
908 919
909 if (EmitsObjectReplacementCharacter()) { 920 if (EmitsObjectReplacementCharacter()) {
910 SpliceBuffer(kObjectReplacementCharacter, Strategy::Parent(*node_), node_, 921 SpliceBuffer(kObjectReplacementCharacter, Strategy::Parent(*node_), node_,
911 0, 1); 922 0, 1);
912 return true; 923 return true;
913 } 924 }
914 925
915 DCHECK_EQ(last_text_node_, text_node_); 926 DCHECK_EQ(last_text_node_, text_node_handler_.GetNode());
916 if (last_text_node_) { 927 if (last_text_node_) {
917 if (FixLeadingWhiteSpaceForReplacedElement( 928 if (text_node_handler_.FixLeadingWhiteSpaceForReplacedElement(
918 Strategy::Parent(*last_text_node_))) 929 Strategy::Parent(*last_text_node_)))
919 return false; 930 return false;
920 } 931 }
921 932
922 if (EntersTextControls() && layout_object->IsTextControl()) { 933 if (EntersTextControls() && layout_object->IsTextControl()) {
923 // The shadow tree should be already visited. 934 // The shadow tree should be already visited.
924 return true; 935 return true;
925 } 936 }
926 937
927 if (EmitsCharactersBetweenAllVisiblePositions()) { 938 if (EmitsCharactersBetweenAllVisiblePositions()) {
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
1209 1, 1); 1220 1, 1);
1210 } 1221 }
1211 } 1222 }
1212 1223
1213 // If nothing was emitted, see if we need to emit a space. 1224 // If nothing was emitted, see if we need to emit a space.
1214 if (!text_state_.PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_)) 1225 if (!text_state_.PositionNode() && ShouldEmitSpaceBeforeAndAfterNode(node_))
1215 SpliceBuffer(kSpaceCharacter, Strategy::Parent(*base_node), base_node, 1, 1226 SpliceBuffer(kSpaceCharacter, Strategy::Parent(*base_node), base_node, 1,
1216 1); 1227 1);
1217 } 1228 }
1218 1229
1219 template <typename Strategy> 1230 void TextIteratorTextNodeHandler::ResetCollapsedWhiteSpaceFixup() {
1220 void TextIteratorAlgorithm<Strategy>::ResetCollapsedWhiteSpaceFixup() {
1221 // This is a hacky way for white space fixup in legacy layout. With LayoutNG, 1231 // This is a hacky way for white space fixup in legacy layout. With LayoutNG,
1222 // we can get rid of this function. 1232 // we can get rid of this function.
1223 last_text_node_ended_with_collapsed_space_ = false; 1233 last_text_node_ended_with_collapsed_space_ = false;
1224 } 1234 }
1225 1235
1226 template <typename Strategy> 1236 template <typename Strategy>
1227 void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c, 1237 void TextIteratorAlgorithm<Strategy>::SpliceBuffer(UChar c,
1228 Node* text_node, 1238 Node* text_node,
1229 Node* offset_base_node, 1239 Node* offset_base_node,
1230 int text_start_offset, 1240 int text_start_offset,
1231 int text_end_offset) { 1241 int text_end_offset) {
1232 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset, 1242 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
1233 text_end_offset); 1243 text_end_offset);
1244 text_node_handler_.ResetCollapsedWhiteSpaceFixup();
1245 }
1246
1247 void TextIteratorTextNodeHandler::SpliceBuffer(UChar c,
1248 Node* text_node,
1249 Node* offset_base_node,
1250 int text_start_offset,
1251 int text_end_offset) {
1252 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset,
1253 text_end_offset);
1234 ResetCollapsedWhiteSpaceFixup(); 1254 ResetCollapsedWhiteSpaceFixup();
1235 } 1255 }
1236 1256
1237 template <typename Strategy> 1257 void TextIteratorTextNodeHandler::EmitText(Node* text_node,
1238 void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node, 1258 LayoutText* layout_object,
1239 LayoutText* layout_object, 1259 int text_start_offset,
1240 int text_start_offset, 1260 int text_end_offset) {
1241 int text_end_offset) {
1242 text_state_.EmitText(text_node, layout_object, text_start_offset, 1261 text_state_.EmitText(text_node, layout_object, text_start_offset,
1243 text_end_offset); 1262 text_end_offset);
1244 ResetCollapsedWhiteSpaceFixup(); 1263 ResetCollapsedWhiteSpaceFixup();
1245 } 1264 }
1246 1265
1247 template <typename Strategy> 1266 template <typename Strategy>
1248 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range() 1267 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range()
1249 const { 1268 const {
1250 // use the current run information, if we have it 1269 // use the current run information, if we have it
1251 if (text_state_.PositionNode()) { 1270 if (text_state_.PositionNode()) {
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
1422 String PlainText(const EphemeralRangeInFlatTree& range, 1441 String PlainText(const EphemeralRangeInFlatTree& range,
1423 const TextIteratorBehavior& behavior) { 1442 const TextIteratorBehavior& behavior) {
1424 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); 1443 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior);
1425 } 1444 }
1426 1445
1427 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; 1446 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>;
1428 template class CORE_TEMPLATE_EXPORT 1447 template class CORE_TEMPLATE_EXPORT
1429 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; 1448 TextIteratorAlgorithm<EditingInFlatTreeStrategy>;
1430 1449
1431 } // namespace blink 1450 } // 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