Title: [201785] trunk
Revision
201785
Author
commit-qu...@webkit.org
Date
2016-06-07 19:07:34 -0700 (Tue, 07 Jun 2016)

Log Message

The backdrop-filter property does not respect border-radius
https://bugs.webkit.org/show_bug.cgi?id=158483
<rdar://problem/24210257>

Patch by Antoine Quint <grao...@apple.com> on 2016-06-07
Reviewed by Simon Fraser.

Source/WebCore:

In order to correctly support border-radius and backdrop-filter together, we change
the value set as the m_backdropFiltersRect from a FloatRect to FloatRoundedRect so
that it accounts for values set by the border-radius property. Then we add a new
m_backdropClippingLayer PlatformCALayer member to clip the backdrop layer in the
event that the border-radius is non-zero in updateBackdropFiltersRect(). Finally,
we follow the same pattern used for other PlatformCALayers owned by a GraphicsLayerCA
to support cloning of the new m_backdropClippingLayer.

Tests: css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html
       css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html
       css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html
       css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html
       css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html
       css3/filters/backdrop/backdrop-filter-with-border-radius.html

* platform/graphics/GraphicsLayer.h:
(WebCore::GraphicsLayer::setBackdropFiltersRect):
(WebCore::GraphicsLayer::backdropFiltersRect):
* platform/graphics/ca/GraphicsLayerCA.cpp:
(WebCore::GraphicsLayerCA::willBeDestroyed):
(WebCore::GraphicsLayerCA::setBackdropFiltersRect):
(WebCore::GraphicsLayerCA::updateBackdropFiltersRect):
(WebCore::GraphicsLayerCA::dumpAdditionalProperties):
* platform/graphics/ca/GraphicsLayerCA.h:
* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateBackdropFiltersGeometry):
Use a rounded rect if there is no clip and we have non-zero border-radius set on the renderer.

LayoutTests:

Adding new tests checking that border-radius correctly affects clipping of the backdrop layer
in a basic scenario, when we change border-radius to a different value, when we set border-radius
back to 0 and when we add a reflection.

* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-value-change-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove-expected.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html: Added.
* css3/filters/backdrop/backdrop-filter-with-border-radius.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (201784 => 201785)


