Title: [185152] trunk
Revision
185152
Author
za...@apple.com
Date
2015-06-03 08:36:41 -0700 (Wed, 03 Jun 2015)

Log Message

Subpixel rendering: Composited layer with subpixel gap does not get painted properly when its position changes.
https://bugs.webkit.org/show_bug.cgi?id=145587

Reviewed by Simon Fraser.

The composited layer always snaps to an enclosing device pixel (floors) while the renderer rounds.
At certain positions (for example 0.5px on a 1x display), a gap is formed between the layer(0px) and its renderer(1px).
In such cases, when the the renderer moves to a position (1.1px) where the gap is closed, we need to issue repaint on the layer
in order to get the renderering right.

Source/WebCore:

Test: compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html

* rendering/RenderLayerBacking.cpp:
(WebCore::RenderLayerBacking::updateAfterLayout):
(WebCore::devicePixelFractionGapFromRendererChanged):
(WebCore::RenderLayerBacking::updateGeometry):
* rendering/RenderLayerBacking.h:

LayoutTests:

* compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves-expected.html: Added.
* compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (185151 => 185152)


--- trunk/LayoutTests/ChangeLog	2015-06-03 14:58:01 UTC (rev 185151)
+++ trunk/LayoutTests/ChangeLog	2015-06-03 15:36:41 UTC (rev 185152)
@@ -1,3 +1,18 @@
+2015-06-03  Zalan Bujtas  <za...@apple.com>
+
+        Subpixel rendering: Composited layer with subpixel gap does not get painted properly when its position changes.
+        https://bugs.webkit.org/show_bug.cgi?id=145587
+
+        Reviewed by Simon Fraser.
+
+        The composited layer always snaps to an enclosing device pixel (floors) while the renderer rounds.
+        At certain positions (for example 0.5px on a 1x display), a gap is formed between the layer(0px) and its renderer(1px).
+        In such cases, when the the renderer moves to a position (1.1px) where the gap is closed, we need to issue repaint on the layer
+        in order to get the renderering right.
+
+        * compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves-expected.html: Added.
+        * compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html: Added.
+
 2015-06-02  Sergio Villar Senin  <svil...@igalia.com>
 
         [CSS Grid Layout] Switch from parenthesis to brackets for grid line names

Added: trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves-expected.html (0 => 185152)


--- trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves-expected.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves-expected.html	2015-06-03 15:36:41 UTC (rev 185152)
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that we repaint child layer if the subpixel gap changes between layers when parent layer moves.</title>
+<style>
+    .outer {
+        position: relative;
+        left: 0.7px;
+        height: 200px;
+        width: 200px;
+        background-color: rgba(0, 0, 255, 1);
+    }
+
+    .container-background {
+        position: relative;
+        transform: translateZ(0);
+        height: 100px;
+        width: 100px;
+        background-color: green;
+    }
+
+</style>
+<body>
+<div id=container class=outer>foo
+  <div class=container-background>bar
+  </div>
+</div>
+</body>

Added: trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html (0 => 185152)


--- trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html	                        (rev 0)
+++ trunk/LayoutTests/compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html	2015-06-03 15:36:41 UTC (rev 185152)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>This tests that we repaint child layer if the subpixel gap changes between layers when parent layer moves.</title>
+<style>
+    .outer {
+        position: relative;
+        left: 0.3px;
+        height: 200px;
+        width: 200px;
+        background-color: rgba(0, 0, 255, 1);
+    }
+
+    .container-background {
+        position: relative;
+        transform: translateZ(0);
+        height: 100px;
+        width: 100px;
+        background-color: green;
+    }
+
+</style>
+<script>
+    if (window.testRunner)
+        testRunner.waitUntilDone();
+
+    function runTest() {
+    	setTimeout(function () {
+    	    document.getElementById("container").style.left = "0.7px";
+            if (window.testRunner)
+                testRunner.notifyDone();
+        }, 0);
+    }
+    window.addEventListener('load', runTest, false);
+</script>
+<body>
+<div id=container class=outer>foo
+  <div class=container-background>bar
+  </div>
+</div>
+</body>

Modified: trunk/Source/WebCore/ChangeLog (185151 => 185152)


