Move line dirtying code to RenderTextLineBoxes
authorantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Oct 2013 20:33:29 +0000 (20:33 +0000)
committerantti@apple.com <antti@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 12 Oct 2013 20:33:29 +0000 (20:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=122699

Reviewed by Andreas Kling.

* rendering/RenderTextLineBoxes.cpp:
(WebCore::RenderTextLineBoxes::removeAllFromParent):

    Also moved the removal loop.

(WebCore::RenderTextLineBoxes::dirtyAll):
(WebCore::RenderTextLineBoxes::dirtyRange):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@157346 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderText.cpp
Source/WebCore/rendering/RenderTextLineBoxes.cpp
Source/WebCore/rendering/RenderTextLineBoxes.h

index d9940da..2783579 100644 (file)
@@ -1,5 +1,20 @@
 2013-10-12  Antti Koivisto  <antti@apple.com>
 
+        Move line dirtying code to RenderTextLineBoxes
+        https://bugs.webkit.org/show_bug.cgi?id=122699
+
+        Reviewed by Andreas Kling.
+
+        * rendering/RenderTextLineBoxes.cpp:
+        (WebCore::RenderTextLineBoxes::removeAllFromParent):
+        
+            Also moved the removal loop.
+
+        (WebCore::RenderTextLineBoxes::dirtyAll):
+        (WebCore::RenderTextLineBoxes::dirtyRange):
+
+2013-10-12  Antti Koivisto  <antti@apple.com>
+
         Move more code to RenderTextLineBoxes
         https://bugs.webkit.org/show_bug.cgi?id=122697
 
index d91bfe6..541c11f 100644 (file)
@@ -239,13 +239,8 @@ void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyl
 
 void RenderText::removeAndDestroyTextBoxes()
 {
-    if (!documentBeingDestroyed()) {
-        if (firstTextBox()) {
-            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
-                box->remove();
-        } else if (parent())
-            parent()->dirtyLinesFromChangedChild(this);
-    }
+    if (!documentBeingDestroyed())
+        m_lineBoxes.removeAllFromParent(*this);
     m_lineBoxes.deleteAll(*this);
 }
 
@@ -1124,79 +1119,12 @@ void RenderText::setTextWithOffset(const String& text, unsigned offset, unsigned
     if (!force && m_text == text)
         return;
 
-    unsigned oldLen = textLength();
-    unsigned newLen = text.length();
-    int delta = newLen - oldLen;
+    int delta = text.length() - textLength();
     unsigned end = len ? offset + len - 1 : offset;
 
-    RootInlineBox* firstRootBox = 0;
-    RootInlineBox* lastRootBox = 0;
-
-    bool dirtiedLines = false;
-
-    // Dirty all text boxes that include characters in between offset and offset+len.
-    for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
-        // FIXME: This shouldn't rely on the end of a dirty line box. See https://bugs.webkit.org/show_bug.cgi?id=97264
-        // Text run is entirely before the affected range.
-        if (curr->end() < offset)
-            continue;
+    m_linesDirty = m_lineBoxes.dirtyRange(*this, offset, end, delta);
 
-        // Text run is entirely after the affected range.
-        if (curr->start() > end) {
-            curr->offsetRun(delta);
-            RootInlineBox& rootBox = curr->root();
-            if (!firstRootBox) {
-                firstRootBox = &rootBox;
-                if (!dirtiedLines) {
-                    // The affected area was in between two runs. Go ahead and mark the root box of
-                    // the run after the affected area as dirty.
-                    firstRootBox->markDirty();
-                    dirtiedLines = true;
-                }
-            }
-            lastRootBox = &rootBox;
-        } else if (curr->end() >= offset && curr->end() <= end) {
-            // Text run overlaps with the left end of the affected range.
-            curr->dirtyLineBoxes();
-            dirtiedLines = true;
-        } else if (curr->start() <= offset && curr->end() >= end) {
-            // Text run subsumes the affected range.
-            curr->dirtyLineBoxes();
-            dirtiedLines = true;
-        } else if (curr->start() <= end && curr->end() >= end) {
-            // Text run overlaps with right end of the affected range.
-            curr->dirtyLineBoxes();
-            dirtiedLines = true;
-        }
-    }
-
-    // Now we have to walk all of the clean lines and adjust their cached line break information
-    // to reflect our updated offsets.
-    if (lastRootBox)
-        lastRootBox = lastRootBox->nextRootBox();
-    if (firstRootBox) {
-        RootInlineBox* prev = firstRootBox->prevRootBox();
-        if (prev)
-            firstRootBox = prev;
-    } else if (lastTextBox()) {
-        ASSERT(!lastRootBox);
-        firstRootBox = &lastTextBox()->root();
-        firstRootBox->markDirty();
-        dirtiedLines = true;
-    }
-    for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
-        if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
-            curr->setLineBreakPos(curr->lineBreakPos() + delta);
-    }
-
-    // If the text node is empty, dirty the line where new text will be inserted.
-    if (!firstTextBox() && parent()) {
-        parent()->dirtyLinesFromChangedChild(this);
-        dirtiedLines = true;
-    }
-
-    m_linesDirty = dirtiedLines;
-    setText(text, force || dirtiedLines);
+    setText(text, force || m_linesDirty);
 }
 
 void RenderText::transformText()
