Index: third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
diff --git a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
index eaea1ac12f72a324f82b9f9960b92b27504c2d08..c077302632824f51f39cc16690d1882d5f4710d1 100644 |
--- a/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
+++ b/third_party/WebKit/Source/core/editing/iterators/TextIterator.cpp |
@@ -1,5 +1,6 @@ |
/* |
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. |
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All |
+ * rights reserved. |
* Copyright (C) 2005 Alexey Proskuryakov. |
* |
* Redistribution and use in source and binary forms, with or without |
@@ -163,13 +164,15 @@ TextIteratorAlgorithm<Strategy>::TextIteratorAlgorithm( |
m_handledFirstLetter(false), |
m_shouldStop(false), |
m_handleShadowRoot(false), |
- // The call to emitsOriginalText() must occur after m_behavior is initialized. |
+ // The call to emitsOriginalText() must occur after m_behavior is |
+ // initialized. |
m_textState(emitsOriginalText()) { |
DCHECK(start.isNotNull()); |
DCHECK(end.isNotNull()); |
- // TODO(dglazkov): TextIterator should not be created for documents that don't have a frame, |
- // but it currently still happens in some cases. See http://crbug.com/591877 for details. |
+ // TODO(dglazkov): TextIterator should not be created for documents that don't |
+ // have a frame, but it currently still happens in some cases. See |
+ // http://crbug.com/591877 for details. |
DCHECK(!start.document()->view() || !start.document()->view()->needsLayout()); |
DCHECK(!start.document()->needsLayoutTreeUpdate()); |
@@ -265,9 +268,9 @@ void TextIteratorAlgorithm<Strategy>::advance() { |
// handle remembered node that needed a newline after the text node's newline |
if (m_needsAnotherNewline) { |
// Emit the extra newline, and position it *inside* m_node, after m_node's |
- // contents, in case it's a block, in the same way that we position the first |
- // newline. The range for the emitted newline should start where the line |
- // break begins. |
+ // contents, in case it's a block, in the same way that we position the |
+ // first newline. The range for the emitted newline should start where the |
+ // line break begins. |
// FIXME: It would be cleaner if we emitted two newlines during the last |
// iteration, instead of using m_needsAnotherNewline. |
Node* lastChild = Strategy::lastChild(*m_node); |
@@ -308,7 +311,8 @@ void TextIteratorAlgorithm<Strategy>::advance() { |
LayoutObject* layoutObject = m_node->layoutObject(); |
if (!layoutObject) { |
if (m_node->isShadowRoot()) { |
- // A shadow root doesn't have a layoutObject, but we want to visit children anyway. |
+ // A shadow root doesn't have a layoutObject, but we want to visit |
+ // children anyway. |
m_iterationProgress = m_iterationProgress < HandledNode |
? HandledNode |
: m_iterationProgress; |
@@ -388,10 +392,12 @@ void TextIteratorAlgorithm<Strategy>::advance() { |
: nullptr; |
m_offset = 0; |
if (!next) { |
- // 2. If we've already iterated children or they are not available, go to the next sibling node. |
+ // 2. If we've already iterated children or they are not available, go to |
+ // the next sibling node. |
next = Strategy::nextSibling(*m_node); |
if (!next) { |
- // 3. If we are at the last child, go up the node tree until we find a next sibling. |
+ // 3. If we are at the last child, go up the node tree until we find a |
+ // next sibling. |
ContainerNode* parentNode = Strategy::parent(*m_node); |
while (!next && parentNode) { |
if (m_node == m_endNode || |
@@ -411,7 +417,8 @@ void TextIteratorAlgorithm<Strategy>::advance() { |
} |
if (!next && !parentNode && m_shadowDepth > 0) { |
- // 4. Reached the top of a shadow root. If it's created by author, then try to visit the next |
+ // 4. Reached the top of a shadow root. If it's created by author, |
+ // then try to visit the next |
// sibling shadow root, if any. |
if (!m_node->isShadowRoot()) { |
NOTREACHED(); |
@@ -427,18 +434,22 @@ void TextIteratorAlgorithm<Strategy>::advance() { |
m_fullyClippedStack.pop(); |
m_node = nextShadowRoot; |
m_iterationProgress = HandledNone; |
- // m_shadowDepth is unchanged since we exit from a shadow root and enter another. |
+ // m_shadowDepth is unchanged since we exit from a shadow root and |
+ // enter another. |
m_fullyClippedStack.pushFullyClippedState(m_node); |
} else { |
- // We are the last shadow root; exit from here and go back to where we were. |
+ // We are the last shadow root; exit from here and go back to |
+ // where we were. |
m_node = &shadowRoot->host(); |
m_iterationProgress = HandledOpenShadowRoots; |
--m_shadowDepth; |
m_fullyClippedStack.pop(); |
} |
} else { |
- // If we are in a closed or user-agent shadow root, then go back to the host. |
- // TODO(kochi): Make sure we treat closed shadow as user agent shadow here. |
+ // If we are in a closed or user-agent shadow root, then go back to |
+ // the host. |
+ // TODO(kochi): Make sure we treat closed shadow as user agent |
+ // shadow here. |
DCHECK(shadowRoot->type() == ShadowRootType::Closed || |
shadowRoot->type() == ShadowRootType::UserAgent); |
m_node = &shadowRoot->host(); |
@@ -595,7 +606,8 @@ size_t TextIteratorAlgorithm<Strategy>::restoreCollapsedTrailingSpace( |
text[subrunEnd - 1] == ' ') |
return subrunEnd; |
- // If there is the leading space in the next line, we don't need to restore the trailing space. |
+ // If there is the leading space in the next line, we don't need to restore |
+ // the trailing space. |
// Example: <div style="width: 2em;"><b><i>foo </i></b> bar</div> |
InlineBox* firstBoxOfNextLine = m_textBox->root().nextRootBox()->firstChild(); |
if (!firstBoxOfNextLine) |
@@ -698,7 +710,8 @@ void TextIteratorAlgorithm<Strategy>::handleTextBox() { |
if (runStart < runEnd) { |
// Handle either a single newline character (which becomes a space), |
// or a run of characters that does not include a newline. |
- // This effectively translates newlines to spaces without copying the text. |
+ // This effectively translates newlines to spaces without copying the |
+ // text. |
if (str[runStart] == '\n') { |
// We need to preserve new lines in case of PRE_LINE. |
// See bug crbug.com/317365. |
@@ -720,7 +733,8 @@ void TextIteratorAlgorithm<Strategy>::handleTextBox() { |
} |
// If we are doing a subrun that doesn't go to the end of the text box, |
- // come back again to finish handling this text box; don't advance to the next one. |
+ // come back again to finish handling this text box; don't advance to |
+ // the next one. |
if (static_cast<unsigned>(m_textState.positionEndOffset()) < textBoxEnd) |
return; |
@@ -965,7 +979,8 @@ static bool shouldEmitExtraNewlineForNode(Node* node) { |
return false; |
} |
-// Whether or not we should emit a character as we enter m_node (if it's a container) or as we hit it (if it's atomic). |
+// Whether or not we should emit a character as we enter m_node (if it's a |
+// container) or as we hit it (if it's atomic). |
template <typename Strategy> |
bool TextIteratorAlgorithm<Strategy>::shouldRepresentNodeOffsetZero() { |
if (emitsCharactersBetweenAllVisiblePositions() && |
@@ -981,13 +996,15 @@ bool TextIteratorAlgorithm<Strategy>::shouldRepresentNodeOffsetZero() { |
if (m_textState.hasEmitted()) |
return true; |
- // We've not emitted anything yet. Generally, there is no need for any positioning then. |
- // The only exception is when the element is visually not in the same line as |
- // the start of the range (e.g. the range starts at the end of the previous paragraph). |
- // NOTE: Creating VisiblePositions and comparing them is relatively expensive, so we |
- // make quicker checks to possibly avoid that. Another check that we could make is |
- // is whether the inline vs block flow changed since the previous visible element. |
- // I think we're already in a special enough case that that won't be needed, tho. |
+ // We've not emitted anything yet. Generally, there is no need for any |
+ // positioning then. The only exception is when the element is visually not in |
+ // the same line as the start of the range (e.g. the range starts at the end |
+ // of the previous paragraph). |
+ // NOTE: Creating VisiblePositions and comparing them is relatively expensive, |
+ // so we make quicker checks to possibly avoid that. Another check that we |
+ // could make is is whether the inline vs block flow changed since the |
+ // previous visible element. I think we're already in a special enough case |
+ // that that won't be needed, tho. |
// No character needed if this is the first node in the range. |
if (m_node == m_startContainer) |
@@ -998,18 +1015,21 @@ bool TextIteratorAlgorithm<Strategy>::shouldRepresentNodeOffsetZero() { |
if (!Strategy::isDescendantOf(*m_node, *m_startContainer)) |
return true; |
- // If we started as m_startContainer offset 0 and the current node is a descendant of |
- // the start container, we already had enough context to correctly decide whether to |
- // emit after a preceding block. We chose not to emit (m_hasEmitted is false), |
- // so don't second guess that now. |
- // NOTE: Is this really correct when m_node is not a leftmost descendant? Probably |
- // immaterial since we likely would have already emitted something by now. |
+ // If we started as m_startContainer offset 0 and the current node is a |
+ // descendant of the start container, we already had enough context to |
+ // correctly decide whether to emit after a preceding block. We chose not to |
+ // emit (m_hasEmitted is false), so don't second guess that now. |
+ // NOTE: Is this really correct when m_node is not a leftmost descendant? |
+ // Probably immaterial since we likely would have already emitted something by |
+ // now. |
if (!m_startOffset) |
return false; |
- // If this node is unrendered or invisible the VisiblePosition checks below won't have much meaning. |
- // Additionally, if the range we are iterating over contains huge sections of unrendered content, |
- // we would create VisiblePositions on every call to this function without this check. |
+ // If this node is unrendered or invisible the VisiblePosition checks below |
+ // won't have much meaning. |
+ // Additionally, if the range we are iterating over contains huge sections of |
+ // unrendered content, we would create VisiblePositions on every call to this |
+ // function without this check. |
if (!m_node->layoutObject() || |
m_node->layoutObject()->style()->visibility() != EVisibility::Visible || |
(m_node->layoutObject()->isLayoutBlockFlow() && |
@@ -1017,10 +1037,12 @@ bool TextIteratorAlgorithm<Strategy>::shouldRepresentNodeOffsetZero() { |
!isHTMLBodyElement(*m_node))) |
return false; |
- // The startPos.isNotNull() check is needed because the start could be before the body, |
- // and in that case we'll get null. We don't want to put in newlines at the start in that case. |
- // The currPos.isNotNull() check is needed because positions in non-HTML content |
- // (like SVG) do not have visible positions, and we don't want to emit for them either. |
+ // The startPos.isNotNull() check is needed because the start could be before |
+ // the body, and in that case we'll get null. We don't want to put in newlines |
+ // at the start in that case. |
+ // The currPos.isNotNull() check is needed because positions in non-HTML |
+ // content (like SVG) do not have visible positions, and we don't want to emit |
+ // for them either. |
VisiblePosition startPos = |
createVisiblePosition(Position(m_startContainer, m_startOffset)); |
VisiblePosition currPos = VisiblePosition::beforeNode(m_node); |
@@ -1040,10 +1062,11 @@ template <typename Strategy> |
void TextIteratorAlgorithm<Strategy>::representNodeOffsetZero() { |
// Emit a character to show the positioning of m_node. |
- // When we haven't been emitting any characters, shouldRepresentNodeOffsetZero() can |
- // create VisiblePositions, which is expensive. So, we perform the inexpensive checks |
- // on m_node to see if it necessitates emitting a character first and will early return |
- // before encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
+ // When we haven't been emitting any characters, |
+ // shouldRepresentNodeOffsetZero() can create VisiblePositions, which is |
+ // expensive. So, we perform the inexpensive checks on m_node to see if it |
+ // necessitates emitting a character first and will early return before |
+ // encountering shouldRepresentNodeOffsetZero()s worse case behavior. |
if (shouldEmitTabBeforeNode(m_node)) { |
if (shouldRepresentNodeOffsetZero()) |
spliceBuffer('\t', Strategy::parent(*m_node), m_node, 0, 0); |
@@ -1071,10 +1094,11 @@ bool TextIteratorAlgorithm<Strategy>::handleNonTextNode() { |
template <typename Strategy> |
void TextIteratorAlgorithm<Strategy>::exitNode() { |
- // prevent emitting a newline when exiting a collapsed block at beginning of the range |
- // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed block... it could |
- // have been an hr (e.g.). Also, a collapsed block could have height (e.g. a table) and |
- // therefore look like a blank line. |
+ // prevent emitting a newline when exiting a collapsed block at beginning of |
+ // the range |
+ // FIXME: !m_hasEmitted does not necessarily mean there was a collapsed |
+ // block... it could have been an hr (e.g.). Also, a collapsed block could |
+ // have height (e.g. a table) and therefore look like a blank line. |
if (!m_textState.hasEmitted()) |
return; |
@@ -1083,10 +1107,11 @@ void TextIteratorAlgorithm<Strategy>::exitNode() { |
// emitted character is positioned visually. |
Node* lastChild = Strategy::lastChild(*m_node); |
Node* baseNode = lastChild ? lastChild : m_node.get(); |
- // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't change that without making |
- // the logic in _web_attributedStringFromRange match. We'll get that for free when we switch to use |
- // TextIterator in _web_attributedStringFromRange. |
- // See <rdar://problem/5428427> for an example of how this mismatch will cause problems. |
+ // FIXME: This shouldn't require the m_lastTextNode to be true, but we can't |
+ // change that without making the logic in _web_attributedStringFromRange |
+ // match. We'll get that for free when we switch to use TextIterator in |
+ // _web_attributedStringFromRange. See <rdar://problem/5428427> for an example |
+ // of how this mismatch will cause problems. |
if (m_lastTextNode && shouldEmitNewlineAfterNode(*m_node)) { |
// use extra newline to represent margin bottom, as needed |
bool addNewline = shouldEmitExtraNewlineForNode(m_node); |
@@ -1300,7 +1325,8 @@ static String createPlainText(const EphemeralRangeTemplate<Strategy>& range, |
if (it.atEnd()) |
return emptyString(); |
- // The initial buffer size can be critical for performance: https://bugs.webkit.org/show_bug.cgi?id=81192 |
+ // The initial buffer size can be critical for performance: |
+ // https://bugs.webkit.org/show_bug.cgi?id=81192 |
static const unsigned initialCapacity = 1 << 15; |
StringBuilder builder; |