Title: [111624] trunk
Revision
111624
Author
[email protected]
Date
2012-03-21 17:20:43 -0700 (Wed, 21 Mar 2012)

Log Message

visual word movement: using cache to decrease the number of collectLeafBoxesInLogicalOrder on RootInlineBox
https://bugs.webkit.org/show_bug.cgi?id=81408

Reviewed by Ryosuke Niwa.

Source/WebCore:

Cache logically ordered leaf boxes under a particular root box.
Also, move 'Vector<UChar, 1024> string' declared in visualWordPosition() to outside of loop (it is always
clear-ed before use).

* editing/visible_units.cpp:
(CachedLogicallyOrderedLeafBoxes): Add class to cache logically ordered leaf boxes under a particular root box.
(WebCore::CachedLogicallyOrderedLeafBoxes::size):
(WebCore::CachedLogicallyOrderedLeafBoxes::firstBox):
(WebCore):
(WebCore::CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes):
(WebCore::CachedLogicallyOrderedLeafBoxes::previousTextBox):
(WebCore::CachedLogicallyOrderedLeafBoxes::nextTextBox):
(WebCore::CachedLogicallyOrderedLeafBoxes::collectBoxes):
(WebCore::CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves):
(WebCore::logicallyPreviousBox): Pass CachedLogicallyOrderedLeafBoxes object around.
(WebCore::logicallyNextBox):
(WebCore::wordBreakIteratorForMinOffsetBoundary):
(WebCore::wordBreakIteratorForMaxOffsetBoundary):
(WebCore::visualWordPosition):

LayoutTests:

* editing/selection/move-by-word-visually-single-space-one-element-expected.txt:
* editing/selection/move-by-word-visually-single-space-one-element.html:
  Add a test case that a word is spreading across multiple inline boxes.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (111623 => 111624)


--- trunk/LayoutTests/ChangeLog	2012-03-22 00:20:38 UTC (rev 111623)
+++ trunk/LayoutTests/ChangeLog	2012-03-22 00:20:43 UTC (rev 111624)
@@ -1,3 +1,14 @@
+2012-03-21  Xiaomei Ji  <[email protected]>
+
+        visual word movement: using cache to decrease the number of collectLeafBoxesInLogicalOrder on RootInlineBox
+        https://bugs.webkit.org/show_bug.cgi?id=81408
+
+        Reviewed by Ryosuke Niwa.
+
+        * editing/selection/move-by-word-visually-single-space-one-element-expected.txt:
+        * editing/selection/move-by-word-visually-single-space-one-element.html:
+          Add a test case that a word is spreading across multiple inline boxes.
+
 2012-03-21  Raphael Kubo da Costa  <[email protected]>
 
         [EFL] Unreviewed gardening; skip a few tests which are not really being rendered correctly.

Modified: trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element-expected.txt (111623 => 111624)


--- trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element-expected.txt	2012-03-22 00:20:38 UTC (rev 111623)
+++ trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element-expected.txt	2012-03-22 00:20:43 UTC (rev 111624)
@@ -97,6 +97,11 @@
 " opq rst "[8, 5, 1], "abc def hij "[8, 4, 0]
 Test 19, LTR:
 Move right by one word
+"abc def this"[0, 4, 8], "end opq rst "[4, 8, 11]
+Move left by one word
+"end opq rst "[11, 8, 4], "abc def this"[8, 4, 0]
+Test 20, LTR:
+Move right by one word
 <DIV>[0]
 Move left by one word
 <DIV>[0]

Modified: trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element.html (111623 => 111624)


--- trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element.html	2012-03-22 00:20:38 UTC (rev 111623)
+++ trunk/LayoutTests/editing/selection/move-by-word-visually-single-space-one-element.html	2012-03-22 00:20:43 UTC (rev 111624)
@@ -71,6 +71,8 @@
 <!-- Test with image -- non-inline-text-box -->
 <div id="d_1" dir=ltr class="test_move_by_word" contenteditable title="[d_1, 0, 1][d_1, 4, 1][d_1, 8, 1][d_1, 1, 3][d_1, 5, 3][d_1, 8, 3]|[d_1, 8, 3][d_1, 5, 3][d_1, 1, 3][d_1, 8, 1][d_1, 4, 1][d_1, 0, 1]">abc def hij <img src="" opq rst </div>
 
