Fix by Mitz Pettel, reviewed by Hyatt.
authorap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Jul 2006 16:55:02 +0000 (16:55 +0000)
committerap <ap@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 24 Jul 2006 16:55:02 +0000 (16:55 +0000)
        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9669
          Incomplete repaint when changing an inline's border

        Test: fast/repaint/line-overflow.html

        * rendering/RenderBlock.h:
        * rendering/bidi.cpp:
        (WebCore::RenderBlock::layoutInlineChildren): Added repaintTop and repaintBottom
        variables to track the vertical edges of the area that changed, accounting for
        lines that were deleted, inserted or moved. Removed unnecessary updating of
        m_overflowHeight.
        (WebCore::RenderBlock::determineStartPosition): Removed unnecessary updating of
        m_overflowHeight.
        (WebCore::RenderBlock::determineEndPosition):
        (WebCore::RenderBlock::matchedEndLine): Added repaintTop and repaintBottom
        arguments, which this method updates to account for deleted lines.
        (WebCore::RenderBlock::checkLinesForOverflow): Removed outdated FIXME.

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

LayoutTests/ChangeLog
LayoutTests/fast/repaint/line-overflow-expected.checksum [new file with mode: 0644]
LayoutTests/fast/repaint/line-overflow-expected.png [new file with mode: 0644]
LayoutTests/fast/repaint/line-overflow-expected.txt [new file with mode: 0644]
LayoutTests/fast/repaint/line-overflow.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/RenderBlock.h
WebCore/rendering/bidi.cpp

index 861f9c33287ad7f77431e18bfdb8d6503c6338aa..315670c1338f4788d3c14933d4ef54ce483767b9 100644 (file)
@@ -1,3 +1,15 @@
+2006-07-24  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Hyatt.
+
+        - repaint test for http://bugzilla.opendarwin.org/show_bug.cgi?id=9669
+          Incomplete repaint when changing an inline's border
+
+        * fast/repaint/line-overflow-expected.checksum: Added.
+        * fast/repaint/line-overflow-expected.png: Added.
+        * fast/repaint/line-overflow-expected.txt: Added.
+        * fast/repaint/line-overflow.html: Added.
+
 2006-07-24  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/repaint/line-overflow-expected.checksum b/LayoutTests/fast/repaint/line-overflow-expected.checksum
