OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All r
ights reserved. |
3 * Copyright (C) 2005 Alexey Proskuryakov. | 3 * Copyright (C) 2005 Alexey Proskuryakov. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 406 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 Text* textNode = toText(m_node); | 417 Text* textNode = toText(m_node); |
418 LayoutText* layoutObject = textNode->layoutObject(); | 418 LayoutText* layoutObject = textNode->layoutObject(); |
419 | 419 |
420 m_lastTextNode = textNode; | 420 m_lastTextNode = textNode; |
421 String str = layoutObject->text(); | 421 String str = layoutObject->text(); |
422 | 422 |
423 // handle pre-formatted text | 423 // handle pre-formatted text |
424 if (!layoutObject->style()->collapseWhiteSpace()) { | 424 if (!layoutObject->style()->collapseWhiteSpace()) { |
425 int runStart = m_offset; | 425 int runStart = m_offset; |
426 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(layoutOb
ject)) { | 426 if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(layoutOb
ject)) { |
427 emitCharacter(space, textNode, 0, runStart, runStart); | 427 emitCharacter(spaceCharacter, textNode, 0, runStart, runStart); |
428 return false; | 428 return false; |
429 } | 429 } |
430 if (!m_handledFirstLetter && layoutObject->isTextFragment() && !m_offset
) { | 430 if (!m_handledFirstLetter && layoutObject->isTextFragment() && !m_offset
) { |
431 handleTextNodeFirstLetter(toLayoutTextFragment(layoutObject)); | 431 handleTextNodeFirstLetter(toLayoutTextFragment(layoutObject)); |
432 if (m_firstLetterText) { | 432 if (m_firstLetterText) { |
433 String firstLetter = m_firstLetterText->text(); | 433 String firstLetter = m_firstLetterText->text(); |
434 emitText(textNode, m_firstLetterText, m_offset, m_offset + first
Letter.length()); | 434 emitText(textNode, m_firstLetterText, m_offset, m_offset + first
Letter.length()); |
435 m_firstLetterText = nullptr; | 435 m_firstLetterText = nullptr; |
436 m_textBox = 0; | 436 m_textBox = 0; |
437 return false; | 437 return false; |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 InlineTextBox* firstTextBox = layoutObject->containsReversedText() ?
(m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : layoutObject->firstT
extBox(); | 501 InlineTextBox* firstTextBox = layoutObject->containsReversedText() ?
(m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : layoutObject->firstT
extBox(); |
502 bool needSpace = m_lastTextNodeEndedWithCollapsedSpace | 502 bool needSpace = m_lastTextNodeEndedWithCollapsedSpace |
503 || (m_textBox == firstTextBox && textBoxStart == runStart && run
Start > 0); | 503 || (m_textBox == firstTextBox && textBoxStart == runStart && run
Start > 0); |
504 if (needSpace && !layoutObject->style()->isCollapsibleWhiteSpace(m_t
extState.lastCharacter()) && m_textState.lastCharacter()) { | 504 if (needSpace && !layoutObject->style()->isCollapsibleWhiteSpace(m_t
extState.lastCharacter()) && m_textState.lastCharacter()) { |
505 if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1
] == ' ') { | 505 if (m_lastTextNode == m_node && runStart > 0 && str[runStart - 1
] == ' ') { |
506 unsigned spaceRunStart = runStart - 1; | 506 unsigned spaceRunStart = runStart - 1; |
507 while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ') | 507 while (spaceRunStart > 0 && str[spaceRunStart - 1] == ' ') |
508 --spaceRunStart; | 508 --spaceRunStart; |
509 emitText(m_node, layoutObject, spaceRunStart, spaceRunStart
+ 1); | 509 emitText(m_node, layoutObject, spaceRunStart, spaceRunStart
+ 1); |
510 } else { | 510 } else { |
511 emitCharacter(space, m_node, 0, runStart, runStart); | 511 emitCharacter(spaceCharacter, m_node, 0, runStart, runStart)
; |
512 } | 512 } |
513 return; | 513 return; |
514 } | 514 } |
515 unsigned textBoxEnd = textBoxStart + m_textBox->len(); | 515 unsigned textBoxEnd = textBoxStart + m_textBox->len(); |
516 unsigned runEnd = std::min(textBoxEnd, end); | 516 unsigned runEnd = std::min(textBoxEnd, end); |
517 | 517 |
518 // Determine what the next text box will be, but don't advance yet | 518 // Determine what the next text box will be, but don't advance yet |
519 InlineTextBox* nextTextBox = nullptr; | 519 InlineTextBox* nextTextBox = nullptr; |
520 if (layoutObject->containsReversedText()) { | 520 if (layoutObject->containsReversedText()) { |
521 if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size()) | 521 if (m_sortedTextBoxesPosition + 1 < m_sortedTextBoxes.size()) |
(...skipping 11 matching lines...) Expand all Loading... |
533 m_textBox = 0; | 533 m_textBox = 0; |
534 return; | 534 return; |
535 } | 535 } |
536 ASSERT(!nextTextBox || nextTextBox->layoutObject() == layoutObject); | 536 ASSERT(!nextTextBox || nextTextBox->layoutObject() == layoutObject); |
537 | 537 |
538 if (runStart < runEnd) { | 538 if (runStart < runEnd) { |
539 // Handle either a single newline character (which becomes a spa
ce), | 539 // Handle either a single newline character (which becomes a spa
ce), |
540 // or a run of characters that does not include a newline. | 540 // or a run of characters that does not include a newline. |
541 // This effectively translates newlines to spaces without copyin
g the text. | 541 // This effectively translates newlines to spaces without copyin
g the text. |
542 if (str[runStart] == '\n') { | 542 if (str[runStart] == '\n') { |
543 emitCharacter(space, m_node, 0, runStart, runStart + 1); | 543 emitCharacter(spaceCharacter, m_node, 0, runStart, runStart
+ 1); |
544 m_offset = runStart + 1; | 544 m_offset = runStart + 1; |
545 } else { | 545 } else { |
546 size_t subrunEnd = str.find('\n', runStart); | 546 size_t subrunEnd = str.find('\n', runStart); |
547 if (subrunEnd == kNotFound || subrunEnd > runEnd) | 547 if (subrunEnd == kNotFound || subrunEnd > runEnd) |
548 subrunEnd = runEnd; | 548 subrunEnd = runEnd; |
549 | 549 |
550 m_offset = subrunEnd; | 550 m_offset = subrunEnd; |
551 emitText(m_node, layoutObject, runStart, subrunEnd); | 551 emitText(m_node, layoutObject, runStart, subrunEnd); |
552 } | 552 } |
553 | 553 |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 LayoutObject* layoutObject = m_node->layoutObject(); | 631 LayoutObject* layoutObject = m_node->layoutObject(); |
632 if (layoutObject->style()->visibility() != VISIBLE && !ignoresStyleVisibilit
y()) | 632 if (layoutObject->style()->visibility() != VISIBLE && !ignoresStyleVisibilit
y()) |
633 return false; | 633 return false; |
634 | 634 |
635 if (emitsObjectReplacementCharacter()) { | 635 if (emitsObjectReplacementCharacter()) { |
636 emitCharacter(objectReplacementCharacter, Strategy::parent(*m_node), m_n
ode, 0, 1); | 636 emitCharacter(objectReplacementCharacter, Strategy::parent(*m_node), m_n
ode, 0, 1); |
637 return true; | 637 return true; |
638 } | 638 } |
639 | 639 |
640 if (m_lastTextNodeEndedWithCollapsedSpace) { | 640 if (m_lastTextNodeEndedWithCollapsedSpace) { |
641 emitCharacter(space, Strategy::parent(*m_lastTextNode), m_lastTextNode,
1, 1); | 641 emitCharacter(spaceCharacter, Strategy::parent(*m_lastTextNode), m_lastT
extNode, 1, 1); |
642 return false; | 642 return false; |
643 } | 643 } |
644 | 644 |
645 if (entersTextControls() && layoutObject->isTextControl()) { | 645 if (entersTextControls() && layoutObject->isTextControl()) { |
646 // The shadow tree should be already visited. | 646 // The shadow tree should be already visited. |
647 return true; | 647 return true; |
648 } | 648 } |
649 | 649 |
650 if (emitsCharactersBetweenAllVisiblePositions()) { | 650 if (emitsCharactersBetweenAllVisiblePositions()) { |
651 // We want replaced elements to behave like punctuation for boundary | 651 // We want replaced elements to behave like punctuation for boundary |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
868 // on m_node to see if it necessitates emitting a character first and will e
arly return | 868 // on m_node to see if it necessitates emitting a character first and will e
arly return |
869 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. | 869 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
870 if (shouldEmitTabBeforeNode(m_node)) { | 870 if (shouldEmitTabBeforeNode(m_node)) { |
871 if (shouldRepresentNodeOffsetZero()) | 871 if (shouldRepresentNodeOffsetZero()) |
872 emitCharacter('\t', Strategy::parent(*m_node), m_node, 0, 0); | 872 emitCharacter('\t', Strategy::parent(*m_node), m_node, 0, 0); |
873 } else if (shouldEmitNewlineBeforeNode(*m_node)) { | 873 } else if (shouldEmitNewlineBeforeNode(*m_node)) { |
874 if (shouldRepresentNodeOffsetZero()) | 874 if (shouldRepresentNodeOffsetZero()) |
875 emitCharacter('\n', Strategy::parent(*m_node), m_node, 0, 0); | 875 emitCharacter('\n', Strategy::parent(*m_node), m_node, 0, 0); |
876 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { | 876 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { |
877 if (shouldRepresentNodeOffsetZero()) | 877 if (shouldRepresentNodeOffsetZero()) |
878 emitCharacter(space, Strategy::parent(*m_node), m_node, 0, 0); | 878 emitCharacter(spaceCharacter, Strategy::parent(*m_node), m_node, 0,
0); |
879 } | 879 } |
880 } | 880 } |
881 | 881 |
882 | 882 |
883 template<typename Strategy> | 883 template<typename Strategy> |
884 bool TextIteratorAlgorithm<Strategy>::handleNonTextNode() | 884 bool TextIteratorAlgorithm<Strategy>::handleNonTextNode() |
885 { | 885 { |
886 if (shouldEmitNewlineForNode(m_node, emitsOriginalText())) | 886 if (shouldEmitNewlineForNode(m_node, emitsOriginalText())) |
887 emitCharacter('\n', Strategy::parent(*m_node), m_node, 0, 1); | 887 emitCharacter('\n', Strategy::parent(*m_node), m_node, 0, 1); |
888 else if (emitsCharactersBetweenAllVisiblePositions() && m_node->layoutObject
() && m_node->layoutObject()->isHR()) | 888 else if (emitsCharactersBetweenAllVisiblePositions() && m_node->layoutObject
() && m_node->layoutObject()->isHR()) |
889 emitCharacter(space, Strategy::parent(*m_node), m_node, 0, 1); | 889 emitCharacter(spaceCharacter, Strategy::parent(*m_node), m_node, 0, 1); |
890 else | 890 else |
891 representNodeOffsetZero(); | 891 representNodeOffsetZero(); |
892 | 892 |
893 return true; | 893 return true; |
894 } | 894 } |
895 | 895 |
896 template<typename Strategy> | 896 template<typename Strategy> |
897 void TextIteratorAlgorithm<Strategy>::exitNode() | 897 void TextIteratorAlgorithm<Strategy>::exitNode() |
898 { | 898 { |
899 // prevent emitting a newline when exiting a collapsed block at beginning of
the range | 899 // prevent emitting a newline when exiting a collapsed block at beginning of
the range |
(...skipping 13 matching lines...) Expand all Loading... |
913 // TextIterator in _web_attributedStringFromRange. | 913 // TextIterator in _web_attributedStringFromRange. |
914 // See <rdar://problem/5428427> for an example of how this mismatch will cau
se problems. | 914 // See <rdar://problem/5428427> for an example of how this mismatch will cau
se problems. |
915 if (m_lastTextNode && shouldEmitNewlineAfterNode(*m_node)) { | 915 if (m_lastTextNode && shouldEmitNewlineAfterNode(*m_node)) { |
916 // use extra newline to represent margin bottom, as needed | 916 // use extra newline to represent margin bottom, as needed |
917 bool addNewline = shouldEmitExtraNewlineForNode(m_node); | 917 bool addNewline = shouldEmitExtraNewlineForNode(m_node); |
918 | 918 |
919 // FIXME: We need to emit a '\n' as we leave an empty block(s) that | 919 // FIXME: We need to emit a '\n' as we leave an empty block(s) that |
920 // contain a VisiblePosition when doing selection preservation. | 920 // contain a VisiblePosition when doing selection preservation. |
921 if (m_textState.lastCharacter() != '\n') { | 921 if (m_textState.lastCharacter() != '\n') { |
922 // insert a newline with a position following this block's contents. | 922 // insert a newline with a position following this block's contents. |
923 emitCharacter('\n', Strategy::parent(*baseNode), baseNode, 1, 1); | 923 emitCharacter(newlineCharacter, Strategy::parent(*baseNode), baseNod
e, 1, 1); |
924 // remember whether to later add a newline for the current node | 924 // remember whether to later add a newline for the current node |
925 ASSERT(!m_needsAnotherNewline); | 925 ASSERT(!m_needsAnotherNewline); |
926 m_needsAnotherNewline = addNewline; | 926 m_needsAnotherNewline = addNewline; |
927 } else if (addNewline) { | 927 } else if (addNewline) { |
928 // insert a newline with a position following this block's contents. | 928 // insert a newline with a position following this block's contents. |
929 emitCharacter('\n', Strategy::parent(*baseNode), baseNode, 1, 1); | 929 emitCharacter(newlineCharacter, Strategy::parent(*baseNode), baseNod
e, 1, 1); |
930 } | 930 } |
931 } | 931 } |
932 | 932 |
933 // If nothing was emitted, see if we need to emit a space. | 933 // If nothing was emitted, see if we need to emit a space. |
934 if (!m_textState.positionNode() && shouldEmitSpaceBeforeAndAfterNode(m_node)
) | 934 if (!m_textState.positionNode() && shouldEmitSpaceBeforeAndAfterNode(m_node)
) |
935 emitCharacter(space, Strategy::parent(*baseNode), baseNode, 1, 1); | 935 emitCharacter(spaceCharacter, Strategy::parent(*baseNode), baseNode, 1,
1); |
936 } | 936 } |
937 | 937 |
938 template<typename Strategy> | 938 template<typename Strategy> |
939 void TextIteratorAlgorithm<Strategy>::emitCharacter(UChar c, Node* textNode, Nod
e* offsetBaseNode, int textStartOffset, int textEndOffset) | 939 void TextIteratorAlgorithm<Strategy>::emitCharacter(UChar c, Node* textNode, Nod
e* offsetBaseNode, int textStartOffset, int textEndOffset) |
940 { | 940 { |
941 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in | 941 // Since m_lastTextNodeEndedWithCollapsedSpace seems better placed in |
942 // TextIterator, but is always reset when we call emitCharacter, we | 942 // TextIterator, but is always reset when we call emitCharacter, we |
943 // wrap TextIteratorTextState::emitCharacter() with this function. | 943 // wrap TextIteratorTextState::emitCharacter() with this function. |
944 m_textState.emitCharacter(c, textNode, offsetBaseNode, textStartOffset, text
EndOffset); | 944 m_textState.emitCharacter(c, textNode, offsetBaseNode, textStartOffset, text
EndOffset); |
945 m_lastTextNodeEndedWithCollapsedSpace = false; | 945 m_lastTextNodeEndedWithCollapsedSpace = false; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1101 | 1101 |
1102 String plainText(const PositionInComposedTree& start, const PositionInComposedTr
ee& end, TextIteratorBehaviorFlags behavior) | 1102 String plainText(const PositionInComposedTree& start, const PositionInComposedTr
ee& end, TextIteratorBehaviorFlags behavior) |
1103 { | 1103 { |
1104 return createPlainText<EditingInComposedTreeStrategy>(start, end, behavior); | 1104 return createPlainText<EditingInComposedTreeStrategy>(start, end, behavior); |
1105 } | 1105 } |
1106 | 1106 |
1107 template class CORE_EXPORT TextIteratorAlgorithm<EditingStrategy>; | 1107 template class CORE_EXPORT TextIteratorAlgorithm<EditingStrategy>; |
1108 template class CORE_EXPORT TextIteratorAlgorithm<EditingInComposedTreeStrategy>; | 1108 template class CORE_EXPORT TextIteratorAlgorithm<EditingInComposedTreeStrategy>; |
1109 | 1109 |
1110 } // namespace blink | 1110 } // namespace blink |
OLD | NEW |