+<div id="d_2" dir=ltr class="test_move_by_word" contenteditable title="[d_2, 0, 1][d_2, 4, 1][d_2, 8, 1][d_2, 4, 5][d_2, 8, 5][d_2, 11, 5]|[d_2, 11, 5][d_2, 8, 5][d_2, 4, 5][d_2, 8, 1][d_2, 4, 1][d_2, 0, 1]">abc def this<span>is</span><span>one</span><span>word</span>end opq rst </div>
+
 <!-- empty div -->
 <div dir=ltr class="test_move_by_word" title="0|0" contenteditable></div>
 

Modified: trunk/Source/WebCore/ChangeLog (111623 => 111624)


--- trunk/Source/WebCore/ChangeLog	2012-03-22 00:20:38 UTC (rev 111623)
+++ trunk/Source/WebCore/ChangeLog	2012-03-22 00:20:43 UTC (rev 111624)
@@ -1,3 +1,30 @@
+2012-03-21  Xiaomei Ji  <[email protected]>
+
+        visual word movement: using cache to decrease the number of collectLeafBoxesInLogicalOrder on RootInlineBox
+        https://bugs.webkit.org/show_bug.cgi?id=81408
+
+        Reviewed by Ryosuke Niwa.
+
+        Cache logically ordered leaf boxes under a particular root box.
+        Also, move 'Vector<UChar, 1024> string' declared in visualWordPosition() to outside of loop (it is always
+        clear-ed before use).
+
+        * editing/visible_units.cpp:
+        (CachedLogicallyOrderedLeafBoxes): Add class to cache logically ordered leaf boxes under a particular root box.
+        (WebCore::CachedLogicallyOrderedLeafBoxes::size):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::firstBox):
+        (WebCore):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::previousTextBox):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::nextTextBox):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::collectBoxes):
+        (WebCore::CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves):
+        (WebCore::logicallyPreviousBox): Pass CachedLogicallyOrderedLeafBoxes object around.
+        (WebCore::logicallyNextBox):
+        (WebCore::wordBreakIteratorForMinOffsetBoundary):
+        (WebCore::wordBreakIteratorForMaxOffsetBoundary):
+        (WebCore::visualWordPosition):
+
 2012-03-21  Dana Jansens  <[email protected]>
 
         [chromium] Early out in a new prepareToDraw() step if checkerboarding an accelerated animation in order to skip the frame

Modified: trunk/Source/WebCore/editing/visible_units.cpp (111623 => 111624)


--- trunk/Source/WebCore/editing/visible_units.cpp	2012-03-22 00:20:38 UTC (rev 111623)
+++ trunk/Source/WebCore/editing/visible_units.cpp	2012-03-22 00:20:43 UTC (rev 111624)
@@ -165,46 +165,96 @@
     return 0;
 }
 
