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

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

Issue 2902173003: Add member TextIterator::text_node_ (Closed)
Patch Set: Wed May 24 22:35:30 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 503 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 return false; 514 return false;
515 if (!layout_text.IsTextFragment()) 515 if (!layout_text.IsTextFragment())
516 return false; 516 return false;
517 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text); 517 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text);
518 return offset_ < static_cast<int>(text_fragment.TextStartOffset()); 518 return offset_ < static_cast<int>(text_fragment.TextStartOffset());
519 } 519 }
520 520
521 template <typename Strategy> 521 template <typename Strategy>
522 void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() { 522 void TextIteratorAlgorithm<Strategy>::HandlePreFormattedTextNode() {
523 // TODO(xiaochengh): Get rid of repeated computation of these fields. 523 // TODO(xiaochengh): Get rid of repeated computation of these fields.
524 Text* const text_node = ToText(node_); 524 LayoutText* const layout_object = text_node_->GetLayoutObject();
525 LayoutText* const layout_object = text_node->GetLayoutObject();
526 const String str = layout_object->GetText(); 525 const String str = layout_object->GetText();
527 526
528 needs_handle_pre_formatted_text_node_ = false; 527 needs_handle_pre_formatted_text_node_ = false;
529 528
530 if (last_text_node_ended_with_collapsed_space_ && 529 if (last_text_node_ended_with_collapsed_space_ &&
531 HasVisibleTextNode(layout_object)) { 530 HasVisibleTextNode(layout_object)) {
532 if (!behavior_.CollapseTrailingSpace() || 531 if (!behavior_.CollapseTrailingSpace() ||
533 (offset_ > 0 && str[offset_ - 1] == ' ')) { 532 (offset_ > 0 && str[offset_ - 1] == ' ')) {
534 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); 533 SpliceBuffer(kSpaceCharacter, text_node_, 0, offset_, offset_);
535 needs_handle_pre_formatted_text_node_ = true; 534 needs_handle_pre_formatted_text_node_ = true;
536 return; 535 return;
537 } 536 }
538 } 537 }
539 if (ShouldHandleFirstLetter(*layout_object)) { 538 if (ShouldHandleFirstLetter(*layout_object)) {
540 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); 539 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object));
541 if (first_letter_text_) { 540 if (first_letter_text_) {
542 const String first_letter = first_letter_text_->GetText(); 541 const String first_letter = first_letter_text_->GetText();
543 const unsigned run_start = offset_; 542 const unsigned run_start = offset_;
544 const bool stops_in_first_letter = 543 const bool stops_in_first_letter =
545 text_node == end_container_ && 544 text_node_ == end_container_ &&
546 end_offset_ <= static_cast<int>(first_letter.length()); 545 end_offset_ <= static_cast<int>(first_letter.length());
547 const unsigned run_end = 546 const unsigned run_end =
548 stops_in_first_letter ? end_offset_ : first_letter.length(); 547 stops_in_first_letter ? end_offset_ : first_letter.length();
549 EmitText(text_node, first_letter_text_, run_start, run_end); 548 EmitText(text_node_, first_letter_text_, run_start, run_end);
550 first_letter_text_ = nullptr; 549 first_letter_text_ = nullptr;
551 text_box_ = 0; 550 text_box_ = 0;
552 offset_ = run_end; 551 offset_ = run_end;
553 if (!stops_in_first_letter) 552 if (!stops_in_first_letter)
554 needs_handle_pre_formatted_text_node_ = true; 553 needs_handle_pre_formatted_text_node_ = true;
555 return; 554 return;
556 } 555 }
557 // We are here only if the DOM and/or layout trees are broken. 556 // We are here only if the DOM and/or layout trees are broken.
558 // For robustness, we should stop processing this node. 557 // For robustness, we should stop processing this node.
559 NOTREACHED(); 558 NOTREACHED();
560 return; 559 return;
561 } 560 }
562 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 561 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
563 !IgnoresStyleVisibility()) 562 !IgnoresStyleVisibility())
564 return; 563 return;
565 DCHECK_GE(static_cast<unsigned>(offset_), layout_object->TextStartOffset()); 564 DCHECK_GE(static_cast<unsigned>(offset_), layout_object->TextStartOffset());
566 const unsigned run_start = offset_ - layout_object->TextStartOffset(); 565 const unsigned run_start = offset_ - layout_object->TextStartOffset();
567 const unsigned str_length = str.length(); 566 const unsigned str_length = str.length();
568 const unsigned end = (text_node == end_container_) 567 const unsigned end = (text_node_ == end_container_)
569 ? end_offset_ - layout_object->TextStartOffset() 568 ? end_offset_ - layout_object->TextStartOffset()
570 : str_length; 569 : str_length;
571 const unsigned run_end = std::min(str_length, end); 570 const unsigned run_end = std::min(str_length, end);
572 571
573 if (run_start >= run_end) 572 if (run_start >= run_end)
574 return; 573 return;
575 574
576 EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end); 575 EmitText(text_node_, text_node_->GetLayoutObject(), run_start, run_end);
577 } 576 }
578 577
579 template <typename Strategy> 578 template <typename Strategy>
580 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { 579 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() {
581 if (ExcludesAutofilledValue()) { 580 if (ExcludesAutofilledValue()) {
582 TextControlElement* control = EnclosingTextControl(node_); 581 TextControlElement* control = EnclosingTextControl(node_);
583 // For security reason, we don't expose suggested value if it is 582 // For security reason, we don't expose suggested value if it is
584 // auto-filled. 583 // auto-filled.
585 if (control && control->IsAutofilled()) 584 if (control && control->IsAutofilled())
586 return true; 585 return true;
587 } 586 }
588 587
589 DCHECK_NE(last_text_node_, node_) 588 DCHECK_NE(last_text_node_, node_)
590 << "We should never call HandleTextNode on the same node twice"; 589 << "We should never call HandleTextNode on the same node twice";
591 590
592 offset_ = node_ == start_container_ ? start_offset_ : 0; 591 text_node_ = ToText(node_);
592 offset_ = text_node_ == start_container_ ? start_offset_ : 0;
593 handled_first_letter_ = false; 593 handled_first_letter_ = false;
594 first_letter_text_ = nullptr; 594 first_letter_text_ = nullptr;
595 595
596 Text* text_node = ToText(node_); 596 LayoutText* layout_object = text_node_->GetLayoutObject();
597 LayoutText* layout_object = text_node->GetLayoutObject();
598 597
599 last_text_node_ = text_node; 598 last_text_node_ = text_node_;
600 String str = layout_object->GetText(); 599 String str = layout_object->GetText();
601 600
602 // handle pre-formatted text 601 // handle pre-formatted text
603 if (!layout_object->Style()->CollapseWhiteSpace()) { 602 if (!layout_object->Style()->CollapseWhiteSpace()) {
604 HandlePreFormattedTextNode(); 603 HandlePreFormattedTextNode();
605 return true; 604 return true;
606 } 605 }
607 606
608 if (layout_object->FirstTextBox()) 607 if (layout_object->FirstTextBox())
609 text_box_ = layout_object->FirstTextBox(); 608 text_box_ = layout_object->FirstTextBox();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
645 644
646 // Restore the collapsed space for copy & paste. See http://crbug.com/318925 645 // Restore the collapsed space for copy & paste. See http://crbug.com/318925
647 template <typename Strategy> 646 template <typename Strategy>
648 size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace( 647 size_t TextIteratorAlgorithm<Strategy>::RestoreCollapsedTrailingSpace(
649 InlineTextBox* next_text_box, 648 InlineTextBox* next_text_box,
650 size_t subrun_end) { 649 size_t subrun_end) {
651 if (next_text_box || !text_box_->Root().NextRootBox() || 650 if (next_text_box || !text_box_->Root().NextRootBox() ||
652 text_box_->Root().LastChild() != text_box_) 651 text_box_->Root().LastChild() != text_box_)
653 return subrun_end; 652 return subrun_end;
654 653
655 const String& text = ToLayoutText(node_->GetLayoutObject())->GetText(); 654 const String& text = text_node_->GetLayoutObject()->GetText();
656 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 || 655 if (text.EndsWith(' ') == 0 || subrun_end != text.length() - 1 ||
657 text[subrun_end - 1] == ' ') 656 text[subrun_end - 1] == ' ')
658 return subrun_end; 657 return subrun_end;
659 658
660 // If there is the leading space in the next line, we don't need to restore 659 // If there is the leading space in the next line, we don't need to restore
661 // the trailing space. 660 // the trailing space.
662 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div> 661 // Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div>
663 InlineBox* first_box_of_next_line = 662 InlineBox* first_box_of_next_line =
664 text_box_->Root().NextRootBox()->FirstChild(); 663 text_box_->Root().NextRootBox()->FirstChild();
665 if (!first_box_of_next_line) 664 if (!first_box_of_next_line)
666 return subrun_end + 1; 665 return subrun_end + 1;
667 Node* first_node_of_next_line = 666 Node* first_node_of_next_line =
668 first_box_of_next_line->GetLineLayoutItem().GetNode(); 667 first_box_of_next_line->GetLineLayoutItem().GetNode();
669 if (!first_node_of_next_line || 668 if (!first_node_of_next_line ||
670 first_node_of_next_line->nodeValue()[0] != ' ') 669 first_node_of_next_line->nodeValue()[0] != ' ')
671 return subrun_end + 1; 670 return subrun_end + 1;
672 671
673 return subrun_end; 672 return subrun_end;
674 } 673 }
675 674
676 template <typename Strategy> 675 template <typename Strategy>
677 void TextIteratorAlgorithm<Strategy>::HandleTextBox() { 676 void TextIteratorAlgorithm<Strategy>::HandleTextBox() {
678 LayoutText* layout_object = first_letter_text_ 677 LayoutText* layout_object =
679 ? first_letter_text_ 678 first_letter_text_ ? first_letter_text_ : text_node_->GetLayoutObject();
680 : ToLayoutText(node_->GetLayoutObject());
681 const unsigned text_start_offset = layout_object->TextStartOffset(); 679 const unsigned text_start_offset = layout_object->TextStartOffset();
682 680
683 if (layout_object->Style()->Visibility() != EVisibility::kVisible && 681 if (layout_object->Style()->Visibility() != EVisibility::kVisible &&
684 !IgnoresStyleVisibility()) { 682 !IgnoresStyleVisibility()) {
685 text_box_ = nullptr; 683 text_box_ = nullptr;
686 } else { 684 } else {
687 String str = layout_object->GetText(); 685 String str = layout_object->GetText();
688 // Start and end offsets in |str|, i.e., str[start..end - 1] should be 686 // Start and end offsets in |str|, i.e., str[start..end - 1] should be
689 // emitted (after handling whitespace collapsing). 687 // emitted (after handling whitespace collapsing).
690 const unsigned start = offset_ - layout_object->TextStartOffset(); 688 const unsigned start = offset_ - layout_object->TextStartOffset();
691 const unsigned end = 689 const unsigned end =
692 (node_ == end_container_) 690 (text_node_ == end_container_)
693 ? static_cast<unsigned>(end_offset_) - text_start_offset 691 ? static_cast<unsigned>(end_offset_) - text_start_offset
694 : INT_MAX; 692 : INT_MAX;
695 while (text_box_) { 693 while (text_box_) {
696 const unsigned text_box_start = text_box_->Start(); 694 const unsigned text_box_start = text_box_->Start();
697 const unsigned run_start = std::max(text_box_start, start); 695 const unsigned run_start = std::max(text_box_start, start);
698 696
699 // Check for collapsed space at the start of this run. 697 // Check for collapsed space at the start of this run.
700 InlineTextBox* first_text_box = 698 InlineTextBox* first_text_box =
701 layout_object->ContainsReversedText() 699 layout_object->ContainsReversedText()
702 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]) 700 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0])
703 : layout_object->FirstTextBox(); 701 : layout_object->FirstTextBox();
704 const bool need_space = last_text_node_ended_with_collapsed_space_ || 702 const bool need_space = last_text_node_ended_with_collapsed_space_ ||
705 (text_box_ == first_text_box && 703 (text_box_ == first_text_box &&
706 text_box_start == run_start && run_start > 0); 704 text_box_start == run_start && run_start > 0);
707 if (need_space && 705 if (need_space &&
708 !layout_object->Style()->IsCollapsibleWhiteSpace( 706 !layout_object->Style()->IsCollapsibleWhiteSpace(
709 text_state_.LastCharacter()) && 707 text_state_.LastCharacter()) &&
710 text_state_.LastCharacter()) { 708 text_state_.LastCharacter()) {
711 if (last_text_node_ == node_ && run_start > 0 && 709 if (last_text_node_ == text_node_ && run_start > 0 &&
712 str[run_start - 1] == ' ') { 710 str[run_start - 1] == ' ') {
713 unsigned space_run_start = run_start - 1; 711 unsigned space_run_start = run_start - 1;
714 while (space_run_start > 0 && str[space_run_start - 1] == ' ') 712 while (space_run_start > 0 && str[space_run_start - 1] == ' ')
715 --space_run_start; 713 --space_run_start;
716 EmitText(node_, layout_object, space_run_start, space_run_start + 1); 714 EmitText(text_node_, layout_object, space_run_start,
715 space_run_start + 1);
717 } else { 716 } else {
718 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start); 717 SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start, run_start);
719 } 718 }
720 return; 719 return;
721 } 720 }
722 const unsigned text_box_end = text_box_start + text_box_->Len(); 721 const unsigned text_box_end = text_box_start + text_box_->Len();
723 const unsigned run_end = std::min(text_box_end, end); 722 const unsigned run_end = std::min(text_box_end, end);
724 723
725 // Determine what the next text box will be, but don't advance yet 724 // Determine what the next text box will be, but don't advance yet
726 InlineTextBox* next_text_box = nullptr; 725 InlineTextBox* next_text_box = nullptr;
727 if (layout_object->ContainsReversedText()) { 726 if (layout_object->ContainsReversedText()) {
728 if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size()) 727 if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size())
(...skipping 16 matching lines...) Expand all
745 next_text_box->GetLineLayoutItem().IsEqual(layout_object)); 744 next_text_box->GetLineLayoutItem().IsEqual(layout_object));
746 745
747 if (run_start < run_end) { 746 if (run_start < run_end) {
748 // Handle either a single newline character (which becomes a space), 747 // Handle either a single newline character (which becomes a space),
749 // or a run of characters that does not include a newline. 748 // or a run of characters that does not include a newline.
750 // This effectively translates newlines to spaces without copying the 749 // This effectively translates newlines to spaces without copying the
751 // text. 750 // text.
752 if (str[run_start] == '\n') { 751 if (str[run_start] == '\n') {
753 // We need to preserve new lines in case of PreLine. 752 // We need to preserve new lines in case of PreLine.
754 // See bug crbug.com/317365. 753 // See bug crbug.com/317365.
755 if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine) 754 if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine) {
756 SpliceBuffer('\n', node_, 0, run_start, run_start); 755 SpliceBuffer('\n', text_node_, 0, run_start, run_start);
757 else 756 } else {
758 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start + 1); 757 SpliceBuffer(kSpaceCharacter, text_node_, 0, run_start,
758 run_start + 1);
759 }
759 offset_ = text_start_offset + run_start + 1; 760 offset_ = text_start_offset + run_start + 1;
760 } else { 761 } else {
761 size_t subrun_end = str.find('\n', run_start); 762 size_t subrun_end = str.find('\n', run_start);
762 if (subrun_end == kNotFound || subrun_end > run_end) { 763 if (subrun_end == kNotFound || subrun_end > run_end) {
763 subrun_end = run_end; 764 subrun_end = run_end;
764 subrun_end = 765 subrun_end =
765 RestoreCollapsedTrailingSpace(next_text_box, subrun_end); 766 RestoreCollapsedTrailingSpace(next_text_box, subrun_end);
766 } 767 }
767 768
768 offset_ = text_start_offset + subrun_end; 769 offset_ = text_start_offset + subrun_end;
769 EmitText(node_, layout_object, run_start, subrun_end); 770 EmitText(text_node_, layout_object, run_start, subrun_end);
770 } 771 }
771 772
772 // If we are doing a subrun that doesn't go to the end of the text box, 773 // If we are doing a subrun that doesn't go to the end of the text box,
773 // come back again to finish handling this text box; don't advance to 774 // come back again to finish handling this text box; don't advance to
774 // the next one. 775 // the next one.
775 if (static_cast<unsigned>(text_state_.PositionEndOffset()) < 776 if (static_cast<unsigned>(text_state_.PositionEndOffset()) <
776 text_box_end) 777 text_box_end)
777 return; 778 return;
778 779
779 if (behavior_.DoesNotEmitSpaceBeyondRangeEnd()) { 780 if (behavior_.DoesNotEmitSpaceBeyondRangeEnd()) {
(...skipping 28 matching lines...) Expand all
808 if (ShouldProceedToRemainingText()) { 809 if (ShouldProceedToRemainingText()) {
809 ProceedToRemainingText(); 810 ProceedToRemainingText();
810 HandleTextBox(); 811 HandleTextBox();
811 } 812 }
812 } 813 }
813 814
814 template <typename Strategy> 815 template <typename Strategy>
815 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { 816 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const {
816 if (text_box_ || !remaining_text_box_) 817 if (text_box_ || !remaining_text_box_)
817 return false; 818 return false;
818 if (node_ != end_container_) 819 if (text_node_ != end_container_)
819 return true; 820 return true;
820 return offset_ < end_offset_; 821 return offset_ < end_offset_;
821 } 822 }
822 823
823 template <typename Strategy> 824 template <typename Strategy>
824 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() { 825 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() {
825 text_box_ = remaining_text_box_; 826 text_box_ = remaining_text_box_;
826 remaining_text_box_ = 0; 827 remaining_text_box_ = 0;
827 first_letter_text_ = nullptr; 828 first_letter_text_ = nullptr;
828 offset_ = ToLayoutText(node_->GetLayoutObject())->TextStartOffset(); 829 offset_ = text_node_->GetLayoutObject()->TextStartOffset();
829 } 830 }
830 831
831 template <typename Strategy> 832 template <typename Strategy>
832 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( 833 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter(
833 LayoutTextFragment* layout_object) { 834 LayoutTextFragment* layout_object) {
834 handled_first_letter_ = true; 835 handled_first_letter_ = true;
835 836
836 if (!layout_object->IsRemainingTextLayoutObject()) 837 if (!layout_object->IsRemainingTextLayoutObject())
837 return; 838 return;
838 839
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after
1404 String PlainText(const EphemeralRangeInFlatTree& range, 1405 String PlainText(const EphemeralRangeInFlatTree& range,
1405 const TextIteratorBehavior& behavior) { 1406 const TextIteratorBehavior& behavior) {
1406 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); 1407 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior);
1407 } 1408 }
1408 1409
1409 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; 1410 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>;
1410 template class CORE_TEMPLATE_EXPORT 1411 template class CORE_TEMPLATE_EXPORT
1411 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; 1412 TextIteratorAlgorithm<EditingInFlatTreeStrategy>;
1412 1413
1413 } // namespace blink 1414 } // 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