REGRESSION (r163382): Overflow hidden for inner elements breaks blurring
authorstavila@adobe.com <stavila@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Aug 2014 15:06:08 +0000 (15:06 +0000)
committerstavila@adobe.com <stavila@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Aug 2014 15:06:08 +0000 (15:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=135318

Reviewed by Zalan Bujtas.

Source/WebCore:

For elements with border radius, clipping must be applied using clipRoundedRect.
This regressed in r163382, when normal clipping started being applied also
for elements having border radius.

Test: fast/filter-image/clipped-filter.html

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::clipToRect):
(WebCore::RenderLayer::restoreClip):

LayoutTests:

Added test for filter applied on an element overflowing its parent, which has overflow:hidden.

* fast/filter-image/clipped-filter-expected.html: Added.
* fast/filter-image/clipped-filter.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/filter-image/clipped-filter-expected.html [new file with mode: 0644]
LayoutTests/fast/filter-image/clipped-filter.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayer.cpp

index 1b3b683..a23610c 100644 (file)
@@ -1,3 +1,15 @@
+2014-08-06  Radu Stavila  <stavila@adobe.com>
+
+        REGRESSION (r163382): Overflow hidden for inner elements breaks blurring
+        https://bugs.webkit.org/show_bug.cgi?id=135318
+
+        Reviewed by Zalan Bujtas.
+
+        Added test for filter applied on an element overflowing its parent, which has overflow:hidden.
+
+        * fast/filter-image/clipped-filter-expected.html: Added.
+        * fast/filter-image/clipped-filter.html: Added.
+
 2014-08-06  Mihnea Ovidenie  <mihnea@adobe.com>
 
         [CSSRegions] Move selection tests under fast/regions/selection
diff --git a/LayoutTests/fast/filter-image/clipped-filter-expected.html b/LayoutTests/fast/filter-image/clipped-filter-expected.html
new file mode 100644 (file)
index 0000000..069ab4f
--- /dev/null
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .circle {
+            width: 300px;
+            height: 300px;
+            margin-left: 100px;
+            margin-top: 60px;
+            background-color: #f5ad61;
+            border-radius: 50% 50%;
+        }
+        .inner {
+            -webkit-filter: drop-shadow(16px 16px 0px black);
+            background-color: red;
+            height: 60px;
+            width: 200px;
+        }
+
+        #clip {
+            position: absolute;
+            top: 0px;
+            left: 0px;
+            width: 500px;
+            height: 500px;
+            background-color: white;
+            -webkit-clip-path: url(#clipPath);
+        }
+    </style>
+</head>
+
+<body>
+    <a href="https://bugs.webkit.org/show_bug.cgi?id=135318">Bug 135318 - This test passes if the red element has a black shadow and is clipped by the orange circle</a>
+
+    <div class="circle">
+        <div class="inner"></div>
+    </div>
+
+    <div id="clip"></div>
+</body>
+
+<svg>
+    <defs>
+        <clipPath id="clipPath">
+            <path d="M18,38 v200 h90 a150,150 0 0,1 300,0 h50 v-200 z"
+        </clipPath>
+    </defs>
+</svg>
+
+</html>
\ No newline at end of file
diff --git a/LayoutTests/fast/filter-image/clipped-filter.html b/LayoutTests/fast/filter-image/clipped-filter.html
new file mode 100644 (file)
index 0000000..a4556ff
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <style>
+        .circle {
+            width: 300px;
+            height: 300px;
+            margin-left: 100px;
+            margin-top: 60px;
+            background-color: #f5ad61;
+            overflow: hidden;
+            border-radius: 50% 50%;
+        }
+
+        .inner {
+            -webkit-filter: drop-shadow(16px 16px 0px black);
+            background-color: red;
+            height: 60px;
+            width: 200px;
+        }
+
+        #clip {
+            position: absolute;
+            top: 0px;
+            left: 0px;
+            width: 500px;
+            height: 500px;
+            background-color: white;
+            -webkit-clip-path: url(#clipPath);
+        }
+    </style>
+</head>
+
+<body>
+    <a href="https://bugs.webkit.org/show_bug.cgi?id=135318">Bug 135318 - This test passes if the red element has a black shadow and is clipped by the orange circle</a>
+
+    <div class="circle">
+        <div class="inner"></div>
+    </div>
+
+    <div id="clip"></div>
+</body>
+
+<svg>
+    <defs>
+        <clipPath id="clipPath">
+            <path d="M18,38 v200 h90 a150,150 0 0,1 300,0 h50 v-200 z"
+        </clipPath>
+    </defs>
+</svg>
+
+</html>
\ No newline at end of file
index 992ee32..a89b9f1 100644 (file)
@@ -1,3 +1,20 @@
+2014-08-06  Radu Stavila  <stavila@adobe.com>
+
+        REGRESSION (r163382): Overflow hidden for inner elements breaks blurring
+        https://bugs.webkit.org/show_bug.cgi?id=135318
+
+        Reviewed by Zalan Bujtas.
+
+        For elements with border radius, clipping must be applied using clipRoundedRect.
+        This regressed in r163382, when normal clipping started being applied also
+        for elements having border radius.
+
+        Test: fast/filter-image/clipped-filter.html
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::clipToRect):
+        (WebCore::RenderLayer::restoreClip):
+
 2014-08-06  Zalan Bujtas  <zalan@apple.com>
 
         Cleanup InlineTextBox::paintSelection and ::localSelectionRect.
