diff options
author | Ben Murdoch <benm@google.com> | 2010-08-11 14:44:44 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-08-12 19:15:41 +0100 |
commit | dd8bb3de4f353a81954234999f1fea748aee2ea9 (patch) | |
tree | 729b52bf09294f0d6c67cd5ea80aee1b727b7bd8 /WebCore/editing/TextIterator.cpp | |
parent | f3d41ba51d86bf719c7a65ab5297aea3c17e2d98 (diff) | |
download | external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.zip external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.gz external_webkit-dd8bb3de4f353a81954234999f1fea748aee2ea9.tar.bz2 |
Merge WebKit at r65072 : Initial merge by git.
Change-Id: Ibcf418498376b2660aacb7f8d46ea7085ef91585
Diffstat (limited to 'WebCore/editing/TextIterator.cpp')
-rw-r--r-- | WebCore/editing/TextIterator.cpp | 155 |
1 files changed, 134 insertions, 21 deletions
diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp index f3bd9df..9589bff 100644 --- a/WebCore/editing/TextIterator.cpp +++ b/WebCore/editing/TextIterator.cpp @@ -37,6 +37,7 @@ #include "RenderTableCell.h" #include "RenderTableRow.h" #include "RenderTextControl.h" +#include "RenderTextFragment.h" #include "VisiblePosition.h" #include "visible_units.h" @@ -253,10 +254,13 @@ TextIterator::TextIterator() , m_positionNode(0) , m_textCharacters(0) , m_textLength(0) + , m_remainingTextBox(0) + , m_firstLetterText(0) , m_lastCharacter(0) , m_emitsCharactersBetweenAllVisiblePositions(false) , m_entersTextControls(false) , m_emitsTextWithoutTranscoding(false) + , m_handledFirstLetter(false) { } @@ -268,10 +272,16 @@ TextIterator::TextIterator(const Range* r, TextIteratorBehavior behavior) , m_positionNode(0) , m_textCharacters(0) , m_textLength(0) + , m_remainingTextBox(0) + , m_firstLetterText(0) , m_emitsCharactersBetweenAllVisiblePositions(behavior & TextIteratorEmitsCharactersBetweenAllVisiblePositions) , m_entersTextControls(behavior & TextIteratorEntersTextControls) , m_emitsTextWithoutTranscoding(behavior & TextIteratorEmitsTextsWithoutTranscoding) + , m_handledFirstLetter(false) { + // FIXME: should support TextIteratorEndsAtEditingBoundary http://webkit.org/b/43609 + ASSERT(behavior != TextIteratorEndsAtEditingBoundary); + if (!r) return; @@ -344,6 +354,12 @@ void TextIterator::advance() return; } + if (!m_textBox && m_remainingTextBox) { + m_textBox = m_remainingTextBox; + m_remainingTextBox = 0; + m_firstLetterText = 0; + m_offset = 0; + } // handle remembered text box if (m_textBox) { handleTextBox(); @@ -417,6 +433,8 @@ void TextIterator::advance() pushFullyClippedState(m_fullyClippedStack, m_node); m_handledNode = false; m_handledChildren = false; + m_handledFirstLetter = false; + m_firstLetterText = 0; // how would this ever be? if (m_positionNode) @@ -435,8 +453,6 @@ bool TextIterator::handleTextNode() return false; RenderText* renderer = toRenderText(m_node->renderer()); - if (renderer->style()->visibility() != VISIBLE) - return false; m_lastTextNode = m_node; String str = renderer->text(); @@ -444,10 +460,22 @@ bool TextIterator::handleTextNode() // handle pre-formatted text if (!renderer->style()->collapseWhiteSpace()) { int runStart = m_offset; - if (m_lastTextNodeEndedWithCollapsedSpace) { + if (m_lastTextNodeEndedWithCollapsedSpace && hasVisibleTextNode(renderer)) { emitCharacter(' ', m_node, 0, runStart, runStart); return false; } + if (!m_handledFirstLetter && renderer->isTextFragment()) { + handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); + if (m_firstLetterText) { + String firstLetter = m_firstLetterText->text(); + emitText(m_node, m_firstLetterText, m_offset, firstLetter.length()); + m_firstLetterText = 0; + m_textBox = 0; + return false; + } + } + if (renderer->style()->visibility() != VISIBLE) + return false; int strLength = str.length(); int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; int runEnd = min(strLength, end); @@ -460,6 +488,15 @@ bool TextIterator::handleTextNode() } if (!renderer->firstTextBox() && str.length() > 0) { + if (!m_handledFirstLetter && renderer->isTextFragment()) { + handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); + if (m_firstLetterText) { + handleTextBox(); + return false; + } + } + if (renderer->style()->visibility() != VISIBLE) + return false; m_lastTextNodeEndedWithCollapsedSpace = true; // entire block is collapsed space return true; } @@ -475,13 +512,19 @@ bool TextIterator::handleTextNode() } m_textBox = renderer->containsReversedText() ? (m_sortedTextBoxes.isEmpty() ? 0 : m_sortedTextBoxes[0]) : renderer->firstTextBox(); + if (!m_handledFirstLetter && renderer->isTextFragment() && !m_offset) + handleTextNodeFirstLetter(static_cast<RenderTextFragment*>(renderer)); handleTextBox(); return true; } void TextIterator::handleTextBox() { - RenderText* renderer = toRenderText(m_node->renderer()); + RenderText* renderer = m_firstLetterText ? m_firstLetterText : toRenderText(m_node->renderer()); + if (renderer->style()->visibility() != VISIBLE) { + m_textBox = 0; + return; + } String str = renderer->text(); int start = m_offset; int end = (m_node == m_endContainer) ? m_endOffset : INT_MAX; @@ -527,7 +570,7 @@ void TextIterator::handleTextBox() subrunEnd = runEnd; m_offset = subrunEnd; - emitText(m_node, runStart, subrunEnd); + emitText(m_node, renderer, runStart, subrunEnd); } // If we are doing a subrun that doesn't go to the end of the text box, @@ -549,6 +592,33 @@ void TextIterator::handleTextBox() if (renderer->containsReversedText()) ++m_sortedTextBoxesPosition; } + if (!m_textBox && m_remainingTextBox) { + m_textBox = m_remainingTextBox; + m_remainingTextBox = 0; + m_firstLetterText = 0; + m_offset = 0; + handleTextBox(); + } +} + +void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer) +{ + if (renderer->firstLetter()) { + RenderObject* r = renderer->firstLetter(); + if (r->style()->visibility() != VISIBLE) + return; + for (RenderObject *currChild = r->firstChild(); currChild; currChild->nextSibling()) { + if (currChild->isText()) { + RenderText* firstLetter = toRenderText(currChild); + m_handledFirstLetter = true; + m_remainingTextBox = m_textBox; + m_textBox = firstLetter->firstTextBox(); + m_firstLetterText = firstLetter; + return; + } + } + } + m_handledFirstLetter = true; } bool TextIterator::handleReplacedElement() @@ -597,6 +667,18 @@ bool TextIterator::handleReplacedElement() return true; } +bool TextIterator::hasVisibleTextNode(RenderText* renderer) +{ + if (renderer->style()->visibility() == VISIBLE) + return true; + if (renderer->isTextFragment()) { + RenderTextFragment* fragment = static_cast<RenderTextFragment*>(renderer); + if (fragment->firstLetter() && fragment->firstLetter()->style()->visibility() == VISIBLE) + return true; + } + return false; +} + static bool shouldEmitTabBeforeNode(Node* node) { RenderObject* r = node->renderer(); @@ -888,9 +970,9 @@ void TextIterator::emitCharacter(UChar c, Node* textNode, Node* offsetBaseNode, m_lastCharacter = c; } -void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset) +void TextIterator::emitText(Node* textNode, RenderObject* renderObject, int textStartOffset, int textEndOffset) { - RenderText* renderer = toRenderText(m_node->renderer()); + RenderText* renderer = toRenderText(renderObject); m_text = m_emitsTextWithoutTranscoding ? renderer->textWithoutTranscoding() : renderer->text(); ASSERT(m_text.characters()); @@ -906,6 +988,11 @@ void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffs m_hasEmitted = true; } +void TextIterator::emitText(Node* textNode, int textStartOffset, int textEndOffset) +{ + emitText(textNode, m_node->renderer(), textStartOffset, textEndOffset); +} + PassRefPtr<Range> TextIterator::range() const { // use the current run information, if we have it @@ -944,13 +1031,19 @@ Node* TextIterator::node() const // -------- SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator() - : m_positionNode(0) + : m_behavior(TextIteratorDefaultBehavior) + , m_node(0) + , m_positionNode(0) { } -SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r) - : m_positionNode(0) +SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior) + : m_behavior(behavior) + , m_node(0) + , m_positionNode(0) { + ASSERT(m_behavior == TextIteratorDefaultBehavior || m_behavior == TextIteratorEndsAtEditingBoundary); + if (!r) return; @@ -974,7 +1067,7 @@ SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r) } } - m_node = endNode; + setCurrentNode(endNode); setUpFullyClippedStack(m_fullyClippedStack, m_node); m_offset = endOffset; m_handledNode = false; @@ -1038,12 +1131,9 @@ void SimplifiedBackwardsTextIterator::advance() } } // Exit all other containers. - next = m_node->previousSibling(); - while (!next) { - Node* parentNode = parentCrossingShadowBoundaries(m_node); - if (!parentNode) + while (!m_node->previousSibling()) { + if (!setCurrentNode(parentCrossingShadowBoundaries(m_node))) break; - m_node = parentNode; m_fullyClippedStack.pop(); exitNode(); if (m_positionNode) { @@ -1051,14 +1141,17 @@ void SimplifiedBackwardsTextIterator::advance() m_handledChildren = true; return; } - next = m_node->previousSibling(); } + + next = m_node->previousSibling(); m_fullyClippedStack.pop(); } - m_node = next; - if (m_node) + if (m_node && setCurrentNode(next)) pushFullyClippedState(m_fullyClippedStack, m_node); + else + clearCurrentNode(); + // For the purpose of word boundary detection, // we should iterate all visible text and trailing (collapsed) whitespaces. m_offset = m_node ? maxOffsetIncludingCollapsedSpaces(m_node) : 0; @@ -1137,6 +1230,26 @@ void SimplifiedBackwardsTextIterator::emitCharacter(UChar c, Node* node, int sta m_lastCharacter = c; } +bool SimplifiedBackwardsTextIterator::crossesEditingBoundary(Node* node) const +{ + return m_node && m_node->isContentEditable() != node->isContentEditable(); +} + +bool SimplifiedBackwardsTextIterator::setCurrentNode(Node* node) +{ + if (!node) + return false; + if (m_behavior == TextIteratorEndsAtEditingBoundary && crossesEditingBoundary(node)) + return false; + m_node = node; + return true; +} + +void SimplifiedBackwardsTextIterator::clearCurrentNode() +{ + m_node = 0; +} + PassRefPtr<Range> SimplifiedBackwardsTextIterator::range() const { if (m_positionNode) @@ -1262,11 +1375,11 @@ BackwardsCharacterIterator::BackwardsCharacterIterator() { } -BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range) +BackwardsCharacterIterator::BackwardsCharacterIterator(const Range* range, TextIteratorBehavior behavior) : m_offset(0) , m_runOffset(0) , m_atBreak(true) - , m_textIterator(range) + , m_textIterator(range, behavior) { while (!atEnd() && !m_textIterator.length()) m_textIterator.advance(); |