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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 #include "platform/fonts/Font.h" | 55 #include "platform/fonts/Font.h" |
56 #include "platform/wtf/text/CString.h" | 56 #include "platform/wtf/text/CString.h" |
57 #include "platform/wtf/text/StringBuilder.h" | 57 #include "platform/wtf/text/StringBuilder.h" |
58 | 58 |
59 namespace blink { | 59 namespace blink { |
60 | 60 |
61 using namespace HTMLNames; | 61 using namespace HTMLNames; |
62 | 62 |
63 namespace { | 63 namespace { |
64 | 64 |
65 const int kInvalidTextOffset = -1; | |
66 | |
67 template <typename Strategy> | 65 template <typename Strategy> |
68 TextIteratorBehavior AdjustBehaviorFlags(const TextIteratorBehavior&); | 66 TextIteratorBehavior AdjustBehaviorFlags(const TextIteratorBehavior&); |
69 | 67 |
70 template <> | 68 template <> |
71 TextIteratorBehavior AdjustBehaviorFlags<EditingStrategy>( | 69 TextIteratorBehavior AdjustBehaviorFlags<EditingStrategy>( |
72 const TextIteratorBehavior& behavior) { | 70 const TextIteratorBehavior& behavior) { |
73 if (!behavior.ForSelectionToString()) | 71 if (!behavior.ForSelectionToString()) |
74 return behavior; | 72 return behavior; |
75 return TextIteratorBehavior::Builder(behavior) | 73 return TextIteratorBehavior::Builder(behavior) |
76 .SetExcludeAutofilledValue(true) | 74 .SetExcludeAutofilledValue(true) |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 text_box_(nullptr), | 166 text_box_(nullptr), |
169 remaining_text_box_(nullptr), | 167 remaining_text_box_(nullptr), |
170 first_letter_text_(nullptr), | 168 first_letter_text_(nullptr), |
171 last_text_node_(nullptr), | 169 last_text_node_(nullptr), |
172 last_text_node_ended_with_collapsed_space_(false), | 170 last_text_node_ended_with_collapsed_space_(false), |
173 sorted_text_boxes_position_(0), | 171 sorted_text_boxes_position_(0), |
174 behavior_(AdjustBehaviorFlags<Strategy>(behavior)), | 172 behavior_(AdjustBehaviorFlags<Strategy>(behavior)), |
175 handled_first_letter_(false), | 173 handled_first_letter_(false), |
176 should_stop_(false), | 174 should_stop_(false), |
177 handle_shadow_root_(false), | 175 handle_shadow_root_(false), |
178 first_letter_start_offset_(kInvalidTextOffset), | |
179 remaining_text_start_offset_(kInvalidTextOffset), | |
180 text_state_(behavior_) { | 176 text_state_(behavior_) { |
181 DCHECK(start.IsNotNull()); | 177 DCHECK(start.IsNotNull()); |
182 DCHECK(end.IsNotNull()); | 178 DCHECK(end.IsNotNull()); |
183 | 179 |
184 // TODO(dglazkov): TextIterator should not be created for documents that don't | 180 // TODO(dglazkov): TextIterator should not be created for documents that don't |
185 // have a frame, but it currently still happens in some cases. See | 181 // have a frame, but it currently still happens in some cases. See |
186 // http://crbug.com/591877 for details. | 182 // http://crbug.com/591877 for details. |
187 DCHECK(!start.GetDocument()->View() || | 183 DCHECK(!start.GetDocument()->View() || |
188 !start.GetDocument()->View()->NeedsLayout()); | 184 !start.GetDocument()->View()->NeedsLayout()); |
189 DCHECK(!start.GetDocument()->NeedsLayoutTreeUpdate()); | 185 DCHECK(!start.GetDocument()->NeedsLayoutTreeUpdate()); |
190 | 186 |
191 if (start.CompareTo(end) > 0) { | 187 if (start.CompareTo(end) > 0) { |
192 Initialize(end.ComputeContainerNode(), end.ComputeOffsetInContainerNode(), | 188 Initialize(end.ComputeContainerNode(), end.ComputeOffsetInContainerNode(), |
193 start.ComputeContainerNode(), | 189 start.ComputeContainerNode(), |
194 start.ComputeOffsetInContainerNode()); | 190 start.ComputeOffsetInContainerNode()); |
195 return; | 191 return; |
196 } | 192 } |
197 Initialize(start.ComputeContainerNode(), start.ComputeOffsetInContainerNode(), | 193 Initialize(start.ComputeContainerNode(), start.ComputeOffsetInContainerNode(), |
198 end.ComputeContainerNode(), end.ComputeOffsetInContainerNode()); | 194 end.ComputeContainerNode(), end.ComputeOffsetInContainerNode()); |
199 } | 195 } |
200 | 196 |
201 template <typename Strategy> | 197 template <typename Strategy> |
202 bool TextIteratorAlgorithm<Strategy>::PrepareForFirstLetterInitialization() { | |
203 if (node_ != start_container_) | |
204 return false; | |
205 | |
206 if (node_->getNodeType() != Node::kTextNode) | |
207 return false; | |
208 | |
209 Text* text_node = ToText(node_); | |
210 LayoutText* layout_object = text_node->GetLayoutObject(); | |
211 if (!layout_object || !layout_object->IsTextFragment()) | |
212 return false; | |
213 | |
214 LayoutTextFragment* text_fragment = ToLayoutTextFragment(layout_object); | |
215 if (!text_fragment->IsRemainingTextLayoutObject()) | |
216 return false; | |
217 | |
218 if (static_cast<unsigned>(start_offset_) >= | |
219 text_fragment->TextStartOffset()) { | |
220 remaining_text_start_offset_ = | |
221 start_offset_ - text_fragment->TextStartOffset(); | |
222 } else { | |
223 first_letter_start_offset_ = start_offset_; | |
224 } | |
225 offset_ = 0; | |
226 | |
227 return true; | |
228 } | |
229 | |
230 template <typename Strategy> | |
231 bool TextIteratorAlgorithm<Strategy>::HasNotAdvancedToStartPosition() { | |
232 if (AtEnd()) | |
233 return false; | |
234 if (remaining_text_start_offset_ == kInvalidTextOffset) | |
235 return false; | |
236 return node_ == start_container_; | |
237 } | |
238 | |
239 template <typename Strategy> | |
240 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, | 198 void TextIteratorAlgorithm<Strategy>::Initialize(Node* start_container, |
241 int start_offset, | 199 int start_offset, |
242 Node* end_container, | 200 Node* end_container, |
243 int end_offset) { | 201 int end_offset) { |
244 DCHECK(start_container); | 202 DCHECK(start_container); |
245 DCHECK(end_container); | 203 DCHECK(end_container); |
246 | 204 |
247 // Remember the range - this does not change. | 205 // Remember the range - this does not change. |
248 start_container_ = start_container; | 206 start_container_ = start_container; |
249 start_offset_ = start_offset; | 207 start_offset_ = start_offset; |
(...skipping 13 matching lines...) Expand all Loading... | |
263 node_ = child; | 221 node_ = child; |
264 else if (!start_offset) | 222 else if (!start_offset) |
265 node_ = start_container; | 223 node_ = start_container; |
266 else | 224 else |
267 node_ = Strategy::NextSkippingChildren(*start_container); | 225 node_ = Strategy::NextSkippingChildren(*start_container); |
268 | 226 |
269 if (!node_) | 227 if (!node_) |
270 return; | 228 return; |
271 | 229 |
272 fully_clipped_stack_.SetUpFullyClippedStack(node_); | 230 fully_clipped_stack_.SetUpFullyClippedStack(node_); |
273 if (!PrepareForFirstLetterInitialization()) | 231 offset_ = node_ == start_container_ ? start_offset_ : 0; |
274 offset_ = node_ == start_container_ ? start_offset_ : 0; | |
275 iteration_progress_ = kHandledNone; | 232 iteration_progress_ = kHandledNone; |
276 | 233 |
277 // Calculate first out of bounds node. | 234 // Calculate first out of bounds node. |
278 past_end_node_ = end_container | 235 past_end_node_ = end_container |
279 ? PastLastNode<Strategy>(*end_container, end_offset) | 236 ? PastLastNode<Strategy>(*end_container, end_offset) |
280 : nullptr; | 237 : nullptr; |
281 | 238 |
282 // Identify the first run. | 239 // Identify the first run. |
283 Advance(); | 240 Advance(); |
284 | |
285 // The current design cannot start in a text node with arbitrary offset, if | |
286 // the node has :first-letter. Instead, we start with offset 0, and have extra | |
287 // advance() calls until we have moved to/past the starting position. | |
288 while (HasNotAdvancedToStartPosition()) | |
289 Advance(); | |
290 | |
291 // Clear temporary data for initialization with :first-letter. | |
292 first_letter_start_offset_ = kInvalidTextOffset; | |
293 remaining_text_start_offset_ = kInvalidTextOffset; | |
294 } | 241 } |
295 | 242 |
296 template <typename Strategy> | 243 template <typename Strategy> |
297 TextIteratorAlgorithm<Strategy>::~TextIteratorAlgorithm() { | 244 TextIteratorAlgorithm<Strategy>::~TextIteratorAlgorithm() { |
298 if (!handle_shadow_root_) | 245 if (!handle_shadow_root_) |
299 return; | 246 return; |
300 Document* document = OwnerDocument(); | 247 Document* document = OwnerDocument(); |
301 if (!document) | 248 if (!document) |
302 return; | 249 return; |
303 if (behavior_.ForInnerText()) | 250 if (behavior_.ForInnerText()) |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 EVisibility::kVisible; | 504 EVisibility::kVisible; |
558 } | 505 } |
559 | 506 |
560 template <typename Strategy> | 507 template <typename Strategy> |
561 bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter( | 508 bool TextIteratorAlgorithm<Strategy>::ShouldHandleFirstLetter( |
562 const LayoutText& layout_text) const { | 509 const LayoutText& layout_text) const { |
563 if (handled_first_letter_) | 510 if (handled_first_letter_) |
564 return false; | 511 return false; |
565 if (!layout_text.IsTextFragment()) | 512 if (!layout_text.IsTextFragment()) |
566 return false; | 513 return false; |
567 // TODO(xiaochengh): Handle the case where :first-letter has multiple chars, | 514 const LayoutTextFragment& text_fragment = ToLayoutTextFragment(layout_text); |
568 // and eliminate the hack with first_letter/remaining_text_start_offset_. | 515 return offset_ < static_cast<int>(text_fragment.TextStartOffset()); |
569 return !offset_; | |
570 } | 516 } |
571 | 517 |
572 template <typename Strategy> | 518 template <typename Strategy> |
573 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { | 519 bool TextIteratorAlgorithm<Strategy>::HandleTextNode() { |
574 if (ExcludesAutofilledValue()) { | 520 if (ExcludesAutofilledValue()) { |
575 TextControlElement* control = EnclosingTextControl(node_); | 521 TextControlElement* control = EnclosingTextControl(node_); |
576 // For security reason, we don't expose suggested value if it is | 522 // For security reason, we don't expose suggested value if it is |
577 // auto-filled. | 523 // auto-filled. |
578 if (control && control->IsAutofilled()) | 524 if (control && control->IsAutofilled()) |
579 return true; | 525 return true; |
580 } | 526 } |
581 | 527 |
582 Text* text_node = ToText(node_); | 528 Text* text_node = ToText(node_); |
583 LayoutText* layout_object = text_node->GetLayoutObject(); | 529 LayoutText* layout_object = text_node->GetLayoutObject(); |
584 | 530 |
585 last_text_node_ = text_node; | 531 last_text_node_ = text_node; |
586 String str = layout_object->GetText(); | 532 String str = layout_object->GetText(); |
587 | 533 |
588 // handle pre-formatted text | 534 // handle pre-formatted text |
589 if (!layout_object->Style()->CollapseWhiteSpace()) { | 535 if (!layout_object->Style()->CollapseWhiteSpace()) { |
590 if (last_text_node_ended_with_collapsed_space_ && | 536 if (last_text_node_ended_with_collapsed_space_ && |
591 HasVisibleTextNode(layout_object)) { | 537 HasVisibleTextNode(layout_object)) { |
592 if (behavior_.CollapseTrailingSpace()) { | 538 if (behavior_.CollapseTrailingSpace()) { |
593 if (offset_ > 0 && str[offset_ - 1] == ' ') { | 539 if (offset_ > 0 && str[offset_ - 1] == ' ') { |
594 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); | 540 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); |
Xiaocheng
2017/05/16 23:33:31
I don't think this line is reachable. I'll remove
| |
595 return false; | 541 return false; |
596 } | 542 } |
597 } else { | 543 } else { |
598 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); | 544 SpliceBuffer(kSpaceCharacter, text_node, 0, offset_, offset_); |
599 return false; | 545 return false; |
600 } | 546 } |
601 } | 547 } |
602 if (ShouldHandleFirstLetter(*layout_object)) { | 548 if (ShouldHandleFirstLetter(*layout_object)) { |
603 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); | 549 HandleTextNodeFirstLetter(ToLayoutTextFragment(layout_object)); |
604 if (first_letter_text_) { | 550 if (first_letter_text_) { |
605 String first_letter = first_letter_text_->GetText(); | 551 String first_letter = first_letter_text_->GetText(); |
606 EmitText(text_node, first_letter_text_, offset_, | 552 const unsigned run_start = offset_; |
607 offset_ + first_letter.length()); | 553 const bool stops_in_first_letter = |
554 text_node == end_container_ && | |
555 end_offset_ <= static_cast<int>(first_letter.length()); | |
556 const unsigned run_end = | |
557 stops_in_first_letter ? end_offset_ : first_letter.length(); | |
558 EmitText(text_node, first_letter_text_, run_start, run_end); | |
608 first_letter_text_ = nullptr; | 559 first_letter_text_ = nullptr; |
609 text_box_ = 0; | 560 text_box_ = 0; |
610 return false; | 561 offset_ = run_end; |
562 return stops_in_first_letter; | |
611 } | 563 } |
564 // We are here only if the DOM and/or layout trees are broken. | |
565 NOTREACHED(); | |
612 } | 566 } |
613 if (layout_object->Style()->Visibility() != EVisibility::kVisible && | 567 if (layout_object->Style()->Visibility() != EVisibility::kVisible && |
614 !IgnoresStyleVisibility()) | 568 !IgnoresStyleVisibility()) |
615 return false; | 569 return false; |
616 const unsigned run_start = offset_; | 570 const unsigned run_start = offset_ - layout_object->TextStartOffset(); |
617 const unsigned str_length = str.length(); | 571 const unsigned str_length = str.length(); |
618 const unsigned end = (text_node == end_container_) ? end_offset_ : INT_MAX; | 572 const unsigned end = (text_node == end_container_) |
573 ? end_offset_ - layout_object->TextStartOffset() | |
574 : INT_MAX; | |
619 const unsigned run_end = std::min(str_length, end); | 575 const unsigned run_end = std::min(str_length, end); |
620 | 576 |
621 if (run_start >= run_end) | 577 if (run_start >= run_end) |
622 return true; | 578 return true; |
623 | 579 |
624 EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end); | 580 EmitText(text_node, text_node->GetLayoutObject(), run_start, run_end); |
625 return true; | 581 return true; |
626 } | 582 } |
627 | 583 |
628 if (layout_object->FirstTextBox()) | 584 if (layout_object->FirstTextBox()) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
691 return subrun_end + 1; | 647 return subrun_end + 1; |
692 | 648 |
693 return subrun_end; | 649 return subrun_end; |
694 } | 650 } |
695 | 651 |
696 template <typename Strategy> | 652 template <typename Strategy> |
697 void TextIteratorAlgorithm<Strategy>::HandleTextBox() { | 653 void TextIteratorAlgorithm<Strategy>::HandleTextBox() { |
698 LayoutText* layout_object = first_letter_text_ | 654 LayoutText* layout_object = first_letter_text_ |
699 ? first_letter_text_ | 655 ? first_letter_text_ |
700 : ToLayoutText(node_->GetLayoutObject()); | 656 : ToLayoutText(node_->GetLayoutObject()); |
657 const unsigned text_start_offset = layout_object->TextStartOffset(); | |
701 | 658 |
702 if (layout_object->Style()->Visibility() != EVisibility::kVisible && | 659 if (layout_object->Style()->Visibility() != EVisibility::kVisible && |
703 !IgnoresStyleVisibility()) { | 660 !IgnoresStyleVisibility()) { |
704 text_box_ = nullptr; | 661 text_box_ = nullptr; |
705 } else { | 662 } else { |
706 String str = layout_object->GetText(); | 663 String str = layout_object->GetText(); |
707 const unsigned start = offset_; | 664 // Start and end offsets in |str|, i.e., str[start..end - 1] should be |
708 const unsigned end = (node_ == end_container_) | 665 // emitted (after handling whitespace collapsing). |
709 ? static_cast<unsigned>(end_offset_) | 666 const unsigned start = offset_ - layout_object->TextStartOffset(); |
710 : INT_MAX; | 667 const unsigned end = |
668 (node_ == end_container_) | |
669 ? static_cast<unsigned>(end_offset_) - text_start_offset | |
670 : INT_MAX; | |
711 while (text_box_) { | 671 while (text_box_) { |
712 const unsigned text_box_start = text_box_->Start(); | 672 const unsigned text_box_start = text_box_->Start(); |
713 const unsigned run_start = std::max(text_box_start, start); | 673 const unsigned run_start = std::max(text_box_start, start); |
714 | 674 |
715 // Check for collapsed space at the start of this run. | 675 // Check for collapsed space at the start of this run. |
716 InlineTextBox* first_text_box = | 676 InlineTextBox* first_text_box = |
717 layout_object->ContainsReversedText() | 677 layout_object->ContainsReversedText() |
718 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]) | 678 ? (sorted_text_boxes_.IsEmpty() ? 0 : sorted_text_boxes_[0]) |
719 : layout_object->FirstTextBox(); | 679 : layout_object->FirstTextBox(); |
720 const bool need_space = last_text_node_ended_with_collapsed_space_ || | 680 const bool need_space = last_text_node_ended_with_collapsed_space_ || |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
765 // or a run of characters that does not include a newline. | 725 // or a run of characters that does not include a newline. |
766 // This effectively translates newlines to spaces without copying the | 726 // This effectively translates newlines to spaces without copying the |
767 // text. | 727 // text. |
768 if (str[run_start] == '\n') { | 728 if (str[run_start] == '\n') { |
769 // We need to preserve new lines in case of PreLine. | 729 // We need to preserve new lines in case of PreLine. |
770 // See bug crbug.com/317365. | 730 // See bug crbug.com/317365. |
771 if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine) | 731 if (layout_object->Style()->WhiteSpace() == EWhiteSpace::kPreLine) |
772 SpliceBuffer('\n', node_, 0, run_start, run_start); | 732 SpliceBuffer('\n', node_, 0, run_start, run_start); |
773 else | 733 else |
774 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start + 1); | 734 SpliceBuffer(kSpaceCharacter, node_, 0, run_start, run_start + 1); |
775 offset_ = run_start + 1; | 735 offset_ = text_start_offset + run_start + 1; |
776 } else { | 736 } else { |
777 size_t subrun_end = str.find('\n', run_start); | 737 size_t subrun_end = str.find('\n', run_start); |
778 if (subrun_end == kNotFound || subrun_end > run_end) { | 738 if (subrun_end == kNotFound || subrun_end > run_end) { |
779 subrun_end = run_end; | 739 subrun_end = run_end; |
780 subrun_end = | 740 subrun_end = |
781 RestoreCollapsedTrailingSpace(next_text_box, subrun_end); | 741 RestoreCollapsedTrailingSpace(next_text_box, subrun_end); |
782 } | 742 } |
783 | 743 |
784 offset_ = subrun_end; | 744 offset_ = text_start_offset + subrun_end; |
785 EmitText(node_, layout_object, run_start, subrun_end); | 745 EmitText(node_, layout_object, run_start, subrun_end); |
786 } | 746 } |
787 | 747 |
788 // If we are doing a subrun that doesn't go to the end of the text box, | 748 // If we are doing a subrun that doesn't go to the end of the text box, |
789 // come back again to finish handling this text box; don't advance to | 749 // come back again to finish handling this text box; don't advance to |
790 // the next one. | 750 // the next one. |
791 if (static_cast<unsigned>(text_state_.PositionEndOffset()) < | 751 if (static_cast<unsigned>(text_state_.PositionEndOffset()) < |
792 text_box_end) | 752 text_box_end) |
793 return; | 753 return; |
794 | 754 |
(...skipping 27 matching lines...) Expand all Loading... | |
822 } | 782 } |
823 | 783 |
824 if (ShouldProceedToRemainingText()) { | 784 if (ShouldProceedToRemainingText()) { |
825 ProceedToRemainingText(); | 785 ProceedToRemainingText(); |
826 HandleTextBox(); | 786 HandleTextBox(); |
827 } | 787 } |
828 } | 788 } |
829 | 789 |
830 template <typename Strategy> | 790 template <typename Strategy> |
831 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { | 791 bool TextIteratorAlgorithm<Strategy>::ShouldProceedToRemainingText() const { |
832 // TODO(xiaochengh): Handle the case where the iterator should stop in | 792 if (text_box_ || !remaining_text_box_) |
833 // :first-letter. | 793 return false; |
834 return !text_box_ && remaining_text_box_; | 794 if (node_ != end_container_) |
795 return true; | |
796 return offset_ < end_offset_; | |
835 } | 797 } |
836 | 798 |
837 template <typename Strategy> | 799 template <typename Strategy> |
838 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() { | 800 void TextIteratorAlgorithm<Strategy>::ProceedToRemainingText() { |
839 text_box_ = remaining_text_box_; | 801 text_box_ = remaining_text_box_; |
840 remaining_text_box_ = 0; | 802 remaining_text_box_ = 0; |
841 first_letter_text_ = nullptr; | 803 first_letter_text_ = nullptr; |
842 // TODO(xiaochengh): |offset_| should be set to the starting offset of the | 804 offset_ = ToLayoutText(node_->GetLayoutObject())->TextStartOffset(); |
843 // remaining text; | |
844 offset_ = 0; | |
845 } | 805 } |
846 | 806 |
847 template <typename Strategy> | 807 template <typename Strategy> |
848 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( | 808 void TextIteratorAlgorithm<Strategy>::HandleTextNodeFirstLetter( |
849 LayoutTextFragment* layout_object) { | 809 LayoutTextFragment* layout_object) { |
850 handled_first_letter_ = true; | 810 handled_first_letter_ = true; |
851 | 811 |
852 if (!layout_object->IsRemainingTextLayoutObject()) | 812 if (!layout_object->IsRemainingTextLayoutObject()) |
853 return; | 813 return; |
854 | 814 |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1223 int text_end_offset) { | 1183 int text_end_offset) { |
1224 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in | 1184 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in |
1225 // TextIterator, but is always reset when we call spliceBuffer, we | 1185 // TextIterator, but is always reset when we call spliceBuffer, we |
1226 // wrap TextIteratorTextState::spliceBuffer() with this function. | 1186 // wrap TextIteratorTextState::spliceBuffer() with this function. |
1227 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset, | 1187 text_state_.SpliceBuffer(c, text_node, offset_base_node, text_start_offset, |
1228 text_end_offset); | 1188 text_end_offset); |
1229 last_text_node_ended_with_collapsed_space_ = false; | 1189 last_text_node_ended_with_collapsed_space_ = false; |
1230 } | 1190 } |
1231 | 1191 |
1232 template <typename Strategy> | 1192 template <typename Strategy> |
1233 int TextIteratorAlgorithm<Strategy>::AdjustedStartForFirstLetter( | |
1234 const Node& text_node, | |
1235 const LayoutText& layout_object, | |
1236 int text_start_offset, | |
1237 int text_end_offset) { | |
1238 if (first_letter_start_offset_ == kInvalidTextOffset) | |
1239 return text_start_offset; | |
1240 if (text_node != start_container_) | |
1241 return text_start_offset; | |
1242 if (!layout_object.IsTextFragment()) | |
1243 return text_start_offset; | |
1244 if (ToLayoutTextFragment(layout_object).IsRemainingTextLayoutObject()) | |
1245 return text_start_offset; | |
1246 if (text_end_offset <= first_letter_start_offset_) | |
1247 return text_start_offset; | |
1248 int adjusted_offset = std::max(text_start_offset, first_letter_start_offset_); | |
1249 first_letter_start_offset_ = kInvalidTextOffset; | |
1250 return adjusted_offset; | |
1251 } | |
1252 | |
1253 template <typename Strategy> | |
1254 int TextIteratorAlgorithm<Strategy>::AdjustedStartForRemainingText( | |
1255 const Node& text_node, | |
1256 const LayoutText& layout_object, | |
1257 int text_start_offset, | |
1258 int text_end_offset) { | |
1259 if (remaining_text_start_offset_ == kInvalidTextOffset) | |
1260 return text_start_offset; | |
1261 if (text_node != start_container_) | |
1262 return text_start_offset; | |
1263 if (!layout_object.IsTextFragment()) | |
1264 return text_start_offset; | |
1265 if (!ToLayoutTextFragment(layout_object).IsRemainingTextLayoutObject()) | |
1266 return text_start_offset; | |
1267 if (text_end_offset <= remaining_text_start_offset_) | |
1268 return text_start_offset; | |
1269 int adjusted_offset = | |
1270 std::max(text_start_offset, remaining_text_start_offset_); | |
1271 remaining_text_start_offset_ = kInvalidTextOffset; | |
1272 return adjusted_offset; | |
1273 } | |
1274 | |
1275 template <typename Strategy> | |
1276 void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node, | 1193 void TextIteratorAlgorithm<Strategy>::EmitText(Node* text_node, |
1277 LayoutText* layout_object, | 1194 LayoutText* layout_object, |
1278 int text_start_offset, | 1195 int text_start_offset, |
1279 int text_end_offset) { | 1196 int text_end_offset) { |
1280 text_start_offset = AdjustedStartForFirstLetter( | |
1281 *text_node, *layout_object, text_start_offset, text_end_offset); | |
1282 text_start_offset = AdjustedStartForRemainingText( | |
1283 *text_node, *layout_object, text_start_offset, text_end_offset); | |
1284 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in | 1197 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in |
1285 // TextIterator, but is always reset when we call spliceBuffer, we | 1198 // TextIterator, but is always reset when we call spliceBuffer, we |
1286 // wrap TextIteratorTextState::spliceBuffer() with this function. | 1199 // wrap TextIteratorTextState::spliceBuffer() with this function. |
1287 text_state_.EmitText(text_node, layout_object, text_start_offset, | 1200 text_state_.EmitText(text_node, layout_object, text_start_offset, |
1288 text_end_offset); | 1201 text_end_offset); |
1289 last_text_node_ended_with_collapsed_space_ = false; | 1202 last_text_node_ended_with_collapsed_space_ = false; |
1290 } | 1203 } |
1291 | 1204 |
1292 template <typename Strategy> | 1205 template <typename Strategy> |
1293 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range() | 1206 EphemeralRangeTemplate<Strategy> TextIteratorAlgorithm<Strategy>::Range() |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1467 String PlainText(const EphemeralRangeInFlatTree& range, | 1380 String PlainText(const EphemeralRangeInFlatTree& range, |
1468 const TextIteratorBehavior& behavior) { | 1381 const TextIteratorBehavior& behavior) { |
1469 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); | 1382 return CreatePlainText<EditingInFlatTreeStrategy>(range, behavior); |
1470 } | 1383 } |
1471 | 1384 |
1472 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; | 1385 template class CORE_TEMPLATE_EXPORT TextIteratorAlgorithm<EditingStrategy>; |
1473 template class CORE_TEMPLATE_EXPORT | 1386 template class CORE_TEMPLATE_EXPORT |
1474 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; | 1387 TextIteratorAlgorithm<EditingInFlatTreeStrategy>; |
1475 | 1388 |
1476 } // namespace blink | 1389 } // namespace blink |
OLD | NEW |