Reviewed by Anders.
authorzimmermann <zimmermann@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Oct 2007 15:19:40 +0000 (15:19 +0000)
committerzimmermann <zimmermann@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 18 Oct 2007 15:19:40 +0000 (15:19 +0000)
Fix last layout test failure seen on buildbot "trunk-mac-ppc-release".
Problem: "svg/custom/mask-excessive-malloc.svg -> crashed"

Clamp any ImageBuffer allocation within SVG to the RenderView's visibleSize
to avoid excessive mallocs (in the testcase above 1000000x1000000)

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@26745 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.checksum
LayoutTests/platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png
WebCore/ChangeLog
WebCore/ksvg2/svg/SVGMaskElement.cpp
WebCore/ksvg2/svg/SVGPatternElement.cpp
WebCore/platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp
WebCore/platform/graphics/svg/cg/SVGResourceMaskerCg.mm
WebCore/rendering/SVGRenderSupport.cpp
WebCore/rendering/SVGRenderSupport.h

index 8a169c3..fcd93a8 100644 (file)
@@ -1,3 +1,13 @@
+2007-10-18  Nikolas Zimmermann  <zimmermann@kde.org>
+
+        Reviewed by Anders.
+
+        Regenerated result of following test, now that ImageBuffers are correctly clipped to the
+        visible frame size (RenderView) - no more drawing outside that region.
+
+        * platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.checksum:
+        * platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png:
+
 2007-10-18  Eric Seidel  <eric@webkit.org>
 
         Reviewed by Maciej.
index 4c14acc..ec56a9d 100644 (file)
Binary files a/LayoutTests/platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png and b/LayoutTests/platform/mac/svg/custom/js-late-gradient-and-object-creation-expected.png differ
index 72ed7e6..6d5c798 100644 (file)
@@ -1,3 +1,26 @@
+2007-10-18  Nikolas Zimmermann  <zimmermann@kde.org>
+
+        Reviewed by Anders.
+
+        Fix last layout test failure seen on buildbot "trunk-mac-ppc-release".
+        Problem: "svg/custom/mask-excessive-malloc.svg -> crashed"
+
+        Clamp any ImageBuffer allocation within SVG to the RenderView's visibleSize
+        to avoid excessive mallocs (in the testcase above 1000000x1000000)
+
+        * ksvg2/svg/SVGMaskElement.cpp:
+        (WebCore::SVGMaskElement::drawMaskerContent):
+        * ksvg2/svg/SVGPatternElement.cpp:
+        (WebCore::SVGPatternElement::buildPattern):
+        * platform/graphics/svg/cg/SVGPaintServerGradientCg.cpp:
+        (WebCore::SVGPaintServerGradient::teardown):
+        (WebCore::SVGPaintServerGradient::setup):
+        * platform/graphics/svg/cg/SVGResourceMaskerCg.mm:
+        (WebCore::SVGResourceMasker::applyMask):
+        * rendering/SVGRenderSupport.cpp:
+        (WebCore::clampImageBufferSizeToViewport):
+        * rendering/SVGRenderSupport.h:
+
 2007-10-18  Alexey Proskuryakov  <ap@webkit.org>
 
         Windows build fix.
index 6a5247c..179314c 100644 (file)
@@ -129,7 +129,16 @@ auto_ptr<ImageBuffer> SVGMaskElement::drawMaskerContent(const FloatRect& targetR
         heightValue = height().value();
     } 
 
-    auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(IntSize(lroundf(widthValue), lroundf(heightValue)), false);
+    IntSize imageSize(lroundf(widthValue), lroundf(heightValue));
+    clampImageBufferSizeToViewport(document()->renderer(), imageSize);
+
+    if (imageSize.width() < static_cast<int>(widthValue))
+        widthValue = imageSize.width();
+
+    if (imageSize.height() < static_cast<int>(heightValue))
+        heightValue = imageSize.height();
+
+    auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(imageSize, false);
     if (!maskImage.get())
         return maskImage;
 
index 69a53cf..819d53d 100644 (file)
@@ -155,6 +155,15 @@ void SVGPatternElement::buildPattern(const FloatRect& targetRect) const
     if (patternBoundaries.height() > targetRect.height())
         patternBoundaries.setHeight(targetRect.height());
 
+    IntSize patternSize(patternBoundaries.width(), patternBoundaries.height());
+    clampImageBufferSizeToViewport(document()->renderer(), patternSize);
+
+    if (patternSize.width() < static_cast<int>(patternBoundaries.width()))
+        patternBoundaries.setWidth(patternSize.width());
+
+    if (patternSize.height() < static_cast<int>(patternBoundaries.height()))
+        patternBoundaries.setHeight(patternSize.height());
+
     // Eventually calculate the pattern content boundaries (only needed with overflow="visible").
     RenderStyle* style = renderer()->style();
     if (style->overflowX() == OVISIBLE && style->overflowY() == OVISIBLE) {
@@ -181,8 +190,10 @@ void SVGPatternElement::buildPattern(const FloatRect& targetRect) const
         patternBoundariesIncludingOverflow.unite(patternContentBoundaries);
     }
 