-static int boxIndexInVector(const InlineTextBox* box, const Vector<InlineBox*>& leafBoxesInLogicalOrder)
+class CachedLogicallyOrderedLeafBoxes {
+public:
+    CachedLogicallyOrderedLeafBoxes();
+
+    const InlineTextBox* previousTextBox(const RootInlineBox*, const InlineTextBox*);
+    const InlineTextBox* nextTextBox(const RootInlineBox*, const InlineTextBox*);
+
+    size_t size() const { return m_leafBoxes.size(); }
+    const InlineBox* firstBox() const { return m_leafBoxes[0]; }
+    
+private:
+    const Vector<InlineBox*>& collectBoxes(const RootInlineBox*);
+    int boxIndexInLeaves(const InlineTextBox*);
+
+    const RootInlineBox* m_rootInlineBox;
+    Vector<InlineBox*> m_leafBoxes;
+};
+
+CachedLogicallyOrderedLeafBoxes::CachedLogicallyOrderedLeafBoxes() : m_rootInlineBox(0) { };
+
+const InlineTextBox* CachedLogicallyOrderedLeafBoxes::previousTextBox(const RootInlineBox* root, const InlineTextBox* box)
 {
-    for (size_t i = 0; i < leafBoxesInLogicalOrder.size(); ++i) {
-        if (box == leafBoxesInLogicalOrder[i])
-            return i;
+    if (!root)
+        return 0;
+
+    collectBoxes(root);
+
+    // If box is null, root is box's previous RootInlineBox, and previousBox is the last logical box in root.
+    int boxIndex = m_leafBoxes.size() - 1;
+    if (box)
+        boxIndex = boxIndexInLeaves(box) - 1;
+
+    for (int i = boxIndex; i >= 0; --i) {
+        if (m_leafBoxes[i]->isInlineTextBox())
+            return toInlineTextBox(m_leafBoxes[i]);
     }
+
     return 0;
 }
 
-static const InlineTextBox* previousBoxInLine(const RootInlineBox* root, const InlineTextBox* box, Vector<InlineBox*>& leafBoxesInLogicalOrder)
+const InlineTextBox* CachedLogicallyOrderedLeafBoxes::nextTextBox(const RootInlineBox* root, const InlineTextBox* box)
 {
     if (!root)
         return 0;
 
-    leafBoxesInLogicalOrder.clear();
-    root->collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
+    collectBoxes(root);
 
-    // If box is null, root is box's previous RootInlineBox, and previousBox is the last logical box in root.
-    int boxIndex = leafBoxesInLogicalOrder.size() - 1;
+    // If box is null, root is box's next RootInlineBox, and nextBox is the first logical box in root.
+    // Otherwise, root is box's RootInlineBox, and nextBox is the next logical box in the same line.
+    size_t nextBoxIndex = 0;
     if (box)
-        boxIndex = boxIndexInVector(box, leafBoxesInLogicalOrder) - 1;
+        nextBoxIndex = boxIndexInLeaves(box) + 1;
 
-    for (int i = boxIndex; i >= 0; --i) {
-        if (leafBoxesInLogicalOrder[i]->isInlineTextBox())
-            return toInlineTextBox(leafBoxesInLogicalOrder[i]);
+    for (size_t i = nextBoxIndex; i < m_leafBoxes.size(); ++i) {
+        if (m_leafBoxes[i]->isInlineTextBox())
+            return toInlineTextBox(m_leafBoxes[i]);
     }
 
     return 0;
 }
 
-static const InlineTextBox* logicallyPreviousBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox, bool& previousBoxInDifferentBlock)
+const Vector<InlineBox*>& CachedLogicallyOrderedLeafBoxes::collectBoxes(const RootInlineBox* root)
 {
+    if (m_rootInlineBox != root) {
+        m_rootInlineBox = root;
+        m_leafBoxes.clear();
+        root->collectLeafBoxesInLogicalOrder(m_leafBoxes);
+    }
+    return m_leafBoxes;
+}
+
+int CachedLogicallyOrderedLeafBoxes::boxIndexInLeaves(const InlineTextBox* box)
+{
+    for (size_t i = 0; i < m_leafBoxes.size(); ++i) {
+        if (box == m_leafBoxes[i])
+            return i;
+    }
+    return 0;
+}
+
+static const InlineTextBox* logicallyPreviousBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
+    bool& previousBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
+{
     const InlineBox* startBox = textBox;
-    Vector<InlineBox*> leafBoxesInLogicalOrder;
 
-    const InlineTextBox* previousBox = previousBoxInLine(startBox->root(), textBox, leafBoxesInLogicalOrder);
+    const InlineTextBox* previousBox = leafBoxes.previousTextBox(startBox->root(), textBox);
     if (previousBox)
         return previousBox;
 
-    previousBox = previousBoxInLine(startBox->root()->prevRootBox(), 0, leafBoxesInLogicalOrder);
+    previousBox = leafBoxes.previousTextBox(startBox->root()->prevRootBox(), 0);
     if (previousBox)
         return previousBox;
 
@@ -213,51 +263,30 @@
         if (!previousRoot)
             break;
 
-        previousBox = previousBoxInLine(previousRoot, 0, leafBoxesInLogicalOrder);
+        previousBox = leafBoxes.previousTextBox(previousRoot, 0);
         if (previousBox) {
             previousBoxInDifferentBlock = true;
             return previousBox;
         }
 
-        if (!leafBoxesInLogicalOrder.size())
+        if (!leafBoxes.size())
             break;
-        startBox = leafBoxesInLogicalOrder[0];
+        startBox = leafBoxes.firstBox();
     }
     return 0;
 }
 
