Applying a filter on an SVG element, which is larger than 4096 pixels, causes this...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 May 2015 22:46:43 +0000 (22:46 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 7 May 2015 22:46:43 +0000 (22:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144335

Patch by Said Abou-Hallawa <sabouhallawa@apple.com> on 2015-05-07
Reviewed by Darin Adler.

Source/WebCore:

When the SVG element is larger than 4096x4096 pixels and it has a filter,
a clipper or a masker, the ImageBuffer which is created for drawing the
sourceGraphicBuffer has to be clamped to this size. The reason for this
clamping is the FilterEffect simply ignores processing any ImageBuffer
larger than this size.

The bug was happening because we did not propagate the clamping logic to
the FilterEffect. The FilterEffect result ImageBuffer was not clamped as
what we do for drawing the sourceGraphicBuffer. If only the destination
point is specified, the GraphicsContext::drawImageBuffer() assumes the
source and the destination images have the same size which is not true
with the clamping.

The fix is to add the clamping logic to the FilterEffect. Two places we
need to change. (1) FilterEffect::createImageBufferResult() has to apply
the same clamping we do in SVGRenderingContext::createImageBuffer(). (2)
FilterEffect::drawingRegionOfInputImage() has to consider the clamping
when mapping from absolute coordinates to the ImageBuffer coordinates.

Tests: svg/filters/big-sized-off-viewport-filter.svg

* platform/graphics/ImageBuffer.cpp:
(WebCore::ImageBuffer::isSizeClamped):
(WebCore::ImageBuffer::clampedSize):
(WebCore::ImageBuffer::clampedRect):
* platform/graphics/ImageBuffer.h:
(WebCore::ImageBuffer::setSpaceSize): Move all the clamping helper methods
from SVGRenderingContext and RenderSVGResourceFilter to the ImageBuffer.

* platform/graphics/filters/FEColorMatrix.cpp:
(WebCore::FEColorMatrix::platformApplySoftware): Use logicalSize() of the
result image instead of using absolutePaintRect(). The later returns the
rectangle of the element without clamping.

* platform/graphics/filters/FETile.cpp:
(WebCore::FETile::platformApplySoftware):
* rendering/svg/RenderSVGResourceClipper.cpp:
(WebCore::RenderSVGResourceClipper::applyClippingToContext):
* rendering/svg/RenderSVGResourceFilter.cpp:
(WebCore::RenderSVGResourceFilter::applyResource):
(WebCore::RenderSVGResourceFilter::fitsInMaximumImageSize): Deleted.
* rendering/svg/RenderSVGResourceFilter.h:
* rendering/svg/RenderSVGResourceGradient.cpp:
(WebCore::createMaskAndSwapContextForTextGradient):
(WebCore::clipToTextMask):
* rendering/svg/RenderSVGResourceMasker.cpp:
(WebCore::RenderSVGResourceMasker::applySVGMask):
* rendering/svg/RenderSVGResourcePattern.cpp:
(WebCore::RenderSVGResourcePattern::buildPattern):
(WebCore::RenderSVGResourcePattern::createTileImage): Make the modifications
which are needed because of moving the clamping helper methods to ImageBuffer
and because of changing the prototype of SVGRenderingContext methods.

* platform/graphics/filters/FilterEffect.cpp:
(WebCore::FilterEffect::drawingRegionOfInputImage): Consider the clamping
when mapping from absolute coordinates to the ImageBuffer coordinates.

(WebCore::FilterEffect::createImageBufferResult): Apply the same clamping
we do in SVGRenderingContext::createImageBuffer() when creating the
FilterEffect result ImageBuffer.

(WebCore::FilterEffect::apply):
(WebCore::FilterEffect::asUnmultipliedImage):
(WebCore::FilterEffect::asPremultipliedImage):
(WebCore::FilterEffect::copyUnmultipliedImage):
(WebCore::FilterEffect::copyPremultipliedImage):
(WebCore::FilterEffect::createUnmultipliedImageResult):
(WebCore::FilterEffect::createPremultipliedImageResult):
(WebCore::FilterEffect::maxFilterArea): Deleted.
(WebCore::FilterEffect::isFilterSizeValid): Deleted.
* platform/graphics/filters/FilterEffect.h: Use the new ImageBuffer clamping
helper methods and delete the local ones.

* platform/graphics/transforms/AffineTransform.cpp:
(WebCore::AffineTransform::scaleNonUniform):
(WebCore::AffineTransform::scale):
(WebCore::AffineTransform::translate):
* platform/graphics/transforms/AffineTransform.h: Add new scale and translate
overloads to AffineTransform.

* rendering/FilterEffectRenderer.cpp:
(WebCore::FilterEffectRenderer::updateBackingStoreRect):
(WebCore::FilterEffectRendererHelper::beginFilterEffect): Code clean up.

* rendering/svg/SVGRenderingContext.cpp:
(WebCore::SVGRenderingContext::calculateScreenFontSizeScalingFactor):
(WebCore::SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem):
Return the AffineTransform instead of passing it through the reference of
an argument.

(WebCore::SVGRenderingContext::createImageBuffer):
(WebCore::SVGRenderingContext::createImageBufferForPattern): Deleted.
Code clean up and method rename.

(WebCore::SVGRenderingContext::clampedAbsoluteTargetRect): Deleted.
(WebCore::SVGRenderingContext::clampedAbsoluteSize): Deleted.
* rendering/svg/SVGRenderingContext.h: Move the clamping helper methods to
the ImageBuffer class.

LayoutTests:

* svg/filters/big-sized-off-viewport-filter-expected.svg: Added.
* svg/filters/big-sized-off-viewport-filter.svg: Added.
Ensure when applying a filter on a large SVG element, the viewport of the
SVG includes the correct drawing part of this element.

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

21 files changed:
LayoutTests/ChangeLog
LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg [new file with mode: 0644]
LayoutTests/svg/filters/big-sized-off-viewport-filter.svg [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/ImageBuffer.cpp
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
Source/WebCore/platform/graphics/filters/FETile.cpp
Source/WebCore/platform/graphics/filters/FilterEffect.cpp
Source/WebCore/platform/graphics/filters/FilterEffect.h
Source/WebCore/platform/graphics/transforms/AffineTransform.cpp
Source/WebCore/platform/graphics/transforms/AffineTransform.h
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/rendering/svg/RenderSVGResourceClipper.cpp
Source/WebCore/rendering/svg/RenderSVGResourceFilter.cpp
Source/WebCore/rendering/svg/RenderSVGResourceFilter.h
Source/WebCore/rendering/svg/RenderSVGResourceGradient.cpp
Source/WebCore/rendering/svg/RenderSVGResourceMasker.cpp
Source/WebCore/rendering/svg/RenderSVGResourcePattern.cpp
Source/WebCore/rendering/svg/SVGRenderingContext.cpp
Source/WebCore/rendering/svg/SVGRenderingContext.h

index 8b0c20a829608f56b362c8aaff7fd7bc467905c3..7d73c34b2c46d99c87464b3c73327c779413aced 100644 (file)
@@ -1,3 +1,15 @@
+2015-05-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        Applying a filter on an SVG element, which is larger than 4096 pixels, causes this element to be rendered shifted to the left
+        https://bugs.webkit.org/show_bug.cgi?id=144335
+
+        Reviewed by Darin Adler.
+
+        * svg/filters/big-sized-off-viewport-filter-expected.svg: Added.
+        * svg/filters/big-sized-off-viewport-filter.svg: Added.
+        Ensure when applying a filter on a large SVG element, the viewport of the
+        SVG includes the correct drawing part of this element.
+
 2015-05-07  Yoav Weiss  <yoav@yoav.ws>
 
         Handle meta viewport in HTMLPreloadScanner
diff --git a/LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg b/LayoutTests/svg/filters/big-sized-off-viewport-filter-expected.svg
new file mode 100644 (file)
index 0000000..a371135
--- /dev/null
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500">
+  <filter id="saturate-back">
+    <feColorMatrix in="SourceGraphic" type="saturate" values="1"/>
+  </filter>
+  <g filter="url(#saturate-back)">
+    <rect x="-500" y="0" width="950" height="100%" fill="green"/>
+    <rect x="550" y="0" width="950" height="100%" fill="green"/>
+  </g>
+  <rect x="450" y="0" width="100" height="100%" fill="none" stroke="white" stroke-width="10"/>
+</svg>
diff --git a/LayoutTests/svg/filters/big-sized-off-viewport-filter.svg b/LayoutTests/svg/filters/big-sized-off-viewport-filter.svg
new file mode 100644 (file)
index 0000000..f2fe477
--- /dev/null
@@ -0,0 +1,11 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500">
+  <filter id="saturate-back">
+    <feColorMatrix in="SourceGraphic" type="saturate" values="1"/>
+  </filter>
+  <g filter="url(#saturate-back)">
+    <rect x="-3500" y="0" width="3950" height="100%" fill="green"/>
+    <rect x="550" y="0" width="3950" height="100%" fill="green"/>
+  </g>
+  <!-- Ensure the edges of the rectangles are sharp after clamping the filter image and scaling it up -->
+  <rect x="450" y="0" width="100" height="100%" fill="none" stroke="white" stroke-width="10"/>
+</svg>
index 2b95090394fd1afc588b3cab55a5498543e9abd8..caaac65eb8febc6880a7c6c3bcb7e63e5829e860 100644 (file)
@@ -1,3 +1,109 @@
+2015-05-07  Said Abou-Hallawa  <sabouhallawa@apple.com>
+
+        Applying a filter on an SVG element, which is larger than 4096 pixels, causes this element to be rendered shifted to the left
+        https://bugs.webkit.org/show_bug.cgi?id=144335
+
+        Reviewed by Darin Adler.
+
+        When the SVG element is larger than 4096x4096 pixels and it has a filter,
+        a clipper or a masker, the ImageBuffer which is created for drawing the
+        sourceGraphicBuffer has to be clamped to this size. The reason for this
+        clamping is the FilterEffect simply ignores processing any ImageBuffer
+        larger than this size.
+        
+        The bug was happening because we did not propagate the clamping logic to
+        the FilterEffect. The FilterEffect result ImageBuffer was not clamped as
+        what we do for drawing the sourceGraphicBuffer. If only the destination
+        point is specified, the GraphicsContext::drawImageBuffer() assumes the
+        source and the destination images have the same size which is not true
+        with the clamping.
+        
+        The fix is to add the clamping logic to the FilterEffect. Two places we
+        need to change. (1) FilterEffect::createImageBufferResult() has to apply
+        the same clamping we do in SVGRenderingContext::createImageBuffer(). (2)
+        FilterEffect::drawingRegionOfInputImage() has to consider the clamping 
+        when mapping from absolute coordinates to the ImageBuffer coordinates.
+        
+        Tests: svg/filters/big-sized-off-viewport-filter.svg
+
+        * platform/graphics/ImageBuffer.cpp:
+        (WebCore::ImageBuffer::isSizeClamped):
+        (WebCore::ImageBuffer::clampedSize):
+        (WebCore::ImageBuffer::clampedRect):
+        * platform/graphics/ImageBuffer.h:
+        (WebCore::ImageBuffer::setSpaceSize): Move all the clamping helper methods
+        from SVGRenderingContext and RenderSVGResourceFilter to the ImageBuffer.
+
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        (WebCore::FEColorMatrix::platformApplySoftware): Use logicalSize() of the
+        result image instead of using absolutePaintRect(). The later returns the
+        rectangle of the element without clamping.
+        
+        * platform/graphics/filters/FETile.cpp:
+        (WebCore::FETile::platformApplySoftware):
+        * rendering/svg/RenderSVGResourceClipper.cpp:
+        (WebCore::RenderSVGResourceClipper::applyClippingToContext):
+        * rendering/svg/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::applyResource):
+        (WebCore::RenderSVGResourceFilter::fitsInMaximumImageSize): Deleted.
+        * rendering/svg/RenderSVGResourceFilter.h:
+        * rendering/svg/RenderSVGResourceGradient.cpp:
+        (WebCore::createMaskAndSwapContextForTextGradient):
+        (WebCore::clipToTextMask):
+        * rendering/svg/RenderSVGResourceMasker.cpp:
+        (WebCore::RenderSVGResourceMasker::applySVGMask):
+        * rendering/svg/RenderSVGResourcePattern.cpp:
+        (WebCore::RenderSVGResourcePattern::buildPattern):
+        (WebCore::RenderSVGResourcePattern::createTileImage): Make the modifications
+        which are needed because of moving the clamping helper methods to ImageBuffer
+        and because of changing the prototype of SVGRenderingContext methods.
+
+        * platform/graphics/filters/FilterEffect.cpp:
+        (WebCore::FilterEffect::drawingRegionOfInputImage): Consider the clamping
+        when mapping from absolute coordinates to the ImageBuffer coordinates.
+
+        (WebCore::FilterEffect::createImageBufferResult): Apply the same clamping
+        we do in SVGRenderingContext::createImageBuffer() when creating the 
+        FilterEffect result ImageBuffer.
+        
+        (WebCore::FilterEffect::apply):
+        (WebCore::FilterEffect::asUnmultipliedImage):
+        (WebCore::FilterEffect::asPremultipliedImage):
+        (WebCore::FilterEffect::copyUnmultipliedImage):
+        (WebCore::FilterEffect::copyPremultipliedImage):
+        (WebCore::FilterEffect::createUnmultipliedImageResult):
+        (WebCore::FilterEffect::createPremultipliedImageResult):
+        (WebCore::FilterEffect::maxFilterArea): Deleted.
+        (WebCore::FilterEffect::isFilterSizeValid): Deleted.
+        * platform/graphics/filters/FilterEffect.h: Use the new ImageBuffer clamping
+        helper methods and delete the local ones.
+
+        * platform/graphics/transforms/AffineTransform.cpp:
+        (WebCore::AffineTransform::scaleNonUniform):
+        (WebCore::AffineTransform::scale):
+        (WebCore::AffineTransform::translate):
+        * platform/graphics/transforms/AffineTransform.h: Add new scale and translate
+        overloads to AffineTransform.
+        
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::FilterEffectRenderer::updateBackingStoreRect):
+        (WebCore::FilterEffectRendererHelper::beginFilterEffect): Code clean up.
+        
+        * rendering/svg/SVGRenderingContext.cpp:
+        (WebCore::SVGRenderingContext::calculateScreenFontSizeScalingFactor):
+        (WebCore::SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem):
+        Return the AffineTransform instead of passing it through the reference of
+        an argument.
+        
+        (WebCore::SVGRenderingContext::createImageBuffer):
+        (WebCore::SVGRenderingContext::createImageBufferForPattern): Deleted.
+        Code clean up and method rename.
+        
+        (WebCore::SVGRenderingContext::clampedAbsoluteTargetRect): Deleted.
+        (WebCore::SVGRenderingContext::clampedAbsoluteSize): Deleted.
+        * rendering/svg/SVGRenderingContext.h: Move the clamping helper methods to
+        the ImageBuffer class.
+    
 2015-05-07  Beth Dakin  <bdakin@apple.com>
 
         New force-related DOM events should fire in WK1 views
index b384372ef3e1186dd4e5fddd329cb8d979068971..1390cdb89bdcb25060dfbae7f8cdce7970e310f4 100644 (file)
 
 namespace WebCore {
 
+static const float MaxClampedLength = 4096;
+static const float MaxClampedArea = MaxClampedLength * MaxClampedLength;
+
+bool ImageBuffer::isSizeClamped(const FloatSize& size)
+{
+    if (size.width() < 0 && size.height() < 0)
+        return false;
+
+    if (size.isEmpty())
+        return true;
+
+    return floorf(size.height()) * floorf(size.width()) <= MaxClampedArea;
+}
+
+bool ImageBuffer::isSizeClamped(const FloatSize& size, FloatSize& scale)
+{
+    FloatSize scaledSize(size);
+    scaledSize.scale(scale.width(), scale.height());
+
+    if (isSizeClamped(scaledSize))
+        return true;
+
+    // The area of scaled size is bigger than the upper limit, adjust the scale to fit.
+    scale.scale(sqrtf(MaxClampedArea / (scaledSize.width() * scaledSize.height())));
+    ASSERT(isSizeClamped(size, scale));
+    return false;
+}
+
+FloatSize ImageBuffer::clampedSize(const FloatSize& size)
+{
+    return size.shrunkTo(FloatSize(MaxClampedLength, MaxClampedLength));
+}
+
+FloatSize ImageBuffer::clampedSize(const FloatSize& size, FloatSize& scale)
+{
+    if (size.isEmpty())
+        return size;
+
+    FloatSize clampedSize = ImageBuffer::clampedSize(size);
+    scale = FloatSize(clampedSize.width() / size.width(), clampedSize.height() / size.height());
+    ASSERT(isSizeClamped(clampedSize));
+    ASSERT(isSizeClamped(size, scale));
+    return clampedSize;
+}
+
+FloatRect ImageBuffer::clampedRect(const FloatRect& rect)
+{
+    return FloatRect(rect.location(), clampedSize(rect.size()));
+}
+
 #if !USE(CG)
 void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace)
 {
index 337be230993ef920da21c8ea53b503b399e5ae06..320d8dfe15e6ed7575768dcc65ad754ce460330c 100644 (file)
@@ -123,10 +123,14 @@ public:
     bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool);
 
     FloatSize spaceSize() const { return m_space; }
-    void setSpaceSize(const FloatSize& space)
-    {
-        m_space = space;
-    }
+    void setSpaceSize(const FloatSize& space) { m_space = space; }
+
+    // These functions are used when clamping the ImageBuffer which is created for filter, masker or clipper.
+    static bool isSizeClamped(const FloatSize&);
+    static bool isSizeClamped(const FloatSize&, FloatSize& scale);
+    static FloatSize clampedSize(const FloatSize&);
+    static FloatSize clampedSize(const FloatSize&, FloatSize& scale);
+    static FloatRect clampedRect(const FloatRect&);
 
 private:
 #if USE(CG)
index e1af4a5497f469e835800c9055bc3a1cba2d308b..363bb38ff151ee555440914ccc8a454786ec19c6 100644 (file)
@@ -149,7 +149,7 @@ void FEColorMatrix::platformApplySoftware()
 
     resultImage->context()->drawImageBuffer(in->asImageBuffer(), ColorSpaceDeviceRGB, drawingRegionOfInputImage(in->absolutePaintRect()));
 
-    IntRect imageRect(IntPoint(), absolutePaintRect().size());
+    IntRect imageRect(IntPoint(), resultImage->logicalSize());
     RefPtr<Uint8ClampedArray> pixelArray = resultImage->getUnmultipliedImageData(imageRect);
 
     switch (m_type) {
index 62b624771c725429d30c61890f074ae1f6c27e37..f0e9b2d7e8df2a9f80ccf97cc14f1e4b52ce4e4b 100644 (file)
@@ -63,8 +63,8 @@ void FETile::platformApplySoftware()
         tileRect.scale(filter.filterResolution().width(), filter.filterResolution().height());
     }
 
-    std::unique_ptr<ImageBuffer> tileImage;
-    if (!SVGRenderingContext::createImageBufferForPattern(tileRect, tileRect, tileImage, ColorSpaceDeviceRGB, filter().renderingMode()))
+    auto tileImage = SVGRenderingContext::createImageBuffer(tileRect, tileRect, ColorSpaceDeviceRGB, filter().renderingMode());
+    if (!tileImage)
         return;
 
     GraphicsContext* tileImageContext = tileImage->context();
index fab67a4c56fe2c58c73cb4ff89810c4d2b14cfd3..bdd6adc0b62091e968af3abfb99668a916d33fd1 100644 (file)
@@ -36,8 +36,6 @@
 
 namespace WebCore {
 
-static const float kMaxFilterArea = 4096 * 4096;
-
 FilterEffect::FilterEffect(Filter& filter)
     : m_alphaImage(false)
     , m_filter(filter)
@@ -55,19 +53,6 @@ FilterEffect::~FilterEffect()
 {
 }
 
-float FilterEffect::maxFilterArea()
-{
-    return kMaxFilterArea;
-}
-
-bool FilterEffect::isFilterSizeValid(const FloatRect& rect)
-{
-    if (rect.width() < 0 || rect.height() < 0
-        || (rect.height() * rect.width() > kMaxFilterArea))
-        return false;
-    return true;
-}
-
 void FilterEffect::determineAbsolutePaintRect()
 {
     m_absolutePaintRect = IntRect();
@@ -93,8 +78,14 @@ IntRect FilterEffect::requestedRegionOfInputImageData(const IntRect& effectRect)
 
 FloatRect FilterEffect::drawingRegionOfInputImage(const IntRect& srcRect) const
 {
-    return FloatRect(FloatPoint(srcRect.x() - m_absolutePaintRect.x(),
-                            srcRect.y() - m_absolutePaintRect.y()), srcRect.size());
+    ASSERT(hasResult());
+
+    FloatSize scale;
+    ImageBuffer::clampedSize(m_absolutePaintRect.size(), scale);
+
+    AffineTransform transform;
+    transform.scale(scale).translate(-m_absolutePaintRect.location());
+    return transform.mapRect(srcRect);
 }
 
 FilterEffect* FilterEffect::inputEffect(unsigned number) const
@@ -156,7 +147,7 @@ void FilterEffect::apply()
     determineAbsolutePaintRect();
     setResultColorSpace(m_operatingColorSpace);
 
-    if (!isFilterSizeValid(m_absolutePaintRect))
+    if (m_absolutePaintRect.isEmpty() || !ImageBuffer::isSizeClamped(m_absolutePaintRect.size()))
         return;
 
     if (requiresValidPreMultipliedPixels()) {
@@ -321,8 +312,8 @@ ImageBuffer* FilterEffect::openCLImageToImageBuffer()
 
 PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& rect)
 {
-    ASSERT(isFilterSizeValid(rect));
     IntSize scaledSize(rect.size());
+    ASSERT(ImageBuffer::isSizeClamped(scaledSize));
     scaledSize.scale(m_filter.filterScale());
     RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
     copyUnmultipliedImage(imageData.get(), rect);
@@ -331,8 +322,8 @@ PassRefPtr<Uint8ClampedArray> FilterEffect::asUnmultipliedImage(const IntRect& r
 
 PassRefPtr<Uint8ClampedArray> FilterEffect::asPremultipliedImage(const IntRect& rect)
 {
-    ASSERT(isFilterSizeValid(rect));
     IntSize scaledSize(rect.size());
+    ASSERT(ImageBuffer::isSizeClamped(scaledSize));
     scaledSize.scale(m_filter.filterScale());
     RefPtr<Uint8ClampedArray> imageData = Uint8ClampedArray::createUninitialized(scaledSize.width() * scaledSize.height() * 4);
     copyPremultipliedImage(imageData.get(), rect);
@@ -397,8 +388,8 @@ void FilterEffect::copyUnmultipliedImage(Uint8ClampedArray* destination, const I
         if (m_imageBufferResult)
             m_unmultipliedImageResult = m_imageBufferResult->getUnmultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
         else {
-            ASSERT(isFilterSizeValid(m_absolutePaintRect));
             IntSize inputSize(m_absolutePaintRect.size());
+            ASSERT(ImageBuffer::isSizeClamped(inputSize));
             inputSize.scale(m_filter.filterScale());
             m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
             unsigned char* sourceComponent = m_premultipliedImageResult->data();
@@ -433,8 +424,8 @@ void FilterEffect::copyPremultipliedImage(Uint8ClampedArray* destination, const
         if (m_imageBufferResult)
             m_premultipliedImageResult = m_imageBufferResult->getPremultipliedImageData(IntRect(IntPoint(), m_absolutePaintRect.size()));
         else {
-            ASSERT(isFilterSizeValid(m_absolutePaintRect));
             IntSize inputSize(m_absolutePaintRect.size());
+            ASSERT(ImageBuffer::isSizeClamped(inputSize));
             inputSize.scale(m_filter.filterScale());
             m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(inputSize.width() * inputSize.height() * 4);
             unsigned char* sourceComponent = m_unmultipliedImageResult->data();
@@ -459,10 +450,13 @@ ImageBuffer* FilterEffect::createImageBufferResult()
     // Only one result type is allowed.
     ASSERT(!hasResult());
     if (m_absolutePaintRect.isEmpty())
-        return 0;
-    m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), m_filter.filterScale(), m_resultColorSpace, m_filter.renderingMode());
+        return nullptr;
+
+    FloatSize clampedSize = ImageBuffer::clampedSize(m_absolutePaintRect.size());
+    m_imageBufferResult = ImageBuffer::create(clampedSize, m_filter.filterScale(), m_resultColorSpace, m_filter.renderingMode());
     if (!m_imageBufferResult)
-        return 0;
+        return nullptr;
+
     ASSERT(m_imageBufferResult->context());
     return m_imageBufferResult.get();
 }
@@ -471,11 +465,11 @@ Uint8ClampedArray* FilterEffect::createUnmultipliedImageResult()
 {
     // Only one result type is allowed.
     ASSERT(!hasResult());
-    ASSERT(isFilterSizeValid(m_absolutePaintRect));
-
     if (m_absolutePaintRect.isEmpty())
-        return 0;
+        return nullptr;
+
     IntSize resultSize(m_absolutePaintRect.size());
+    ASSERT(ImageBuffer::isSizeClamped(resultSize));
     resultSize.scale(m_filter.filterScale());
     m_unmultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
     return m_unmultipliedImageResult.get();
@@ -485,11 +479,11 @@ Uint8ClampedArray* FilterEffect::createPremultipliedImageResult()
 {
     // Only one result type is allowed.
     ASSERT(!hasResult());
-    ASSERT(isFilterSizeValid(m_absolutePaintRect));
-
     if (m_absolutePaintRect.isEmpty())
-        return 0;
+        return nullptr;
+
     IntSize resultSize(m_absolutePaintRect.size());
+    ASSERT(ImageBuffer::isSizeClamped(resultSize));
     resultSize.scale(m_filter.filterScale());
     m_premultipliedImageResult = Uint8ClampedArray::createUninitialized(resultSize.width() * resultSize.height() * 4);
     return m_premultipliedImageResult.get();
index ca7e0afa4be8c6e1277e8a89313848ac6a132cf8..ced7044bc3170dd3c0fa011057f77312daa44407 100644 (file)
@@ -58,9 +58,6 @@ class FilterEffect : public RefCounted<FilterEffect> {
 public:
     virtual ~FilterEffect();
 
-    static bool isFilterSizeValid(const FloatRect&);
-    static float maxFilterArea();
-
     void clearResult();
     void clearResultsRecursive();
 
index 306a11e8153a2caac34eb069b8484a3274e744c0..53647d4348e6654e02a16e7731f66e2412614aac 100644 (file)
@@ -172,6 +172,16 @@ AffineTransform& AffineTransform::scale(double sx, double sy)
     return *this;
 }
 
+AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+{
+    return scale(sx, sy);
+}
+
+AffineTransform& AffineTransform::scale(const FloatSize& s)
+{
+    return scale(s.width(), s.height());
+}
+
 // *this = *this * translation
 AffineTransform& AffineTransform::translate(double tx, double ty)
 {
@@ -186,9 +196,9 @@ AffineTransform& AffineTransform::translate(double tx, double ty)
     return *this;
 }
 
-AffineTransform& AffineTransform::scaleNonUniform(double sx, double sy)
+AffineTransform& AffineTransform::translate(const FloatPoint& t)
 {
-    return scale(sx, sy);
+    return translate(t.x(), t.y());
 }
 
 AffineTransform& AffineTransform::rotateFromVector(double x, double y)
index 641db00fa4c1797117422af860bb10cf6c74d8c9..2f7817f326f5f52be0272ef38f14100a9298e050 100644 (file)
@@ -98,9 +98,11 @@ public:
     WEBCORE_EXPORT AffineTransform& scale(double);
     AffineTransform& scale(double sx, double sy); 
     AffineTransform& scaleNonUniform(double sx, double sy);
+    AffineTransform& scale(const FloatSize&);
     AffineTransform& rotate(double d);
     AffineTransform& rotateFromVector(double x, double y);
     WEBCORE_EXPORT AffineTransform& translate(double tx, double ty);
+    AffineTransform& translate(const FloatPoint&);
     AffineTransform& shear(double sx, double sy);
     AffineTransform& flipX();
     WEBCORE_EXPORT AffineTransform& flipY();
@@ -172,7 +174,7 @@ public:
     {
         return AffineTransform(1, 0, 0, 1, x, y);
     }
-    
+
     // decompose the matrix into its component parts
     typedef struct {
         double scaleX, scaleY;
index f72949d4dc4087c1d8626af200eb3cbd86ae1524..4c8cadcd4ffd79258a8c38a4b718d61641ec96a0 100644 (file)
@@ -305,14 +305,14 @@ bool FilterEffectRenderer::build(RenderElement* renderer, const FilterOperations
 
 bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
 {
-    if (!filterRect.isZero() && FilterEffect::isFilterSizeValid(filterRect)) {
-        FloatRect currentSourceRect = sourceImageRect();
-        if (filterRect != currentSourceRect) {
-            setSourceImageRect(filterRect);
-            return true;
-        }
-    }
-    return false;
+    if (filterRect.isEmpty() || !ImageBuffer::isSizeClamped(filterRect.size()))
+        return false;
+
+    if (filterRect == sourceImageRect())
+        return false;
+
+    setSourceImageRect(filterRect);
+    return true;
 }
 
 void FilterEffectRenderer::allocateBackingStoreIfNeeded()
@@ -401,7 +401,7 @@ bool FilterEffectRendererHelper::beginFilterEffect()
     filter->allocateBackingStoreIfNeeded();
     // Paint into the context that represents the SourceGraphic of the filter.
     GraphicsContext* sourceGraphicsContext = filter->inputContext();
-    if (!sourceGraphicsContext || !FilterEffect::isFilterSizeValid(filter->filterRegion())) {
+    if (!sourceGraphicsContext || filter->filterRegion().isEmpty() || !ImageBuffer::isSizeClamped(filter->filterRegion().size())) {
         // Disable the filters and continue.
         m_haveFilterEffect = false;
         return false;
index d170f2889f75cfda4daa19f320e404dfddb36917..8b9a6289e28205c90b1e04e3c7d48bd5a185fa58 100644 (file)
@@ -138,11 +138,11 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderElement& renderer, c
     if (shouldCreateClipperMaskImage && pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
         return true;
 
-    AffineTransform absoluteTransform;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
 
     if (shouldCreateClipperMaskImage && !repaintRect.isEmpty()) {
-        if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
+        clipperMaskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceDeviceRGB, Unaccelerated);
+        if (!clipperMaskImage)
             return false;
 
         GraphicsContext* maskContext = clipperMaskImage->context();
index ae33fac55c45aeb13ecadf7498cd54b9a927ac89..6770e8b5ab22ac6ab8a2cc32e9f3763fab3e0f1d 100644 (file)
@@ -96,21 +96,6 @@ std::unique_ptr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFi
     return builder;
 }
 
-bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
-{
-    FloatSize scaledSize(size);
-    scaledSize.scale(scale.width(), scale.height());
-    float scaledArea = scaledSize.width() * scaledSize.height();
-
-    if (scaledArea <= FilterEffect::maxFilterArea())
-        return true;
-
-    // If area of scaled size is bigger than the upper limit, adjust the scale
-    // to fit.
-    scale.scale(sqrt(FilterEffect::maxFilterArea() / scaledArea));
-    return false;
-}
-
 bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const RenderStyle&, GraphicsContext*& context, unsigned short resourceMode)
 {
     ASSERT(context);
@@ -131,8 +116,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
         return false;
 
     // Determine absolute transformation matrix for filter. 
-    AffineTransform absoluteTransform;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
     if (!absoluteTransform.isInvertible())
         return false;
 
@@ -167,8 +151,8 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
 
     // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
     FloatRect tempSourceRect = absoluteDrawingRegion;
+    ImageBuffer::isSizeClamped(tempSourceRect.size(), scale);
     tempSourceRect.scale(scale.width(), scale.height());
-    fitsInMaximumImageSize(tempSourceRect.size(), scale);
 
     // Set the scale level in SVGFilter.
     filterData->filter->setFilterResolution(scale);
@@ -182,7 +166,7 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
     FloatRect subRegion = lastEffect->maxEffectRect();
     // At least one FilterEffect has a too big image size,
     // recalculate the effect sizes with new scale factors.
-    if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
+    if (!ImageBuffer::isSizeClamped(subRegion.size(), scale)) {
         filterData->filter->setFilterResolution(scale);
         RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(*lastEffect);
     }
@@ -201,9 +185,10 @@ bool RenderSVGResourceFilter::applyResource(RenderElement& renderer, const Rende
     effectiveTransform.scale(scale.width(), scale.height());
     effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
 
-    std::unique_ptr<ImageBuffer> sourceGraphic;
     RenderingMode renderingMode = renderer.frame().settings().acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
-    if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+
+    auto sourceGraphic = SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, ColorSpaceLinearRGB, renderingMode);
+    if (!sourceGraphic) {
         ASSERT(!m_filter.contains(&renderer));
         filterData->savedContext = context;
         m_filter.set(&renderer, WTF::move(filterData));
index c6f5c7275a4bb61e4e52a379a0694580befeb40c..d6ccfbf866fdc0aebbf7d7e615017f57f0c41918 100644 (file)
@@ -91,8 +91,6 @@ private:
     virtual const char* renderName() const override { return "RenderSVGResourceFilter"; }
     virtual bool isSVGResourceFilter() const override { return true; }
 
-    bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
-
     HashMap<RenderObject*, std::unique_ptr<FilterData>> m_filter;
 };
 
index 3a20f68628009e0ae65f9906720d9c4526ab9b33..cbca103ef3056979ef465c2b57b5337a98b5d74e 100644 (file)
@@ -58,12 +58,11 @@ static inline bool createMaskAndSwapContextForTextGradient(GraphicsContext*& con
     auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
     ASSERT(textRootBlock);
 
-    AffineTransform absoluteTransform;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock, absoluteTransform);
-
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
     FloatRect repaintRect = textRootBlock->repaintRectInLocalCoordinates();
-    std::unique_ptr<ImageBuffer> maskImage;
-    if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskImage, ColorSpaceDeviceRGB, Unaccelerated))
+
+    auto maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, ColorSpaceDeviceRGB, Unaccelerated);
+    if (!maskImage)
         return false;
 
     GraphicsContext* maskImageContext = maskImage->context();
@@ -80,10 +79,10 @@ static inline AffineTransform clipToTextMask(GraphicsContext* context, std::uniq
     auto* textRootBlock = RenderSVGText::locateRenderSVGTextAncestor(*object);
     ASSERT(textRootBlock);
 
-    AffineTransform absoluteTransform;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock, absoluteTransform);
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(*textRootBlock);
 
     targetRect = textRootBlock->repaintRectInLocalCoordinates();
+
     SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, targetRect, imageBuffer, false);
 
     AffineTransform matrix;
index 293d83c110554f7815e444b23a64f441916c582c..0115075684866033077794da4950a32061d7b642 100644 (file)
@@ -63,16 +63,14 @@ bool RenderSVGResourceMasker::applySVGMask(RenderElement& renderer, GraphicsCont
         m_masker.set(&renderer, std::make_unique<MaskerData>());
 
     MaskerData* maskerData = m_masker.get(&renderer);
-
-    AffineTransform absoluteTransform;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransform);
-
+    AffineTransform absoluteTransform = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
     FloatRect repaintRect = renderer.repaintRectInLocalCoordinates();
 
     if (!maskerData->maskImage && !repaintRect.isEmpty()) {
         const SVGRenderStyle& svgStyle = style().svgStyle();
         ColorSpace colorSpace = svgStyle.colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB;
-        if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
+        maskerData->maskImage = SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, colorSpace, Unaccelerated);
+        if (!maskerData->maskImage)
             return false;
 
         if (!drawContentIntoMaskImage(maskerData, colorSpace, &renderer))
index 7bb6ef6acb104b191ec6a9eb5ac4b51c134e3249..4bc0d9512b290c727d7a77c8b24584999c1f69be 100644 (file)
@@ -70,20 +70,19 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns
 
     // If we couldn't determine the pattern content element root, stop here.
     if (!m_attributes.patternContentElement())
-        return 0;
+        return nullptr;
 
     // An empty viewBox disables rendering.
     if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty())
-        return 0;
+        return nullptr;
 
     // Compute all necessary transformations to build the tile image & the pattern.
     FloatRect tileBoundaries;
     AffineTransform tileImageTransform;
     if (!buildTileImageTransform(renderer, m_attributes, patternElement(), tileBoundaries, tileImageTransform))
-        return 0;
+        return nullptr;
 
-    AffineTransform absoluteTransformIgnoringRotation;
-    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer, absoluteTransformIgnoringRotation);
+    AffineTransform absoluteTransformIgnoringRotation = SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(renderer);
 
     // Ignore 2D rotation, as it doesn't affect the size of the tile.
     SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
@@ -95,13 +94,13 @@ PatternData* RenderSVGResourcePattern::buildPattern(RenderElement& renderer, uns
         static_cast<float>(m_attributes.patternTransform().yScale()));
 
     // Build tile image.
-    std::unique_ptr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+    auto tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
     if (!tileImage)
-        return 0;
+        return nullptr;
 
     RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
     if (!copiedImage)
-        return 0;
+        return nullptr;
 
     // Build pattern.
     auto patternData = std::make_unique<PatternData>();
@@ -233,11 +232,9 @@ bool RenderSVGResourcePattern::buildTileImageTransform(RenderElement& renderer,
 
 std::unique_ptr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes, const FloatRect& tileBoundaries, const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform, FloatRect& clampedAbsoluteTileBoundaries) const
 {
-    clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
-
-    std::unique_ptr<ImageBuffer> tileImage;
-
-    if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
+    clampedAbsoluteTileBoundaries = ImageBuffer::clampedRect(absoluteTileBoundaries);
+    auto tileImage = SVGRenderingContext::createImageBuffer(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, ColorSpaceDeviceRGB, Unaccelerated);
+    if (!tileImage)
         return nullptr;
 
     GraphicsContext* tileImageContext = tileImage->context();
index 6c12e1c871642d31921534b179b8c3f0957a1e8e..926f23b37f5d61c72e45f88ff933f92fa138f5c5 100644 (file)
@@ -39,8 +39,6 @@
 #include "SVGResources.h"
 #include "SVGResourcesCache.h"
 
-static int kMaxImageBufferSize = 4096;
-
 namespace WebCore {
 
 static inline bool isRenderingMaskImage(const RenderObject& object)
@@ -204,14 +202,13 @@ static AffineTransform& currentContentTransformation()
 
 float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject& renderer)
 {
-    AffineTransform ctm;
-    calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+    AffineTransform ctm = calculateTransformationToOutermostCoordinateSystem(renderer);
     return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
 }
 
-void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer, AffineTransform& absoluteTransform)
+AffineTransform SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject& renderer)
 {
-    absoluteTransform = currentContentTransformation();
+    AffineTransform absoluteTransform = currentContentTransformation();
 
     float deviceScaleFactor = renderer.document().deviceScaleFactor();
     // Walk up the render tree, accumulating SVG transforms.
@@ -237,53 +234,53 @@ void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(con
     }
 
     absoluteTransform.scale(deviceScaleFactor);
+    return absoluteTransform;
 }
 
-bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace colorSpace, RenderingMode renderingMode)
 {
     IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
     // Don't create empty ImageBuffers.
     if (paintRect.isEmpty())
-        return false;
+        return nullptr;
 
-    IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
-    std::unique_ptr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
-    if (!image)
-        return false;
+    FloatSize scale;
+    FloatSize clampedSize = ImageBuffer::clampedSize(paintRect.size(), scale);
 
-    GraphicsContext* imageContext = image->context();
-    ASSERT(imageContext);
+    auto imageBuffer = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+    if (!imageBuffer)
+        return nullptr;
 
-    imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
-                                  static_cast<float>(clampedSize.height()) / paintRect.height()));
-    imageContext->translate(-paintRect.x(), -paintRect.y());
-    imageContext->concatCTM(absoluteTransform);
+    AffineTransform transform;
+    transform.scale(scale).translate(-paintRect.location()).multiply(absoluteTransform);
 
-    imageBuffer = WTF::move(image);
-    return true;
+    GraphicsContext* imageContext = imageBuffer->context();
+    ASSERT(imageContext);
+    imageContext->concatCTM(transform);
+
+    return imageBuffer;
 }
 
-bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+std::unique_ptr<ImageBuffer> SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace colorSpace, RenderingMode renderingMode)
 {
-    IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
-    IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
+    IntSize clampedSize = roundedIntSize(clampedRect.size());
+    IntSize unclampedSize = roundedIntSize(targetRect.size());
 
     // Don't create empty ImageBuffers.
-    if (imageSize.isEmpty())
-        return false;
+    if (clampedSize.isEmpty())
+        return nullptr;
 
-    std::unique_ptr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
-    if (!image)
-        return false;
+    auto imageBuffer = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+    if (!imageBuffer)
+        return nullptr;
 
-    GraphicsContext* imageContext = image->context();
+    GraphicsContext* imageContext = imageBuffer->context();
     ASSERT(imageContext);
 
     // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
-    imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
+    imageContext->scale(FloatSize(unclampedSize.width() / targetRect.width(), unclampedSize.height() / targetRect.height()));
 
-    imageBuffer = WTF::move(image);
-    return true;
+    return imageBuffer;
 }
 
 void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderElement& item, const AffineTransform& subtreeContentTransformation)
@@ -322,18 +319,6 @@ void SVGRenderingContext::clipToImageBuffer(GraphicsContext* context, const Affi
         imageBuffer.reset();
 }
 
-FloatRect SVGRenderingContext::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
-{
-    const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
-    return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
-}
-
-IntSize SVGRenderingContext::clampedAbsoluteSize(const IntSize& absoluteSize)
-{
-    const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
-    return absoluteSize.shrunkTo(maxImageBufferSize);
-}
-
 void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
 {
     AffineTransform::DecomposedType decomposition;
index d7c781cfb8a99c0d098ecb0feccdc503e7cccd05..9a23c25123b87ec29cfda0cec7ec245659843d8a 100644 (file)
@@ -71,17 +71,14 @@ public:
     void prepareToRenderSVGContent(RenderElement&, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext);
     bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; }
 
-    static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
-    // Patterns need a different float-to-integer coordinate mapping.
-    static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, std::unique_ptr<ImageBuffer>&, ColorSpace, RenderingMode);
+    static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, ColorSpace, RenderingMode);
+    static std::unique_ptr<ImageBuffer> createImageBuffer(const FloatRect& targetRect, const FloatRect& clampedRect, ColorSpace, RenderingMode);
 
     static void renderSubtreeToImageBuffer(ImageBuffer*, RenderElement&, const AffineTransform&);
     static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, std::unique_ptr<ImageBuffer>&, bool safeToClear);
 
     static float calculateScreenFontSizeScalingFactor(const RenderObject&);
-    static void calculateTransformationToOutermostCoordinateSystem(const RenderObject&, AffineTransform& absoluteTransform);
-    static IntSize clampedAbsoluteSize(const IntSize&);
-    static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
+    static AffineTransform calculateTransformationToOutermostCoordinateSystem(const RenderObject&);
     static void clear2DRotation(AffineTransform&);
 
     static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)