Source/WebCore: [CSS Masking] -webkit-mask-repeat: space does not work
Added the space option to background-repeat and -webkit-mask-repeat.
With the property value 'space', the background or mask image gets repeated as often as it fits within the background positioning
area. The repeated images are spaced equally to fill the unused area.
https://bugs.webkit.org/show_bug.cgi?id=119324

Patch by Andrei Parvu <parvu@adobe.com> on 2013-08-30
Reviewed by Dirk Schulze.

Tests: css3/background/background-repeat-space-border.html
       css3/background/background-repeat-space-content.html
       css3/background/background-repeat-space-padding.html
       css3/masking/mask-repeat-space-border.html
       css3/masking/mask-repeat-space-content.html
       css3/masking/mask-repeat-space-padding.html

* platform/graphics/GeneratorGeneratedImage.cpp:
(WebCore::GeneratorGeneratedImage::drawPattern): Passed the space values to the image buffer.
* platform/graphics/Image.cpp:
(WebCore::Image::drawTiled): Added the space values when computing the location of the tile.
* platform/graphics/Image.h: Added the space property.
(WebCore::Image::spaceSize):
(WebCore::Image::setSpaceSize):
* platform/graphics/ImageBuffer.h: Added the space property.
(WebCore::ImageBuffer::spaceSize):
(WebCore::ImageBuffer::setSpaceSize):
* platform/graphics/cg/ImageBufferCG.cpp: Passed the space values when copying an image.
(WebCore::ImageBuffer::copyImage):
* platform/graphics/cg/ImageCG.cpp: Added the space values when creating a platform pattern.
(WebCore::Image::drawPattern):
* rendering/RenderBoxModelObject.cpp:
(WebCore::RenderBoxModelObject::paintFillLayerExtended): Computed the space values on x and y axis.
(WebCore::getSpace):
(WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): Pass the space values to the Image class.
* rendering/RenderBoxModelObject.h: Added the space property.
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize):
(WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize):
* svg/graphics/SVGImage.cpp: Passed the space property to the created image.
(WebCore::SVGImage::drawPatternForContainer):
* svg/graphics/SVGImageForContainer.cpp: Passed the space property to the image property.
(WebCore::SVGImageForContainer::drawPattern):

LayoutTests: [CSS Masking] -webkit-mask-repeat: space does not work
Added tests to verify correct usage of background-repeat: space and mask-repeat: space.
Added one test for each possible mask/background clip: border, padding and content
https://bugs.webkit.org/show_bug.cgi?id=119324

Patch by Andrei Parvu <parvu@adobe.com> on 2013-08-30
Reviewed by Dirk Schulze.

* css3/background/background-repeat-space-border-expected.html: Added.
* css3/background/background-repeat-space-border.html: Added.
* css3/background/background-repeat-space-content-expected.html: Added.
* css3/background/background-repeat-space-content.html: Added.
* css3/background/background-repeat-space-padding-expected.html: Added.
* css3/background/background-repeat-space-padding.html: Added.
* css3/masking/mask-repeat-space-border-expected.html: Added.
* css3/masking/mask-repeat-space-border.html: Added.
* css3/masking/mask-repeat-space-content-expected.html: Added.
* css3/masking/mask-repeat-space-content.html: Added.
* css3/masking/mask-repeat-space-padding-expected.html: Added.
* css3/masking/mask-repeat-space-padding.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154875 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 36d3956..1ab10a9 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,46 @@
+2013-08-30  Andrei Parvu  <parvu@adobe.com>
+
+        [CSS Masking] -webkit-mask-repeat: space does not work
+        Added the space option to background-repeat and -webkit-mask-repeat.
+        With the property value 'space', the background or mask image gets repeated as often as it fits within the background positioning
+        area. The repeated images are spaced equally to fill the unused area.
+        https://bugs.webkit.org/show_bug.cgi?id=119324
+
+        Reviewed by Dirk Schulze.
+
+        Tests: css3/background/background-repeat-space-border.html
+               css3/background/background-repeat-space-content.html
+               css3/background/background-repeat-space-padding.html
+               css3/masking/mask-repeat-space-border.html
+               css3/masking/mask-repeat-space-content.html
+               css3/masking/mask-repeat-space-padding.html
+
+        * platform/graphics/GeneratorGeneratedImage.cpp:
+        (WebCore::GeneratorGeneratedImage::drawPattern): Passed the space values to the image buffer.
+        * platform/graphics/Image.cpp:
+        (WebCore::Image::drawTiled): Added the space values when computing the location of the tile.
+        * platform/graphics/Image.h: Added the space property.
+        (WebCore::Image::spaceSize):
+        (WebCore::Image::setSpaceSize):
+        * platform/graphics/ImageBuffer.h: Added the space property.
+        (WebCore::ImageBuffer::spaceSize):
+        (WebCore::ImageBuffer::setSpaceSize):
+        * platform/graphics/cg/ImageBufferCG.cpp: Passed the space values when copying an image.
+        (WebCore::ImageBuffer::copyImage):
+        * platform/graphics/cg/ImageCG.cpp: Added the space values when creating a platform pattern.
+        (WebCore::Image::drawPattern):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended): Computed the space values on x and y axis.
+        (WebCore::getSpace):
+        (WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry): Pass the space values to the Image class.
+        * rendering/RenderBoxModelObject.h: Added the space property.
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::spaceSize):
+        (WebCore::RenderBoxModelObject::BackgroundImageGeometry::setSpaceSize):
+        * svg/graphics/SVGImage.cpp: Passed the space property to the created image.
+        (WebCore::SVGImage::drawPatternForContainer):
+        * svg/graphics/SVGImageForContainer.cpp: Passed the space property to the image property.
+        (WebCore::SVGImageForContainer::drawPattern):
+
 2013-08-30  Antti Koivisto  <antti@apple.com>
 
         Remove AttachContext
diff --git a/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp b/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
index a7fc565..84100a1 100644
--- a/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
+++ b/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
@@ -74,6 +74,7 @@
         m_cachedAdjustedSize = adjustedSize;
     }
 
+    m_cachedImageBuffer->setSpaceSize(spaceSize());
     // Tile the image buffer into the context.
     m_cachedImageBuffer->drawPattern(destContext, adjustedSrcRect, adjustedPatternCTM, phase, styleColorSpace, compositeOp, destRect);
 }
diff --git a/Source/WebCore/platform/graphics/Image.cpp b/Source/WebCore/platform/graphics/Image.cpp
index 2be0eba..8b6efc3 100644
--- a/Source/WebCore/platform/graphics/Image.cpp
+++ b/Source/WebCore/platform/graphics/Image.cpp
@@ -114,8 +114,9 @@
                     scaledTileSize.height() / intrinsicTileSize.height());
 
     FloatRect oneTileRect;
-    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), scaledTileSize.width()) - scaledTileSize.width(), scaledTileSize.width()));
-    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), scaledTileSize.height()) - scaledTileSize.height(), scaledTileSize.height()));
+    FloatSize actualTileSize(scaledTileSize.width() + spaceSize().width(), scaledTileSize.height() + spaceSize().height());
+    oneTileRect.setX(destRect.x() + fmodf(fmodf(-srcPoint.x(), actualTileSize.width()) - actualTileSize.width(), actualTileSize.width()));
+    oneTileRect.setY(destRect.y() + fmodf(fmodf(-srcPoint.y(), actualTileSize.height()) - actualTileSize.height(), actualTileSize.height()));
     oneTileRect.setSize(scaledTileSize);
     
     // Check and see if a single draw of the image can cover the entire area we are supposed to tile.    
@@ -130,9 +131,9 @@
     }
 
     AffineTransform patternTransform = AffineTransform().scaleNonUniform(scale.width(), scale.height());
-    FloatRect tileRect(FloatPoint(), intrinsicTileSize);    
+    FloatRect tileRect(FloatPoint(), intrinsicTileSize);
     drawPattern(ctxt, tileRect, patternTransform, oneTileRect.location(), styleColorSpace, op, destRect, blendMode);
-    
+
     startAnimation();
 }
 
diff --git a/Source/WebCore/platform/graphics/Image.h b/Source/WebCore/platform/graphics/Image.h
index e706b5c..768d0e4 100644
--- a/Source/WebCore/platform/graphics/Image.h
+++ b/Source/WebCore/platform/graphics/Image.h
@@ -29,6 +29,7 @@
 
 #include "Color.h"
 #include "ColorSpace.h"
+#include "FloatSize.h"
 #include "GraphicsTypes.h"
 #include "ImageOrientation.h"
 #include "IntRect.h"
@@ -187,6 +188,11 @@
     virtual bool notSolidColor() { return true; }
 #endif
 
+    FloatSize spaceSize() const { return m_space; }
+    void setSpaceSize(const FloatSize& space)
+    {
+        m_space = space;
+    }
 protected:
     Image(ImageObserver* = 0);
 
@@ -209,6 +215,7 @@
 private:
     RefPtr<SharedBuffer> m_encodedImageData;
     ImageObserver* m_imageObserver;
+    FloatSize m_space;
 };
 
 }
diff --git a/Source/WebCore/platform/graphics/ImageBuffer.h b/Source/WebCore/platform/graphics/ImageBuffer.h
index dc8c643..9f57192 100644
--- a/Source/WebCore/platform/graphics/ImageBuffer.h
+++ b/Source/WebCore/platform/graphics/ImageBuffer.h
@@ -128,6 +128,12 @@
         // with textures that are RGB or RGBA format, and UNSIGNED_BYTE type.
         bool copyToPlatformTexture(GraphicsContext3D&, Platform3DObject, GC3Denum, bool, bool);
 
+        FloatSize spaceSize() const { return m_space; }
+        void setSpaceSize(const FloatSize& space)
+        {
+            m_space = space;
+        }
+
     private:
 #if USE(CG)
         PassNativeImagePtr copyNativeImage(BackingStoreCopy = CopyBackingStore) const;
@@ -152,6 +158,7 @@
         IntSize m_logicalSize;
         float m_resolutionScale;
         OwnPtr<GraphicsContext> m_context;
+        FloatSize m_space;
 
         // This constructor will place its success into the given out-variable
         // so that create() knows when it should return failure.
diff --git a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index 49d9eb4..4e3acdf 100644
--- a/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -237,7 +237,10 @@
     if (!image)
         return 0;
 
-    return BitmapImage::create(image.get());
+    RefPtr<BitmapImage> bitmapImage = BitmapImage::create(image.get());
+    bitmapImage->setSpaceSize(spaceSize());
+
+    return bitmapImage.release();
 }
 
 BackingStoreCopy ImageBuffer::fastCopyImageMode()
diff --git a/Source/WebCore/platform/graphics/cg/ImageCG.cpp b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
index a535737..69ba2d6 100644
--- a/Source/WebCore/platform/graphics/cg/ImageCG.cpp
+++ b/Source/WebCore/platform/graphics/cg/ImageCG.cpp
@@ -73,6 +73,16 @@
     CGContextDrawImage(context, GraphicsContext(context).roundToDevicePixels(FloatRect(0, 0, CGImageGetWidth(image), CGImageGetHeight(image))), image);
 }
 
+static void patternReleaseOnMainThreadCallback(void* info)
+{
+    CGImageRelease((CGImageRef)info);
+}
+
+static void patternReleaseCallback(void* info)
+{
+    callOnMainThread(patternReleaseOnMainThreadCallback, info);
+}
+
 void Image::drawPattern(GraphicsContext* ctxt, const FloatRect& tileRect, const AffineTransform& patternTransform,
     const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect, BlendMode blendMode)
 {
@@ -112,42 +122,43 @@
 
     // Adjust the color space.
     subImage = Image::imageWithColorSpace(subImage.get(), styleColorSpace);
-    
+
     // Leopard has an optimized call for the tiling of image patterns, but we can only use it if the image has been decoded enough that
     // its buffer is the same size as the overall image.  Because a partially decoded CGImageRef with a smaller width or height than the
     // overall image buffer needs to tile with "gaps", we can't use the optimized tiling call in that case.
     // FIXME: We cannot use CGContextDrawTiledImage with scaled tiles on Leopard, because it suffers from rounding errors.  Snow Leopard is ok.
     float scaledTileWidth = tileRect.width() * narrowPrecisionToFloat(patternTransform.a());
     float w = CGImageGetWidth(tileImage);
-    if (w == size().width() && h == size().height())
+    if (w == size().width() && h == size().height() && !spaceSize().width() && !spaceSize().height())
         CGContextDrawTiledImage(context, FloatRect(adjustedX, adjustedY, scaledTileWidth, scaledTileHeight), subImage.get());
     else {
+        // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
+        static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, patternReleaseCallback };
+        CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
+        matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
+        // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
+        matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
+        CGImageRef platformImage = CGImageRetain(subImage.get());
+        RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(platformImage, CGRectMake(0, 0, tileRect.width(), tileRect.height()), matrix,
+            tileRect.width() + spaceSize().width() * (1 / narrowPrecisionToFloat(patternTransform.a())),
+            tileRect.height() + spaceSize().height() * (1 / narrowPrecisionToFloat(patternTransform.d())),
+            kCGPatternTilingConstantSpacing, true, &patternCallbacks));
+        
+        if (!pattern)
+            return;
 
