| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |