2011-04-20 Dirk Schulze <krit@webkit.org>
authorkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 20:05:27 +0000 (20:05 +0000)
committerkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 20 Apr 2011 20:05:27 +0000 (20:05 +0000)
        Reviewed by Simon Fraser.

        SVG feDropShadow implementation of SVG Filters 1.2
        https://bugs.webkit.org/show_bug.cgi?id=52513

        Support different radii for horizontal and vertical blurring in ShadowBlur. This is a preperation for feDropShadow.
        feDropShadow is a new shorthand filter effect for the up-comming Filter 1.0 specification and will use ShadowBlur.
        feGaussianBlur might make use of ShadowBlur as well later (on SourceAlpha input).
        Added ShadowBlur to remaining platforms.

        The changes can't be tested before the changes in feGaussianBlur or feDropShadow. Current behavior is not affected.

        * Android.mk:
        * CMakeLists.txt:
        * GNUmakefile.list.am:
        * WebCore.pro:
        * platform/graphics/FloatSize.h:
        (WebCore::FloatSize::scale):
        * platform/graphics/ShadowBlur.cpp:
        (WebCore::ScratchBuffer::ScratchBuffer):
        (WebCore::ScratchBuffer::setLastShadowValues):
        (WebCore::ScratchBuffer::setLastInsetShadowValues):
        (WebCore::ScratchBuffer::matchesLastShadow):
        (WebCore::ScratchBuffer::matchesLastInsetShadow):
        (WebCore::ScratchBuffer::clearScratchBuffer):
        (WebCore::ShadowBlur::ShadowBlur):
        (WebCore::calculateLobes):
        (WebCore::ShadowBlur::blurLayerImage):
        (WebCore::ShadowBlur::adjustBlurRadius):
        (WebCore::ShadowBlur::calculateLayerBoundingRect):
        (WebCore::computeSliceSizesFromRadii):
        (WebCore::ShadowBlur::templateSize):
        (WebCore::ShadowBlur::drawInsetShadowWithTiling):
        (WebCore::ShadowBlur::drawRectShadowWithTiling):
        (WebCore::ShadowBlur::drawLayerPieces):
        * platform/graphics/ShadowBlur.h:
        * platform/graphics/cg/GraphicsContextCG.cpp:
        (WebCore::GraphicsContext::fillRect):
        (WebCore::GraphicsContext::fillRoundedRect):
        (WebCore::GraphicsContext::fillRectWithRoundedHole):

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

Source/WebCore/Android.mk
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/WebCore.pro
Source/WebCore/platform/graphics/FloatSize.h
Source/WebCore/platform/graphics/ShadowBlur.cpp
Source/WebCore/platform/graphics/ShadowBlur.h
Source/WebCore/platform/graphics/cg/GraphicsContextCG.cpp

index 5be12a9..29c306f 100644 (file)
@@ -555,6 +555,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
        platform/graphics/Pattern.cpp \
        platform/graphics/RoundedIntRect.cpp \
        platform/graphics/SegmentedFontData.cpp \
+       platform/graphics/ShadowBlur.cpp \
        platform/graphics/SimpleFontData.cpp \
        platform/graphics/StringTruncator.cpp \
        platform/graphics/WidthIterator.cpp
index 9941b76..f961b1f 100644 (file)
@@ -1108,6 +1108,7 @@ SET(WebCore_SOURCES
     platform/graphics/Pattern.cpp
     platform/graphics/RoundedIntRect.cpp
     platform/graphics/SegmentedFontData.cpp
+    platform/graphics/ShadowBlur.cpp
     platform/graphics/SimpleFontData.cpp
     platform/graphics/StringTruncator.cpp
     platform/graphics/WidthIterator.cpp
index 3885ea2..b33f32f 100644 (file)
@@ -1,3 +1,46 @@
+2011-04-20  Dirk Schulze  <krit@webkit.org>
+
+        Reviewed by Simon Fraser.
+
+        SVG feDropShadow implementation of SVG Filters 1.2
+        https://bugs.webkit.org/show_bug.cgi?id=52513
+
+        Support different radii for horizontal and vertical blurring in ShadowBlur. This is a preperation for feDropShadow.
+        feDropShadow is a new shorthand filter effect for the up-comming Filter 1.0 specification and will use ShadowBlur.
+        feGaussianBlur might make use of ShadowBlur as well later (on SourceAlpha input).
+        Added ShadowBlur to remaining platforms.
+
+        The changes can't be tested before the changes in feGaussianBlur or feDropShadow. Current behavior is not affected.
+
+        * Android.mk:
+        * CMakeLists.txt:
+        * GNUmakefile.list.am:
+        * WebCore.pro:
+        * platform/graphics/FloatSize.h:
+        (WebCore::FloatSize::scale):
+        * platform/graphics/ShadowBlur.cpp:
+        (WebCore::ScratchBuffer::ScratchBuffer):
+        (WebCore::ScratchBuffer::setLastShadowValues):
+        (WebCore::ScratchBuffer::setLastInsetShadowValues):
+        (WebCore::ScratchBuffer::matchesLastShadow):
+        (WebCore::ScratchBuffer::matchesLastInsetShadow):
+        (WebCore::ScratchBuffer::clearScratchBuffer):
+        (WebCore::ShadowBlur::ShadowBlur):
+        (WebCore::calculateLobes):
+        (WebCore::ShadowBlur::blurLayerImage):
+        (WebCore::ShadowBlur::adjustBlurRadius):
+        (WebCore::ShadowBlur::calculateLayerBoundingRect):
+        (WebCore::computeSliceSizesFromRadii):
+        (WebCore::ShadowBlur::templateSize):
+        (WebCore::ShadowBlur::drawInsetShadowWithTiling):
+        (WebCore::ShadowBlur::drawRectShadowWithTiling):
+        (WebCore::ShadowBlur::drawLayerPieces):
+        * platform/graphics/ShadowBlur.h:
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::fillRect):
+        (WebCore::GraphicsContext::fillRoundedRect):
+        (WebCore::GraphicsContext::fillRectWithRoundedHole):
+
 2011-04-19  Roland Steiner  <rolandsteiner@chromium.org>
 
         Reviewed by Dimitri Glazkov.
index 2801232..fe93244 100644 (file)
@@ -2463,6 +2463,8 @@ webcore_sources += \
        Source/WebCore/platform/graphics/RoundedIntRect.h \
        Source/WebCore/platform/graphics/SegmentedFontData.cpp \
        Source/WebCore/platform/graphics/SegmentedFontData.h \
+       Source/WebCore/platform/graphics/ShadowBlur.cpp \
+       Source/WebCore/platform/graphics/ShadowBlur.h \
        Source/WebCore/platform/graphics/SimpleFontData.cpp \
        Source/WebCore/platform/graphics/SimpleFontData.h \
        Source/WebCore/platform/graphics/StringTruncator.cpp \
index d805809..9579199 100644 (file)
@@ -995,6 +995,7 @@ SOURCES += \
     platform/graphics/Pattern.cpp \
     platform/graphics/RoundedIntRect.cpp \
     platform/graphics/SegmentedFontData.cpp \
+    platform/graphics/ShadowBlur.cpp \
     platform/graphics/SimpleFontData.cpp \
     platform/graphics/TiledBackingStore.cpp \
     platform/graphics/transforms/AffineTransform.cpp \
@@ -1971,6 +1972,7 @@ HEADERS += \
     platform/graphics/qt/StillImageQt.h \
     platform/graphics/qt/TransparencyLayer.h \
     platform/graphics/SegmentedFontData.h \
+    platform/graphics/ShadowBlur.h \
     platform/graphics/SimpleFontData.h \
     platform/graphics/Tile.h \
     platform/graphics/TiledBackingStore.h \    
index 1485c71..df9c19a 100644 (file)
@@ -65,10 +65,12 @@ public:
 
     float aspectRatio() const { return m_width / m_height; }
 
