Setting -webkit-filter: in :active selector causes failure to redraw
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Aug 2013 00:15:08 +0000 (00:15 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Aug 2013 00:15:08 +0000 (00:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=120135

Source/WebCore:

Reviewed by Jer Noble.

When removing a filter on an inline child of a compositing layer,
the inline loses its RenderLayer and compositing layer, but we fail to
repaint the compositing layer that the inline is now painting into.

This worked correctly for opacity, because opacity toggles cause
layouts (which then paint the correct layer), so do the same for filters.

Test: css3/filters/remove-filter-repaint.html

* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::changeRequiresLayout): Return true if we toggled
between having filters and not. Drive-by cleanup, making use of new convenience
function for hasOpacity().
* rendering/style/StyleRareNonInheritedData.cpp:
(WebCore::StyleRareNonInheritedData::hasFilters): Returns true if we have any
filters.
* rendering/style/StyleRareNonInheritedData.h:
(WebCore::StyleRareNonInheritedData::hasOpacity): Convenience function that
returns true if opacity is < 1.

LayoutTests:

Reviewed by Jer Noble.

Ref test for removing a filter on an inline.

* css3/filters/remove-filter-repaint-expected.html: Added.
* css3/filters/remove-filter-repaint.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/css3/filters/remove-filter-repaint-expected.html [new file with mode: 0644]
LayoutTests/css3/filters/remove-filter-repaint.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/style/RenderStyle.cpp
Source/WebCore/rendering/style/StyleRareNonInheritedData.cpp
Source/WebCore/rendering/style/StyleRareNonInheritedData.h

index ea46eb3..11559cd 100644 (file)
@@ -1,3 +1,15 @@
+2013-08-21  Simon Fraser  <simon.fraser@apple.com>
+
+        Setting -webkit-filter: in :active selector causes failure to redraw
+        https://bugs.webkit.org/show_bug.cgi?id=120135
+
+        Reviewed by Jer Noble.
+        
+        Ref test for removing a filter on an inline.
+
+        * css3/filters/remove-filter-repaint-expected.html: Added.
+        * css3/filters/remove-filter-repaint.html: Added.
+
 2013-08-21  Yi Shen  <max.hong.shen@gmail.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=119900
diff --git a/LayoutTests/css3/filters/remove-filter-repaint-expected.html b/LayoutTests/css3/filters/remove-filter-repaint-expected.html
new file mode 100644 (file)
index 0000000..07ff2c3
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>filter-bug</title>
+    <style>
+    .backdrop {
+        position: absolute;
+        top: 0;
+        left: 0;
+        height: 100px;
+        width: 100px;
+        background-color: silver;
+    }
+
+    .overlay {
+        position: absolute;
+        top: 50px;
+        left: 50px;
+        width: 400px;
+        height: 100px;
+        background: gray;
+        box-shadow: 0 0 4px black;
+    }
+    
+    .play {
+        font-size: 36pt;
+        background-color: navy;
+        color: white;
+    }
+    .composited {
+        -webkit-transform: translateZ(0);
+    }
+    </style>
+</head>
+<body>
+    <div class="composited backdrop"></div>
+    <div class="overlay">
+        <span id="play" class="play changed">this should be visible</span>
+    </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/LayoutTests/css3/filters/remove-filter-repaint.html b/LayoutTests/css3/filters/remove-filter-repaint.html
new file mode 100644 (file)
index 0000000..59b41d0
--- /dev/null
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>filter-bug</title>
+    <style>
+    .backdrop {
+        position: absolute;
+        top: 0;
+        left: 0;
+        height: 100px;
+        width: 100px;
+        background-color: silver;
+    }
+
+    .overlay {
+        position: absolute;
+        top: 50px;
+        left: 50px;
+        width: 400px;
+        height: 100px;
+        background: gray;
+        box-shadow: 0 0 4px black;
+    }
+    
+    .play {
+        font-size: 36pt;
+        background-color: navy;
+        color: white;
+    }
+    .play.changed {
+        -webkit-filter: drop-shadow(black 0 0 5px);
+    }
+    .composited {
+        -webkit-transform: translateZ(0);
+    }
+    </style>
+    <script>
+        if (window.testRunner)
+            testRunner.waitUntilDone();
+        function doTest()
+        {
+            window.setTimeout(function() {
+                document.getElementById('play').classList.remove('changed');
+                if (window.testRunner)
+                    testRunner.notifyDone();
+            }, 0);
+        }
+        window.addEventListener('load', doTest, false);
+    </script>
+</head>
+<body>
+    <div class="composited backdrop"></div>
+    <div class="overlay">
+        <span id="play" class="play changed">this should be visible</span>
+    </div>
+</body>
+</html>
\ No newline at end of file
index 2e820d3..e2cc958 100644 (file)
@@ -1,3 +1,30 @@
+2013-08-21  Simon Fraser  <simon.fraser@apple.com>
+
+        Setting -webkit-filter: in :active selector causes failure to redraw
+        https://bugs.webkit.org/show_bug.cgi?id=120135
+
+        Reviewed by Jer Noble.
+        
+        When removing a filter on an inline child of a compositing layer,
+        the inline loses its RenderLayer and compositing layer, but we fail to
+        repaint the compositing layer that the inline is now painting into.
+        
+        This worked correctly for opacity, because opacity toggles cause
+        layouts (which then paint the correct layer), so do the same for filters.
+
+        Test: css3/filters/remove-filter-repaint.html
+
+        * rendering/style/RenderStyle.cpp:
+        (WebCore::RenderStyle::changeRequiresLayout): Return true if we toggled
+        between having filters and not. Drive-by cleanup, making use of new convenience
+        function for hasOpacity().
+        * rendering/style/StyleRareNonInheritedData.cpp:
+        (WebCore::StyleRareNonInheritedData::hasFilters): Returns true if we have any
+        filters.
+        * rendering/style/StyleRareNonInheritedData.h:
+        (WebCore::StyleRareNonInheritedData::hasOpacity): Convenience function that
+        returns true if opacity is < 1.
+
 2013-08-21  Gavin Barraclough  <barraclough@apple.com>
 
         https://bugs.webkit.org/show_bug.cgi?id=120139
index c0b148c..6dcd815 100644 (file)
@@ -597,8 +597,7 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& chang
     if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
         return true;
 
-    if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1)
-        || (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
+    if (rareNonInheritedData->hasOpacity() != other->rareNonInheritedData->hasOpacity()) {
         // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
         // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
         // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
@@ -607,6 +606,11 @@ bool RenderStyle::changeRequiresLayout(const RenderStyle* other, unsigned& chang
         return true;
     }
 
+#if ENABLE(CSS_FILTERS)
+    if (rareNonInheritedData->hasFilters() != other->rareNonInheritedData->hasFilters())
+        return true;
+#endif
+
     const QuotesData* quotesDataA = rareInheritedData->quotes.get();
     const QuotesData* quotesDataB = other->rareInheritedData->quotes.get();
     if (!(quotesDataA == quotesDataB || (quotesDataA && quotesDataB && *quotesDataA == *quotesDataB)))
index a592957..216d787 100644 (file)
@@ -326,4 +326,9 @@ bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInher
     return true;
 }
 
+bool StyleRareNonInheritedData::hasFilters() const
+{
+    return m_filter.get() && !m_filter->m_operations.isEmpty();
+}
+
 } // namespace WebCore
index 33fdf08..2a00fa3 100644 (file)
@@ -90,8 +90,10 @@ public:
     bool reflectionDataEquivalent(const StyleRareNonInheritedData&) const;
     bool animationDataEquivalent(const StyleRareNonInheritedData&) const;
     bool transitionDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool hasFilters() const;
+    bool hasOpacity() const { return opacity < 1; }
 
-    float opacity; // Whether or not we're transparent.
+    float opacity;
 
     float m_aspectRatioDenominator;
     float m_aspectRatioNumerator;