Paint artifacts when hovering on http://jsfiddle.net/Sherbrow/T87Mn/
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Oct 2015 02:51:29 +0000 (02:51 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 7 Oct 2015 02:51:29 +0000 (02:51 +0000)
https://bugs.webkit.org/show_bug.cgi?id=149535
rdar://problem/22874920

Reviewed by Simon Fraser.

When due to some style change, a renderer's self-painting layer is getting destroyed
and the parent's overflow is no longer set to visible, we don't clean up the overflow part.

When a renderer has a self-painting layer, the parent stops tracking the child's
visual overflow rect. All overflow painting is delegated to the self-painting layer.
However when this layer gets destroyed, no-one issues repaint to clean up
the overflow bits.
This patch ensures that we issue a repaint when the self-painting layer is destroyed
and the triggering style change requires full repaint.

Source/WebCore:

Test: fast/repaint/overflow-hidden-with-self-painting-child-layer.html

* rendering/RenderLayer.h:
* rendering/RenderLayerModelObject.cpp:
(WebCore::RenderLayerModelObject::styleDidChange):

LayoutTests:

* css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt: progression.
* fast/repaint/absolute-position-change-containing-block-expected.txt: progression.
* fast/repaint/overflow-hidden-with-self-painting-child-layer-expected.txt: Added.
* fast/repaint/overflow-hidden-with-self-painting-child-layer.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt
LayoutTests/fast/repaint/absolute-position-change-containing-block-expected.txt
LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer-expected.txt [new file with mode: 0644]
LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/rendering/RenderLayer.h
Source/WebCore/rendering/RenderLayerModelObject.cpp

index 595e37d..d493afc 100644 (file)
@@ -1,3 +1,26 @@
+2015-10-06  Zalan Bujtas  <zalan@apple.com>
+
+        Paint artifacts when hovering on http://jsfiddle.net/Sherbrow/T87Mn/
+        https://bugs.webkit.org/show_bug.cgi?id=149535
+        rdar://problem/22874920
+
+        Reviewed by Simon Fraser.
+
+        When due to some style change, a renderer's self-painting layer is getting destroyed 
+        and the parent's overflow is no longer set to visible, we don't clean up the overflow part.
+
+        When a renderer has a self-painting layer, the parent stops tracking the child's 
+        visual overflow rect. All overflow painting is delegated to the self-painting layer.
+        However when this layer gets destroyed, no-one issues repaint to clean up
+        the overflow bits.
+        This patch ensures that we issue a repaint when the self-painting layer is destroyed
+        and the triggering style change requires full repaint.
+
+        * css3/blending/repaint/blend-mode-isolate-stacking-context-expected.txt: progression.
+        * fast/repaint/absolute-position-change-containing-block-expected.txt: progression.
+        * fast/repaint/overflow-hidden-with-self-painting-child-layer-expected.txt: Added.
+        * fast/repaint/overflow-hidden-with-self-painting-child-layer.html: Added.
+
 2015-10-06  Jon Honeycutt  <jhoneycutt@apple.com>
 
         More unreviewed Windows test gardening after r190629.
index e805205..ce0354a 100644 (file)
@@ -19,6 +19,7 @@ Test if unsetting a parent's stacking context correctly updates its parent isola
   (rect 48 172 60 60)
   (rect 28 290 60 60)
   (rect 48 290 60 60)
+  (rect 28 290 60 60)
   (rect 48 290 60 60)
   (rect 48 408 60 60)
   (rect 48 408 60 60)
@@ -26,6 +27,7 @@ Test if unsetting a parent's stacking context correctly updates its parent isola
   (rect 48 526 60 60)
   (rect 48 644 60 60)
   (rect 68 644 60 60)
+  (rect 48 644 60 60)
   (rect 68 644 60 60)
   (rect 28 290 60 60)
   (rect 48 644 60 60)
index b2d535f..a7c6dc5 100644 (file)
@@ -2,6 +2,7 @@
   (rect 8 5000 100 100)
   (rect 108 5100 100 100)
   (rect 8 8 784 2000)
+  (rect 8 5000 100 100)
   (rect 108 5100 100 100)
   (rect 100 100 100 100)
   (rect 16 5008 100 100)
diff --git a/LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer-expected.txt b/LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer-expected.txt
new file mode 100644 (file)
index 0000000..8731b40
--- /dev/null
@@ -0,0 +1,5 @@
+PASS window.internals.repaintRectsAsText().indexOf('200 200') is not -1
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer.html b/LayoutTests/fast/repaint/overflow-hidden-with-self-painting-child-layer.html
new file mode 100644 (file)
index 0000000..9527fe7
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<script>jsTestIsAsync = true;</script>
+<script src="../../resources/js-test-pre.js"></script>
+<head>
+<title>This tests that we don't leave bits behind, when the self-painting child layer get destroyed while the parent becomes overflow: hidden.</title>
+<style>
+#container { 
+       position: relative;
+       overflow: visible; 
+       height: 100px;
+       width: 100px;
+}
+
+#content { 
+       position: relative;
+       height: 200px;
+       width: 200px;
+       background: green;
+}
+</style>
+</head>
+<body>
+<div id=container>
+    <div id=content></div>
+</div>
+<script>
+setTimeout(
+       function() { 
+        if (window.internals)
+               internals.startTrackingRepaints();
+               document.getElementById("container").style.overflow = "hidden";
+               document.getElementById("content").style.position = "static";
+               document.body.offsetWidth;
+
+        if (window.internals) {
+            shouldNotBe("window.internals.repaintRectsAsText().indexOf('200 200')", "-1");
+            internals.stopTrackingRepaints();
+        }
+        finishJSTest();
+       }, 0);
+</script>
+</body>
+<script src="../../resources/js-test-post.js"></script>
+</html>
index 5380e03..081ffdf 100644 (file)
@@ -1,3 +1,27 @@
+2015-10-06  Zalan Bujtas  <zalan@apple.com>
+
+        Paint artifacts when hovering on http://jsfiddle.net/Sherbrow/T87Mn/
+        https://bugs.webkit.org/show_bug.cgi?id=149535
+        rdar://problem/22874920
+
+        Reviewed by Simon Fraser.
+
+        When due to some style change, a renderer's self-painting layer is getting destroyed 
+        and the parent's overflow is no longer set to visible, we don't clean up the overflow part.
+
+        When a renderer has a self-painting layer, the parent stops tracking the child's 
+        visual overflow rect. All overflow painting is delegated to the self-painting layer.
+        However when this layer gets destroyed, no-one issues repaint to clean up
+        the overflow bits.
+        This patch ensures that we issue a repaint when the self-painting layer is destroyed
+        and the triggering style change requires full repaint.
+
+        Test: fast/repaint/overflow-hidden-with-self-painting-child-layer.html
+
+        * rendering/RenderLayer.h:
+        * rendering/RenderLayerModelObject.cpp:
+        (WebCore::RenderLayerModelObject::styleDidChange):
+
 2015-10-06  Jer Noble  <jer.noble@apple.com>
 
         [Mac] REGRESSION(r173318): Seeks never complete for media loaded with QTKit.
index ed1b400..979b6c0 100644 (file)
@@ -536,6 +536,7 @@ public:
     LayoutRect repaintRectIncludingNonCompositingDescendants() const;
 
     void setRepaintStatus(RepaintStatus status) { m_repaintStatus = status; }
+    RepaintStatus repaintStatus() const { return static_cast<RepaintStatus>(m_repaintStatus); }
 
     LayoutUnit staticInlinePosition() const { return m_staticInlinePosition; }
     LayoutUnit staticBlockPosition() const { return m_staticBlockPosition; }
index 28ba58c..599a173 100644 (file)
@@ -159,6 +159,9 @@ void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderSt
 #endif
         setHasTransformRelatedProperty(false); // All transform-related propeties force layers, so we know we don't have one or the object doesn't support them.
         setHasReflection(false);
+        // Repaint the about to be destroyed self-painting layer when style change also triggers repaint.
+        if (layer()->isSelfPaintingLayer() && layer()->repaintStatus() == NeedsFullRepaint)
+            repaintUsingContainer(containerForRepaint(), layer()->repaintRect());
         layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer
         if (s_wasFloating && isFloating())
             setChildNeedsLayout();