-    void scale(float scale)
+    void scale(float s) { scale(s, s); }
+
+    void scale(float scaleX, float scaleY)
     {
-        m_width *= scale;
-        m_height *= scale;
+        m_width *= scaleX;
+        m_height *= scaleY;
     }
 
     FloatSize expandedTo(const FloatSize& other) const
index 2f25221..92a0404 100644 (file)
@@ -42,6 +42,11 @@ using namespace std;
 
 namespace WebCore {
 
+enum {
+    leftLobe = 0,
+    rightLobe = 1
+};
+
 static inline int roundUpToMultipleOf32(int d)
 {
     return (1 + (d >> 5)) << 5;
@@ -54,7 +59,6 @@ class ScratchBuffer {
 public:
     ScratchBuffer()
         : m_purgeTimer(this, &ScratchBuffer::timerFired)
-        , m_lastRadius(0)
         , m_lastWasInset(false)
 #if !ASSERT_DISABLED
         , m_bufferInUse(false)
@@ -79,7 +83,7 @@ public:
         return m_imageBuffer.get();
     }
 
-    void setLastShadowValues(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
+    void setLastShadowValues(const FloatSize& radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
     {
         m_lastWasInset = false;
         m_lastRadius = radius;
@@ -89,7 +93,7 @@ public:
         m_lastRadii = radii;
     }
 
-    void setLastInsetShadowValues(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
+    void setLastInsetShadowValues(const FloatSize& radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii)
     {
         m_lastWasInset = true;
         m_lastInsetBounds = bounds;
@@ -100,14 +104,14 @@ public:
         m_lastRadii = radii;
     }
     
-    bool matchesLastShadow(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
+    bool matchesLastShadow(const FloatSize& radius, const Color& color, ColorSpace colorSpace, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
     {
         if (m_lastWasInset)
             return false;
         return m_lastRadius == radius && m_lastColor == color && m_lastColorSpace == colorSpace && shadowRect == m_lastShadowRect && radii == m_lastRadii;
     }
 
-    bool matchesLastInsetShadow(float radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
+    bool matchesLastInsetShadow(const FloatSize& radius, const Color& color, ColorSpace colorSpace, const FloatRect& bounds, const FloatRect& shadowRect, const RoundedIntRect::Radii& radii) const
     {
         if (!m_lastWasInset)
             return false;
@@ -137,7 +141,7 @@ private:
     void clearScratchBuffer()
     {
         m_imageBuffer = 0;
-        m_lastRadius = 0;
+        m_lastRadius = FloatSize();
     }
 
     OwnPtr<ImageBuffer> m_imageBuffer;
@@ -148,7 +152,7 @@ private:
     RoundedIntRect::Radii m_lastRadii;
     Color m_lastColor;
     ColorSpace m_lastColorSpace;
-    float m_lastRadius;
+    FloatSize m_lastRadius;
     bool m_lastWasInset;
     
 #if !ASSERT_DISABLED
@@ -164,7 +168,7 @@ ScratchBuffer& ScratchBuffer::shared()
 
 static const int templateSideLength = 1;
 
-ShadowBlur::ShadowBlur(float radius, const FloatSize& offset, const Color& color, ColorSpace colorSpace)
+ShadowBlur::ShadowBlur(const FloatSize& radius, const FloatSize& offset, const Color& color, ColorSpace colorSpace)
     : m_color(color)
     , m_colorSpace(colorSpace)
     , m_blurRadius(radius)
@@ -173,13 +177,13 @@ ShadowBlur::ShadowBlur(float radius, const FloatSize& offset, const Color& color
     , m_shadowsIgnoreTransforms(false)
 {
     // Limit blur radius to 128 to avoid lots of very expensive blurring.
-    m_blurRadius = min<float>(m_blurRadius, 128);
+    m_blurRadius = m_blurRadius.shrunkTo(FloatSize(128, 128));
 
     // The type of shadow is decided by the blur radius, shadow offset, and shadow color.
     if (!m_color.isValid() || !color.alpha()) {
         // Can't paint the shadow with invalid or invisible color.
         m_type = NoShadow;
-    } else if (m_blurRadius > 0) {
+    } else if (m_blurRadius.width() > 0 || m_blurRadius.height() > 0) {
         // Shadow is always blurred, even the offset is zero.
         m_type = BlurShadow;
     } else if (!m_offset.width() && !m_offset.height()) {
@@ -192,32 +196,24 @@ ShadowBlur::ShadowBlur(float radius, const FloatSize& offset, const Color& color
 // Instead of integer division, we use 17.15 for fixed-point division.
 static const int blurSumShift = 15;
 
-void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
+// Takes a two dimensional array with three rows and two columns for the lobes.
+static void calculateLobes(int lobes[][2], float blurRadius, bool shadowsIgnoreTransforms)
 {
-    const int channels[4] = { 3, 0, 1, 3 };
-
     int diameter;
-    if (m_shadowsIgnoreTransforms)
-        diameter = max(2, static_cast<int>(floorf((2 / 3.f) * m_blurRadius))); // Canvas shadow. FIXME: we should adjust the blur radius higher up.
+    if (shadowsIgnoreTransforms)
+        diameter = max(2, static_cast<int>(floorf((2 / 3.f) * blurRadius))); // Canvas shadow. FIXME: we should adjust the blur radius higher up.
     else {
         // http://dev.w3.org/csswg/css3-background/#box-shadow
         // Approximate a Gaussian blur with a standard deviation equal to half the blur radius,
         // which http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement tell us how to do.
         // However, shadows rendered according to that spec will extend a little further than m_blurRadius,
         // so we apply a fudge factor to bring the radius down slightly.
-        float stdDev = m_blurRadius / 2;
+        float stdDev = blurRadius / 2;
         const float gaussianKernelFactor = 3 / 4.f * sqrtf(2 * piFloat);
         const float fudgeFactor = 0.88f;
         diameter = max(2, static_cast<int>(floorf(stdDev * gaussianKernelFactor * fudgeFactor + 0.5f)));
     }
 
-    enum {
-        leftLobe = 0,
-        rightLobe = 1
-    };
-
-    int lobes[3][2]; // indexed by pass, and left/right lobe
-    
     if (diameter & 1) {
         // if d is odd, use three box-blurs of size 'd', centered on the output pixel.
         int lobeSize = (diameter - 1) / 2;
@@ -239,6 +235,14 @@ void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, i
         lobes[2][leftLobe] = lobeSize;
         lobes[2][rightLobe] = lobeSize;
     }
+}
+
+void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
+{
+    const int channels[4] = { 3, 0, 1, 3 };
+
+    int lobes[3][2]; // indexed by pass, and left/right lobe
+    calculateLobes(lobes, m_blurRadius.width(), m_shadowsIgnoreTransforms);
 
     // First pass is horizontal.
     int stride = 4;
@@ -248,6 +252,8 @@ void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, i
 
     // Two stages: horizontal and vertical
     for (int pass = 0; pass < 2; ++pass) {
+        if (pass && m_blurRadius.width() != m_blurRadius.height())
+            calculateLobes(lobes, m_blurRadius.height(), m_shadowsIgnoreTransforms);
         unsigned char* pixels = imageData;
 
         for (int j = 0; j < final; ++j, pixels += delta) {
@@ -333,19 +339,17 @@ void ShadowBlur::adjustBlurRadius(GraphicsContext* context)
     const float yAxisScale = sqrtf(yUnitChange.width() * yUnitChange.width()
                                    + yUnitChange.height() * yUnitChange.height());
 
-    // blurLayerImage() does not support per-axis blurring, so calculate a balanced scaling.
-    // FIXME: does AffineTransform.xScale()/yScale() help?
-    const float scale = sqrtf(xAxisScale * yAxisScale);
-    m_blurRadius = roundf(m_blurRadius / scale);
+    // Scale blur radius
+    m_blurRadius.scale(1 / xAxisScale, 1 / yAxisScale);
 }
 
 IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const FloatRect& shadowedRect, const IntRect& clipRect)
 {
-    const float roundedRadius = ceilf(m_blurRadius);
+    const IntSize roundedRadius = expandedIntSize(m_blurRadius);
 
     // Calculate the destination of the blurred and/or transformed layer.
     FloatRect layerRect;
-    float inflation = 0;
+    IntSize inflation;
 
     const AffineTransform transform = context->getCTM();
     if (m_shadowsIgnoreTransforms && !transform.isIdentity()) {
@@ -359,7 +363,8 @@ IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const F
 
     // We expand the area by the blur radius to give extra space for the blur transition.
     if (m_type == BlurShadow) {
-        layerRect.inflate(roundedRadius);
+        layerRect.inflateX(roundedRadius.width());
+        layerRect.inflateY(roundedRadius.height());
         inflation = roundedRadius;
     }
 
@@ -373,14 +378,17 @@ IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const F
         IntRect inflatedClip = clipRect;
         // Pixels at the edges can be affected by pixels outside the buffer,
         // so intersect with the clip inflated by the blur.
-        if (m_type == BlurShadow)
-            inflatedClip.inflate(roundedRadius);
+        if (m_type == BlurShadow) {
+            inflatedClip.inflateX(roundedRadius.width());
+            inflatedClip.inflateY(roundedRadius.height());
+        }
         
         layerRect.intersect(inflatedClip);
     }
 
-    const float frameSize = inflation * 2;
-    m_sourceRect = FloatRect(0, 0, shadowedRect.width() + frameSize, shadowedRect.height() + frameSize);
+    IntSize frameSize = inflation;
+    frameSize.scale(2);
+    m_sourceRect = FloatRect(0, 0, shadowedRect.width() + frameSize.width(), shadowedRect.height() + frameSize.height());
     m_layerOrigin = FloatPoint(layerRect.x(), layerRect.y());
     m_layerSize = layerRect.size();
 
@@ -389,8 +397,8 @@ IntRect ShadowBlur::calculateLayerBoundingRect(GraphicsContext* context, const F
 
     // Set the origin as the top left corner of the scratch image, or, in case there's a clipped
     // out region, set the origin accordingly to the full bounding rect's top-left corner.
-    float translationX = -shadowedRect.x() + inflation - fabsf(clippedOut.width());
-    float translationY = -shadowedRect.y() + inflation - fabsf(clippedOut.height());
+    float translationX = -shadowedRect.x() + inflation.width() - fabsf(clippedOut.width());
+    float translationY = -shadowedRect.y() + inflation.height() - fabsf(clippedOut.height());
     m_layerContextTranslation = FloatSize(translationX, translationY);
 
     return enclosingIntRect(layerRect);
@@ -418,13 +426,13 @@ void ShadowBlur::drawShadowBuffer(GraphicsContext* graphicsContext)
     graphicsContext->restore();
 }
 
-static void computeSliceSizesFromRadii(int twiceRadius, const RoundedIntRect::Radii& radii, int& leftSlice, int& rightSlice, int& topSlice, int& bottomSlice)
+static void computeSliceSizesFromRadii(const IntSize& twiceRadius, const RoundedIntRect::Radii& radii, int& leftSlice, int& rightSlice, int& topSlice, int& bottomSlice)
 {
-    leftSlice = twiceRadius + max(radii.topLeft().width(), radii.bottomLeft().width()); 
-    rightSlice = twiceRadius + max(radii.topRight().width(), radii.bottomRight().width()); 
+    leftSlice = twiceRadius.width() + max(radii.topLeft().width(), radii.bottomLeft().width()); 
+    rightSlice = twiceRadius.width() + max(radii.topRight().width(), radii.bottomRight().width()); 
 
-    topSlice = twiceRadius + max(radii.topLeft().height(), radii.topRight().height());
-    bottomSlice = twiceRadius + max(radii.bottomLeft().height(), radii.bottomRight().height());
+    topSlice = twiceRadius.height() + max(radii.topLeft().height(), radii.topRight().height());
+    bottomSlice = twiceRadius.height() + max(radii.bottomLeft().height(), radii.bottomRight().height());
 }
 
 IntSize ShadowBlur::templateSize(const RoundedIntRect::Radii& radii) const
@@ -435,7 +443,10 @@ IntSize ShadowBlur::templateSize(const RoundedIntRect::Radii& radii) const
     int rightSlice;
     int topSlice;
     int bottomSlice;
-    computeSliceSizesFromRadii(2 * ceilf(m_blurRadius), radii, leftSlice, rightSlice, topSlice, bottomSlice);
+    IntSize twiceRadius = expandedIntSize(m_blurRadius);
+    twiceRadius.scale(2);
+
+    computeSliceSizesFromRadii(twiceRadius, radii, leftSlice, rightSlice, topSlice, bottomSlice);
     
     return IntSize(templateSideLength + leftSlice + rightSlice,
                    templateSideLength + topSlice + bottomSlice);
@@ -609,8 +620,8 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, con
     graphicsContext->save();
     graphicsContext->clearShadow();
 
-    const float roundedRadius = ceilf(m_blurRadius);
-    const float twiceRadius = roundedRadius * 2;
+    const IntSize roundedRadius = expandedIntSize(m_blurRadius);
+    const IntSize twiceRadius = IntSize(roundedRadius.width() * 2, roundedRadius.height() * 2);
 
     m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
     if (!m_layerImage)
@@ -618,7 +629,7 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, con
 
     // Draw the rectangle with hole.
     FloatRect templateBounds(0, 0, templateSize.width(), templateSize.height());
-    FloatRect templateHole = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
+    FloatRect templateHole = FloatRect(roundedRadius.width(), roundedRadius.height(), templateSize.width() - twiceRadius.width(), templateSize.height() - twiceRadius.height());
 
     if (!ScratchBuffer::shared().matchesLastInsetShadow(m_blurRadius, m_color, m_colorSpace, templateBounds, templateHole, radii)) {
         // Draw shadow into a new ImageBuffer.
@@ -649,7 +660,8 @@ void ShadowBlur::drawInsetShadowWithTiling(GraphicsContext* graphicsContext, con
     FloatRect destHoleRect = holeRect;
     destHoleRect.move(m_offset);
     FloatRect destHoleBounds = destHoleRect;
-    destHoleBounds.inflate(roundedRadius);
+    destHoleBounds.inflateX(roundedRadius.width());
+    destHoleBounds.inflateY(roundedRadius.height());
 
     // Fill the external part of the shadow (which may be visible because of offset).
     Path exteriorPath;
@@ -675,14 +687,14 @@ void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, cons
     graphicsContext->save();
     graphicsContext->clearShadow();
 
-    const float roundedRadius = ceilf(m_blurRadius);
-    const float twiceRadius = roundedRadius * 2;
+    const IntSize roundedRadius = expandedIntSize(m_blurRadius);
+    const IntSize twiceRadius = IntSize(roundedRadius.width() * 2, roundedRadius.height() * 2);
 
     m_layerImage = ScratchBuffer::shared().getScratchBuffer(templateSize);
     if (!m_layerImage)
         return;
 
-    FloatRect templateShadow = FloatRect(roundedRadius, roundedRadius, templateSize.width() - twiceRadius, templateSize.height() - twiceRadius);
+    FloatRect templateShadow = FloatRect(roundedRadius.width(), roundedRadius.height(), templateSize.width() - twiceRadius.width(), templateSize.height() - twiceRadius.height());
 
     if (!ScratchBuffer::shared().matchesLastShadow(m_blurRadius, m_color, m_colorSpace, templateShadow, radii)) {
         // Draw shadow into the ImageBuffer.
@@ -707,7 +719,8 @@ void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, cons
 
     FloatRect shadowBounds = shadowedRect;
     shadowBounds.move(m_offset.width(), m_offset.height());
-    shadowBounds.inflate(roundedRadius);
+    shadowBounds.inflateX(roundedRadius.width());
+    shadowBounds.inflateY(roundedRadius.height());
 
     drawLayerPieces(graphicsContext, shadowBounds, radii, roundedRadius, templateSize, OuterShadow);
 
@@ -717,9 +730,9 @@ void ShadowBlur::drawRectShadowWithTiling(GraphicsContext* graphicsContext, cons
     ScratchBuffer::shared().scheduleScratchBufferPurge();
 }
 
-void ShadowBlur::drawLayerPieces(GraphicsContext* graphicsContext, const FloatRect& shadowBounds, const RoundedIntRect::Radii& radii, float roundedRadius, const IntSize& templateSize, ShadowDirection direction)
+void ShadowBlur::drawLayerPieces(GraphicsContext* graphicsContext, const FloatRect& shadowBounds, const RoundedIntRect::Radii& radii, const IntSize& roundedRadius, const IntSize& templateSize, ShadowDirection direction)
 {
-    const float twiceRadius = roundedRadius * 2;
+    const IntSize twiceRadius = IntSize(roundedRadius.width() * 2, roundedRadius.height() * 2);
 
     int leftSlice;
     int rightSlice;
index 4ba8e23..7c9613b 100644 (file)
@@ -44,7 +44,7 @@ class ImageBuffer;
 class ShadowBlur {
     WTF_MAKE_NONCOPYABLE(ShadowBlur);
 public:
-    ShadowBlur(float radius, const FloatSize& offset, const Color&, ColorSpace);
+    ShadowBlur(const FloatSize& radius, const FloatSize& offset, const Color&, ColorSpace);
 
     void setShadowsIgnoreTransforms(bool ignoreTransforms) { m_shadowsIgnoreTransforms = ignoreTransforms; }
     bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
@@ -72,7 +72,7 @@ private:
     void drawInsetShadowWithoutTiling(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii&, const IntRect& layerRect);
     void drawInsetShadowWithTiling(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii&, const IntSize& shadowTemplateSize);
     
-    void drawLayerPieces(GraphicsContext*, const FloatRect& shadowBounds, const RoundedIntRect::Radii&, float roundedRadius, const IntSize& templateSize, ShadowDirection);
+    void drawLayerPieces(GraphicsContext*, const FloatRect& shadowBounds, const RoundedIntRect::Radii&, const IntSize& roundedRadius, const IntSize& templateSize, ShadowDirection);
     
     void blurShadowBuffer(const IntSize& templateSize);
     void blurAndColorShadowBuffer(const IntSize& templateSize);
@@ -87,7 +87,7 @@ private:
 
     Color m_color;
     ColorSpace m_colorSpace;
-    float m_blurRadius;
+    FloatSize m_blurRadius;
     FloatSize m_offset;
 
     ImageBuffer* m_layerImage; // Buffer to where the temporary shadow will be drawn to.
index c7626b9..b9fef00 100644 (file)
@@ -702,7 +702,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
         CGContextSaveGState(context);
         CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
 
-        ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+        ShadowBlur contextShadow(FloatSize(shadowBlur, shadowBlur), m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
         contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
     }
 
@@ -731,7 +731,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
         CGContextSaveGState(context);
         CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
 
-        ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+        ShadowBlur contextShadow(FloatSize(shadowBlur, shadowBlur), m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
         contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii());
     }
 
@@ -764,7 +764,7 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
         CGContextSaveGState(context);
         CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
 
-        ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+        ShadowBlur contextShadow(FloatSize(shadowBlur, shadowBlur), m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
         contextShadow.drawRectShadow(this, rect, RoundedIntRect::Radii(topLeft, topRight, bottomLeft, bottomRight));
     }
 
@@ -816,7 +816,7 @@ void GraphicsContext::fillRectWithRoundedHole(const IntRect& rect, const Rounded
         CGContextSaveGState(context);
         CGContextSetShadowWithColor(platformContext(), CGSizeZero, 0, 0);
 
-        ShadowBlur contextShadow(shadowBlur, m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
+        ShadowBlur contextShadow(FloatSize(shadowBlur, shadowBlur), m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace);
         contextShadow.drawInsetShadow(this, rect, roundedHoleRect.rect(), roundedHoleRect.radii());
     }