Title: [93499] branches/chromium/835

Diff

Copied: branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash-expected.txt (from rev 93347, trunk/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash-expected.txt) (0 => 93499)


--- branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash-expected.txt	                        (rev 0)
+++ branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash-expected.txt	2011-08-22 09:07:56 UTC (rev 93499)
@@ -0,0 +1 @@
+PASS if WebKit did not hit assertions

Copied: branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash.html (from rev 93347, trunk/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash.html) (0 => 93499)


--- branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash.html	                        (rev 0)
+++ branches/chromium/835/LayoutTests/editing/text-iterator/backward-textiterator-first-letter-crash.html	2011-08-22 09:07:56 UTC (rev 93499)
@@ -0,0 +1,15 @@
+<style>
+div:first-letter { margin-top: 0em; }
+</style>
+<script>
+if (window.layoutTestController) {
+    layoutTestController.dumpAsText();
+    layoutTestController.waitUntilDone();
+}
+function done() {
+    document.body.innerHTML = 'PASS if WebKit did not hit assertions';
+    if (window.layoutTestController)
+        layoutTestController.notifyDone();
+}
+</script>
+<body _onload_="setTimeout(done, 100);"><div>AB<select autofocus contenteditable>

Modified: branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary-expected.txt (93498 => 93499)


--- branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary-expected.txt	2011-08-22 09:04:29 UTC (rev 93498)
+++ branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary-expected.txt	2011-08-22 09:07:56 UTC (rev 93499)
@@ -2,9 +2,9 @@
 
  hello world'
 white-space: normal;
-FAIL: moving forward by word put caret at offset 4 but expected 6
-PASS: moving backward by word put caret at offset 0
+FAIL: moving forward by word from offset 4 put caret at offset 10 but expected 6
+PASS: moving backward by word from offset 4 put caret at offset 1
 white-space: pre;
-FAIL: moving forward by word put caret at offset 4 but expected 6
-PASS: moving backward by word put caret at offset 0
+FAIL: moving forward by word from offset 4 put caret at offset 10 but expected 6
+PASS: moving backward by word from offset 4 put caret at offset 1
 

Modified: branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary.html (93498 => 93499)


--- branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary.html	2011-08-22 09:04:29 UTC (rev 93498)
+++ branches/chromium/835/LayoutTests/editing/text-iterator/first-letter-word-boundary.html	2011-08-22 09:07:56 UTC (rev 93499)
@@ -20,7 +20,8 @@
     layoutTestController.dumpAsText();
 
 function runTest(actor, expectedOffset) {
-    var action = "" + ' put caret at offset ';
+    window.getSelection().setPosition(test.firstChild, 4);
+    var action = "" + ' from offset ' + 4 + ' put caret at offset ';
     var startOffset = window.getSelection().getRangeAt(0).startOffset;
     action += startOffset;
     if (startOffset == expectedOffset)
@@ -31,16 +32,15 @@
 
 var test = document.getElementById('test');
 var console = document.getElementById('console');
-window.getSelection().setPosition(test, 0);
 
 console.innerHTML += 'white-space: normal;\n';
 runTest(function () {window.getSelection().modify('move', 'forward', 'word'); return 'moving forward by word';}, 6);
-runTest(function () {window.getSelection().modify('move', 'backward', 'word'); return 'moving backward by word';}, 0);
+runTest(function () {window.getSelection().modify('move', 'backward', 'word'); return 'moving backward by word';}, 1);
 
 console.innerHTML += 'white-space: pre;\n';
 test.style.whiteSpace = 'pre';
 runTest(function () {window.getSelection().modify('move', 'forward', 'word'); return 'moving forward by word';}, 6);
-runTest(function () {window.getSelection().modify('move', 'backward', 'word'); return 'moving backward by word';}, 0);
+runTest(function () {window.getSelection().modify('move', 'backward', 'word'); return 'moving backward by word';}, 1);
 
 </script>
 </body>

Modified: branches/chromium/835/Source/WebCore/editing/TextIterator.cpp (93498 => 93499)


--- branches/chromium/835/Source/WebCore/editing/TextIterator.cpp	2011-08-22 09:04:29 UTC (rev 93498)
+++ branches/chromium/835/Source/WebCore/editing/TextIterator.cpp	2011-08-22 09:07:56 UTC (rev 93499)
@@ -603,21 +603,30 @@
     }
 }
 
+static inline RenderText* firstRenderTextInFirstLetter(RenderObject* firstLetter)
+{
+    if (!firstLetter)
+        return 0;
+
+    // FIXME: Should this check descendent objects?
+    for (RenderObject* current = firstLetter->firstChild(); current; current = current->nextSibling()) {
+        if (current->isText())
+            return toRenderText(current);
+    }
+    return 0;
+}
+
 void TextIterator::handleTextNodeFirstLetter(RenderTextFragment* renderer)
 {
     if (renderer->firstLetter()) {
         RenderObject* r = renderer->firstLetter();
         if (r->style()->visibility() != VISIBLE && !m_ignoresStyleVisibility)
             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;
-            }
+        if (RenderText* firstLetter = firstRenderTextInFirstLetter(r)) {
+            m_handledFirstLetter = true;
+            m_remainingTextBox = m_textBox;
+            m_textBox = firstLetter->firstTextBox();
+            m_firstLetterText = firstLetter;
         }
     }
     m_handledFirstLetter = true;
@@ -1043,14 +1052,46 @@
 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator()
     : m_behavior(TextIteratorDefaultBehavior)
     , m_node(0)
