Chromium Code Reviews| 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 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 740 | 740 |
| 741 static bool shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) | 741 static bool shouldEmitNewlineForNode(Node* node, bool emitsOriginalText) |
| 742 { | 742 { |
| 743 RenderObject* renderer = node->renderer(); | 743 RenderObject* renderer = node->renderer(); |
| 744 | 744 |
| 745 if (renderer ? !renderer->isBR() : !node->hasTagName(brTag)) | 745 if (renderer ? !renderer->isBR() : !node->hasTagName(brTag)) |
| 746 return false; | 746 return false; |
| 747 return emitsOriginalText || !(node->isInShadowTree() && node->shadowHost()-> hasTagName(inputTag)); | 747 return emitsOriginalText || !(node->isInShadowTree() && node->shadowHost()-> hasTagName(inputTag)); |
| 748 } | 748 } |
| 749 | 749 |
| 750 static bool shouldEmitNewlinesBeforeAndAfterNode(Node* node) | 750 static bool shouldEmitNewlinesBeforeAndAfterNode(Node& node) |
| 751 { | 751 { |
| 752 // Block flow (versus inline flow) is represented by having | 752 // Block flow (versus inline flow) is represented by having |
| 753 // a newline both before and after the element. | 753 // a newline both before and after the element. |
| 754 RenderObject* r = node->renderer(); | 754 RenderObject* r = node.renderer(); |
| 755 if (!r) { | 755 if (!r) { |
| 756 return (node->hasTagName(blockquoteTag) | 756 return (node.hasTagName(blockquoteTag) |
| 757 || node->hasTagName(ddTag) | 757 || node.hasTagName(ddTag) |
| 758 || node->hasTagName(divTag) | 758 || node.hasTagName(divTag) |
| 759 || node->hasTagName(dlTag) | 759 || node.hasTagName(dlTag) |
| 760 || node->hasTagName(dtTag) | 760 || node.hasTagName(dtTag) |
| 761 || node->hasTagName(h1Tag) | 761 || node.hasTagName(h1Tag) |
| 762 || node->hasTagName(h2Tag) | 762 || node.hasTagName(h2Tag) |
| 763 || node->hasTagName(h3Tag) | 763 || node.hasTagName(h3Tag) |
| 764 || node->hasTagName(h4Tag) | 764 || node.hasTagName(h4Tag) |
| 765 || node->hasTagName(h5Tag) | 765 || node.hasTagName(h5Tag) |
| 766 || node->hasTagName(h6Tag) | 766 || node.hasTagName(h6Tag) |
| 767 || node->hasTagName(hrTag) | 767 || node.hasTagName(hrTag) |
| 768 || node->hasTagName(liTag) | 768 || node.hasTagName(liTag) |
| 769 || node->hasTagName(listingTag) | 769 || node.hasTagName(listingTag) |
| 770 || node->hasTagName(olTag) | 770 || node.hasTagName(olTag) |
| 771 || node->hasTagName(pTag) | 771 || node.hasTagName(pTag) |
| 772 || node->hasTagName(preTag) | 772 || node.hasTagName(preTag) |
| 773 || node->hasTagName(trTag) | 773 || node.hasTagName(trTag) |
| 774 || node->hasTagName(ulTag)); | 774 || node.hasTagName(ulTag)); |
| 775 } | 775 } |
| 776 | 776 |
| 777 // Need to make an exception for table cells, because they are blocks, but w e | 777 // Need to make an exception for table cells, because they are blocks, but w e |
| 778 // want them tab-delimited rather than having newlines before and after. | 778 // want them tab-delimited rather than having newlines before and after. |
| 779 if (isTableCell(node)) | 779 if (isTableCell(&node)) |
| 780 return false; | 780 return false; |
| 781 | 781 |
| 782 // Need to make an exception for table row elements, because they are neithe r | 782 // Need to make an exception for table row elements, because they are neithe r |
| 783 // "inline" or "RenderBlock", but we want newlines for them. | 783 // "inline" or "RenderBlock", but we want newlines for them. |
| 784 if (r->isTableRow()) { | 784 if (r->isTableRow()) { |
| 785 RenderTable* t = toRenderTableRow(r)->table(); | 785 RenderTable* t = toRenderTableRow(r)->table(); |
| 786 if (t && !t->isInline()) | 786 if (t && !t->isInline()) |
| 787 return true; | 787 return true; |
| 788 } | 788 } |
| 789 | 789 |
| 790 return !r->isInline() && r->isRenderBlock() | 790 return !r->isInline() && r->isRenderBlock() |
| 791 && !r->isFloatingOrOutOfFlowPositioned() && !r->isBody() && !r->isRubyTe xt(); | 791 && !r->isFloatingOrOutOfFlowPositioned() && !r->isBody() && !r->isRubyTe xt(); |
| 792 } | 792 } |
| 793 | 793 |
| 794 static bool shouldEmitNewlineAfterNode(Node* node) | 794 static bool shouldEmitNewlineAfterNode(Node& node) |
| 795 { | 795 { |
| 796 // FIXME: It should be better but slower to create a VisiblePosition here. | 796 // FIXME: It should be better but slower to create a VisiblePosition here. |
| 797 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) | 797 if (!shouldEmitNewlinesBeforeAndAfterNode(node)) |
| 798 return false; | 798 return false; |
| 799 // Check if this is the very last renderer in the document. | 799 // Check if this is the very last renderer in the document. |
| 800 // If so, then we should not emit a newline. | 800 // If so, then we should not emit a newline. |
| 801 while ((node = NodeTraversal::nextSkippingChildren(node))) { | 801 Node* next = &node; |
| 802 if (node->renderer()) | 802 while ((next = NodeTraversal::nextSkippingChildren(*next))) { |
|
adamk
2013/11/12 21:07:43
Nit: can you remove the extra parentheses while yo
Inactive
2013/11/12 21:19:16
I would but I cannot :)
../../third_party/WebKit/
adamk
2013/11/12 22:21:36
Sigh. Oh well, lgtm anyway
| |
| 803 if (next->renderer()) | |
| 803 return true; | 804 return true; |
| 804 } | 805 } |
| 805 return false; | 806 return false; |
| 806 } | 807 } |
| 807 | 808 |
| 808 static bool shouldEmitNewlineBeforeNode(Node* node) | 809 static bool shouldEmitNewlineBeforeNode(Node& node) |
| 809 { | 810 { |
| 810 return shouldEmitNewlinesBeforeAndAfterNode(node); | 811 return shouldEmitNewlinesBeforeAndAfterNode(node); |
| 811 } | 812 } |
| 812 | 813 |
| 813 static bool shouldEmitExtraNewlineForNode(Node* node) | 814 static bool shouldEmitExtraNewlineForNode(Node* node) |
| 814 { | 815 { |
| 815 // When there is a significant collapsed bottom margin, emit an extra | 816 // When there is a significant collapsed bottom margin, emit an extra |
| 816 // newline for a more realistic result. We end up getting the right | 817 // newline for a more realistic result. We end up getting the right |
| 817 // result even without margin collapsing. For example: <div><p>text</p></div > | 818 // result even without margin collapsing. For example: <div><p>text</p></div > |
| 818 // will work right even if both the <div> and the <p> have bottom margins. | 819 // will work right even if both the <div> and the <p> have bottom margins. |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 929 { | 930 { |
| 930 // Emit a character to show the positioning of m_node. | 931 // Emit a character to show the positioning of m_node. |
| 931 | 932 |
| 932 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe ro() can | 933 // When we haven't been emitting any characters, shouldRepresentNodeOffsetZe ro() can |
| 933 // create VisiblePositions, which is expensive. So, we perform the inexpensi ve checks | 934 // create VisiblePositions, which is expensive. So, we perform the inexpensi ve checks |
| 934 // on m_node to see if it necessitates emitting a character first and will e arly return | 935 // on m_node to see if it necessitates emitting a character first and will e arly return |
| 935 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. | 936 // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
| 936 if (shouldEmitTabBeforeNode(m_node)) { | 937 if (shouldEmitTabBeforeNode(m_node)) { |
| 937 if (shouldRepresentNodeOffsetZero()) | 938 if (shouldRepresentNodeOffsetZero()) |
| 938 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); | 939 emitCharacter('\t', m_node->parentNode(), m_node, 0, 0); |
| 939 } else if (shouldEmitNewlineBeforeNode(m_node)) { | 940 } else if (shouldEmitNewlineBeforeNode(*m_node)) { |
| 940 if (shouldRepresentNodeOffsetZero()) | 941 if (shouldRepresentNodeOffsetZero()) |
| 941 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); | 942 emitCharacter('\n', m_node->parentNode(), m_node, 0, 0); |
| 942 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { | 943 } else if (shouldEmitSpaceBeforeAndAfterNode(m_node)) { |
| 943 if (shouldRepresentNodeOffsetZero()) | 944 if (shouldRepresentNodeOffsetZero()) |
| 944 emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); | 945 emitCharacter(' ', m_node->parentNode(), m_node, 0, 0); |
| 945 } | 946 } |
| 946 } | 947 } |
| 947 | 948 |
| 948 bool TextIterator::handleNonTextNode() | 949 bool TextIterator::handleNonTextNode() |
| 949 { | 950 { |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 967 return; | 968 return; |
| 968 | 969 |
| 969 // Emit with a position *inside* m_node, after m_node's contents, in | 970 // Emit with a position *inside* m_node, after m_node's contents, in |
| 970 // case it is a block, because the run should start where the | 971 // case it is a block, because the run should start where the |
| 971 // emitted character is positioned visually. | 972 // emitted character is positioned visually. |
| 972 Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; | 973 Node* baseNode = m_node->lastChild() ? m_node->lastChild() : m_node; |
| 973 // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making | 974 // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making |
| 974 // the logic in _web_attributedStringFromRange match. We'll get that for fre e when we switch to use | 975 // the logic in _web_attributedStringFromRange match. We'll get that for fre e when we switch to use |
| 975 // TextIterator in _web_attributedStringFromRange. | 976 // TextIterator in _web_attributedStringFromRange. |
| 976 // See <rdar://problem/5428427> for an example of how this mismatch will cau se problems. | 977 // See <rdar://problem/5428427> for an example of how this mismatch will cau se problems. |
| 977 if (m_lastTextNode && shouldEmitNewlineAfterNode(m_node)) { | 978 if (m_lastTextNode && shouldEmitNewlineAfterNode(*m_node)) { |
| 978 // use extra newline to represent margin bottom, as needed | 979 // use extra newline to represent margin bottom, as needed |
| 979 bool addNewline = shouldEmitExtraNewlineForNode(m_node); | 980 bool addNewline = shouldEmitExtraNewlineForNode(m_node); |
| 980 | 981 |
| 981 // FIXME: We need to emit a '\n' as we leave an empty block(s) that | 982 // FIXME: We need to emit a '\n' as we leave an empty block(s) that |
| 982 // contain a VisiblePosition when doing selection preservation. | 983 // contain a VisiblePosition when doing selection preservation. |
| 983 if (m_lastCharacter != '\n') { | 984 if (m_lastCharacter != '\n') { |
| 984 // insert a newline with a position following this block's contents. | 985 // insert a newline with a position following this block's contents. |
| 985 emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); | 986 emitCharacter('\n', baseNode->parentNode(), baseNode, 1, 1); |
| 986 // remember whether to later add a newline for the current node | 987 // remember whether to later add a newline for the current node |
| 987 ASSERT(!m_needsAnotherNewline); | 988 ASSERT(!m_needsAnotherNewline); |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1306 // code in moveParagraphs, so we use a comma. Unconditionally emit | 1307 // code in moveParagraphs, so we use a comma. Unconditionally emit |
| 1307 // here because this iterator is only used for boundary finding. | 1308 // here because this iterator is only used for boundary finding. |
| 1308 emitCharacter(',', m_node->parentNode(), index, index + 1); | 1309 emitCharacter(',', m_node->parentNode(), index, index + 1); |
| 1309 return true; | 1310 return true; |
| 1310 } | 1311 } |
| 1311 | 1312 |
| 1312 bool SimplifiedBackwardsTextIterator::handleNonTextNode() | 1313 bool SimplifiedBackwardsTextIterator::handleNonTextNode() |
| 1313 { | 1314 { |
| 1314 // We can use a linefeed in place of a tab because this simple iterator is o nly used to | 1315 // We can use a linefeed in place of a tab because this simple iterator is o nly used to |
| 1315 // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. | 1316 // find boundaries, not actual content. A linefeed breaks words, sentences, and paragraphs. |
| 1316 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neAfterNode(m_node) || shouldEmitTabBeforeNode(m_node)) { | 1317 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neAfterNode(*m_node) || shouldEmitTabBeforeNode(m_node)) { |
| 1317 unsigned index = m_node->nodeIndex(); | 1318 unsigned index = m_node->nodeIndex(); |
| 1318 // The start of this emitted range is wrong. Ensuring correctness would require | 1319 // The start of this emitted range is wrong. Ensuring correctness would require |
| 1319 // VisiblePositions and so would be slow. previousBoundary expects this. | 1320 // VisiblePositions and so would be slow. previousBoundary expects this. |
| 1320 emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); | 1321 emitCharacter('\n', m_node->parentNode(), index + 1, index + 1); |
| 1321 } | 1322 } |
| 1322 return true; | 1323 return true; |
| 1323 } | 1324 } |
| 1324 | 1325 |
| 1325 void SimplifiedBackwardsTextIterator::exitNode() | 1326 void SimplifiedBackwardsTextIterator::exitNode() |
| 1326 { | 1327 { |
| 1327 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neBeforeNode(m_node) || shouldEmitTabBeforeNode(m_node)) { | 1328 if (shouldEmitNewlineForNode(m_node, m_emitsOriginalText) || shouldEmitNewli neBeforeNode(*m_node) || shouldEmitTabBeforeNode(m_node)) { |
| 1328 // The start of this emitted range is wrong. Ensuring correctness would require | 1329 // The start of this emitted range is wrong. Ensuring correctness would require |
| 1329 // VisiblePositions and so would be slow. previousBoundary expects this. | 1330 // VisiblePositions and so would be slow. previousBoundary expects this. |
| 1330 emitCharacter('\n', m_node, 0, 0); | 1331 emitCharacter('\n', m_node, 0, 0); |
| 1331 } | 1332 } |
| 1332 } | 1333 } |
| 1333 | 1334 |
| 1334 void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta rtOffset, int endOffset) | 1335 void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta rtOffset, int endOffset) |
| 1335 { | 1336 { |
| 1336 m_singleCharacterBuffer = c; | 1337 m_singleCharacterBuffer = c; |
| 1337 m_positionNode = node; | 1338 m_positionNode = node; |
| (...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2325 if (!matchLength) | 2326 if (!matchLength) |
| 2326 return collapsedToBoundary(range, !(options & Backwards)); | 2327 return collapsedToBoundary(range, !(options & Backwards)); |
| 2327 } | 2328 } |
| 2328 | 2329 |
| 2329 // Then, find the document position of the start and the end of the text. | 2330 // Then, find the document position of the start and the end of the text. |
| 2330 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls ); | 2331 CharacterIterator computeRangeIterator(range, TextIteratorEntersTextControls ); |
| 2331 return characterSubrange(computeRangeIterator, matchStart, matchLength); | 2332 return characterSubrange(computeRangeIterator, matchStart, matchLength); |
| 2332 } | 2333 } |
| 2333 | 2334 |
| 2334 } | 2335 } |
| OLD | NEW |