-    auto_ptr<ImageBuffer> patternImage = ImageBuffer::create(IntSize(lroundf(patternBoundariesIncludingOverflow.width()),
-                                                                     lroundf(patternBoundariesIncludingOverflow.height())), false);
+    IntSize imageSize(lroundf(patternBoundariesIncludingOverflow.width()), lroundf(patternBoundariesIncludingOverflow.height()));
+    clampImageBufferSizeToViewport(document()->renderer(), imageSize);
+
+    auto_ptr<ImageBuffer> patternImage = ImageBuffer::create(imageSize, false);
 
     if (!patternImage.get())
         return;
index 1af4eaa..07cbe4f 100644 (file)
@@ -32,6 +32,7 @@
 #include "SVGGradientElement.h"
 #include "SVGPaintServerLinearGradient.h"
 #include "SVGPaintServerRadialGradient.h"
+#include "SVGRenderSupport.h"
 
 using namespace std;
 
@@ -187,6 +188,15 @@ void SVGPaintServerGradient::teardown(GraphicsContext*& context, const RenderObj
             AffineTransform transform = object->absoluteTransform();
             FloatRect textBoundary = transform.mapRect(maskBBox);
 
+            IntSize maskSize(lroundf(textBoundary.width()), lroundf(textBoundary.height()));
+            clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);
+
+            if (maskSize.width() < static_cast<int>(textBoundary.width()))
+                textBoundary.setWidth(maskSize.width());
+
+            if (maskSize.height() < static_cast<int>(textBoundary.height()))
+                textBoundary.setHeight(maskSize.height());
+
             // Clip current context to mask image (gradient)
             m_savedContext->concatCTM(transform.inverse());
             CGContextClipToMask(m_savedContext->platformContext(), CGRect(textBoundary), m_imageBuffer->cgImage());
@@ -276,7 +286,10 @@ bool SVGPaintServerGradient::setup(GraphicsContext*& context, const RenderObject
         FloatRect maskBBox = const_cast<RenderObject*>(findTextRootObject(object))->relativeBBox(false);
         IntRect maskRect = enclosingIntRect(object->absoluteTransform().mapRect(maskBBox));
 
-        auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(IntSize(maskRect.width(), maskRect.height()), false);
+        IntSize maskSize(maskRect.width(), maskRect.height());
+        clampImageBufferSizeToViewport(object->document()->renderer(), maskSize);
+
+        auto_ptr<ImageBuffer> maskImage = ImageBuffer::create(maskSize, false);
 
         if (!maskImage.get()) {
             context->restore();
index 4de4f2a..00e62e7 100644 (file)
@@ -34,6 +34,7 @@
 #import "GraphicsContext.h"
 #import "ImageBuffer.h"
 #import "SVGMaskElement.h"
+#import "SVGRenderSupport.h"
 #import "SVGRenderStyle.h"
 #import "SVGResourceFilter.h"
 #import <QuartzCore/CIFilter.h>
@@ -99,6 +100,7 @@ void SVGResourceMasker::applyMask(GraphicsContext* context, const FloatRect& bou
         return;
     
     IntSize maskSize(static_cast<int>(m_maskRect.width()), static_cast<int>(m_maskRect.height()));
+    clampImageBufferSizeToViewport(m_ownerElement->document()->renderer(), maskSize);
 
     // Create new graphics context in gray scale mode for image rendering
     auto_ptr<ImageBuffer> grayScaleImage(ImageBuffer::create(maskSize, true));
@@ -114,7 +116,7 @@ void SVGResourceMasker::applyMask(GraphicsContext* context, const FloatRect& bou
     if (!colorMask)
         return;
     CIImage* grayScaleMask = transformImageIntoGrayscaleMask(colorMask);
-    [ciGrayscaleContext drawImage:grayScaleMask atPoint:CGPointZero fromRect:CGRectMake(0, 0, m_maskRect.width(), m_maskRect.height())];
+    [ciGrayscaleContext drawImage:grayScaleMask atPoint:CGPointZero fromRect:CGRectMake(0, 0, maskSize.width(), maskSize.height())];
 
     CGContextClipToMask(context->platformContext(), m_maskRect, grayScaleImage->cgImage());
     END_BLOCK_OBJC_EXCEPTIONS
index bfc34b1..31df302 100644 (file)
@@ -31,6 +31,7 @@
 #include "ImageBuffer.h"
 #include "RenderObject.h"
 #include "RenderSVGContainer.h"
+#include "RenderView.h"
 #include "SVGResourceClipper.h"
 #include "SVGResourceFilter.h"
 #include "SVGResourceMasker.h"
@@ -143,6 +144,25 @@ void renderSubtreeToImage(ImageBuffer* image, RenderObject* item)
         svgContainer->setDrawsContents(false);
 }
 
+void clampImageBufferSizeToViewport(RenderObject* object, IntSize& size)
+{
+    if (!object || !object->isRenderView())
+        return;
+
+    RenderView* view = static_cast<RenderView*>(object);
+    if (!view->frameView())
+        return;
+
+    int viewWidth = view->frameView()->visibleWidth();
+    int viewHeight = view->frameView()->visibleHeight();
+
+    if (size.width() > viewWidth)
+        size.setWidth(viewWidth);
+
+    if (size.height() > viewHeight)
+        size.setHeight(viewHeight);
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SVG)
index a856ae5..2e3d51d 100644 (file)
@@ -35,6 +35,8 @@ void finishRenderSVGContent(RenderObject*, RenderObject::PaintInfo&, const Float
 class ImageBuffer;
 void renderSubtreeToImage(ImageBuffer*, RenderObject*);
 
+void clampImageBufferSizeToViewport(RenderObject*, IntSize&);
+
 }
 
 #endif