--- trunk/Source/WebCore/ChangeLog	2015-06-03 14:58:01 UTC (rev 185151)
+++ trunk/Source/WebCore/ChangeLog	2015-06-03 15:36:41 UTC (rev 185152)
@@ -1,3 +1,23 @@
+2015-06-03  Zalan Bujtas  <za...@apple.com>
+
+        Subpixel rendering: Composited layer with subpixel gap does not get painted properly when its position changes.
+        https://bugs.webkit.org/show_bug.cgi?id=145587
+
+        Reviewed by Simon Fraser.
+
+        The composited layer always snaps to an enclosing device pixel (floors) while the renderer rounds.
+        At certain positions (for example 0.5px on a 1x display), a gap is formed between the layer(0px) and its renderer(1px).
+        In such cases, when the the renderer moves to a position (1.1px) where the gap is closed, we need to issue repaint on the layer
+        in order to get the renderering right.
+
+        Test: compositing/child-layer-with-subpixel-gap-needs-repaint-when-parent-moves.html
+
+        * rendering/RenderLayerBacking.cpp:
+        (WebCore::RenderLayerBacking::updateAfterLayout):
+        (WebCore::devicePixelFractionGapFromRendererChanged):
+        (WebCore::RenderLayerBacking::updateGeometry):
+        * rendering/RenderLayerBacking.h:
+
 2015-06-03  Xabier Rodriguez Calvar  <calva...@igalia.com> and Youenn Fablet <youenn.fab...@crf.canon.fr>
 
         [Streams API] ReadableStreamReader::closed() should be called once by binding code

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.cpp (185151 => 185152)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2015-06-03 14:58:01 UTC (rev 185151)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.cpp	2015-06-03 15:36:41 UTC (rev 185152)
@@ -536,7 +536,7 @@
         }
     }
     
-    if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
+    if (flags & NeedsFullRepaint && canIssueSetNeedsDisplay())
         setContentsNeedDisplay();
 }
 
@@ -655,6 +655,13 @@
     return result;
 }
 
+static bool devicePixelFractionGapFromRendererChanged(const LayoutSize& previousDevicePixelFractionFromRenderer, const LayoutSize& currentDevicePixelFractionFromRenderer, float deviceScaleFactor)
+{
+    FloatSize previous = snapSizeToDevicePixel(previousDevicePixelFractionFromRenderer, LayoutPoint(), deviceScaleFactor);
+    FloatSize current = snapSizeToDevicePixel(currentDevicePixelFractionFromRenderer, LayoutPoint(), deviceScaleFactor);
+    return previous != current;
+}
+
 static FloatSize pixelFractionForLayerPainting(const LayoutPoint& point, float pixelSnappingFactor)
 {
     LayoutUnit x = point.x();
@@ -749,6 +756,7 @@
     FloatSize devicePixelOffsetFromRenderer;
     LayoutSize devicePixelFractionFromRenderer;
     calculateDevicePixelOffsetFromRenderer(rendererOffsetFromGraphicsLayer, devicePixelOffsetFromRenderer, devicePixelFractionFromRenderer, deviceScaleFactor);
+    LayoutSize oldDevicePixelFractionFromRenderer = m_devicePixelFractionFromRenderer;
     m_devicePixelFractionFromRenderer = LayoutSize(-devicePixelFractionFromRenderer.width(), -devicePixelFractionFromRenderer.height());
 
     adjustAncestorCompositingBoundsForFlowThread(ancestorCompositingBounds, compAncestor);
@@ -1002,6 +1010,9 @@
 #endif
     updateAfterWidgetResize();
 
+    if (devicePixelFractionGapFromRendererChanged(oldDevicePixelFractionFromRenderer, m_devicePixelFractionFromRenderer, deviceScaleFactor) && canIssueSetNeedsDisplay())
+        setContentsNeedDisplay();
+
     compositor().updateScrollCoordinatedStatus(m_owningLayer);
 }
 

Modified: trunk/Source/WebCore/rendering/RenderLayerBacking.h (185151 => 185152)


--- trunk/Source/WebCore/rendering/RenderLayerBacking.h	2015-06-03 14:58:01 UTC (rev 185151)
+++ trunk/Source/WebCore/rendering/RenderLayerBacking.h	2015-06-03 15:36:41 UTC (rev 185152)
@@ -333,6 +333,8 @@
     static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
     static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID);
 
+    bool canIssueSetNeedsDisplay() const { return !paintsIntoWindow() && !paintsIntoCompositedAncestor(); }
+
     RenderLayer& m_owningLayer;
 
     std::unique_ptr<GraphicsLayer> m_ancestorClippingLayer; // Only used if we are clipped by an ancestor which is not a stacking context.
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to