Title: [105092] trunk/Source/WebCore
Revision
105092
Author
[email protected]
Date
2012-01-16 14:37:13 -0800 (Mon, 16 Jan 2012)

Log Message

Huge filter area cause hangs and malloc failures
https://bugs.webkit.org/show_bug.cgi?id=75711

Reviewed by Dean Jackson.

Filtering an element with a child that had a huge negative text-indent
was extremely slow, because transparencyClipBox() returned a huge rect.

Add a method, paintingExtent(), that wraps transparencyClipBox()
and intersects it with the paintDirtyRect to constrain the size
of the rect used for filters and transparency layers.

Transparency layer extent is not testable in layout tests.

* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintingExtent):
(WebCore::RenderLayer::beginTransparencyLayers): Floating point literals are required
to avoid ambiguous constructor call.
(WebCore::RenderLayer::paintLayer):
(WebCore::RenderLayer::paintLayerContents):
* rendering/RenderLayer.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (105091 => 105092)


--- trunk/Source/WebCore/ChangeLog	2012-01-16 22:21:48 UTC (rev 105091)
+++ trunk/Source/WebCore/ChangeLog	2012-01-16 22:37:13 UTC (rev 105092)
@@ -1,5 +1,29 @@
 2012-01-16  Simon Fraser  <[email protected]>
 
+        Huge filter area cause hangs and malloc failures
+        https://bugs.webkit.org/show_bug.cgi?id=75711
+
+        Reviewed by Dean Jackson.
+        
+        Filtering an element with a child that had a huge negative text-indent
+        was extremely slow, because transparencyClipBox() returned a huge rect.
+        
+        Add a method, paintingExtent(), that wraps transparencyClipBox()
+        and intersects it with the paintDirtyRect to constrain the size
+        of the rect used for filters and transparency layers.
+
+        Transparency layer extent is not testable in layout tests.
+
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintingExtent):
+        (WebCore::RenderLayer::beginTransparencyLayers): Floating point literals are required
+        to avoid ambiguous constructor call.
+        (WebCore::RenderLayer::paintLayer):
+        (WebCore::RenderLayer::paintLayerContents):
+        * rendering/RenderLayer.h:
+
+2012-01-16  Simon Fraser  <[email protected]>
+
         Borders and box masks behave incorrectly with overlapping offsets
         https://bugs.webkit.org/show_bug.cgi?id=76137
 

Modified: trunk/Source/WebCore/rendering/RenderLayer.cpp (105091 => 105092)


--- trunk/Source/WebCore/rendering/RenderLayer.cpp	2012-01-16 22:21:48 UTC (rev 105091)
+++ trunk/Source/WebCore/rendering/RenderLayer.cpp	2012-01-16 22:37:13 UTC (rev 105092)
@@ -1045,23 +1045,28 @@
     return clipRect;
 }
 
-void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, PaintBehavior paintBehavior)
+LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
 {
+    return intersection(transparencyClipBox(this, rootLayer, paintBehavior), paintDirtyRect);
+}
+
+void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
+{
     if (context->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
         return;
     
     RenderLayer* ancestor = transparentPaintingAncestor();
     if (ancestor)
-        ancestor->beginTransparencyLayers(context, rootLayer, paintBehavior);
+        ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
     
     if (paintsWithTransparency(paintBehavior)) {
         m_usedTransparency = true;
         context->save();
-        LayoutRect clipRect = transparencyClipBox(this, rootLayer, paintBehavior);
+        LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior);
         context->clip(clipRect);
         context->beginTransparencyLayer(renderer()->opacity());
 #ifdef REVEAL_TRANSPARENCY_LAYERS
-        context->setFillColor(Color(0, 0, 0.5f, 0.2f), ColorSpaceDeviceRGB);
+        context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB);
         context->fillRect(clipRect);
 #endif
     }
@@ -2750,9 +2755,9 @@
         // layer from the parent now, assuming there is a parent
         if (paintFlags & PaintLayerHaveTransparency) {
             if (parent())
-                parent()->beginTransparencyLayers(context, rootLayer, paintBehavior);
+                parent()->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
             else
-                beginTransparencyLayers(context, rootLayer, paintBehavior);
+                beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
         }
 
         // Make sure the parent's clip rects have been calculated.
@@ -2860,11 +2865,11 @@
         if (shouldPaintContent && !selectionOnly) {
             // Begin transparency layers lazily now that we know we have to paint something.
             if (haveTransparency)
-                beginTransparencyLayers(context, rootLayer, paintBehavior);
+                beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
         
 #if ENABLE(CSS_FILTERS)
             if (filterPainter.haveFilterEffect() && !context->paintingDisabled())
-                context = filterPainter.beginFilterEffect(this, context, transparencyClipBox(this, rootLayer, paintBehavior));
+                context = filterPainter.beginFilterEffect(this, context, paintingExtent(rootLayer, paintDirtyRect, paintBehavior));
 #endif
         
             // Paint our background first, before painting any child layers.
@@ -2888,12 +2893,12 @@
         if (shouldPaintContent && !clipRectToApply.isEmpty()) {
             // Begin transparency layers lazily now that we know we have to paint something.
             if (haveTransparency)
-                beginTransparencyLayers(context, rootLayer, paintBehavior);
+                beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
 
 #if ENABLE(CSS_FILTERS)
             // If the filter was not started yet, start it now, after the transparency layer was lazily created.
             if (filterPainter.haveFilterEffect() && !filterPainter.hasStartedFilterEffect() && !context->paintingDisabled())
-                context = filterPainter.beginFilterEffect(this, context, transparencyClipBox(this, rootLayer, paintBehavior));
+                context = filterPainter.beginFilterEffect(this, context, paintingExtent(rootLayer, paintDirtyRect, paintBehavior));
 #endif
             // Set up the clip used when painting our children.
             clipToRect(rootLayer, context, paintDirtyRect, clipRectToApply);

Modified: trunk/Source/WebCore/rendering/RenderLayer.h (105091 => 105092)


--- trunk/Source/WebCore/rendering/RenderLayer.h	2012-01-16 22:21:48 UTC (rev 105091)
+++ trunk/Source/WebCore/rendering/RenderLayer.h	2012-01-16 22:37:13 UTC (rev 105092)
@@ -257,7 +257,7 @@
 
     bool isTransparent() const;
     RenderLayer* transparentPaintingAncestor();
-    void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, PaintBehavior);
+    void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
 
     bool hasReflection() const { return renderer()->hasReflection(); }
     bool isReflection() const { return renderer()->isReplica(); }
@@ -704,6 +704,7 @@
 
     void parentClipRects(const RenderLayer* rootLayer, RenderRegion*, ClipRects&, bool temporaryClipRects = false, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
     ClipRect backgroundClipRect(const RenderLayer* rootLayer, RenderRegion*, bool temporaryClipRects, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+    LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
 
     RenderLayer* enclosingTransformedAncestor() const;
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to