- 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.