--- trunk/LayoutTests/ChangeLog	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/LayoutTests/ChangeLog	2016-06-08 02:07:34 UTC (rev 201785)
@@ -1,3 +1,28 @@
+2016-06-07  Antoine Quint  <grao...@apple.com>
+
+        The backdrop-filter property does not respect border-radius
+        https://bugs.webkit.org/show_bug.cgi?id=158483
+        <rdar://problem/24210257>
+
+        Reviewed by Simon Fraser.
+
+        Adding new tests checking that border-radius correctly affects clipping of the backdrop layer
+        in a basic scenario, when we change border-radius to a different value, when we set border-radius
+        back to 0 and when we add a reflection.
+
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-value-change-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove-expected.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html: Added.
+        * css3/filters/backdrop/backdrop-filter-with-border-radius.html: Added.
+
 2016-06-07  Sam Weinig  <s...@webkit.org>
 
         Update tests to work around https://bugs.webkit.org/show_bug.cgi?id=158507.

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,37 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that we correctly add the reflection of an element with a backdrop-filter applied to it.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    .backdrop:last-of-type {
+        top: 110px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<div class="backdrop"></div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,49 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that we correctly add the reflection of an element with a backdrop-filter applied to it.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+        -webkit-box-reflect: none;
+    }
+
+    .changed {
+        -webkit-box-reflect: below 20px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<script type="text/_javascript_">
+    
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    window.requestAnimationFrame(function() {
+        document.querySelector(".backdrop").classList.add("changed");
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+    
+</script>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,37 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that the reflection of an element with a backdrop-filter applied also has a backdrop-filter of its own.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    .backdrop:last-of-type {
+        top: 110px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<div class="backdrop"></div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,32 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that we correctly remove the reflection of an element with a backdrop-filter applied to it.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,49 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that we correctly remove the reflection of an element with a backdrop-filter applied to it.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+        -webkit-box-reflect: below 20px;
+    }
+
+    .changed {
+        -webkit-box-reflect: none;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<script type="text/_javascript_">
+    
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    window.requestAnimationFrame(function() {
+        document.querySelector(".backdrop").classList.add("changed");
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+    
+</script>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,33 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that the reflection of an element with a backdrop-filter applied also has a backdrop-filter of its own.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 10px;
+        left: 60px;
+        width: 80px;
+        height: 80px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+        -webkit-box-reflect: below 20px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,56 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property.</title>
+    <style>
+
+    .background {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .stencil {
+        position: absolute;
+        top: 0;
+        left: 0;
+    }
+
+    .stencil > div {
+        position: absolute;
+        background-color: black;
+    }
+
+    .stencil > div:nth-of-type(1) {
+        width: 200px;
+        height: 20px;
+    }
+
+    .stencil > div:nth-of-type(2) {
+        width: 160px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(3) {
+        left: 180px;
+        width: 20px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(4) {
+        top: 40px;
+        width: 200px;
+        height: 160px;
+    }
+
+    </style>
+</head>
+<div class="background"></div>
+<div class="stencil">
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+</div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,56 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property and correctly updates the clipping when the border-radius property changes.</title>
+    <style>
+
+    .background {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .stencil {
+        position: absolute;
+        top: 0;
+        left: 0;
+    }
+
+    .stencil > div {
+        position: absolute;
+        background-color: black;
+    }
+
+    .stencil > div:nth-of-type(1) {
+        width: 200px;
+        height: 20px;
+    }
+
+    .stencil > div:nth-of-type(2) {
+        width: 160px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(3) {
+        left: 180px;
+        width: 20px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(4) {
+        top: 40px;
+        width: 200px;
+        height: 160px;
+    }
+
+    </style>
+</head>
+<div class="background"></div>
+<div class="stencil">
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+</div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,87 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property and correctly updates the clipping when the border-radius property changes.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 20px;
+        left: 20px;
+        width: 160px;
+        height: 160px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    .changed {
+        border-radius: 100%;
+    }
+
+    .stencil {
+        position: absolute;
+        top: 0;
+        left: 0;
+    }
+
+    .stencil > div {
+        position: absolute;
+        background-color: black;
+    }
+
+    .stencil > div:nth-of-type(1) {
+        width: 200px;
+        height: 20px;
+    }
+
+    .stencil > div:nth-of-type(2) {
+        width: 160px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(3) {
+        left: 180px;
+        width: 20px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(4) {
+        top: 40px;
+        width: 200px;
+        height: 160px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<div class="stencil">
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+</div>
+<script type="text/_javascript_">
+    
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    window.requestAnimationFrame(function() {
+        document.querySelector(".backdrop").classList.add("changed");
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+    
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove-expected.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove-expected.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove-expected.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,31 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property and correctly updates the clipping when the border-radius property changes to 0.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 20px;
+        left: 20px;
+        width: 160px;
+        height: 160px;
+        background-color: rgba(255, 255, 255, 0.5);
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,48 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property and correctly updates the clipping when the border-radius property changes to 0.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 20px;
+        left: 20px;
+        width: 160px;
+        height: 160px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 20px;
+        -webkit-backdrop-filter: invert(100%);
+    }
+
+    .changed {
+        border-radius: 0;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<script type="text/_javascript_">
+    
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    window.requestAnimationFrame(function() {
+        document.querySelector(".backdrop").classList.add("changed");
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+    
+</script>
\ No newline at end of file

Added: trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius.html (0 => 201785)


--- trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius.html	                        (rev 0)
+++ trunk/LayoutTests/css3/filters/backdrop/backdrop-filter-with-border-radius.html	2016-06-08 02:07:34 UTC (rev 201785)
@@ -0,0 +1,71 @@
+<head>
+    <meta name="viewport" content="width=device-width">
+    <title>This tests that an element clips its backdrop according to the border-radius property.</title>
+    <style>
+
+    svg {
+        position: absolute;
+        top: 0px;
+        left: 0px;
+        width: 200px;
+        height: 200px;
+        background-color: lightgray;
+    }
+
+    .backdrop {
+        position: absolute;
+        top: 20px;
+        left: 20px;
+        width: 160px;
+        height: 160px;
+        background-color: rgba(255, 255, 255, 0.5);
+        border-radius: 100%;
+        -webkit-backdrop-filter: invert(75%);
+    }
+
+    .stencil {
+        position: absolute;
+        top: 0;
+        left: 0;
+    }
+
+    .stencil > div {
+        position: absolute;
+        background-color: black;
+    }
+
+    .stencil > div:nth-of-type(1) {
+        width: 200px;
+        height: 20px;
+    }
+
+    .stencil > div:nth-of-type(2) {
+        width: 160px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(3) {
+        left: 180px;
+        width: 20px;
+        height: 200px;
+    }
+
+    .stencil > div:nth-of-type(4) {
+        top: 40px;
+        width: 200px;
+        height: 160px;
+    }
+
+    </style>
+</head>
+<svg viewbox="0 0 2 2">
+    <rect fill="black" x="0" y="0" width="1" height="1"></rect>
+    <rect fill="black" x="1" y="1" width="1" height="1"></rect>
+</svg>
+<div class="backdrop"></div>
+<div class="stencil">
+    <div></div>
+    <div></div>
+    <div></div>
+    <div></div>
+</div>

Modified: trunk/Source/WebCore/ChangeLog (201784 => 201785)


--- trunk/Source/WebCore/ChangeLog	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/Source/WebCore/ChangeLog	2016-06-08 02:07:34 UTC (rev 201785)
@@ -1,3 +1,39 @@
+2016-06-07  Antoine Quint  <grao...@apple.com>
+
+        The backdrop-filter property does not respect border-radius
+        https://bugs.webkit.org/show_bug.cgi?id=158483
+        <rdar://problem/24210257>
+
+        Reviewed by Simon Fraser.
+
+        In order to correctly support border-radius and backdrop-filter together, we change
+        the value set as the m_backdropFiltersRect from a FloatRect to FloatRoundedRect so
+        that it accounts for values set by the border-radius property. Then we add a new
+        m_backdropClippingLayer PlatformCALayer member to clip the backdrop layer in the
+        event that the border-radius is non-zero in updateBackdropFiltersRect(). Finally,
+        we follow the same pattern used for other PlatformCALayers owned by a GraphicsLayerCA
+        to support cloning of the new m_backdropClippingLayer.
+
+        Tests: css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-add.html
+               css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection-remove.html
+               css3/filters/backdrop/backdrop-filter-with-border-radius-and-reflection.html
+               css3/filters/backdrop/backdrop-filter-with-border-radius-value-change.html
+               css3/filters/backdrop/backdrop-filter-with-border-radius-value-remove.html
+               css3/filters/backdrop/backdrop-filter-with-border-radius.html
+
+        * platform/graphics/GraphicsLayer.h:
+        (WebCore::GraphicsLayer::setBackdropFiltersRect):
+        (WebCore::GraphicsLayer::backdropFiltersRect):
+        * platform/graphics/ca/GraphicsLayerCA.cpp:
+        (WebCore::GraphicsLayerCA::willBeDestroyed):
+        (WebCore::GraphicsLayerCA::setBackdropFiltersRect):
+        (WebCore::GraphicsLayerCA::updateBackdropFiltersRect):
+        (WebCore::GraphicsLayerCA::dumpAdditionalProperties):
+        * platform/graphics/ca/GraphicsLayerCA.h:
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateBackdropFiltersGeometry):
+        Use a rounded rect if there is no clip and we have non-zero border-radius set on the renderer.
+
 2016-06-07  Andreas Kling  <akl...@apple.com>
 
         CachedScript should avoid recomputing its hash multiple times.

Modified: trunk/Source/WebCore/platform/graphics/GraphicsLayer.h (201784 => 201785)


--- trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/Source/WebCore/platform/graphics/GraphicsLayer.h	2016-06-08 02:07:34 UTC (rev 201785)
@@ -377,8 +377,8 @@
     const FilterOperations& backdropFilters() const { return m_backdropFilters; }
     virtual bool setBackdropFilters(const FilterOperations& filters) { m_backdropFilters = filters; return true; }
 
-    virtual void setBackdropFiltersRect(const FloatRect& backdropFiltersRect) { m_backdropFiltersRect = backdropFiltersRect; }
-    FloatRect backdropFiltersRect() const { return m_backdropFiltersRect; }
+    virtual void setBackdropFiltersRect(const FloatRoundedRect& backdropFiltersRect) { m_backdropFiltersRect = backdropFiltersRect; }
+    const FloatRoundedRect& backdropFiltersRect() const { return m_backdropFiltersRect; }
 
 #if ENABLE(CSS_COMPOSITING)
     BlendMode blendMode() const { return m_blendMode; }
@@ -645,7 +645,7 @@
     FloatRoundedRect m_masksToBoundsRect;
     FloatSize m_contentsTilePhase;
     FloatSize m_contentsTileSize;
-    FloatRect m_backdropFiltersRect;
+    FloatRoundedRect m_backdropFiltersRect;
 
     int m_repaintCount;
     CustomAppearance m_customAppearance;

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp (201784 => 201785)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp	2016-06-08 02:07:34 UTC (rev 201785)
@@ -434,6 +434,9 @@
     if (m_backdropLayer)
         m_backdropLayer->setOwner(nullptr);
 
+    if (m_backdropClippingLayer)
+        m_backdropClippingLayer->setOwner(nullptr);
+
     removeCloneLayers();
 
     GraphicsLayer::willBeDestroyed();
@@ -771,7 +774,7 @@
     return canCompositeFilters;
 }
 
-void GraphicsLayerCA::setBackdropFiltersRect(const FloatRect& backdropFiltersRect)
+void GraphicsLayerCA::setBackdropFiltersRect(const FloatRoundedRect& backdropFiltersRect)
 {
     if (backdropFiltersRect == m_backdropFiltersRect)
         return;
@@ -1964,15 +1967,31 @@
 {
     if (!m_backdropLayer)
         return;
-    FloatRect contentBounds(0, 0, m_backdropFiltersRect.width(), m_backdropFiltersRect.height());
+
+    FloatRect contentBounds(0, 0, m_backdropFiltersRect.rect().width(), m_backdropFiltersRect.rect().height());
     m_backdropLayer->setBounds(contentBounds);
-    m_backdropLayer->setPosition(m_backdropFiltersRect.location());
+    m_backdropLayer->setPosition(m_backdropFiltersRect.rect().location());
 
-    if (LayerMap* layerCloneMap = m_backdropLayerClones.get()) {
-        for (auto& clone : *layerCloneMap) {
-            PlatformCALayer* cloneLayer = clone.value.get();
-            cloneLayer->setBounds(contentBounds);
-            cloneLayer->setPosition(m_backdropFiltersRect.location());
+    updateClippingStrategy(*m_backdropLayer, m_backdropClippingLayer, m_backdropFiltersRect);
+
+    if (m_backdropLayerClones) {
+        for (auto& clone : *m_backdropLayerClones) {
+            PlatformCALayer* backdropCloneLayer = clone.value.get();
+            backdropCloneLayer->setBounds(contentBounds);
+            backdropCloneLayer->setPosition(m_backdropFiltersRect.rect().location());
+
+            CloneID cloneID = clone.key;
+            RefPtr<PlatformCALayer> backdropClippingLayerClone;
+            if (m_backdropClippingLayerClones)
+                backdropClippingLayerClone = m_backdropClippingLayerClones->get(cloneID);
+
+            bool hadBackdropClippingLayer = backdropClippingLayerClone;
+            updateClippingStrategy(*backdropCloneLayer, backdropClippingLayerClone, m_backdropFiltersRect);
+
+            if (!backdropClippingLayerClone && m_backdropClippingLayerClones)
+                m_backdropClippingLayerClones->remove(cloneID);
+            else if (backdropClippingLayerClone && !hadBackdropClippingLayer)
+                m_backdropClippingLayerClones->add(cloneID, backdropClippingLayerClone);
         }
     }
 }
@@ -3451,6 +3470,7 @@
         dumpInnerLayer(textStream, "structural layer", m_structuralLayer.get(), indent, behavior);
         dumpInnerLayer(textStream, "contents clipping layer", m_contentsClippingLayer.get(), indent, behavior);
         dumpInnerLayer(textStream, "shape mask layer", m_shapeMaskLayer.get(), indent, behavior);
+        dumpInnerLayer(textStream, "backdrop clipping layer", m_backdropClippingLayer.get(), indent, behavior);
         dumpInnerLayer(textStream, "contents layer", m_contentsLayer.get(), indent, behavior);
         dumpInnerLayer(textStream, "contents shape mask layer", m_contentsShapeMaskLayer.get(), indent, behavior);
         dumpInnerLayer(textStream, "backdrop layer", m_backdropLayer.get(), indent, behavior);
@@ -3609,7 +3629,7 @@
 }   
 
 void GraphicsLayerCA::ensureCloneLayers(CloneID cloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer,
-    RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, RefPtr<PlatformCALayer>& contentsShapeMaskLayer, RefPtr<PlatformCALayer>& shapeMaskLayer, RefPtr<PlatformCALayer>& backdropLayer, CloneLevel cloneLevel)
+    RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, RefPtr<PlatformCALayer>& contentsShapeMaskLayer, RefPtr<PlatformCALayer>& shapeMaskLayer, RefPtr<PlatformCALayer>& backdropLayer, RefPtr<PlatformCALayer>& backdropClippingLayer, CloneLevel cloneLevel)
 {
     structuralLayer = nullptr;
     contentsLayer = nullptr;
@@ -3634,7 +3654,10 @@
 
     if (!m_backdropLayerClones && m_backdropLayer)
         m_backdropLayerClones = std::make_unique<LayerMap>();
-    
+
+    if (!m_backdropClippingLayerClones && m_backdropClippingLayer)
+        m_backdropClippingLayerClones = std::make_unique<LayerMap>();
+
     primaryLayer = findOrMakeClone(cloneID, m_layer.get(), m_layerClones.get(), cloneLevel);
     structuralLayer = findOrMakeClone(cloneID, m_structuralLayer.get(), m_structuralLayerClones.get(), cloneLevel);
     contentsLayer = findOrMakeClone(cloneID, m_contentsLayer.get(), m_contentsLayerClones.get(), cloneLevel);
@@ -3642,6 +3665,7 @@
     contentsShapeMaskLayer = findOrMakeClone(cloneID, m_contentsShapeMaskLayer.get(), m_contentsShapeMaskLayerClones.get(), cloneLevel);
     shapeMaskLayer = findOrMakeClone(cloneID, m_shapeMaskLayer.get(), m_shapeMaskLayerClones.get(), cloneLevel);
     backdropLayer = findOrMakeClone(cloneID, m_backdropLayer.get(), m_backdropLayerClones.get(), cloneLevel);
+    backdropClippingLayer = findOrMakeClone(cloneID, m_backdropClippingLayer.get(), m_backdropClippingLayerClones.get(), cloneLevel);
 }
 
 void GraphicsLayerCA::clearClones(std::unique_ptr<LayerMap>& layerMap)
@@ -3664,6 +3688,7 @@
     clearClones(m_contentsShapeMaskLayerClones);
     clearClones(m_shapeMaskLayerClones);
     clearClones(m_backdropLayerClones);
+    clearClones(m_backdropClippingLayerClones);
 }
 
 FloatPoint GraphicsLayerCA::positionForCloneRootLayer() const
@@ -3698,7 +3723,8 @@
     RefPtr<PlatformCALayer> contentsShapeMaskLayer;
     RefPtr<PlatformCALayer> shapeMaskLayer;
     RefPtr<PlatformCALayer> backdropLayer;
-    ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, contentsClippingLayer, contentsShapeMaskLayer, shapeMaskLayer, backdropLayer, cloneLevel);
+    RefPtr<PlatformCALayer> backdropClippingLayer;
+    ensureCloneLayers(replicaState.cloneID(), primaryLayer, structuralLayer, contentsLayer, contentsClippingLayer, contentsShapeMaskLayer, shapeMaskLayer, backdropLayer, backdropClippingLayer, cloneLevel);
 
     if (m_maskLayer) {
         RefPtr<PlatformCALayer> maskClone = downcast<GraphicsLayerCA>(*m_maskLayer).fetchCloneLayers(replicaRoot, replicaState, IntermediateCloneLevel);
@@ -3745,8 +3771,10 @@
 
     if (replicaLayer || structuralLayer || contentsLayer || contentsClippingLayer || childLayers.size() > 0) {
         if (structuralLayer) {
-            if (backdropLayer)
+            if (backdropLayer) {
                 clonalSublayers.append(backdropLayer);
+                backdropLayer->setMask(backdropClippingLayer.get());
+            }
             
             // Replicas render behind the actual layer content.
             if (replicaLayer)

Modified: trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h (201784 => 201785)


--- trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h	2016-06-08 02:07:34 UTC (rev 201785)
@@ -104,7 +104,7 @@
     virtual bool filtersCanBeComposited(const FilterOperations&);
 
     WEBCORE_EXPORT bool setBackdropFilters(const FilterOperations&) override;
-    WEBCORE_EXPORT void setBackdropFiltersRect(const FloatRect&) override;
+    WEBCORE_EXPORT void setBackdropFiltersRect(const FloatRoundedRect&) override;
 
 #if ENABLE(CSS_COMPOSITING)
     WEBCORE_EXPORT void setBlendMode(BlendMode) override;
@@ -375,7 +375,9 @@
     PassRefPtr<PlatformCALayer> findOrMakeClone(CloneID, PlatformCALayer *, LayerMap*, CloneLevel);
 
     void ensureCloneLayers(CloneID, RefPtr<PlatformCALayer>& primaryLayer, RefPtr<PlatformCALayer>& structuralLayer,
-        RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, RefPtr<PlatformCALayer>& contentsShapeMaskLayer, RefPtr<PlatformCALayer>& shapeMaskLayer, RefPtr<PlatformCALayer>& backdropLayer, CloneLevel);
+        RefPtr<PlatformCALayer>& contentsLayer, RefPtr<PlatformCALayer>& contentsClippingLayer, RefPtr<PlatformCALayer>& contentsShapeMaskLayer,
+        RefPtr<PlatformCALayer>& shapeMaskLayer, RefPtr<PlatformCALayer>& backdropLayer, RefPtr<PlatformCALayer>& backdropClippingLayer,
+        CloneLevel);
 
     static void clearClones(std::unique_ptr<LayerMap>&);
 
@@ -508,6 +510,7 @@
     RefPtr<PlatformCALayer> m_structuralLayer; // A layer used for structural reasons, like preserves-3d or replica-flattening. Is the parent of m_layer.
     RefPtr<PlatformCALayer> m_contentsClippingLayer; // A layer used to clip inner content
     RefPtr<PlatformCALayer> m_shapeMaskLayer; // Used to clip with non-trivial corner radii.
+    RefPtr<PlatformCALayer> m_backdropClippingLayer; // Used to clip the backdrop layer with corner radii.
     RefPtr<PlatformCALayer> m_contentsLayer; // A layer used for inner content, like image and video
     RefPtr<PlatformCALayer> m_contentsShapeMaskLayer; // Used to clip the content layer with non-trivial corner radii.
     RefPtr<PlatformCALayer> m_backdropLayer; // The layer used for backdrop rendering, if necessary.
@@ -520,6 +523,7 @@
     std::unique_ptr<LayerMap> m_contentsShapeMaskLayerClones;
     std::unique_ptr<LayerMap> m_shapeMaskLayerClones;
     std::unique_ptr<LayerMap> m_backdropLayerClones;
+    std::unique_ptr<LayerMap> m_backdropClippingLayerClones;
 
 #ifdef VISIBLE_TILE_WASH
     RefPtr<PlatformCALayer> m_visibleTileWashLayer;

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (201784 => 201785)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2016-06-08 01:53:44 UTC (rev 201784)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2016-06-08 02:07:34 UTC (rev 201785)
@@ -425,12 +425,18 @@
         return;
 
     RenderBox& renderer = downcast<RenderBox>(this->renderer());
-    LayoutRect backdropFiltersRect = renderer.borderBoxRect();
+    LayoutRect boxRect = renderer.borderBoxRect();
     if (renderer.hasClip())
-        backdropFiltersRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
+        boxRect.intersect(renderer.clipRect(LayoutPoint(), nullptr));
+    boxRect.move(contentOffsetInCompostingLayer());
 
-    backdropFiltersRect.move(contentOffsetInCompostingLayer());
-    m_graphicsLayer->setBackdropFiltersRect(snapRectToDevicePixels(backdropFiltersRect, deviceScaleFactor()));
+    FloatRoundedRect backdropFiltersRect;
+    if (renderer.style().hasBorderRadius() && !renderer.hasClip())
+        backdropFiltersRect = renderer.style().getRoundedInnerBorderFor(boxRect).pixelSnappedRoundedRectForPainting(deviceScaleFactor());
+    else
+        backdropFiltersRect = FloatRoundedRect(snapRectToDevicePixels(boxRect, deviceScaleFactor()));
+
+    m_graphicsLayer->setBackdropFiltersRect(backdropFiltersRect);
 }
 #endif
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to