Title: [164252] trunk
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;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to