@@ -1338,10 +1266,8 @@ void RenderText::dirtyLineBoxes(bool fullLayout)
 {
     if (fullLayout)
         m_lineBoxes.deleteAll(*this);
-    else if (!m_linesDirty) {
-        for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
-            box->dirtyLineBoxes();
-    }
+    else if (!m_linesDirty)
+        m_lineBoxes.dirtyAll();
     m_linesDirty = false;
 }
 
index 76185b3..d7aab7a 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "InlineTextBox.h"
 #include "RenderStyle.h"
+#include "RootInlineBox.h"
 
 namespace WebCore {
 
@@ -103,6 +104,17 @@ void RenderTextLineBoxes::remove(InlineTextBox& box)
     checkConsistency();
 }
 
+void RenderTextLineBoxes::removeAllFromParent(RenderText& renderer)
+{
+    if (!m_first) {
+        if (renderer.parent())
+            renderer.parent()->dirtyLinesFromChangedChild(&renderer);
+        return;
+    }
+    for (auto box = m_first; box; box = box->nextTextBox())
+        box->remove();
+}
+
 void RenderTextLineBoxes::deleteAll(RenderText& renderer)
 {
     if (!m_first)
@@ -212,6 +224,87 @@ int RenderTextLineBoxes::caretMaxOffset(const RenderText& renderer) const
     return maxOffset;
 }
 
+void RenderTextLineBoxes::dirtyAll()
+{
+    for (auto box = m_first; box; box = box->nextTextBox())
+        box->dirtyLineBoxes();
+}
+
+bool RenderTextLineBoxes::dirtyRange(RenderText& renderer, unsigned start, unsigned end, int lengthDelta)
+{
+    RootInlineBox* firstRootBox = nullptr;
+    RootInlineBox* lastRootBox = nullptr;
+
+    // Dirty all text boxes that include characters in between offset and offset+len.
+    bool dirtiedLines = false;
+    for (auto current = m_first; current; current = current->nextTextBox()) {
+        // FIXME: This shouldn't rely on the end of a dirty line box. See https://bugs.webkit.org/show_bug.cgi?id=97264
+        // Text run is entirely before the affected range.
+        if (current->end() < start)
+            continue;
+        // Text run is entirely after the affected range.
+        if (current->start() > end) {
+            current->offsetRun(lengthDelta);
+            auto& rootBox = current->root();
+            if (!firstRootBox) {
+                firstRootBox = &rootBox;
+                if (!dirtiedLines) {
+                    // The affected area was in between two runs. Go ahead and mark the root box of
+                    // the run after the affected area as dirty.
+                    firstRootBox->markDirty();
+                    dirtiedLines = true;
+                }
+            }
+            lastRootBox = &rootBox;
+            continue;
+        }
+        if (current->end() >= start && current->end() <= end) {
+            // Text run overlaps with the left end of the affected range.
+            current->dirtyLineBoxes();
+            dirtiedLines = true;
+            continue;
+        }
+        if (current->start() <= start && current->end() >= end) {
+            // Text run subsumes the affected range.
+            current->dirtyLineBoxes();
+            dirtiedLines = true;
+            continue;
+        }
+        if (current->start() <= end && current->end() >= end) {
+            // Text run overlaps with right end of the affected range.
+            current->dirtyLineBoxes();
+            dirtiedLines = true;
+            continue;
+        }
+    }
+
+    // Now we have to walk all of the clean lines and adjust their cached line break information
+    // to reflect our updated offsets.
+    if (lastRootBox)
+        lastRootBox = lastRootBox->nextRootBox();
+    if (firstRootBox) {
+        auto previousRootBox = firstRootBox->prevRootBox();
+        if (previousRootBox)
+            firstRootBox = previousRootBox;
+    } else if (m_last) {
+        ASSERT(!lastRootBox);
+        firstRootBox = &m_last->root();
+        firstRootBox->markDirty();
+        dirtiedLines = true;
+    }
+    for (auto current = firstRootBox; current && current != lastRootBox; current = current->nextRootBox()) {
+        if (current->lineBreakObj() == &renderer && current->lineBreakPos() > end)
+            current->setLineBreakPos(current->lineBreakPos() + lengthDelta);
+    }
+    
+    // If the text node is empty, dirty the line where new text will be inserted.
+    if (!m_first && renderer.parent()) {
+        renderer.parent()->dirtyLinesFromChangedChild(&renderer);
+        dirtiedLines = true;
+    }
+    return dirtiedLines;
+}
+
 #if !ASSERT_DISABLED
 RenderTextLineBoxes::~RenderTextLineBoxes()
 {
index acc770b..93aca13 100644 (file)
@@ -47,6 +47,7 @@ public:
     void attach(InlineTextBox&);
     void remove(InlineTextBox&);
 
+    void removeAllFromParent(RenderText&);
     void deleteAll(RenderText&);
 
     InlineTextBox* findNext(int offset, int& position) const;
@@ -58,6 +59,9 @@ public:
     IntRect boundingBox(const RenderText&) const;
     LayoutRect visualOverflowBoundingBox(const RenderText&) const;
 
+    void dirtyAll();
+    bool dirtyRange(RenderText&, unsigned start, unsigned end, int lengthDelta);
+
 #if !ASSERT_DISABLED
     ~RenderTextLineBoxes();
 #endif