new file mode 100644 (file)
index 0000000..d19178a
--- /dev/null
@@ -0,0 +1 @@
+8551d6ed1a5a5dcc87796f285231cba1
\ No newline at end of file
diff --git a/LayoutTests/fast/repaint/line-overflow-expected.png b/LayoutTests/fast/repaint/line-overflow-expected.png
new file mode 100644 (file)
index 0000000..1087778
Binary files /dev/null and b/LayoutTests/fast/repaint/line-overflow-expected.png differ
diff --git a/LayoutTests/fast/repaint/line-overflow-expected.txt b/LayoutTests/fast/repaint/line-overflow-expected.txt
new file mode 100644 (file)
index 0000000..534e6fe
--- /dev/null
@@ -0,0 +1,34 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x286
+  RenderBlock {HTML} at (0,0) size 800x286
+    RenderBody {BODY} at (8,16) size 784x262
+      RenderBlock {P} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 104x18
+          text run at (0,0) width 104: "This is a test for "
+        RenderInline {I} at (0,0) size 744x36
+          RenderInline {A} at (0,0) size 348x18 [color=#0000EE]
+            RenderText {#text} at (104,0) size 348x18
+              text run at (104,0) width 348: "http://bugzilla.opendarwin.org/show_bug.cgi?id=9669"
+          RenderText {#text} at (452,0) size 744x36
+            text run at (452,0) width 4: " "
+            text run at (456,0) width 288: "Incomplete repaint when changing an inline's"
+            text run at (0,18) width 43: "border"
+        RenderText {#text} at (43,18) size 4x18
+          text run at (43,18) width 4: "."
+      RenderBlock {HR} at (0,52) size 784x2 [border: (1px inset #000000)]
+      RenderBlock {DIV} at (0,62) size 200x200
+        RenderText {#text} at (0,0) size 192x54
+          text run at (0,0) width 129: "Cras faucibus. Nunc"
+          text run at (0,18) width 192: "adipiscing, enim in scelerisque"
+          text run at (0,36) width 64: "convallis, "
+          text run at (64,36) width 42: "augue "
+        RenderInline {SPAN} at (0,0) size 35x48 [border: (30px solid #0000FF) none]
+          RenderText {#text} at (106,36) size 35x18
+            text run at (106,36) width 35: "purus"
+        RenderText {#text} at (141,36) size 195x90
+          text run at (141,36) width 54: " eleifend"
+          text run at (0,54) width 151: "lacus, at sagittis eros leo"
+          text run at (0,72) width 135: "pulvinar velit. Integer"
+          text run at (0,90) width 190: "sollicitudin nisi ut urna blandit"
+          text run at (0,108) width 60: "convallis."
diff --git a/LayoutTests/fast/repaint/line-overflow.html b/LayoutTests/fast/repaint/line-overflow.html
new file mode 100644 (file)
index 0000000..30e65d0
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+        "http://www.w3.org/TR/html4/strict.dtd">
+<html lang="en">
+<head>
+       <script src="repaint.js" type="text/javascript"></script>
+       <script type="text/javascript">
+          function repaintTest()
+          {
+              var target = document.getElementById('t');
+           target.style.borderTop = "30px solid blue";
+           target.style.margin = "0";
+          }
+       </script>
+       <style type="text/css">
+          span#t { margin: 30px; }
+       </style>
+</head>
+<body onload="runRepaintTest();">
+    <p>
+        This is a test for <i><a href="http://bugzilla.opendarwin.org/show_bug.cgi?id=9669">http://bugzilla.opendarwin.org/show_bug.cgi?id=9669</a>
+        Incomplete repaint when changing an inline's border</i>.
+    </p>
+    <hr>
+    <div style="width: 200px; height: 200px;">
+        Cras faucibus. Nunc adipiscing, enim in scelerisque convallis,
+        augue <span id="t">purus</span> eleifend lacus, at sagittis eros leo pulvinar velit. Integer sollicitudin nisi ut urna blandit convallis.
+    </div>
+</body>
index 3226f7e65dd3cfb0e6599167a8022c2238adf75c..4761cfda4bc98e4a63091e9e09b06b156b80eb50 100644 (file)
@@ -1,3 +1,25 @@
+2006-07-24  Mitz Pettel  <opendarwin.org@mitzpettel.com>
+
+        Reviewed by Hyatt.
+
+        - fix http://bugzilla.opendarwin.org/show_bug.cgi?id=9669
+          Incomplete repaint when changing an inline's border
+
+        Test: fast/repaint/line-overflow.html
+
+        * rendering/RenderBlock.h:
+        * rendering/bidi.cpp:
+        (WebCore::RenderBlock::layoutInlineChildren): Added repaintTop and repaintBottom
+        variables to track the vertical edges of the area that changed, accounting for
+        lines that were deleted, inserted or moved. Removed unnecessary updating of
+        m_overflowHeight.
+        (WebCore::RenderBlock::determineStartPosition): Removed unnecessary updating of
+        m_overflowHeight.
+        (WebCore::RenderBlock::determineEndPosition):
+        (WebCore::RenderBlock::matchedEndLine): Added repaintTop and repaintBottom
+        arguments, which this method updates to account for deleted lines.
+        (WebCore::RenderBlock::checkLinesForOverflow): Removed outdated FIXME.
+
 2006-07-24  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Reviewed by Darin.
index 8edb170cb81884856e4b65f2f714bf1ec46d8968..4d7124214a061b99b7c34193caddeff05f533ca6 100644 (file)
@@ -134,8 +134,8 @@ public:
                                         BidiStatus& cleanLineBidiStatus, BidiContext*& cleanLineBidiContext,
                                         int& yPos);
     bool matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,
-                        const BidiIterator& endLineStart, const BidiStatus& endLineStatus,
-                        BidiContext* endLineContext, RootInlineBox*& endLine, int& endYPos);
+                        const BidiIterator& endLineStart, const BidiStatus& endLineStatus, BidiContext* endLineContext,
+                        RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
     int skipWhitespace(BidiIterator& , BidiState &);
     BidiIterator findNextLineBreak(BidiIterator& start, BidiState &info );
     RootInlineBox* constructLine(const BidiIterator& start, const BidiIterator& end);
index 15d745c14dcf4f7c30e5ad789882a2840bfecd16..b2de68dc541e3b608e51f245511197e0abd554c3 100644 (file)
@@ -1480,7 +1480,8 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
     BidiState bidi;
 
     bool useRepaintRect = false;
-    IntRect repaintRect(0,0,0,0);
+    int repaintTop = 0;
+    int repaintBottom = 0;
 
     m_overflowHeight = 0;
     
@@ -1509,9 +1510,6 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
     if (hasTextOverflow)
          deleteEllipsisLineBoxes();
 
-    int oldLineBottom = lastRootBox() ? lastRootBox()->bottomOverflow() : m_height;
-    int startLineBottom = 0;
-
     if (firstChild()) {
         // layout replaced elements
         bool endOfInline = false;
@@ -1595,11 +1593,13 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
             cleanLineBidiContext->ref();
         if (startLine) {
             useRepaintRect = true;
-            startLineBottom = startLine->bottomOverflow();
-            repaintRect.setY(min(m_height, startLine->topOverflow()));
+            repaintTop = m_height;
+            repaintBottom = m_height;
             RenderArena* arena = renderArena();
             RootInlineBox* box = startLine;
             while (box) {
+                repaintTop = min(repaintTop, box->topOverflow());
+                repaintBottom = max(repaintBottom, box->bottomOverflow());
                 RootInlineBox* next = box->nextRootBox();
                 box->deleteLine(arena);
                 box = next;
@@ -1612,7 +1612,7 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
         bool endLineMatched = false;
         while (!end.atEnd()) {
             start = end;
-            if (endLine && (endLineMatched = matchedEndLine(start, bidi.status, bidi.context.get(), cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLine, endLineYPos)))
+            if (endLine && (endLineMatched = matchedEndLine(start, bidi.status, bidi.context.get(), cleanLineStart, cleanLineBidiStatus, cleanLineBidiContext, endLine, endLineYPos, repaintBottom, repaintTop)))
                 break;
 
             betweenMidpoints = false;
@@ -1661,8 +1661,13 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
                     bidi.adjustEmbedding = false;
                 }
 
-                if (lineBox)
+                if (lineBox) {
                     lineBox->setLineBreakInfo(end.obj, end.pos, &bidi.status, bidi.context.get());
+                    if (useRepaintRect) {
+                        repaintTop = min(repaintTop, lineBox->topOverflow());
+                        repaintBottom = max(repaintBottom, lineBox->bottomOverflow());
+                    }
+                }
                 
                 m_firstLine = false;
                 newLine();
@@ -1676,12 +1681,6 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
         
         if (endLine) {
             if (endLineMatched) {
-                // Note our current y-position for correct repainting when no lines move.  If no lines move, we still have to
-                // repaint up to the maximum of the bottom overflow of the old start line or the bottom overflow of the new last line.
-                int currYPos = max(startLineBottom, m_height);
-                if (lastRootBox())
-                    currYPos = max(currYPos, lastRootBox()->bottomOverflow());
-                
                 // Attach all the remaining lines, and then adjust their y-positions as needed.
                 for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
                     line->attachLine();
@@ -1689,28 +1688,21 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
                 // Now apply the offset to each line if needed.
                 int delta = m_height - endLineYPos;
                 if (delta) {
-                    for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
+                    for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
+                        repaintTop = min(repaintTop, line->topOverflow() + (delta < 0 ? delta : 0));
+                        repaintBottom = max(repaintBottom, line->bottomOverflow() + (delta > 0 ? delta : 0));
                         line->adjustPosition(0, delta);
+                    }
                 }
                 m_height = lastRootBox()->blockHeight();
-                m_overflowHeight = max(m_height, m_overflowHeight);
-                int bottomOfLine = lastRootBox()->bottomOverflow();
-                if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
-                    m_overflowHeight = bottomOfLine;
-                if (delta)
-                    repaintRect.setHeight(max(m_overflowHeight-delta, m_overflowHeight) - repaintRect.y());
-                else
-                    repaintRect.setHeight(currYPos - repaintRect.y());
-            }
-            else {
+            } else {
                 // Delete all the remaining lines.
-                m_overflowHeight = max(m_height, m_overflowHeight);
                 InlineRunBox* line = endLine;
                 RenderArena* arena = renderArena();
                 while (line) {
+                    repaintTop = min(repaintTop, line->topOverflow());
+                    repaintBottom = max(repaintBottom, line->bottomOverflow());
                     InlineRunBox* next = line->nextLineBox();
-                    if (!next)
-                        repaintRect.setHeight(max(m_overflowHeight, line->bottomOverflow()) - repaintRect.y());
                     line->deleteLine(arena);
                     line = next;
                 }
@@ -1737,11 +1729,12 @@ IntRect RenderBlock::layoutInlineChildren(bool relayoutChildren)
     // See if any lines spill out of the block.  If so, we need to update our overflow width.
     checkLinesForOverflow();
 
+    IntRect repaintRect(0, 0, 0, 0);
     if (useRepaintRect) {
         repaintRect.setX(m_overflowLeft);
-        repaintRect.setWidth(max((int)m_width, m_overflowWidth) - m_overflowLeft);
-        if (repaintRect.height() == 0)
-            repaintRect.setHeight(max(oldLineBottom, m_overflowHeight) - repaintRect.y());
+        repaintRect.setWidth(m_overflowWidth - m_overflowLeft);
+        repaintRect.setY(repaintTop);
+        repaintRect.setHeight(repaintBottom - repaintTop);
         if (hasOverflowClip())
             // Don't allow this rect to spill out of our overflow box.
             repaintRect.intersect(IntRect(0, 0, m_width, m_height));
@@ -1805,9 +1798,6 @@ RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiIterator
     previousLineBrokeCleanly = !last || last->endsWithBreak();
     if (last) {
         m_height = last->blockHeight();
-        int bottomOfLine = last->bottomOverflow();
-        if (bottomOfLine > m_height && bottomOfLine > m_overflowHeight)
-            m_overflowHeight = bottomOfLine;
         startObj = last->lineBreakObj();
         pos = last->lineBreakPos();
         bidi.status = last->lineBreakBidiStatus();
@@ -1846,7 +1836,7 @@ RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiI
     cleanLineStart = BidiIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
     cleanLineBidiStatus = prev->lineBreakBidiStatus();
     cleanLineBidiContext = prev->lineBreakBidiContext();
-    yPos = last->prevRootBox()->blockHeight();
+    yPos = prev->blockHeight();
     
     for (RootInlineBox* line = last; line; line = line->nextRootBox())
         line->extractLine(); // Disconnect all line boxes from their render objects while preserving
@@ -1856,8 +1846,8 @@ RootInlineBox* RenderBlock::determineEndPosition(RootInlineBox* startLine, BidiI
 }
 
 bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& status, BidiContext* context,
-                                 const BidiIterator& endLineStart, const BidiStatus& endLineStatus,
-                                 BidiContext* endLineContext, RootInlineBox*& endLine, int& endYPos)
+                                 const BidiIterator& endLineStart, const BidiStatus& endLineStatus, BidiContext* endLineContext, 
+                                 RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop)
 {
     if (start == endLineStart)
         return status == endLineStatus && *context == *endLineContext;
@@ -1881,6 +1871,8 @@ bool RenderBlock::matchedEndLine(const BidiIterator& start, const BidiStatus& st
                 RootInlineBox* boxToDelete = endLine;
                 RenderArena* arena = renderArena();
                 while (boxToDelete && boxToDelete != result) {
+                    repaintTop = min(repaintTop, boxToDelete->topOverflow());
+                    repaintBottom = max(repaintBottom, boxToDelete->bottomOverflow());
                     RootInlineBox* next = boxToDelete->nextRootBox();
                     boxToDelete->deleteLine(arena);
                     boxToDelete = next;
@@ -2548,8 +2540,6 @@ BidiIterator RenderBlock::findNextLineBreak(BidiIterator &start, BidiState &bidi
 
 void RenderBlock::checkLinesForOverflow()
 {
-    // FIXME: Inline blocks can have overflow.  Need to understand when those objects are present on a line
-    // and factor that in somehow.
     m_overflowWidth = m_width;
     for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
         m_overflowLeft = min(curr->leftOverflow(), m_overflowLeft);