2009-03-26 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Mar 2009 18:34:03 +0000 (18:34 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Mar 2009 18:34:03 +0000 (18:34 +0000)
        Reviewed by Dave Hyatt

        https://bugs.webkit.org/show_bug.cgi?id=23914

        Tests: compositing/overflow/ancestor-overflow.html
               compositing/overflow/parent-overflow.html

        * rendering/RenderLayer.cpp:
        (WebCore::RenderLayer::calculateClipRects):
        * rendering/RenderLayer.h:
        (WebCore::ClipRects::infiniteRect):
        New static method that returns a large rect that is used by the clipping
        logic.

        * rendering/RenderLayerBacking.cpp:
        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
        Use parentClipRects(), rather than calculateRects(), to compute the overflow
        rect that we'll use to create a masking layer for composited clipping.

        * rendering/RenderLayerCompositor.cpp:
        (WebCore::RenderLayerCompositor::clippedByAncestor):
        Use parentClipRects() to see whether there's a layer between us and our
        compositing ancestor which applies clipping.

        (WebCore::RenderLayerCompositor::clipsCompositingDescendants):
        A layer which imposes clipping to its children doesn't have to be a stacking
        context; it might be a normal flow layer; in either case, we can rely on the
        hasCompositingDescendant() bit.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/compositing/overflow/ancestor-overflow.html [new file with mode: 0644]
LayoutTests/compositing/overflow/parent-overflow.html [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.txt [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/RenderLayer.cpp
WebCore/rendering/RenderLayer.h
WebCore/rendering/RenderLayerBacking.cpp
WebCore/rendering/RenderLayerCompositor.cpp

index 44abbcb..75b4fb4 100644 (file)
@@ -1,3 +1,20 @@
+2009-03-26  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+        
+        https://bugs.webkit.org/show_bug.cgi?id=23914
+        
+        Tests for overflow:hidden with various configurations of position.
+
+        * compositing/overflow/ancestor-overflow.html: Added.
+        * compositing/overflow/parent-overflow.html: Added.
+        * platform/mac/compositing/overflow/ancestor-overflow-expected.checksum: Added.
+        * platform/mac/compositing/overflow/ancestor-overflow-expected.png: Added.
+        * platform/mac/compositing/overflow/ancestor-overflow-expected.txt: Added.
+        * platform/mac/compositing/overflow/parent-overflow-expected.checksum: Added.
+        * platform/mac/compositing/overflow/parent-overflow-expected.png: Added.
+        * platform/mac/compositing/overflow/parent-overflow-expected.txt: Added.
+
 2009-03-25  Brian Weinstein  <bweinstein@gmail.com>
 
         Update Windows skipped list based on failures in r41995, to try and make Windows build-bot green
diff --git a/LayoutTests/compositing/overflow/ancestor-overflow.html b/LayoutTests/compositing/overflow/ancestor-overflow.html
new file mode 100644 (file)
index 0000000..d8b0c9d
--- /dev/null
@@ -0,0 +1,82 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Overflow Test</title>
+  <style type="text/css" media="screen">
+    .container {
+      display: inline-block;
+      margin: 20px;
+      width: 120px;
+      height: 120px;
+      padding: 10px;
+      border: 1px solid black;
+      overflow: hidden;
+    }
+    
+    .intermediate {
+      width: 100px;
+      height: 100px;
+      padding: 10px;
+      border: 1px solid blue;
+    }
+    
+    .box {
+      width: 100px;
+      height: 150px;
+      background-color: gray;
+      -webkit-transform: translateZ(0);
+    }
+  </style>
+</head>
+<body>
+
+<p>Test overflow clipping of composited elements in various configurations.</p>
+<div class="container">
+  <div class="intermediate">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+<div class="container">
+  <div class="intermediate" style="position: absolute">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+<div class="container" style="position: relative">
+  <div class="intermediate" style="position: absolute">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+<br>
+
+<div class="container" style="z-index: 0">
+  <div class="intermediate">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+<div class="container" style="z-index: 0">
+  <div class="intermediate" style="position: absolute; z-index: 0;">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+<div class="container" style="position: relative; z-index: 0">
+  <div class="intermediate" style="position: absolute;">
+    <div class="box">
+    </div>
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/compositing/overflow/parent-overflow.html b/LayoutTests/compositing/overflow/parent-overflow.html
new file mode 100644 (file)
index 0000000..d922976
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+
+<html lang="en">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+  <title>Overflow Test</title>
+  <style type="text/css" media="screen">
+    .container {
+      display: inline-block;
+      margin: 20px;
+      width: 100px;
+      height: 100px;
+      padding: 10px;
+      border: 1px solid black;
+      overflow: hidden;
+    }
+    
+    .box {
+      width: 100px;
+      height: 300px;
+      background-color: gray;
+      -webkit-transform: translateZ(0);
+    }
+  </style>
+</head>
+<body>
+<p>Gray box should be clipped by black border in each case.</p>
+<div class="container">
+  <div class="box">
+  </div>
+</div>
+
+<div class="container" style="position: relative">
+  <div class="box">
+  </div>
+</div>
+
+<div class="container" style="position: relative; z-index: 0">
+  <div class="box">
+  </div>
+</div>
+
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.checksum b/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.checksum
new file mode 100644 (file)
index 0000000..4a5b3af
--- /dev/null
@@ -0,0 +1 @@
+70e0c168d948f393213f127242ad349a
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.png b/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.png
new file mode 100644 (file)
index 0000000..0547b39
Binary files /dev/null and b/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.png differ
diff --git a/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.txt b/LayoutTests/platform/mac/compositing/overflow/ancestor-overflow-expected.txt
new file mode 100644 (file)
index 0000000..ad2ae55
--- /dev/null
@@ -0,0 +1,57 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x430
+  RenderBlock {HTML} at (0,0) size 800x430
+    RenderBody {BODY} at (8,16) size 784x406
+      RenderBlock {P} at (0,0) size 784x18
+        RenderText {#text} at (0,0) size 459x18
+          text run at (0,0) width 459: "Test overflow clipping of composited elements in various configurations."
+      RenderBlock (anonymous) at (0,34) size 784x372
+        RenderText {#text} at (182,168) size 4x18
+          text run at (182,168) width 4: " "
+        RenderText {#text} at (368,168) size 4x18
+          text run at (368,168) width 4: " "
+        RenderText {#text} at (554,168) size 4x18
+          text run at (554,168) width 4: " "
+        RenderBR {BR} at (0,0) size 0x0
+        RenderText {#text} at (182,354) size 4x18
+          text run at (182,354) width 4: " "
+        RenderText {#text} at (368,354) size 4x18
+          text run at (368,354) width 4: " "
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (28,70) size 142x142 clip at (29,71) size 140x140 scrollHeight 171
+  RenderBlock {DIV} at (20,20) size 142x142 [border: (1px solid #000000)]
+    RenderBlock {DIV} at (11,11) size 122x122 [border: (1px solid #0000FF)]
+layer at (214,70) size 142x142 clip at (215,71) size 140x140
+  RenderBlock {DIV} at (206,20) size 142x142 [border: (1px solid #000000)]
+layer at (28,256) size 142x142 clip at (29,257) size 140x140 scrollHeight 171
+  RenderBlock {DIV} at (20,206) size 142x142 [border: (1px solid #000000)]
+    RenderBlock {DIV} at (11,11) size 122x122 [border: (1px solid #0000FF)]
+layer at (214,256) size 142x142 clip at (215,257) size 140x140
+  RenderBlock {DIV} at (206,206) size 142x142 [border: (1px solid #000000)]
+layer at (50,92) size 100x150 backgroundClip at (29,71) size 140x140 clip at (29,71) size 140x140 outlineClip at (29,71) size 140x140
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
+layer at (225,81) size 122x161
+  RenderBlock (positioned) {DIV} at (225,81) size 122x122 [border: (1px solid #0000FF)]
+layer at (236,92) size 100x150
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
+layer at (400,70) size 142x142 clip at (401,71) size 140x140 scrollHeight 171
+  RenderBlock (relative positioned) {DIV} at (392,20) size 142x142 [border: (1px solid #000000)]
+layer at (411,81) size 122x161 backgroundClip at (401,71) size 140x140 clip at (401,71) size 140x140 outlineClip at (401,71) size 140x140
+  RenderBlock (positioned) {DIV} at (11,11) size 122x122 [border: (1px solid #0000FF)]
+layer at (422,92) size 100x150 backgroundClip at (401,71) size 140x140 clip at (401,71) size 140x140 outlineClip at (401,71) size 140x140
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
+layer at (50,278) size 100x150 backgroundClip at (29,257) size 140x140 clip at (29,257) size 140x140 outlineClip at (29,257) size 140x140
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
+layer at (225,267) size 122x161
+  RenderBlock (positioned) {DIV} at (225,267) size 122x122 [border: (1px solid #0000FF)]
+layer at (236,278) size 100x150
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
+layer at (400,256) size 142x142 clip at (401,257) size 140x140 scrollHeight 171
+  RenderBlock (relative positioned) {DIV} at (392,206) size 142x142 [border: (1px solid #000000)]
+layer at (411,267) size 122x161 backgroundClip at (401,257) size 140x140 clip at (401,257) size 140x140 outlineClip at (401,257) size 140x140
+  RenderBlock (positioned) {DIV} at (11,11) size 122x122 [border: (1px solid #0000FF)]
+layer at (422,278) size 100x150 backgroundClip at (401,257) size 140x140 clip at (401,257) size 140x140 outlineClip at (401,257) size 140x140
+  RenderBlock {DIV} at (11,11) size 100x150 [bgcolor=#808080]
diff --git a/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.checksum b/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.checksum
new file mode 100644 (file)
index 0000000..c2adefb
--- /dev/null
@@ -0,0 +1 @@
+c27a903ad8f307bebc88ec3d991c1002
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.png b/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.png
new file mode 100644 (file)
index 0000000..2d6e940
Binary files /dev/null and b/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.png differ
diff --git a/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.txt b/LayoutTests/platform/mac/compositing/overflow/parent-overflow-expected.txt
new file mode 100644 (file)
index 0000000..c5892ea
--- /dev/null
@@ -0,0 +1,28 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x224
+  RenderBlock {HTML} at (0,0) size 800x224
+    RenderBody {BODY} at (8,16) size 784x200
+      RenderBlock {P} at (0,0) size 784x18
+        RenderText {#text} at (0,0) size 362x18
+          text run at (0,0) width 362: "Gray box should be clipped by black border in each case."
+      RenderBlock (anonymous) at (0,34) size 784x166
+        RenderText {#text} at (162,148) size 4x18
+          text run at (162,148) width 4: " "
+        RenderText {#text} at (328,148) size 4x18
+          text run at (328,148) width 4: " "
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+        RenderText {#text} at (0,0) size 0x0
+layer at (28,70) size 122x122 clip at (29,71) size 120x120 scrollHeight 320
+  RenderBlock {DIV} at (20,20) size 122x122 [border: (1px solid #000000)]
+layer at (39,81) size 100x300 backgroundClip at (29,71) size 120x120 clip at (29,71) size 120x120 outlineClip at (29,71) size 120x120
+  RenderBlock {DIV} at (11,11) size 100x300 [bgcolor=#808080]
+layer at (194,70) size 122x122 clip at (195,71) size 120x120 scrollHeight 320
+  RenderBlock (relative positioned) {DIV} at (186,20) size 122x122 [border: (1px solid #000000)]
+layer at (205,81) size 100x300 backgroundClip at (195,71) size 120x120 clip at (195,71) size 120x120 outlineClip at (195,71) size 120x120
+  RenderBlock {DIV} at (11,11) size 100x300 [bgcolor=#808080]
+layer at (360,70) size 122x122 clip at (361,71) size 120x120 scrollHeight 320
+  RenderBlock (relative positioned) {DIV} at (352,20) size 122x122 [border: (1px solid #000000)]
+layer at (371,81) size 100x300 backgroundClip at (361,71) size 120x120 clip at (361,71) size 120x120 outlineClip at (361,71) size 120x120
+  RenderBlock {DIV} at (11,11) size 100x300 [bgcolor=#808080]
index 6ecd291..bf0c2fb 100644 (file)
@@ -1,3 +1,34 @@
+2009-03-26  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+        
+        https://bugs.webkit.org/show_bug.cgi?id=23914
+
+        Tests: compositing/overflow/ancestor-overflow.html
+               compositing/overflow/parent-overflow.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::calculateClipRects):
+        * rendering/RenderLayer.h:
+        (WebCore::ClipRects::infiniteRect):
+        New static method that returns a large rect that is used by the clipping
+        logic.
+        
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateGraphicsLayerGeometry):
+        Use parentClipRects(), rather than calculateRects(), to compute the overflow
+        rect that we'll use to create a masking layer for composited clipping.
+        
+        * rendering/RenderLayerCompositor.cpp:
+        (WebCore::RenderLayerCompositor::clippedByAncestor):
+        Use parentClipRects() to see whether there's a layer between us and our
+        compositing ancestor which applies clipping.
+        
+        (WebCore::RenderLayerCompositor::clipsCompositingDescendants):
+        A layer which imposes clipping to its children doesn't have to be a stacking
+        context; it might be a normal flow layer; in either case, we can rely on the
+        hasCompositingDescendant() bit.
+
 2009-03-26  Steve Falkenburg  <sfalken@apple.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=24837
index 695eaf8..fd88120 100644 (file)
@@ -2468,10 +2468,9 @@ void RenderLayer::updateClipRects(const RenderLayer* rootLayer)
 
 void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& clipRects, bool useCached) const
 {
-    IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
     if (!parent()) {
         // The root layer's clip rect is always infinite.
-        clipRects.reset(infiniteRect);
+        clipRects.reset(ClipRects::infiniteRect());
         return;
     }
 
@@ -2487,7 +2486,7 @@ void RenderLayer::calculateClipRects(const RenderLayer* rootLayer, ClipRects& cl
             parentLayer->calculateClipRects(rootLayer, clipRects);
     }
     else
-        clipRects.reset(infiniteRect);
+        clipRects.reset(ClipRects::infiniteRect());
 
     // A fixed object is essentially the root of its containing block hierarchy, so when
     // we encounter such an object, we reset our clip rects to the fixedClipRect.
index b8ce0d3..6e70a4b 100644 (file)
@@ -145,7 +145,9 @@ public:
         m_fixed = other.fixed();
         return *this;
     }
-        
+    
+    static IntRect infiniteRect() { return IntRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX); }
+
 private:
     // The normal operator new is disallowed on all render objects.
     void* operator new(size_t) throw();
index 36cec87..f61b976 100644 (file)
@@ -204,19 +204,19 @@ void RenderLayerBacking::updateGraphicsLayerGeometry()
         // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
         // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
         // for a compositing layer, rootLayer is the layer itself.
-        IntRect infiniteRect(INT_MIN/2, INT_MIN/2, INT_MAX, INT_MAX);
-        IntRect layerBounds, backgroundRect, foregroundRect, outlineRect;
-        m_owningLayer->calculateRects(compAncestor, infiniteRect, layerBounds, backgroundRect, foregroundRect, outlineRect, true);
+        ClipRects parentRects;
+        m_owningLayer->parentClipRects(compAncestor, parentRects, true);
+        IntRect parentClipRect = parentRects.overflowClipRect();
         
-        m_ancestorClippingLayer->setPosition(FloatPoint() + (backgroundRect.location() - graphicsLayerParentLocation));
-        m_ancestorClippingLayer->setSize(backgroundRect.size());
+        m_ancestorClippingLayer->setPosition(FloatPoint() + (parentClipRect.location() - graphicsLayerParentLocation));
+        m_ancestorClippingLayer->setSize(parentClipRect.size());
 
         // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
-        IntSize rendererOffset(backgroundRect.location().x() - deltaX, backgroundRect.location().y() - deltaY);
+        IntSize rendererOffset(parentClipRect.location().x() - deltaX, parentClipRect.location().y() - deltaY);
         m_ancestorClippingLayer->setOffsetFromRenderer(rendererOffset);
 
         // The primary layer is then parented in, and positioned relative to this clipping layer.
-        graphicsLayerParentLocation = backgroundRect.location();
+        graphicsLayerParentLocation = parentClipRect.location();
     }
 
     m_graphicsLayer->setPosition(FloatPoint() + (relativeCompositingBounds.location() - graphicsLayerParentLocation));
index 1af00e2..cbb3df7 100644 (file)
@@ -677,20 +677,30 @@ bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
         return false;
 
     RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
+    if (!compositingAncestor)
+        return false;
 
-    // We need ancestor clipping if something clips between this layer and its compositing, stacking context ancestor
-    for (RenderLayer* curLayer = layer->parent(); curLayer && curLayer != compositingAncestor; curLayer = curLayer->parent()) {
-        // FIXME: need to look at hasClip() too eventually
-        if (curLayer->renderer()->hasOverflowClip())
-            return true;
-        
-        // Clip is reset for an absolutely positioned element.
-        // FIXME: many cases are broken. We need more of the logic in calculateClipRects() here
-        if (curLayer->renderer()->style()->position() == AbsolutePosition)
+    // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
+    // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
+    // and layer.
+    RenderLayer* computeClipRoot = 0;
+    RenderLayer* curr = layer;
+    while (curr) {
+        RenderLayer* next = curr->parent();
+        if (next == compositingAncestor) {
+            computeClipRoot = curr;
             break;
+        }
+        curr = next;
     }
+    
+    if (!computeClipRoot || computeClipRoot == layer)
+        return false;
 
-    return false;
+    ClipRects parentRects;
+    layer->parentClipRects(computeClipRoot, parentRects, true);
+
+    return parentRects.overflowClipRect() != ClipRects::infiniteRect();
 }
 
 // Return true if the given layer is a stacking context and has compositing child
@@ -700,7 +710,6 @@ bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer
 {
     // FIXME: need to look at hasClip() too eventually
     return layer->hasCompositingDescendant() &&
-           layer->isStackingContext() &&
            layer->renderer()->hasOverflowClip();
 }