index e3ea545..49f2abc 100644 (file)
@@ -3586,36 +3586,34 @@ static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLaye
 void RenderLayer::clipToRect(const LayerPaintingInfo& paintingInfo, GraphicsContext* context, const ClipRect& clipRect, BorderRadiusClippingRule rule)
 {
     float deviceScaleFactor = renderer().document().deviceScaleFactor();
-    if (clipRect.rect() != paintingInfo.paintDirtyRect || clipRect.hasRadius()) {
+    if (clipRect.hasRadius()) {
+        context->save();
+        
+        // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
+        // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
+        // containing block chain so we check that also.
+        for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
+            if (layer->renderer().hasOverflowClip() && layer->renderer().style().hasBorderRadius() && inContainingBlockChain(this, layer)) {
+                LayoutRect adjustedClipRect = LayoutRect(toLayoutPoint(layer->offsetFromAncestor(paintingInfo.rootLayer)), layer->size());
+                adjustedClipRect.move(paintingInfo.subpixelAccumulation);
+                context->clipRoundedRect(layer->renderer().style().getRoundedInnerBorderFor(adjustedClipRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor));
+            }
+            
+            if (layer == paintingInfo.rootLayer)
+                break;
+        }
+    } else if (clipRect.rect() != paintingInfo.paintDirtyRect) {
         context->save();
         LayoutRect adjustedClipRect = clipRect.rect();
         adjustedClipRect.move(paintingInfo.subpixelAccumulation);
         context->clip(pixelSnappedForPainting(adjustedClipRect, deviceScaleFactor));
     }
-
-    if (!clipRect.hasRadius())
-        return;
-
-    // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
-    // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
-    // containing block chain so we check that also.
-    for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
-        if (layer->renderer().hasOverflowClip() && layer->renderer().style().hasBorderRadius() && inContainingBlockChain(this, layer)) {
-            LayoutRect adjustedClipRect = LayoutRect(toLayoutPoint(layer->offsetFromAncestor(paintingInfo.rootLayer)), layer->size());
-            adjustedClipRect.move(paintingInfo.subpixelAccumulation);
-            context->clipRoundedRect(layer->renderer().style().getRoundedInnerBorderFor(adjustedClipRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor));
-        }
-
-        if (layer == paintingInfo.rootLayer)
-            break;
-    }
 }
 
 void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
 {
-    if (clipRect.rect() == paintDirtyRect && !clipRect.hasRadius())
-        return;
-    context->restore();
+    if (clipRect.rect() != paintDirtyRect || clipRect.hasRadius())
+        context->restore();
 }
 
 static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)