WebCore:
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Nov 2007 21:03:35 +0000 (21:03 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 6 Nov 2007 21:03:35 +0000 (21:03 +0000)
        Reviewed by Antti Koivisto and Dave Hyatt.

        - fix <rdar://problem/5582961> Incorrect layout and floating object list corruption when CSS decreases a block's height

        Test: fast/block/float/overhanging-after-height-decrease.html

        * rendering/RenderBlock.cpp:
        (WebCore::RenderBlock::layoutBlock): If after calculating the height
        it turns out that there are overhanging floats that were not overhanging
        before, rescan children with overhanging floats and add them.
        (WebCore::RenderBlock::layoutBlockChildren): Added a parameter that
        returns the lowest float bottom of any of the children.
        (WebCore::RenderBlock::addOverhangingFloats): Changed to return the
        lowest float bottom.
        * rendering/RenderBlock.h:

LayoutTests:

        Reviewed by Antti Koivisto and Dave Hyatt.

        - test for <rdar://problem/5582961> Incorrect layout and floating object list corruption when CSS decreases a block's height

        * fast/block/float/overhanging-after-height-decrease.html: Added.
        * platform/mac-leopard/fast/block: Added.
        * platform/mac-leopard/fast/block/float: Added.
        * platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.checksum: Added.
        * platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png: Added.
        * platform/mac/fast/block/float/overhanging-after-height-decrease-expected.txt: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/block/float/overhanging-after-height-decrease.html [new file with mode: 0644]
LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/block/float/overhanging-after-height-decrease-expected.txt [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h

index 00c15f6e22101a8a0c2c3e43edc21fe7886eb555..ce16b7846e843dcb26f8bef98e01385b6521dc31 100644 (file)
@@ -1,3 +1,16 @@
+2007-11-06  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Antti Koivisto and Dave Hyatt.
+
+        - test for <rdar://problem/5582961> Incorrect layout and floating object list corruption when CSS decreases a block's height
+
+        * fast/block/float/overhanging-after-height-decrease.html: Added.
+        * platform/mac-leopard/fast/block: Added.
+        * platform/mac-leopard/fast/block/float: Added.
+        * platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.checksum: Added.
+        * platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png: Added.
+        * platform/mac/fast/block/float/overhanging-after-height-decrease-expected.txt: Added.
+
 2007-11-05  Adele Peterson  <adele@apple.com>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/block/float/overhanging-after-height-decrease.html b/LayoutTests/fast/block/float/overhanging-after-height-decrease.html
new file mode 100644 (file)
index 0000000..c9d89ea
--- /dev/null
@@ -0,0 +1,46 @@
+<html>
+<head>
+    <script>
+        function test()
+        {
+            var float = document.getElementById("float");
+            var float2 = document.getElementById("float2");
+            document.body.offsetHeight;
+            float.parentNode.style.height = "40px";
+            document.body.offsetTop;
+            float.parentNode.removeChild(float);
+            document.body.offsetLeft;
+            float2.parentNode.style.height = "40px";
+            document.body.offsetTop;
+            float2.parentNode.removeChild(float2);
+            document.body.offsetLeft;
+        }
+    </script>
+</head>
+<body onload="test()">        
+    <div style="height: 20px;">
+        <div style="background-color: gray;">
+            <div id="float" style="float: left; height: 30px; background-color: blue; width: 100px;"></div>
+        </div>
+    </div>
+    <div style="background-color: silver; height: 80px;">
+        <div></div>
+    </div>
+    <div style="height: 20px;">
+        <div style="background-color: gray;">
+            <div id="float2" style="float: left; height: 30px; background-color: blue; width: 100px;"></div>
+        </div>
+    </div>
+    <div style="background-color: silver; height: 80px;">
+        <div>This line should start at the left margin.</div>
+    </div>
+    <div style="height: 20px;">
+        <div style="background-color: gray; height: 40px;">
+            <div style="float: left; height: 30px; background-color: blue; width: 100px;"></div>
+        </div>
+    </div>
+    <div style="background-color: silver; height: 80px;">
+        This line should not overlap the blue box.
+    </div>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.checksum b/LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.checksum
new file mode 100644 (file)
index 0000000..c5a430d
--- /dev/null
@@ -0,0 +1 @@
+734e7c6e7c49f8e7a693dda633fb0bbc
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png b/LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png
new file mode 100644 (file)
index 0000000..f9b44b2
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/fast/block/float/overhanging-after-height-decrease-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/block/float/overhanging-after-height-decrease-expected.txt b/LayoutTests/platform/mac/fast/block/float/overhanging-after-height-decrease-expected.txt
new file mode 100644 (file)
index 0000000..d4f6cfc
--- /dev/null
@@ -0,0 +1,21 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x20
+        RenderBlock {DIV} at (0,0) size 784x40 [bgcolor=#808080]
+      RenderBlock {DIV} at (0,20) size 784x80 [bgcolor=#C0C0C0]
+        RenderBlock {DIV} at (0,0) size 784x0
+      RenderBlock {DIV} at (0,100) size 784x20
+        RenderBlock {DIV} at (0,0) size 784x40 [bgcolor=#808080]
+      RenderBlock {DIV} at (0,120) size 784x80 [bgcolor=#C0C0C0]
+        RenderBlock {DIV} at (0,0) size 784x18
+          RenderText {#text} at (0,0) size 245x18
+            text run at (0,0) width 245: "This line should start at the left margin."
+      RenderBlock {DIV} at (0,200) size 784x20
+        RenderBlock {DIV} at (0,0) size 784x40 [bgcolor=#808080]
+          RenderBlock (floating) {DIV} at (0,0) size 100x30 [bgcolor=#0000FF]
+      RenderBlock {DIV} at (0,220) size 784x80 [bgcolor=#C0C0C0]
+        RenderText {#text} at (100,0) size 262x18
+          text run at (100,0) width 262: "This line should not overlap the blue box."
index 1d52892fc3ab98b4be7966924397e545fb42632f..3e743c78c41a85986e8b9b7d973f489af6c16fab 100644 (file)
@@ -1,3 +1,21 @@
+2007-11-06  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Antti Koivisto and Dave Hyatt.
+
+        - fix <rdar://problem/5582961> Incorrect layout and floating object list corruption when CSS decreases a block's height
+
+        Test: fast/block/float/overhanging-after-height-decrease.html
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::layoutBlock): If after calculating the height
+        it turns out that there are overhanging floats that were not overhanging
+        before, rescan children with overhanging floats and add them. 
+        (WebCore::RenderBlock::layoutBlockChildren): Added a parameter that
+        returns the lowest float bottom of any of the children.
+        (WebCore::RenderBlock::addOverhangingFloats): Changed to return the
+        lowest float bottom.
+        * rendering/RenderBlock.h:
+
 2007-11-06  Adele Peterson  <adele@apple.com>
 
         Reviewed by Darin.
index a9cabf803757b5acb88886a5d33c861068a6278f..1b5a3b92caa5b898ff060dce7a278ba4740a0ace 100644 (file)
@@ -577,10 +577,11 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
 
     int repaintTop = 0;
     int repaintBottom = 0;
+    int maxFloatBottom = 0;
     if (childrenInline())
         layoutInlineChildren(relayoutChildren, repaintTop, repaintBottom);
     else
-        layoutBlockChildren(relayoutChildren);
+        layoutBlockChildren(relayoutChildren, maxFloatBottom);
 
     // Expand our intrinsic height to encompass floats.
     int toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
@@ -596,6 +597,16 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
     int oldHeight = m_height;
     calcHeight();
     if (oldHeight != m_height) {
+        if (oldHeight > m_height && maxFloatBottom > m_height && !childrenInline()) {
+            // One of our children's floats may have become an overhanging float for us. We need to look for it.
+            for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+                if (child->isBlockFlow() && !child->isFloatingOrPositioned()) {
+                    RenderBlock* block = static_cast<RenderBlock*>(child);
+                    if (block->floatBottom() + block->yPos() > m_height)
+                        addOverhangingFloats(block, block->xPos(), block->yPos());
+                }
+            }
+        }
         // We have to rebalance columns to the new height.
         layoutColumns(singleColumnBottom);
 
@@ -1132,7 +1143,7 @@ void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInf
     setCollapsedBottomMargin(marginInfo);
 }
 
-void RenderBlock::layoutBlockChildren(bool relayoutChildren)
+void RenderBlock::layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom)
 {
     int top = borderTop() + paddingTop();
     int bottom = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
@@ -1148,6 +1159,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
     RenderObject* legend = layoutLegend(relayoutChildren);
 
     int previousFloatBottom = 0;
+    maxFloatBottom = 0;
 
     RenderObject* child = firstChild();
     while (child) {
@@ -1235,7 +1247,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
         }
         // If the child has overhanging floats that intrude into following siblings (or possibly out
         // of this block), then the parent gets notified of the floats now.
-        addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos());
+        maxFloatBottom = max(maxFloatBottom, addOverhangingFloats(static_cast<RenderBlock *>(child), -child->xPos(), -child->yPos()));
 
         // Update our overflow in case the child spills out the block.
         m_overflowTop = min(m_overflowTop, child->yPos() + child->overflowTop(false));
@@ -2631,18 +2643,23 @@ RenderBlock::clearFloats()
         addIntrudingFloats(block, xoffset, offset);
 }
 
-void RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff)
+int RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff)
 {
     // Prevent floats from being added to the canvas by the root element, e.g., <html>.
     if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot())
-        return;
+        return 0;
+
+    int lowestFloatBottom = 0;
 
     // Floats that will remain the child's responsiblity to paint should factor into its
     // visual overflow.
     IntRect floatsOverflowRect;
     DeprecatedPtrListIterator<FloatingObject> it(*child->m_floatingObjects);
     for (FloatingObject* r; (r = it.current()); ++it) {
-        if (child->yPos() + r->endY > height()) {
+        int bottom = child->yPos() + r->endY;
+        lowestFloatBottom = max(lowestFloatBottom, bottom);
+
+        if (bottom > height()) {
             // If the object is not in the list, we add it now.
             if (!containsFloat(r->node)) {
                 FloatingObject *floatingObj = new FloatingObject(r->type());
@@ -2676,6 +2693,7 @@ void RenderBlock::addOverhangingFloats(RenderBlock* child, int xoff, int yoff)
         }
     }
     child->addVisualOverflow(floatsOverflowRect);
+    return lowestFloatBottom;
 }
 
 void RenderBlock::addIntrudingFloats(RenderBlock* prev, int xoff, int yoff)
index 64470237371d0dadd4d78c74564e13d9e58e962c..da433da2d25bee6ec959a5c46eb5b2ca36667abc 100644 (file)
@@ -110,7 +110,7 @@ public:
 
     virtual void layout();
     virtual void layoutBlock(bool relayoutChildren);
-    void layoutBlockChildren(bool relayoutChildren);
+    void layoutBlockChildren(bool relayoutChildren, int& maxFloatBottom);
     void layoutInlineChildren(bool relayoutChildren, int& repaintTop, int& repaintBottom);
 
     void layoutPositionedObjects(bool relayoutChildren);
@@ -176,7 +176,7 @@ public:
 
     virtual bool hasOverhangingFloats() { return !hasColumns() && floatBottom() > m_height; }
     void addIntrudingFloats(RenderBlock* prev, int xoffset, int yoffset);
-    void addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset);
+    int addOverhangingFloats(RenderBlock* child, int xoffset, int yoffset);
 
     int nearestFloatBottom(int height) const;
     int floatBottom() const;