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 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
335 // line break begins. | 335 // line break begins. |
336 // FIXME: It would be cleaner if we emitted two newlines during the last | 336 // FIXME: It would be cleaner if we emitted two newlines during the last |
337 // iteration, instead of using m_needsAnotherNewline. | 337 // iteration, instead of using m_needsAnotherNewline. |
338 Node* last_child = Strategy::LastChild(*node_); | 338 Node* last_child = Strategy::LastChild(*node_); |
339 Node* base_node = last_child ? last_child : node_.Get(); | 339 Node* base_node = last_child ? last_child : node_.Get(); |
340 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1); | 340 SpliceBuffer('\n', Strategy::Parent(*base_node), base_node, 1, 1); |
341 needs_another_newline_ = false; | 341 needs_another_newline_ = false; |
342 return; | 342 return; |
343 } | 343 } |
344 | 344 |
345 if (!text_box_ && remaining_text_box_) { | 345 if (ShouldProceedToRemainingText()) |
346 text_box_ = remaining_text_box_; | 346 ProceedToRemainingText(); |
347 remaining_text_box_ = 0; | |
348 first_letter_text_ = nullptr; | |
349 offset_ = 0; | |
350 } | |
351 // handle remembered text box | 347 // handle remembered text box |
352 if (text_box_) { | 348 if (text_box_) { |
353 HandleTextBox(); | 349 HandleTextBox(); |
354 if (text_state_.PositionNode()) | 350 if (text_state_.PositionNode()) |
355 return; | 351 return; |
356 } | 352 } |
357 | 353 |
358 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) { | 354 while (node_ && (node_ != past_end_node_ || shadow_depth_ > 0)) { |
359 if (!should_stop_ && StopsOnFormControls() && | 355 if (!should_stop_ && StopsOnFormControls() && |
360 HTMLFormControlElement::EnclosingFormControlElement(node_)) | 356 HTMLFormControlElement::EnclosingFormControlElement(node_)) |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 | 551 |
556 DCHECK(fragment->GetFirstLetterPseudoElement()); | 552 DCHECK(fragment->GetFirstLetterPseudoElement()); |
557 LayoutObject* pseudo_element_layout_object = | 553 LayoutObject* pseudo_element_layout_object = |
558 fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); | 554 fragment->GetFirstLetterPseudoElement()->GetLayoutObject(); |
559 return pseudo_element_layout_object && | 555 return pseudo_element_layout_object && |
560 pseudo_element_layout_object->Style()->Visibility() == | 556 pseudo_element_layout_object->Style()->Visibility() == |
561 EVisibility::kVisible; | 557 EVisibility::kVisible; |
562 } | 558 } |
563 | 559 |
564 template <typename Strategy> | 560 template <typename Strategy> |
| 561 bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter( |
| 562 const LayoutText& layout_text) const { |
| 563 if (handled_first_letter_) |
| 564 return false; |
| 565 if (!layout_text.IsTextFragment()) |
| 566 return false; |
| 567 // TODO(xiaochengh): Handle the case where :first-letter has multiple chars, |
| 568 // and eliminate the hack with first_letter/remaining_text_start_offset_. |
| 569 return !offset_; |
| 570 } |
| 571 |
| 572 template <typename Strategy> |
565 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { | 573 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { |
566 if (ExcludesAutofilledValue()) { | 574 if (ExcludesAutofilledValue()) { |
567 TextControlElement* control = EnclosingTextControl(node_); | 575 TextControlElement* control = EnclosingTextControl(node_); |
568 // For security reason, we don't expose suggested value if it is | 576 // For security reason, we don't expose suggested value if it is |
569 // auto-filled. | 577 // auto-filled. |
570 if (control && control->IsAutofilled()) | 578 if (control && control->IsAutofilled()) |
571 return true; | 579 return true; |
572 } | 580 } |
573 | 581 |
574 Text* text_node = ToText(node_); | 582 Text* text_node = ToText(node_); |
575 LayoutText* layout_object = text_node->GetLayoutObject(); | 583 LayoutText* layout_object = text_node->GetLayoutObject(); |
576 | 584 |
577 last_text_node_ = text_node; | 585 last_text_node_ = text_node; |
578 String str = layout_object->GetText(); | 586 String str = layout_object->GetText(); |
579 | 587 |
580 // handle pre-formatted text | 588 // handle pre-formatted text |
581 if (!layout_object->Style()->CollapseWhiteSpace()) { | 589 if (!layout_object->Style()->CollapseWhiteSpace()) { |
582 int run_start = offset_; | |
583 if (last_text_node_ended_with_collapsed_space_ && | 590 if (last_text_node_ended_with_collapsed_space_ && |
584 HasVisibleTextNode(layout_object)) { | 591 HasVisibleTextNode(layout_object)) { |
585 if (behavior_.CollapseTrailingSpace()) { | 592 if (behavior_.CollapseTrailingSpace()) { |
586 if (run_start > 0 && str[run_start - 1] == ' ') { | 593 if (offset_ > 0 && str[offset_ - 1] == ' ') { |
587 SpliceBuffer(kSpaceCharacter, text_node, 0, run_start, run_start); | 594 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); |
588 return false; | 595 return false; |
589 } | 596 } |
590 } else { | 597 } else { |
591 SpliceBuffer(kSpaceCharacter, text_node, 0, run_start, run_start); | 598 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); |
592 return false; | 599 return false; |
593 } | 600 } |
594 } | 601 } |
595 if (!handled_first_letter_ && layout_object->IsTextFragment() && !offset_) { | 602 if (ShouldHandleFirstLetter(*layout_object)) { |
596 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); | 603 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); |
597 if (first_letter_text_) { | 604 if (first_letter_text_) { |
598 String first_letter = first_letter_text_->GetText(); | 605 String first_letter = first_letter_text_->GetText(); |
599 EmitText(text_node, first_letter_text_, offset_, | 606 EmitText(text_node, first_letter_text_, offset_, |
600 offset_ + first_letter.length()); | 607 offset_ + first_letter.length()); |
601 first_letter_text_ = nullptr; | 608 first_letter_text_ = nullptr; |
602 text_box_ = 0; | 609 text_box_ = 0; |
603 return false; | 610 return false; |
604 } | 611 } |
605 } | 612 } |
606 if (layout_object->Style()->Visibility() != EVisibility::kVisible && | 613 if (layout_object->Style()->Visibility() != EVisibility::kVisible && |
607 !IgnoresStyleVisibility()) | 614 !IgnoresStyleVisibility()) |
608 return false; | 615 return false; |
609 int str_length = str.length(); | 616 const unsigned run_start = offset_; |
610 int end = (text_node == end_container_) ? end_offset_ : INT_MAX; | 617 const unsigned str_length = str.length(); |
611 int run_end = std::min(str_length, end); | 618 const unsigned end = (text_node == end_container_) ? end_offset_ : INT_MAX; |
| 619 const unsigned run_end = std::min(str_length, end); |
612 | 620 |
613 if (run_start >= run_end) | 621 if (run_start >= run_end) |
614 return true; | 622 return true; |
615 | 623 |
616 EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end); | 624 EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end); |
617 return true; | 625 return true; |
618 } | 626 } |
619 | 627 |
620 if (layout_object->FirstTextBox()) | 628 if (layout_object->FirstTextBox()) |
621 text_box_ = layout_object->FirstTextBox(); | 629 text_box_ = layout_object->FirstTextBox(); |
622 | 630 |
623 bool should_handle_first_letter = | 631 const bool should_handle_first_letter = |
624 !handled_first_letter_ && layout_object->IsTextFragment() && !offset_; | 632 ShouldHandleFirstLetter(*layout_object); |
625 if (should_handle_first_letter) | 633 if (should_handle_first_letter) |
626 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); | 634 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); |
627 | 635 |
628 if (!layout_object->FirstTextBox() && str.length() > 0 && | 636 if (!layout_object->FirstTextBox() && str.length() > 0 && |
629 !should_handle_first_letter) { | 637 !should_handle_first_letter) { |
630 if (layout_object->Style()->Visibility() != EVisibility::kVisible && | 638 if (layout_object->Style()->Visibility() != EVisibility::kVisible && |
631 !IgnoresStyleVisibility()) | 639 !IgnoresStyleVisibility()) |
632 return false; | 640 return false; |
633 last_text_node_ended_with_collapsed_space_ = | 641 last_text_node_ended_with_collapsed_space_ = |
634 true; // entire block is collapsed space | 642 true; // entire block is collapsed space |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 void TextIteratorAlgorithm<Strategy>::HandleTextBox() { | 697 void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
690 LayoutText* layout_object = first_letter_text_ | 698 LayoutText* layout_object = first_letter_text_ |
691 ? first_letter_text_ | 699 ? first_letter_text_ |
692 : ToLayoutText(node_->GetLayoutObject()); | 700 : ToLayoutText(node_->GetLayoutObject()); |
693 | 701 |
694 if (layout_object->Style()->Visibility() != EVisibility::kVisible && | 702 if (layout_object->Style()->Visibility() != EVisibility::kVisible && |
695 !IgnoresStyleVisibility()) { | 703 !IgnoresStyleVisibility()) { |
696 text_box_ = nullptr; | 704 text_box_ = nullptr; |
697 } else { | 705 } else { |
698 String str = layout_object->GetText(); | 706 String str = layout_object->GetText(); |
699 unsigned start = offset_; | 707 const unsigned start = offset_; |
700 unsigned end = (node_ == end_container_) | 708 const unsigned end = (node_ == end_container_) |
701 ? static_cast<unsigned>(end_offset_) | 709 ? static_cast<unsigned>(end_offset_) |
702 : INT_MAX; | 710 : INT_MAX; |
703 while (text_box_) { | 711 while (text_box_) { |
704 unsigned text_box_start = text_box_->Start(); | 712 const unsigned text_box_start = text_box_->Start(); |
705 unsigned run_start = std::max(text_box_start, start); | 713 const unsigned run_start = std::max(text_box_start, start); |
706 | 714 |
707 // Check for collapsed space at the start of this run. | 715 // Check for collapsed space at the start of this run. |
708 InlineTextBox* first_text_box = | 716 InlineTextBox* first_text_box = |
709 layout_object->ContainsReversedText() | 717 layout_object->ContainsReversedText() |
710 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]) | 718 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]) |
711 : layout_object->FirstTextBox(); | 719 : layout_object->FirstTextBox(); |
712 bool need_space = last_text_node_ended_with_collapsed_space_ || | 720 const bool need_space = last_text_node_ended_with_collapsed_space_ || |
713 (text_box_ == first_text_box && | 721 (text_box_ == first_text_box && |
714 text_box_start == run_start && run_start > 0); | 722 text_box_start == run_start && run_start > 0); |
715 if (need_space && | 723 if (need_space && |
716 !layout_object->Style()->IsCollapsibleWhiteSpace( | 724 !layout_object->Style()->IsCollapsibleWhiteSpace( |
717 text_state_.LastCharacter()) && | 725 text_state_.LastCharacter()) && |
718 text_state_.LastCharacter()) { | 726 text_state_.LastCharacter()) { |
719 if (last_text_node_ == node_ && run_start > 0 && | 727 if (last_text_node_ == node_ && run_start > 0 && |
720 str[run_start - 1] == ' ') { | 728 str[run_start - 1] == ' ') { |
721 unsigned space_run_start = run_start - 1; | 729 unsigned space_run_start = run_start - 1; |
722 while (space_run_start > 0 && str[space_run_start - 1] == ' ') | 730 while (space_run_start > 0 && str[space_run_start - 1] == ' ') |
723 --space_run_start; | 731 --space_run_start; |
724 EmitText(node_, layout_object, space_run_start, space_run_start + 1); | 732 EmitText(node_, layout_object, space_run_start, space_run_start + 1); |
725 } else { | 733 } else { |
726 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start); | 734 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start); |
727 } | 735 } |
728 return; | 736 return; |
729 } | 737 } |
730 unsigned text_box_end = text_box_start + text_box_->Len(); | 738 const unsigned text_box_end = text_box_start + text_box_->Len(); |
731 unsigned run_end = std::min(text_box_end, end); | 739 const unsigned run_end = std::min(text_box_end, end); |
732 | 740 |
733 // Determine what the next text box will be, but don't advance yet | 741 // Determine what the next text box will be, but don't advance yet |
734 InlineTextBox* next_text_box = nullptr; | 742 InlineTextBox* next_text_box = nullptr; |
735 if (layout_object->ContainsReversedText()) { | 743 if (layout_object->ContainsReversedText()) { |
736 if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size()) | 744 if (sorted_text_boxes_position_ + 1 < sorted_text_boxes_.size()) |
737 next_text_box = sorted_text_boxes_[sorted_text_boxes_position_ + 1]; | 745 next_text_box = sorted_text_boxes_[sorted_text_boxes_position_ + 1]; |
738 } else { | 746 } else { |
739 next_text_box = text_box_->NextTextBox(); | 747 next_text_box = text_box_->NextTextBox(); |
740 } | 748 } |
741 | 749 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
788 // If the subrun went to the text box end and this end is also the end | 796 // If the subrun went to the text box end and this end is also the end |
789 // of the range, do not advance to the next text box and do not | 797 // of the range, do not advance to the next text box and do not |
790 // generate a space, just stop. | 798 // generate a space, just stop. |
791 if (text_box_end == end) { | 799 if (text_box_end == end) { |
792 text_box_ = nullptr; | 800 text_box_ = nullptr; |
793 return; | 801 return; |
794 } | 802 } |
795 } | 803 } |
796 | 804 |
797 // Advance and return | 805 // Advance and return |
798 unsigned next_run_start = | 806 const unsigned next_run_start = |
799 next_text_box ? next_text_box->Start() : str.length(); | 807 next_text_box ? next_text_box->Start() : str.length(); |
800 if (next_run_start > run_end) | 808 if (next_run_start > run_end) |
801 last_text_node_ended_with_collapsed_space_ = | 809 last_text_node_ended_with_collapsed_space_ = |
802 true; // collapsed space between runs or at the end | 810 true; // collapsed space between runs or at the end |
803 | 811 |
804 text_box_ = next_text_box; | 812 text_box_ = next_text_box; |
805 if (layout_object->ContainsReversedText()) | 813 if (layout_object->ContainsReversedText()) |
806 ++sorted_text_boxes_position_; | 814 ++sorted_text_boxes_position_; |
807 return; | 815 return; |
808 } | 816 } |
809 // Advance and continue | 817 // Advance and continue |
810 text_box_ = next_text_box; | 818 text_box_ = next_text_box; |
811 if (layout_object->ContainsReversedText()) | 819 if (layout_object->ContainsReversedText()) |
812 ++sorted_text_boxes_position_; | 820 ++sorted_text_boxes_position_; |
813 } | 821 } |
814 } | 822 } |
815 | 823 |
816 if (!text_box_ && remaining_text_box_) { | 824 if (ShouldProceedToRemainingText()) { |
817 text_box_ = remaining_text_box_; | 825 ProceedToRemainingText(); |
818 remaining_text_box_ = 0; | |
819 first_letter_text_ = nullptr; | |
820 offset_ = 0; | |
821 HandleTextBox(); | 826 HandleTextBox(); |
822 } | 827 } |
823 } | 828 } |
824 | 829 |
825 template <typename Strategy> | 830 template <typename Strategy> |
| 831 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { |
| 832 // TODO(xiaochengh): Handle the case where the iterator should stop in |
| 833 // :first-letter. |
| 834 return !text_box_ && remaining_text_box_; |
| 835 } |
| 836 |
| 837 template <typename Strategy> |
| 838 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() { |
| 839 text_box_ = remaining_text_box_; |
| 840 remaining_text_box_ = 0; |
| 841 first_letter_text_ = nullptr; |
| 842 // TODO(xiaochengh): |offset_| should be set to the starting offset of the |
| 843 // remaining text; |
| 844 offset_ = 0; |
| 845 } |
| 846 |
| 847 template <typename Strategy> |
826 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( | 848 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( |
827 LayoutTextFragment* layout_object) { | 849 LayoutTextFragment* layout_object) { |
828 handled_first_letter_ = true; | 850 handled_first_letter_ = true; |
829 | 851 |
830 if (!layout_object->IsRemainingTextLayoutObject()) | 852 if (!layout_object->IsRemainingTextLayoutObject()) |
831 return; | 853 return; |
832 | 854 |
833 FirstLetterPseudoElement* first_letter_element = | 855 FirstLetterPseudoElement* first_letter_element = |
834 layout_object->GetFirstLetterPseudoElement(); | 856 layout_object->GetFirstLetterPseudoElement(); |
835 if (!first_letter_element) | 857 if (!first_letter_element) |
(...skipping 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1445 String PlainText(const EphemeralRangeInFlatTree& range, | 1467 String PlainText(const EphemeralRangeInFlatTree& range, |
1446 const TextIteratorBehavior& behavior) { | 1468 const TextIteratorBehavior& behavior) { |
1447 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); | 1469 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); |
1448 } | 1470 } |
1449 | 1471 |
1450 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; | 1472 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; |
1451 template class CORE_TEMPLATE_EXPORT | 1473 template class CORE_TEMPLATE_EXPORT |
1452 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; | 1474 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; |
1453 | 1475 |
1454 } // namespace blink | 1476 } // namespace blink |
OLD | NEW |