-    // On Leopard and newer, this code now only runs for partially decoded images whose buffers do not yet match the overall size of the image.
-    static const CGPatternCallbacks patternCallbacks = { 0, drawPatternCallback, NULL };
-    CGAffineTransform matrix = CGAffineTransformMake(narrowPrecisionToCGFloat(patternTransform.a()), 0, 0, narrowPrecisionToCGFloat(patternTransform.d()), adjustedX, adjustedY);
-    matrix = CGAffineTransformConcat(matrix, CGContextGetCTM(context));
-    // The top of a partially-decoded image is drawn at the bottom of the tile. Map it to the top.
-    matrix = CGAffineTransformTranslate(matrix, 0, size().height() - h);
-    RetainPtr<CGPatternRef> pattern = adoptCF(CGPatternCreate(subImage.get(), CGRectMake(0, 0, tileRect.width(), tileRect.height()),
-                                             matrix, tileRect.width(), tileRect.height(), 
-                                             kCGPatternTilingConstantSpacing, true, &patternCallbacks));
-    if (!pattern)
-        return;
+        RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0));
 
-    RetainPtr<CGColorSpaceRef> patternSpace = adoptCF(CGColorSpaceCreatePattern(0));
-    
-    CGFloat alpha = 1;
-    RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
-    CGContextSetFillColorSpace(context, patternSpace.get());
+        CGFloat alpha = 1;
+        RetainPtr<CGColorRef> color = adoptCF(CGColorCreateWithPattern(patternSpace.get(), pattern.get(), &alpha));
+        CGContextSetFillColorSpace(context, patternSpace.get());
 
-    // FIXME: Really want a public API for this.  It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
-    wkSetBaseCTM(context, CGAffineTransformIdentity);
-    CGContextSetPatternPhase(context, CGSizeZero);
+        // FIXME: Really want a public API for this. It is just CGContextSetBaseCTM(context, CGAffineTransformIdentiy).
+        wkSetBaseCTM(context, CGAffineTransformIdentity);
+        CGContextSetPatternPhase(context, CGSizeZero);
 
-    CGContextSetFillColorWithColor(context, color.get());
-    CGContextFillRect(context, CGContextGetClipBoundingBox(context));
-
+        CGContextSetFillColorWithColor(context, color.get());
+        CGContextFillRect(context, CGContextGetClipBoundingBox(context));
     }
 
     stateSaver.restore();
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.cpp b/Source/WebCore/rendering/RenderBoxModelObject.cpp
index 9b3b2cf..c3400b1 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/Source/WebCore/rendering/RenderBoxModelObject.cpp
@@ -994,6 +994,8 @@
             RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
             RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geometry.tileSize());
             bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), bgLayer, geometry.tileSize());
+            if (image.get())
+                image->setSpaceSize(geometry.spaceSize());
             context->drawTiledImage(image.get(), style()->colorSpace(), geometry.destRect(), geometry.relativePhase(), geometry.tileSize(), 
                 compositeOp, useLowQualityScaling, bgLayer->blendMode());
         }
@@ -1225,6 +1227,17 @@
 #endif
 }
 
+static inline int getSpace(int areaSize, int tileSize)
+{
+    int numberOfTiles = areaSize / tileSize;
+    int space = 0;
+
+    if (numberOfTiles > 1)
+        space = roundedLayoutUnit((float)(areaSize - numberOfTiles * tileSize) / (numberOfTiles - 1));
+
+    return space;
+}
+
 void RenderBoxModelObject::calculateBackgroundImageGeometry(const RenderLayerModelObject* paintContainer, const FillLayer* fillLayer, const LayoutRect& paintRect,
     BackgroundImageGeometry& geometry, RenderObject* backgroundObject) const
 {
@@ -1314,6 +1327,7 @@
         fillTileSize.setWidth(positioningAreaSize.width() / nrTiles);
         geometry.setTileSize(fillTileSize);
         geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
+        geometry.setSpaceSize(FloatSize());
     }
 
     LayoutUnit computedYPosition = minimumValueForLength(fillLayer->yPosition(), availableHeight, &view(), true);
@@ -1326,20 +1340,37 @@
         fillTileSize.setHeight(positioningAreaSize.height() / nrTiles);
         geometry.setTileSize(fillTileSize);
         geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0);
+        geometry.setSpaceSize(FloatSize());
     }
 