-static const InlineTextBox* nextBoxInLine(const RootInlineBox* root, const InlineTextBox* box, Vector<InlineBox*>& leafBoxesInLogicalOrder)
-{
-    if (!root)
-        return 0;
 
-    leafBoxesInLogicalOrder.clear();
-    root->collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
-
-    // If box is null, root is box's next RootInlineBox, and nextBox is the first logical box in root.
-    // Otherwise, root is box's RootInlineBox, and nextBox is the next logical box in the same line.
-    size_t nextBoxIndex = 0;
-    if (box)
-        nextBoxIndex = boxIndexInVector(box, leafBoxesInLogicalOrder) + 1;
-
-    for (size_t i = nextBoxIndex; i < leafBoxesInLogicalOrder.size(); ++i) {
-        if (leafBoxesInLogicalOrder[i]->isInlineTextBox())
-            return toInlineTextBox(leafBoxesInLogicalOrder[i]);
-    }
-
-    return 0;
-}
-
-static const InlineTextBox* logicallyNextBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox, bool& nextBoxInDifferentBlock)
+static const InlineTextBox* logicallyNextBox(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
+    bool& nextBoxInDifferentBlock, CachedLogicallyOrderedLeafBoxes& leafBoxes)
 {
     const InlineBox* startBox = textBox;
-    Vector<InlineBox*> leafBoxesInLogicalOrder;
 
-    const InlineTextBox* nextBox = nextBoxInLine(startBox->root(), textBox, leafBoxesInLogicalOrder);
+    const InlineTextBox* nextBox = leafBoxes.nextTextBox(startBox->root(), textBox);
     if (nextBox)
         return nextBox;
 
-    nextBox = nextBoxInLine(startBox->root()->nextRootBox(), 0, leafBoxesInLogicalOrder);
+    nextBox = leafBoxes.nextTextBox(startBox->root()->nextRootBox(), 0);
     if (nextBox)
         return nextBox;
 
@@ -266,26 +295,26 @@
         if (!nextRoot)
             break;
 
-        nextBox = nextBoxInLine(nextRoot, 0, leafBoxesInLogicalOrder);
+        nextBox = leafBoxes.nextTextBox(nextRoot, 0);
         if (nextBox) {
             nextBoxInDifferentBlock = true;
             return nextBox;
         }
 
-        if (!leafBoxesInLogicalOrder.size())
+        if (!leafBoxes.size())
             break;
-        startBox = leafBoxesInLogicalOrder[0];
+        startBox = leafBoxes.firstBox();
     }
     return 0;
 }
 
 static TextBreakIterator* wordBreakIteratorForMinOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
-     int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 1024>& string)
+     int& previousBoxLength, bool& previousBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
 {
     previousBoxInDifferentBlock = false;
 
     // FIXME: Handle the case when we don't have an inline text box.
-    const InlineTextBox* previousBox = logicallyPreviousBox(visiblePosition, textBox, previousBoxInDifferentBlock);
+    const InlineTextBox* previousBox = logicallyPreviousBox(visiblePosition, textBox, previousBoxInDifferentBlock, leafBoxes);
 
     int len = 0;
     string.clear();
@@ -301,12 +330,12 @@
 } 
 
 static TextBreakIterator* wordBreakIteratorForMaxOffsetBoundary(const VisiblePosition& visiblePosition, const InlineTextBox* textBox,
-    bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string)
+    bool& nextBoxInDifferentBlock, Vector<UChar, 1024>& string, CachedLogicallyOrderedLeafBoxes& leafBoxes)
 {
     nextBoxInDifferentBlock = false;
 
     // FIXME: Handle the case when we don't have an inline text box.
-    const InlineTextBox* nextBox = logicallyNextBox(visiblePosition, textBox, nextBoxInDifferentBlock);
+    const InlineTextBox* nextBox = logicallyNextBox(visiblePosition, textBox, nextBoxInDifferentBlock, leafBoxes);
 
     int len = 0;
     string.clear();
@@ -349,6 +378,9 @@
     VisiblePosition current = visiblePosition;
     TextBreakIterator* iter = 0;
 
+    CachedLogicallyOrderedLeafBoxes leafBoxes;
+    Vector<UChar, 1024> string;
+
     while (1) {
         VisiblePosition adjacentCharacterPosition = direction == MoveRight ? current.right(true) : current.left(true); 
         if (adjacentCharacterPosition == current || adjacentCharacterPosition.isNull())
@@ -371,11 +403,10 @@
         bool nextBoxInDifferentBlock = false;
         bool movingIntoNewBox = previouslyVisitedBox != box;
 
-        Vector<UChar, 1024> string;
         if (offsetInBox == box->caretMinOffset())
-            iter = wordBreakIteratorForMinOffsetBoundary(visiblePosition, textBox, previousBoxLength, previousBoxInDifferentBlock, string);
+            iter = wordBreakIteratorForMinOffsetBoundary(visiblePosition, textBox, previousBoxLength, previousBoxInDifferentBlock, string, leafBoxes);
         else if (offsetInBox == box->caretMaxOffset())
-            iter = wordBreakIteratorForMaxOffsetBoundary(visiblePosition, textBox, nextBoxInDifferentBlock, string);
+            iter = wordBreakIteratorForMaxOffsetBoundary(visiblePosition, textBox, nextBoxInDifferentBlock, string, leafBoxes);
         else if (movingIntoNewBox) {
             iter = wordBreakIterator(textBox->textRenderer()->text()->characters() + textBox->start(), textBox->len());
             previouslyVisitedBox = box;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to