+    , m_offset(0)
+    , m_handledNode(false)
+    , m_handledChildren(false)
+    , m_startNode(0)
+    , m_startOffset(0)
+    , m_endNode(0)
+    , m_endOffset(0)
     , m_positionNode(0)
+    , m_positionStartOffset(0)
+    , m_positionEndOffset(0)
+    , m_textCharacters(0)
+    , m_textLength(0)
+    , m_lastTextNode(0)
+    , m_lastCharacter(0)
+    , m_singleCharacterBuffer(0)
+    , m_havePassedStartNode(false)
+    , m_shouldHandleFirstLetter(false)
 {
 }
 
 SimplifiedBackwardsTextIterator::SimplifiedBackwardsTextIterator(const Range* r, TextIteratorBehavior behavior)
     : m_behavior(behavior)
     , m_node(0)
+    , m_offset(0)
+    , m_handledNode(false)
+    , m_handledChildren(false)
+    , m_startNode(0)
+    , m_startOffset(0)
+    , m_endNode(0)
+    , m_endOffset(0)
     , m_positionNode(0)
+    , m_positionStartOffset(0)
+    , m_positionEndOffset(0)
+    , m_textCharacters(0)
+    , m_textLength(0)
+    , m_lastTextNode(0)
+    , m_lastCharacter(0)
+    , m_singleCharacterBuffer(0)
+    , m_havePassedStartNode(false)
+    , m_shouldHandleFirstLetter(false)
 {
     ASSERT(m_behavior == TextIteratorDefaultBehavior);
 
@@ -1178,25 +1219,64 @@
 {
     m_lastTextNode = m_node;
 
-    RenderText* renderer = toRenderText(m_node->renderer());
-    String str = renderer->text();
+    int startOffset;
+    int offsetInNode;
+    RenderText* renderer = handleFirstLetter(startOffset, offsetInNode);
+    if (!renderer)
+        return true;
 
-    if (!renderer->firstTextBox() && str.length() > 0)
+    String text = renderer->text();
+    if (!renderer->firstTextBox() && text.length() > 0)
         return true;
 
     m_positionEndOffset = m_offset;
-
-    m_offset = (m_node == m_startNode) ? m_startOffset : 0;
+    m_offset = startOffset + offsetInNode;
     m_positionNode = m_node;
     m_positionStartOffset = m_offset;
+
+    ASSERT(0 <= m_positionStartOffset - offsetInNode && m_positionStartOffset - offsetInNode <= static_cast<int>(text.length()));
+    ASSERT(1 <= m_positionEndOffset - offsetInNode && m_positionEndOffset - offsetInNode <= static_cast<int>(text.length()));
+    ASSERT(m_positionStartOffset <= m_positionEndOffset);
+
     m_textLength = m_positionEndOffset - m_positionStartOffset;
-    m_textCharacters = str.characters() + m_positionStartOffset;
+    m_textCharacters = text.characters() + (m_positionStartOffset - offsetInNode);
+    ASSERT(m_textCharacters >= text.characters());
+    ASSERT(m_textCharacters + m_textLength <= text.characters() + static_cast<int>(text.length()));
 
-    m_lastCharacter = str[m_positionEndOffset - 1];
+    m_lastCharacter = text[m_positionEndOffset - 1];
 
-    return true;
+    return !m_shouldHandleFirstLetter;
 }
 
+RenderText* SimplifiedBackwardsTextIterator::handleFirstLetter(int& startOffset, int& offsetInNode)
+{
+    RenderText* renderer = toRenderText(m_node->renderer());
+    startOffset = (m_node == m_startNode) ? m_startOffset : 0;
+
+    if (!renderer->isTextFragment()) {
+        offsetInNode = 0;
+        return renderer;
+    }
+
+    RenderTextFragment* fragment = toRenderTextFragment(renderer);
+    int offsetAfterFirstLetter = fragment->start();
+    if (startOffset >= offsetAfterFirstLetter) {
+        ASSERT(!m_shouldHandleFirstLetter);
+        offsetInNode = offsetAfterFirstLetter;
+        return renderer;
+    }
+
+    if (!m_shouldHandleFirstLetter && offsetAfterFirstLetter < m_offset) {
+        m_shouldHandleFirstLetter = true;
+        offsetInNode = offsetAfterFirstLetter;
+        return renderer;
+    }
+
+    m_shouldHandleFirstLetter = false;
+    offsetInNode = 0;
+    return firstRenderTextInFirstLetter(fragment->firstLetter());
+}
+
 bool SimplifiedBackwardsTextIterator::handleReplacedElement()
 {
     unsigned index = m_node->nodeIndex();

Modified: branches/chromium/835/Source/WebCore/editing/TextIterator.h (93498 => 93499)


--- branches/chromium/835/Source/WebCore/editing/TextIterator.h	2011-08-22 09:04:29 UTC (rev 93498)
+++ branches/chromium/835/Source/WebCore/editing/TextIterator.h	2011-08-22 09:07:56 UTC (rev 93499)
@@ -203,6 +203,7 @@
 private:
     void exitNode();
     bool handleTextNode();
+    RenderText* handleFirstLetter(int& startOffset, int& offsetInNode);
     bool handleReplacedElement();
     bool handleNonTextNode();
     void emitCharacter(UChar, Node*, int startOffset, int endOffset);
@@ -240,6 +241,9 @@
 
     // Whether m_node has advanced beyond the iteration range (i.e. m_startNode).
     bool m_havePassedStartNode;
+
+    // Should handle first-letter renderer in the next call to handleTextNode.
+    bool m_shouldHandleFirstLetter;
 };
 
 // Builds on the text iterator, adding a character position so we can walk one
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to