- Revision
- 164252
- Author
- [email protected]
- Date
- 2014-02-17 15:45:44 -0800 (Mon, 17 Feb 2014)
Log Message
box-shadows get truncated with a combination of transforms and clip: (affects Google Maps)
https://bugs.webkit.org/show_bug.cgi?id=128937
Source/WebCore:
Reviewed by Dean Jackson.
RenderLayer::calculateLayerBounds() incorrectly assumed that if localClipRect() returns
a non-infinite rect, that rect is OK to use as the compositing bounds.
That is not a valid assumption when clip() has a larger rect than the element (e.g.
with negative top/left in the rect). In that case, localClipRect() still just
returns the background rect, but we actually need a larger compositing layer
to show the unclipped parts of descendants.
Fix by detecting clip() that exceeds the renderer bounds, and when it does,
not early returning in the UseLocalClipRectIfPossible clause.
Test: compositing/geometry/css-clip-oversize.html
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::localClipRect): Do a convertToLayerCoords()
because we need offsetFromRoot later, and we can pass our value down to
calculateRects(). Compute clipExceedsBounds based on the CSS clip rect.
(WebCore::RenderLayer::calculateClipRects): Don't early return if clipExceedsBounds
is true.
* rendering/RenderLayer.h:
LayoutTests:
Reviewed by Dean Jackson.
Test with CSS clip() with a rect larger than the border box, and compositing.
* compositing/geometry/clip-expected.txt: New expectation. This is a progression.
* compositing/geometry/css-clip-oversize-expected.html: Added.
* compositing/geometry/css-clip-oversize.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (164251 => 164252)
--- trunk/LayoutTests/ChangeLog 2014-02-17 23:29:31 UTC (rev 164251)
+++ trunk/LayoutTests/ChangeLog 2014-02-17 23:45:44 UTC (rev 164252)
@@ -1,3 +1,16 @@
+2014-02-17 Simon Fraser <[email protected]>
+
+ box-shadows get truncated with a combination of transforms and clip: (affects Google Maps)
+ https://bugs.webkit.org/show_bug.cgi?id=128937
+
+ Reviewed by Dean Jackson.
+
+ Test with CSS clip() with a rect larger than the border box, and compositing.
+
+ * compositing/geometry/clip-expected.txt: New expectation. This is a progression.
+ * compositing/geometry/css-clip-oversize-expected.html: Added.
+ * compositing/geometry/css-clip-oversize.html: Added.
+
2014-02-17 Chris Fleizach <[email protected]>
AX: Invalid cast in WebCore::AccessibilityTable::isDataTable (CRBug 280352)
Modified: trunk/LayoutTests/compositing/geometry/clip-expected.txt (164251 => 164252)
--- trunk/LayoutTests/compositing/geometry/clip-expected.txt 2014-02-17 23:29:31 UTC (rev 164251)
+++ trunk/LayoutTests/compositing/geometry/clip-expected.txt 2014-02-17 23:45:44 UTC (rev 164252)
@@ -8,9 +8,8 @@
(contentsOpaque 1)
(children 2
(GraphicsLayer
- (position 20.00 20.00)
- (bounds 100.00 100.00)
- (contentsOpaque 1)
+ (position 15.00 15.00)
+ (bounds 110.00 110.00)
(drawsContent 1)
(transform [1.00 0.00 0.00 0.00] [0.00 1.00 0.00 0.00] [0.00 0.00 1.00 0.00] [0.00 0.00 1.00 1.00])
)
Added: trunk/LayoutTests/compositing/geometry/css-clip-oversize-expected.html (0 => 164252)
--- trunk/LayoutTests/compositing/geometry/css-clip-oversize-expected.html (rev 0)
+++ trunk/LayoutTests/compositing/geometry/css-clip-oversize-expected.html 2014-02-17 23:45:44 UTC (rev 164252)
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ .parent {
+ position: absolute;
+ height: 100px;
+ width: 500px;
+ margin: 50px;
+ background: silver;
+ clip: rect(0px, 520px, 600px, -20px); /* top, right, bottom, left */
+ -webkit-transform: translateZ(0);
+ }
+
+ .child {
+ position: absolute;
+ top: 50px;
+ height: 100px;
+ width: 400px;
+ background: #ffea61;
+ box-shadow: 0 0 50px black;
+ }
+ </style>
+</head>
+<body>
+ <div class="shared parent">
+ <div class="shared child"></div>
+ </div>
+</body>
+</html>
Added: trunk/LayoutTests/compositing/geometry/css-clip-oversize.html (0 => 164252)
--- trunk/LayoutTests/compositing/geometry/css-clip-oversize.html (rev 0)
+++ trunk/LayoutTests/compositing/geometry/css-clip-oversize.html 2014-02-17 23:45:44 UTC (rev 164252)
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+ <style>
+ .parent {
+ position: absolute;
+ height: 100px;
+ width: 500px;
+ margin: 50px;
+ background: silver;
+ clip: rect(0px, 520px, 600px, -20px); /* top, right, bottom, left */
+ }
+
+ .child {
+ position: absolute;
+ top: 50px;
+ height: 100px;
+ width: 400px;
+ background: #ffea61;
+ box-shadow: 0 0 50px black;
+ }
+ </style>
+</head>
+<body>
+ <div class="shared parent">
+ <div class="shared child"></div>
+ </div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (164251 => 164252)
--- trunk/Source/WebCore/ChangeLog 2014-02-17 23:29:31 UTC (rev 164251)
+++ trunk/Source/WebCore/ChangeLog 2014-02-17 23:45:44 UTC (rev 164252)
@@ -1,3 +1,31 @@
+2014-02-17 Simon Fraser <[email protected]>
+
+ box-shadows get truncated with a combination of transforms and clip: (affects Google Maps)
+ https://bugs.webkit.org/show_bug.cgi?id=128937
+
+ Reviewed by Dean Jackson.
+
+ RenderLayer::calculateLayerBounds() incorrectly assumed that if localClipRect() returns
+ a non-infinite rect, that rect is OK to use as the compositing bounds.
+
+ That is not a valid assumption when clip() has a larger rect than the element (e.g.
+ with negative top/left in the rect). In that case, localClipRect() still just
+ returns the background rect, but we actually need a larger compositing layer
+ to show the unclipped parts of descendants.
+
+ Fix by detecting clip() that exceeds the renderer bounds, and when it does,
+ not early returning in the UseLocalClipRectIfPossible clause.
+
+ Test: compositing/geometry/css-clip-oversize.html
+
+ * rendering/RenderLayer.cpp:
+ (WebCore::RenderLayer::localClipRect): Do a convertToLayerCoords()
+ because we need offsetFromRoot later, and we can pass our value down to
+ calculateRects(). Compute clipExceedsBounds based on the CSS clip rect.
+ (WebCore::RenderLayer::calculateClipRects): Don't early return if clipExceedsBounds
+ is true.
+ * rendering/RenderLayer.h:
+
2014-02-17 Antti Koivisto <[email protected]>
Make TreeScope::rootNode return a reference
Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (164251 => 164252)
--- trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-02-17 23:29:31 UTC (rev 164251)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp 2014-02-17 23:45:44 UTC (rev 164252)
@@ -5526,20 +5526,32 @@
return clippingRootLayer->renderer().localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
}
-LayoutRect RenderLayer::localClipRect() const
+LayoutRect RenderLayer::localClipRect(bool& clipExceedsBounds) const
{
+ clipExceedsBounds = false;
+
// FIXME: border-radius not accounted for.
// FIXME: Regions not accounted for.
RenderLayer* clippingRootLayer = clippingRootForPainting();
+
+ LayoutPoint offsetFromRoot;
+ convertToLayerCoords(clippingRootLayer, offsetFromRoot);
+
LayoutRect layerBounds;
ClipRect backgroundRect, foregroundRect, outlineRect;
ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
- calculateRects(clipRectsContext, LayoutRect::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+ calculateRects(clipRectsContext, LayoutRect::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect, &offsetFromRoot);
LayoutRect clipRect = backgroundRect.rect();
if (clipRect == LayoutRect::infiniteRect())
return clipRect;
+ if (renderer().hasClip()) {
+ // CSS clip may be larger than our border box.
+ LayoutRect cssClipRect = toRenderBox(renderer()).clipRect(offsetFromRoot, clipRectsContext.region);
+ clipExceedsBounds = !clipRect.contains(cssClipRect);
+ }
+
LayoutPoint clippingRootOffset;
convertToLayerCoords(clippingRootLayer, clippingRootOffset);
clipRect.moveBy(-clippingRootOffset);
@@ -5729,8 +5741,9 @@
LayoutRect unionBounds = boundingBoxRect;
if (flags & UseLocalClipRectIfPossible) {
- LayoutRect localClipRect = this->localClipRect();
- if (localClipRect != LayoutRect::infiniteRect()) {
+ bool clipExceedsBounds = false;
+ LayoutRect localClipRect = this->localClipRect(clipExceedsBounds);
+ if (localClipRect != LayoutRect::infiniteRect() && !clipExceedsBounds) {
if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehaviorNormal))
localClipRect = transform()->mapRect(localClipRect);
Modified: trunk/Source/WebCore/rendering/RenderLayer.h (164251 => 164252)
--- trunk/Source/WebCore/rendering/RenderLayer.h 2014-02-17 23:29:31 UTC (rev 164251)
+++ trunk/Source/WebCore/rendering/RenderLayer.h 2014-02-17 23:45:44 UTC (rev 164252)
@@ -693,7 +693,7 @@
LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
LayoutRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
- LayoutRect localClipRect() const; // Returns the background clip rect of the layer in the local coordinate space.
+ LayoutRect localClipRect(bool& clipExceedsBounds) const; // Returns the background clip rect of the layer in the local coordinate space.
// Pass offsetFromRoot if known.
bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0, RenderRegion* = 0) const;