-    if (backgroundRepeatX == RepeatFill)
+    if (backgroundRepeatX == RepeatFill) {
         geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
-    else if (backgroundRepeatX == NoRepeatFill) {
+        geometry.setSpaceSize(FloatSize(0, geometry.spaceSize().height()));
+    } else if (backgroundRepeatX == SpaceFill && fillTileSize.width() > 0) {
+        int space = getSpace(positioningAreaSize.width(), geometry.tileSize().width());
+        int actualWidth = geometry.tileSize().width() + space;
+
+        geometry.setSpaceSize(FloatSize(space, 0));
+        geometry.setPhaseX(actualWidth ? actualWidth - roundToInt(computedXPosition + left) % actualWidth : 0);
+    } else if (backgroundRepeatX == NoRepeatFill) {
         int xOffset = fillLayer->backgroundXOrigin() == RightEdge ? availableWidth - computedXPosition : computedXPosition;
         geometry.setNoRepeatX(left + xOffset);
+        geometry.setSpaceSize(FloatSize(0, geometry.spaceSize().height()));
     }
 
-    if (backgroundRepeatY == RepeatFill)
+    if (backgroundRepeatY == RepeatFill) {
         geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0);
-    else if (backgroundRepeatY == NoRepeatFill) {
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), 0));
+    } else if (backgroundRepeatY == SpaceFill && fillTileSize.height() > 0) {
+        int space = getSpace(positioningAreaSize.height(), geometry.tileSize().height());
+        int actualHeight = geometry.tileSize().height() + space;
+
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), space));
+        geometry.setPhaseY(actualHeight ? actualHeight - roundToInt(computedYPosition + top) % actualHeight : 0);
+    } else if (backgroundRepeatY == NoRepeatFill) {
         int yOffset = fillLayer->backgroundYOrigin() == BottomEdge ? availableHeight - computedYPosition : computedYPosition;
         geometry.setNoRepeatY(top + yOffset);
+        geometry.setSpaceSize(FloatSize(geometry.spaceSize().width(), 0));
     }
 
     if (fixedAttachment)
diff --git a/Source/WebCore/rendering/RenderBoxModelObject.h b/Source/WebCore/rendering/RenderBoxModelObject.h
index 9b8e05e..d00403b 100644
--- a/Source/WebCore/rendering/RenderBoxModelObject.h
+++ b/Source/WebCore/rendering/RenderBoxModelObject.h
@@ -228,7 +228,12 @@
         {
             m_tileSize = tileSize;
         }
-        
+        FloatSize spaceSize() const { return m_space; }
+        void setSpaceSize(const FloatSize& space)
+        {
+            m_space = space;
+        }
+
         void setPhaseX(int x) { m_phase.setX(x); }
         void setPhaseY(int y) { m_phase.setY(y); }
         
@@ -247,6 +252,7 @@
         IntPoint m_destOrigin;
         IntPoint m_phase;
         IntSize m_tileSize;
+        FloatSize m_space;
         bool m_hasNonLocalGeometry; // Has background-attachment: fixed. Implies that we can't always cheaply compute destRect.
     };
 
diff --git a/Source/WebCore/svg/graphics/SVGImage.cpp b/Source/WebCore/svg/graphics/SVGImage.cpp
index 1cf6d07..4944e5e 100644
--- a/Source/WebCore/svg/graphics/SVGImage.cpp
+++ b/Source/WebCore/svg/graphics/SVGImage.cpp
@@ -201,6 +201,7 @@
         return;
     drawForContainer(buffer->context(), containerSize, zoom, imageBufferSize, zoomedContainerRect, ColorSpaceDeviceRGB, CompositeSourceOver, BlendModeNormal);
     RefPtr<Image> image = buffer->copyImage(DontCopyBackingStore, Unscaled);
+    image->setSpaceSize(spaceSize());
 
     // Adjust the source rect and transform due to the image buffer's scaling.
     FloatRect scaledSrcRect = srcRect;
diff --git a/Source/WebCore/svg/graphics/SVGImageForContainer.cpp b/Source/WebCore/svg/graphics/SVGImageForContainer.cpp
index e9e2728..ddf4c68 100644
--- a/Source/WebCore/svg/graphics/SVGImageForContainer.cpp
+++ b/Source/WebCore/svg/graphics/SVGImageForContainer.cpp
@@ -45,6 +45,7 @@
 void SVGImageForContainer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
     const FloatPoint& phase, ColorSpace colorSpace, CompositeOperator compositeOp, const FloatRect& dstRect, BlendMode)
 {
+    m_image->setSpaceSize(spaceSize());
     m_image->drawPatternForContainer(context, m_containerSize, m_zoom, srcRect, patternTransform, phase, colorSpace, compositeOp, dstRect);
 }