2011-07-05 Igor Oliveira <igor.oliveira@openbossa.org>
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Jul 2011 21:29:42 +0000 (21:29 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 5 Jul 2011 21:29:42 +0000 (21:29 +0000)
        [Qt] Add ShadowBlur support
        https://bugs.webkit.org/show_bug.cgi?id=62997

        Use ShadowBlur instead of ContextShadow to handle canvas and css shadows. ShadowBlur is
        a newer and platform independent shadow implementation.
        Qt QPainter does not have support for shadows so is necessary to create a layer support
        to draw complex shapes and fonts. The beginShadowLayer creates a temporary shadow buffer
        where the canvas can draw onto and endShadowLayer applies the blur filter, colors the
        shadow buffer and draw the final shadow to the graphics context.

        Reviewed by Andreas Kling.

        * WebCore.pro:
        * platform/graphics/GraphicsContext.cpp:
        * platform/graphics/GraphicsContext.h:
        * platform/graphics/ShadowBlur.cpp:
        (WebCore::ShadowBlur::ShadowBlur):
        (WebCore::ShadowBlur::setShadowValues):
        (WebCore::ShadowBlur::updateShadowBlurValues):
        (WebCore::ShadowBlur::clear):
        (WebCore::ShadowBlur::blurAndColorShadowBuffer):
        (WebCore::ShadowBlur::beginShadowLayer):
        (WebCore::ShadowBlur::endShadowLayer):
        * platform/graphics/ShadowBlur.h:
        (WebCore::ShadowBlur::type):
        * platform/graphics/qt/ContextShadowQt.cpp: Removed.
        * platform/graphics/qt/FontQt.cpp:
        (WebCore::drawTextCommon):
        (WebCore::Font::drawGlyphs):
        * platform/graphics/qt/GraphicsContextQt.cpp:
        (WebCore::GraphicsContextPlatformPrivate::mustUseShadowBlur):
        (WebCore::GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate):
        (WebCore::GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate):
        (WebCore::GraphicsContext::savePlatformState):
        (WebCore::GraphicsContext::restorePlatformState):
        (WebCore::GraphicsContext::fillPath):
        (WebCore::GraphicsContext::strokePath):
        (WebCore::GraphicsContext::fillRect):
        (WebCore::GraphicsContext::fillRoundedRect):
        (WebCore::GraphicsContext::shadowBlur):
        (WebCore::GraphicsContext::clipBounds):
        (WebCore::GraphicsContext::setPlatformShadow):
        (WebCore::GraphicsContext::clearPlatformShadow):
        * platform/graphics/qt/ImageQt.cpp:
        (WebCore::BitmapImage::draw):
        * platform/graphics/qt/StillImageQt.cpp:
        (WebCore::StillImage::draw):

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

Source/WebCore/ChangeLog
Source/WebCore/WebCore.pro
Source/WebCore/platform/graphics/GraphicsContext.cpp
Source/WebCore/platform/graphics/GraphicsContext.h
Source/WebCore/platform/graphics/ShadowBlur.cpp
Source/WebCore/platform/graphics/ShadowBlur.h
Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp [deleted file]
Source/WebCore/platform/graphics/qt/FontQt.cpp
Source/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
Source/WebCore/platform/graphics/qt/ImageQt.cpp
Source/WebCore/platform/graphics/qt/StillImageQt.cpp

index 6dd0557..b4e9817 100644 (file)
@@ -1,3 +1,53 @@
+2011-07-05  Igor Oliveira  <igor.oliveira@openbossa.org>
+
+        [Qt] Add ShadowBlur support
+        https://bugs.webkit.org/show_bug.cgi?id=62997
+
+        Use ShadowBlur instead of ContextShadow to handle canvas and css shadows. ShadowBlur is
+        a newer and platform independent shadow implementation.
+        Qt QPainter does not have support for shadows so is necessary to create a layer support
+        to draw complex shapes and fonts. The beginShadowLayer creates a temporary shadow buffer
+        where the canvas can draw onto and endShadowLayer applies the blur filter, colors the
+        shadow buffer and draw the final shadow to the graphics context.
+
+        Reviewed by Andreas Kling.
+
+        * WebCore.pro:
+        * platform/graphics/GraphicsContext.cpp:
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/ShadowBlur.cpp:
+        (WebCore::ShadowBlur::ShadowBlur):
+        (WebCore::ShadowBlur::setShadowValues):
+        (WebCore::ShadowBlur::updateShadowBlurValues):
+        (WebCore::ShadowBlur::clear):
+        (WebCore::ShadowBlur::blurAndColorShadowBuffer):
+        (WebCore::ShadowBlur::beginShadowLayer):
+        (WebCore::ShadowBlur::endShadowLayer):
+        * platform/graphics/ShadowBlur.h:
+        (WebCore::ShadowBlur::type):
+        * platform/graphics/qt/ContextShadowQt.cpp: Removed.
+        * platform/graphics/qt/FontQt.cpp:
+        (WebCore::drawTextCommon):
+        (WebCore::Font::drawGlyphs):
+        * platform/graphics/qt/GraphicsContextQt.cpp:
+        (WebCore::GraphicsContextPlatformPrivate::mustUseShadowBlur):
+        (WebCore::GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate):
+        (WebCore::GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate):
+        (WebCore::GraphicsContext::savePlatformState):
+        (WebCore::GraphicsContext::restorePlatformState):
+        (WebCore::GraphicsContext::fillPath):
+        (WebCore::GraphicsContext::strokePath):
+        (WebCore::GraphicsContext::fillRect):
+        (WebCore::GraphicsContext::fillRoundedRect):
+        (WebCore::GraphicsContext::shadowBlur):
+        (WebCore::GraphicsContext::clipBounds):
+        (WebCore::GraphicsContext::setPlatformShadow):
+        (WebCore::GraphicsContext::clearPlatformShadow):
+        * platform/graphics/qt/ImageQt.cpp:
+        (WebCore::BitmapImage::draw):
+        * platform/graphics/qt/StillImageQt.cpp:
+        (WebCore::StillImage::draw):
+
 2011-07-05  Sam Weinig  <sam@webkit.org>
 
         Null deref accessing CustomEvent.detail
index d78a13c..0e871ed 100644 (file)
@@ -978,7 +978,7 @@ SOURCES += \
     platform/graphics/FontFamily.cpp \
     platform/graphics/BitmapImage.cpp \
     platform/graphics/Color.cpp \
-    platform/graphics/ContextShadow.cpp \
+    platform/graphics/ShadowBlur.cpp \
     platform/graphics/FloatPoint3D.cpp \
     platform/graphics/FloatPoint.cpp \
     platform/graphics/FloatQuad.cpp \
@@ -1939,7 +1939,7 @@ HEADERS += \
     platform/mock/SpeechInputClientMock.h \
     platform/graphics/BitmapImage.h \
     platform/graphics/Color.h \
-    platform/graphics/ContextShadow.h \
+    platform/graphics/ShadowBlur.h \
     platform/graphics/filters/FEBlend.h \
     platform/graphics/filters/FEColorMatrix.h \
     platform/graphics/filters/FEComponentTransfer.h \
@@ -2521,7 +2521,6 @@ SOURCES += \
     page/qt/FrameQt.cpp \
     platform/graphics/qt/TransformationMatrixQt.cpp \
     platform/graphics/qt/ColorQt.cpp \
-    platform/graphics/qt/ContextShadowQt.cpp \
     platform/graphics/qt/FontQt.cpp \
     platform/graphics/qt/FontPlatformDataQt.cpp \
     platform/graphics/qt/FloatPointQt.cpp \
index 3b77b9f..f3f99e4 100644 (file)
@@ -585,7 +585,7 @@ void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& re
     buffer->clip(this, rect);
 }
 
-#if !USE(CG)
+#if !USE(CG) && !PLATFORM(QT)
 IntRect GraphicsContext::clipBounds() const
 {
     ASSERT_NOT_REACHED();
index 360a7c5..063f762 100644 (file)
@@ -54,6 +54,7 @@ typedef class WebCore::SurfaceOpenVG PlatformGraphicsContext;
 #include <QPainter>
 namespace WebCore {
 class ContextShadow;
+class ShadowBlur;
 }
 typedef QPainter PlatformGraphicsContext;
 #elif PLATFORM(WX)
@@ -486,10 +487,14 @@ namespace WebCore {
         void takeOwnershipOfPlatformContext();
 #endif
 
-#if PLATFORM(QT) || USE(CAIRO)
+#if USE(CAIRO)
         ContextShadow* contextShadow();
 #endif
 
+#if PLATFORM(QT)
+        ShadowBlur* shadowBlur();
+#endif
+
 #if USE(CAIRO)
         GraphicsContext(cairo_t*);
 #endif
index 25fc9aa..fa735aa 100644 (file)
@@ -176,11 +176,34 @@ ShadowBlur::ShadowBlur(const FloatSize& radius, const FloatSize& offset, const C
     , m_layerImage(0)
     , m_shadowsIgnoreTransforms(false)
 {
+    updateShadowBlurValues();
+}
+
+ShadowBlur::ShadowBlur()
+    : m_type(NoShadow)
+    , m_blurRadius(0, 0)
+    , m_shadowsIgnoreTransforms(false)
+{
+}
+
+void ShadowBlur::setShadowValues(const FloatSize& radius, const FloatSize& offset, const Color& color, ColorSpace colorSpace, bool ignoreTransforms)
+{
+    m_blurRadius = radius;
+    m_offset = offset;
+    m_color = color;
+    m_colorSpace = colorSpace;
+    m_shadowsIgnoreTransforms = ignoreTransforms;
+
+    updateShadowBlurValues();
+}
+
+void ShadowBlur::updateShadowBlurValues()
+{
     // Limit blur radius to 128 to avoid lots of very expensive blurring.
     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()) {
+    if (!m_color.isValid() || !m_color.alpha()) {
         // Can't paint the shadow with invalid or invisible color.
         m_type = NoShadow;
     } else if (m_blurRadius.width() > 0 || m_blurRadius.height() > 0) {
@@ -237,6 +260,14 @@ static void calculateLobes(int lobes[][2], float blurRadius, bool shadowsIgnoreT
     }
 }
 
+void ShadowBlur::clear()
+{
+    m_type = NoShadow;
+    m_color = Color();
+    m_blurRadius = FloatSize();
+    m_offset = FloatSize();
+}
+
 void ShadowBlur::blurLayerImage(unsigned char* imageData, const IntSize& size, int rowStride)
 {
     const int channels[4] = { 3, 0, 1, 3 };
@@ -828,9 +859,43 @@ void ShadowBlur::blurAndColorShadowBuffer(const IntSize& templateSize)
 
     // Mask the image with the shadow color.
     GraphicsContext* shadowContext = m_layerImage->context();
+    GraphicsContextStateSaver stateSaver(*shadowContext);
     shadowContext->setCompositeOperation(CompositeSourceIn);
     shadowContext->setFillColor(m_color, m_colorSpace);
     shadowContext->fillRect(FloatRect(0, 0, templateSize.width(), templateSize.height()));
 }
 
+GraphicsContext* ShadowBlur::beginShadowLayer(GraphicsContext *context, const FloatRect& layerArea)
+{
+    adjustBlurRadius(context);
+
+    IntRect layerRect = calculateLayerBoundingRect(context, layerArea, context->clipBounds());
+
+    if (layerRect.isEmpty())
+        return 0;
+
+    m_layerImage = ScratchBuffer::shared().getScratchBuffer(layerRect.size());
+
+    GraphicsContext* shadowContext = m_layerImage->context();
+    shadowContext->save();
+    shadowContext->clearRect(FloatRect(0, 0, m_layerSize.width(), m_layerSize.height()));
+
+    shadowContext->translate(m_layerContextTranslation);
+    return shadowContext;
+}
+
+void ShadowBlur::endShadowLayer(GraphicsContext* context)
+{
+    m_layerImage->context()->restore();
+
+    blurAndColorShadowBuffer(expandedIntSize(m_layerSize));
+    GraphicsContextStateSaver stateSave(*context);
+
+    context->clearShadow();
+    context->drawImageBuffer(m_layerImage, ColorSpaceDeviceRGB, roundedIntPoint(m_layerOrigin), IntRect(0, 0, m_layerSize.width(), m_layerSize.height()), context->compositeOperation());
+
+    m_layerImage = 0;
+    ScratchBuffer::shared().scheduleScratchBufferPurge();
+}
+
 } // namespace WebCore
index 202ff3d..99eea53 100644 (file)
@@ -44,17 +44,34 @@ class ImageBuffer;
 class ShadowBlur {
     WTF_MAKE_NONCOPYABLE(ShadowBlur);
 public:
+    enum ShadowType {
+        NoShadow,
+        SolidShadow,
+        BlurShadow
+    };
+
     ShadowBlur(const FloatSize& radius, const FloatSize& offset, const Color&, ColorSpace);
+    ShadowBlur();
+
+    void setShadowValues(const FloatSize&, const FloatSize& , const Color&, ColorSpace, bool ignoreTransforms = false);
 
     void setShadowsIgnoreTransforms(bool ignoreTransforms) { m_shadowsIgnoreTransforms = ignoreTransforms; }
     bool shadowsIgnoreTransforms() const { return m_shadowsIgnoreTransforms; }
 
+    GraphicsContext* beginShadowLayer(GraphicsContext*, const FloatRect& layerArea);
+    void endShadowLayer(GraphicsContext*);
+
     void drawRectShadow(GraphicsContext*, const FloatRect&, const RoundedIntRect::Radii&);
     void drawInsetShadow(GraphicsContext*, const FloatRect&, const FloatRect& holeRect, const RoundedIntRect::Radii& holeRadii);
 
     void blurLayerImage(unsigned char*, const IntSize&, int stride);
 
+    void clear();
+
+    ShadowType type() const { return m_type; }
 private:
+    void updateShadowBlurValues();
+
     void drawShadowBuffer(GraphicsContext*);
 
     void adjustBlurRadius(GraphicsContext*);
@@ -80,11 +97,6 @@ private:
     
     IntSize blurredEdgeSize() const;
     
-    enum ShadowType {
-        NoShadow,
-        SolidShadow,
-        BlurShadow
-    };
     
     ShadowType m_type;
 
diff --git a/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp b/Source/WebCore/platform/graphics/qt/ContextShadowQt.cpp
deleted file mode 100644 (file)
index 9eb31a7..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2010 Sencha, Inc.
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ContextShadow.h"
-
-#include "AffineTransform.h"
-#include "GraphicsContext.h"
-#include <QPainter>
-#include <QTimerEvent>
-
-namespace WebCore {
-
-// ContextShadow needs a scratch image as the buffer for the blur filter.
-// Instead of creating and destroying the buffer for every operation,
-// we create a buffer which will be automatically purged via a timer.
-
-class ShadowBuffer: public QObject {
-public:
-    ShadowBuffer(QObject* parent = 0);
-
-    QImage* scratchImage(const QSize& size);
-
-    void schedulePurge();
-
-protected:
-    void timerEvent(QTimerEvent* event);
-
-private:
-    QImage image;
-    int timerId;
-};
-
-ShadowBuffer::ShadowBuffer(QObject* parent)
-    : QObject(parent)
-    , timerId(-1)
-{
-}
-
-QImage* ShadowBuffer::scratchImage(const QSize& size)
-{
-    int width = size.width();
-    int height = size.height();
-
-    // We do not need to recreate the buffer if the buffer is reasonably
-    // larger than the requested size. However, if the requested size is
-    // much smaller than our buffer, reduce our buffer so that we will not
-    // keep too many allocated pixels for too long.
-    if (!image.isNull() && (image.width() > width) && (image.height() > height))
-        if (((2 * width) > image.width()) && ((2 * height) > image.height())) {
-            image.fill(0);
-            return &image;
-        }
-
-    // Round to the nearest 32 pixels so we do not grow the buffer everytime
-    // there is larger request by 1 pixel.
-    width = (1 + (width >> 5)) << 5;
-    height = (1 + (height >> 5)) << 5;
-
-    image = QImage(width, height, QImage::Format_ARGB32_Premultiplied);
-    image.fill(0);
-    return &image;
-}
-
-void ShadowBuffer::schedulePurge()
-{
-    static const double BufferPurgeDelay = 2; // seconds
-    if (timerId >= 0)
-        killTimer(timerId);
-    timerId = startTimer(BufferPurgeDelay * 1000);
-}
-
-void ShadowBuffer::timerEvent(QTimerEvent* event)
-{
-    if (event->timerId() == timerId) {
-        killTimer(timerId);
-        image = QImage();
-    }
-    QObject::timerEvent(event);
-}
-
-Q_GLOBAL_STATIC(ShadowBuffer, scratchShadowBuffer)
-
-PlatformContext ContextShadow::beginShadowLayer(GraphicsContext* context, const FloatRect& layerArea)
-{
-    // Set m_blurDistance.
-    adjustBlurDistance(context);
-
-    PlatformContext p = context->platformContext();
-
-    QRect clipRect;
-    if (p->hasClipping())
-#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
-        clipRect = p->clipBoundingRect().toAlignedRect();
-#else
-        clipRect = p->clipRegion().boundingRect();
-#endif
-    else
-        clipRect = p->transform().inverted().mapRect(p->window());
-
-    // Set m_layerOrigin, m_layerContextTranslation, m_sourceRect.
-    IntRect clip(clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
-    IntRect layerRect = calculateLayerBoundingRect(context, layerArea, clip);
-
-    // Don't paint if we are totally outside the clip region.
-    if (layerRect.isEmpty())
-        return 0;
-
-    ShadowBuffer* shadowBuffer = scratchShadowBuffer();
-    QImage* shadowImage = shadowBuffer->scratchImage(layerRect.size());
-    m_layerImage = QImage(*shadowImage);
-
-    m_layerContext = new QPainter;
-    m_layerContext->begin(&m_layerImage);
-    m_layerContext->setFont(p->font());
-    m_layerContext->translate(m_layerContextTranslation);
-    return m_layerContext;
-}
-
-void ContextShadow::endShadowLayer(GraphicsContext* context)
-{
-    m_layerContext->end();
-    delete m_layerContext;
-    m_layerContext = 0;
-
-    if (m_type == BlurShadow) {
-        blurLayerImage(m_layerImage.bits(), IntSize(m_layerImage.width(), m_layerImage.height()),
-                       m_layerImage.bytesPerLine());
-    }
-
-    if (m_type != NoShadow) {
-        // "Colorize" with the right shadow color.
-        QPainter p(&m_layerImage);
-        p.setCompositionMode(QPainter::CompositionMode_SourceIn);
-        p.fillRect(m_layerImage.rect(), m_color.rgb());
-        p.end();
-    }
-
-    context->platformContext()->drawImage(m_layerOrigin, m_layerImage, m_sourceRect);
-
-    scratchShadowBuffer()->schedulePurge();
-}
-
-}
index a5a16e0..a212eef 100644 (file)
@@ -23,7 +23,6 @@
 #include "Font.h"
 
 #include "AffineTransform.h"
-#include "ContextShadow.h"
 #include "FontDescription.h"
 #include "FontFallbackList.h"
 #include "FontSelector.h"
@@ -34,6 +33,7 @@
 #include "GraphicsContext.h"
 #include "NotImplemented.h"
 #include "Pattern.h"
+#include "ShadowBlur.h"
 #include "TextRun.h"
 
 #include <QBrush>
@@ -142,40 +142,43 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
             QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
             QRectF clip = boundingRect;
 
-            ContextShadow* ctxShadow = ctx->contextShadow();
-
-            if (ctxShadow->m_type != ContextShadow::NoShadow) {
+            ShadowBlur* ctxShadow = ctx->shadowBlur();
+            if (ctxShadow->type() != ShadowBlur::NoShadow) {
+                const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
                 qreal dx1 = 0, dx2 = 0, dy1 = 0, dy2 = 0;
-                if (ctxShadow->offset().x() > 0)
-                    dx2 = ctxShadow->offset().x();
+                if (shadowOffset.x() > 0)
+                    dx2 = shadowOffset.x();
                 else
-                    dx1 = -ctxShadow->offset().x();
-                if (ctxShadow->offset().y() > 0)
-                    dy2 = ctxShadow->offset().y();
+                    dx1 = -shadowOffset.x();
+                if (shadowOffset.y() > 0)
+                    dy2 = shadowOffset.y();
                 else
-                    dy1 = -ctxShadow->offset().y();
+                    dy1 = -shadowOffset.y();
                 // expand the clip rect to include the text shadow as well
+                const float blurDistance = ctx->state().shadowBlur;
                 clip.adjust(dx1, dx2, dy1, dy2);
-                clip.adjust(-ctxShadow->m_blurDistance, -ctxShadow->m_blurDistance, ctxShadow->m_blurDistance, ctxShadow->m_blurDistance);
+                clip.adjust(-blurDistance, -blurDistance, blurDistance, blurDistance);
             }
             p->save();
             p->setClipRect(clip.toRect(), Qt::IntersectClip);
             pt.setY(pt.y() - ascent);
 
-            if (ctxShadow->m_type != ContextShadow::NoShadow) {
-                ContextShadow* ctxShadow = ctx->contextShadow();
-                if (!ctxShadow->mustUseContextShadow(ctx)) {
+            if (ctxShadow->type() != ShadowBlur::NoShadow) {
+                ShadowBlur* ctxShadow = ctx->shadowBlur();
+                if (ctxShadow->type() != ShadowBlur::BlurShadow
+                    && (!ctxShadow->shadowsIgnoreTransforms() || ctx->getCTM().isIdentity())) {
                     p->save();
-                    p->setPen(ctxShadow->m_color);
-                    p->translate(ctxShadow->offset());
+                    p->setPen(ctx->state().shadowColor);
+                    p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
                     line.draw(p, pt);
                     p->restore();
                 } else {
-                    QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect);
-                    if (shadowPainter) {
+                    GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+                    if (shadowContext) {
+                        QPainter* shadowPainter = shadowContext->platformContext();
                         // Since it will be blurred anyway, we don't care about render hints.
                         shadowPainter->setFont(p->font());
-                        shadowPainter->setPen(ctxShadow->m_color);
+                        shadowPainter->setPen(ctx->state().shadowColor);
                         line.draw(shadowPainter, pt);
                         ctxShadow->endShadowLayer(ctx);
                     }
@@ -201,40 +204,43 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
     if (ctx->textDrawingMode() & TextModeStroke)
         textStrokePath.addText(pt, font, string);
 
-    ContextShadow* ctxShadow = ctx->contextShadow();
-    if (ctxShadow->m_type != ContextShadow::NoShadow) {
+    ShadowBlur* ctxShadow = ctx->shadowBlur();
+    if (ctx->hasShadow() && ctxShadow->type() != ShadowBlur::NoShadow) {
         if (ctx->textDrawingMode() & TextModeFill) {
-            if (ctxShadow->m_type != ContextShadow::BlurShadow) {
+            if (ctxShadow->type() != ShadowBlur::BlurShadow) {
                 p->save();
-                p->setPen(ctxShadow->m_color);
-                p->translate(ctxShadow->offset());
+                p->setPen(ctx->state().shadowColor);
+                p->translate(QPointF(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height()));
                 p->drawText(pt, string, flags, run.expansion());
                 p->restore();
             } else {
                 QFontMetrics fm(font);
                 QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
-                QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect);
-                if (shadowPainter) {
+                GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+                if (shadowContext) {
+                    QPainter* shadowPainter = shadowContext->platformContext();
                     // Since it will be blurred anyway, we don't care about render hints.
                     shadowPainter->setFont(p->font());
-                    shadowPainter->setPen(ctxShadow->m_color);
+                    shadowPainter->setPen(ctx->state().shadowColor);
                     shadowPainter->drawText(pt, string, flags, run.expansion());
                     ctxShadow->endShadowLayer(ctx);
                 }
             }
         } else if (ctx->textDrawingMode() & TextModeStroke) {
-            if (ctxShadow->m_type != ContextShadow::BlurShadow) {
-                p->translate(ctxShadow->offset());
-                p->strokePath(textStrokePath, QPen(ctxShadow->m_color));
-                p->translate(-ctxShadow->offset());
+            if (ctxShadow->type() != ShadowBlur::BlurShadow) {
+                const QPointF shadowOffset(ctx->state().shadowOffset.width(), ctx->state().shadowOffset.height());
+                p->translate(shadowOffset);
+                p->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
+                p->translate(-shadowOffset);
             } else {
                 QFontMetrics fm(font);
                 QRectF boundingRect(pt.x(), point.y() - fm.ascent(), fm.width(string, -1, flags), fm.height());
-                QPainter* shadowPainter = ctxShadow->beginShadowLayer(ctx, boundingRect);
-                if (shadowPainter) {
+                GraphicsContext* shadowContext = ctxShadow->beginShadowLayer(ctx, boundingRect);
+                if (shadowContext) {
+                    QPainter* shadowPainter = shadowContext->platformContext();
                     // Since it will be blurred anyway, we don't care about render hints.
                     shadowPainter->setFont(p->font());
-                    shadowPainter->strokePath(textStrokePath, QPen(ctxShadow->m_color));
+                    shadowPainter->strokePath(textStrokePath, QPen(ctx->state().shadowColor));
                     ctxShadow->endShadowLayer(ctx);
                 }
             }
@@ -328,7 +334,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
     ASSERT(!shouldStroke);
 
     // Shadowed text should always take the complex path.
-    ASSERT(context->contextShadow()->m_type == ContextShadow::NoShadow);
+    ASSERT(context->contextShadow()->type() == ShadowBlur::NoShadow);
 
     if (!shouldFill && !shouldStroke)
         return;
@@ -361,7 +367,7 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
     QPainter* painter = context->platformContext();
 
     ContextShadow* shadow = context->contextShadow();
-    switch (shadow->m_type) {
+    switch (shadow->type()) {
     case ContextShadow::SolidShadow: {
         QPen previousPen = painter->pen();
         painter->setPen(shadow->m_color);
@@ -374,8 +380,9 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
     case ContextShadow::BlurShadow: {
         qreal height = rawFont.ascent() + rawFont.descent() + 1;
         QRectF boundingRect(point.x(), point.y() - rawFont.ascent(), width, height);
-        QPainter* shadowPainter = shadow->beginShadowLayer(context, boundingRect);
-        if (shadowPainter) {
+        GraphicsContext* shadowContext = shadow->beginShadowLayer(context, boundingRect);
+        if (shadowContext) {
+            QPainter* shadowPainter = shadowContext->platformContext();
             shadowPainter->setPen(shadow->m_color);
             shadowPainter->drawGlyphRun(point, qtGlyphs);
             shadow->endShadowLayer(context);
index 7f112d4..521a47e 100644 (file)
 
 #include "AffineTransform.h"
 #include "Color.h"
-#include "ContextShadow.h"
 #include "FloatConversion.h"
 #include "Font.h"
 #include "ImageBuffer.h"
 #include "NotImplemented.h"
 #include "Path.h"
 #include "Pattern.h"
+#include "ShadowBlur.h"
 #include "TransparencyLayer.h"
 
 #include <QBrush>
@@ -196,8 +196,23 @@ public:
     InterpolationQuality imageInterpolationQuality;
     bool initialSmoothPixmapTransformHint;
 
-    ContextShadow shadow;
-    QStack<ContextShadow> shadowStack;
+    ShadowBlur* shadow;
+
+    bool mustUseShadowBlur() const
+    {
+        // We can't avoid ShadowBlur, since the shadow has blur.
+        if (shadow->type() == ShadowBlur::BlurShadow)
+            return true;
+        // We can avoid ShadowBlur and optimize, since we're not drawing on a
+        // canvas and box shadows are affected by the transformation matrix.
+        if (!shadow->shadowsIgnoreTransforms())
+            return false;
+        // We can avoid ShadowBlur, since there are no transformations to apply to the canvas.
+        if (p()->combinedTransform().isIdentity())
+            return false;
+        // Otherwise, no chance avoiding ShadowBlur.
+        return true;
+    }
 
     QRectF clipBoundingRect() const
     {
@@ -221,6 +236,7 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons
     , solidColor(initialSolidColor)
     , imageInterpolationQuality(InterpolationDefault)
     , initialSmoothPixmapTransformHint(false)
+    , shadow(new ShadowBlur())
     , painter(p)
     , platformContextIsOwned(false)
 {
@@ -241,6 +257,7 @@ GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p, cons
     initialSmoothPixmapTransformHint = painter->testRenderHint(QPainter::SmoothPixmapTransform);
 
     painter->setRenderHint(QPainter::Antialiasing, true);
+
 }
 
 GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
@@ -250,6 +267,7 @@ GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
 
     QPaintDevice* device = painter->device();
     painter->end();
+    delete shadow;
     delete painter;
     delete device;
 }
@@ -297,7 +315,6 @@ void GraphicsContext::savePlatformState()
     if (!m_data->layers.isEmpty() && !m_data->layers.top()->alphaMask.isNull())
         ++m_data->layers.top()->saveCounter;
     m_data->p()->save();
-    m_data->shadowStack.push(m_data->shadow);
 }
 
 void GraphicsContext::restorePlatformState()
@@ -308,10 +325,7 @@ void GraphicsContext::restorePlatformState()
 
     m_data->p()->restore();
 
-    if (m_data->shadowStack.isEmpty())
-        m_data->shadow = ContextShadow();
-    else
-        m_data->shadow = m_data->shadowStack.pop();
+    m_data->shadow->setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur), m_state.shadowOffset, m_state.shadowColor, m_state.shadowColorSpace, m_state.shadowsIgnoreTransforms);
 }
 
 // Draws a filled rectangle with a stroked border.
@@ -495,31 +509,29 @@ void GraphicsContext::fillPath(const Path& path)
     platformPath.setFillRule(toQtFillRule(fillRule()));
 
     if (hasShadow()) {
-        ContextShadow* shadow = contextShadow();
-        if (shadow->mustUseContextShadow(this) || m_state.fillPattern || m_state.fillGradient)
+        ShadowBlur* shadow = shadowBlur();
+        if (m_data->mustUseShadowBlur() || m_state.fillPattern || m_state.fillGradient)
         {
-            QPainter* shadowPainter = shadow->beginShadowLayer(this, platformPath.controlPointRect());
-            if (shadowPainter) {
+            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, platformPath.controlPointRect());
+            if (shadowContext) {
+                QPainter* shadowPainter = shadowContext->platformContext();
                 if (m_state.fillPattern) {
                     AffineTransform affine;
-                    shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
                     shadowPainter->fillPath(platformPath, QBrush(m_state.fillPattern->createPlatformPattern(affine)));
                 } else if (m_state.fillGradient) {
                     QBrush brush(*m_state.fillGradient->platformGradient());
                     brush.setTransform(m_state.fillGradient->gradientSpaceTransform());
-                    shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
                     shadowPainter->fillPath(platformPath, brush);
                 } else {
-                    QColor shadowColor = shadow->m_color;
-                    shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
-                    shadowPainter->fillPath(platformPath, shadowColor);
+                    QColor shadowColor = m_state.shadowColor;
+                    shadowPainter->fillPath(platformPath, p->brush().color());
                 }
                 shadow->endShadowLayer(this);
             }
         } else {
-            QPointF offset = shadow->offset();
+            QPointF offset(m_state.shadowOffset.width(), m_state.shadowOffset.height());
             p->translate(offset);
-            QColor shadowColor = shadow->m_color;
+            QColor shadowColor = m_state.shadowColor;
             shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
             p->fillPath(platformPath, shadowColor);
             p->translate(-offset);
@@ -547,30 +559,29 @@ void GraphicsContext::strokePath(const Path& path)
     platformPath.setFillRule(toQtFillRule(fillRule()));
 
     if (hasShadow()) {
-        ContextShadow* shadow = contextShadow();
-        if (shadow->mustUseContextShadow(this) || m_state.strokePattern || m_state.strokeGradient)
+        ShadowBlur* shadow = shadowBlur();
+        if (m_data->mustUseShadowBlur() || m_state.strokePattern || m_state.strokeGradient)
         {
             FloatRect boundingRect = platformPath.controlPointRect();
             boundingRect.inflate(pen.miterLimit() + pen.widthF());
-            QPainter* shadowPainter = shadow->beginShadowLayer(this, boundingRect);
-            if (shadowPainter) {
+            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, boundingRect);
+            if (shadowContext) {
+                QPainter* shadowPainter = shadowContext->platformContext();
                 if (m_state.strokeGradient) {
                     QBrush brush(*m_state.strokeGradient->platformGradient());
                     brush.setTransform(m_state.strokeGradient->gradientSpaceTransform());
                     QPen shadowPen(pen);
                     shadowPen.setBrush(brush);
-                    shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
                     shadowPainter->strokePath(platformPath, shadowPen);
                 } else {
-                    shadowPainter->setOpacity(static_cast<qreal>(m_data->shadow.m_color.alpha()) / 255);
                     shadowPainter->strokePath(platformPath, pen);
                 }
                 shadow->endShadowLayer(this);
             }
         } else {
-            QPointF offset = shadow->offset();
+            QPointF offset(m_state.shadowOffset.width(), m_state.shadowOffset.height());
             p->translate(offset);
-            QColor shadowColor = shadow->m_color;
+            QColor shadowColor = m_state.shadowColor;
             shadowColor.setAlphaF(shadowColor.alphaF() * pen.color().alphaF());
             QPen shadowPen(pen);
             shadowPen.setColor(shadowColor);
@@ -668,44 +679,42 @@ void GraphicsContext::fillRect(const FloatRect& rect)
 
     QPainter* p = m_data->p();
     QRectF normalizedRect = rect.normalized();
-    ContextShadow* shadow = contextShadow();
+    ShadowBlur* shadow = shadowBlur();
 
     if (m_state.fillPattern) {
         QPixmap* image = m_state.fillPattern->tileImage()->nativeImageForCurrentFrame();
-        QPainter* shadowPainter = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0;
-        if (shadowPainter) {
+        GraphicsContext* shadowContext = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0;
+        if (shadowContext) {
+            QPainter* shadowPainter = shadowContext->platformContext();
             drawRepeatPattern(shadowPainter, image, normalizedRect, m_state.fillPattern->repeatX(), m_state.fillPattern->repeatY());
-            shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn);
-            shadowPainter->fillRect(normalizedRect, shadow->m_color);
             shadow->endShadowLayer(this);
         }
         drawRepeatPattern(p, image, normalizedRect, m_state.fillPattern->repeatX(), m_state.fillPattern->repeatY());
     } else if (m_state.fillGradient) {
         QBrush brush(*m_state.fillGradient->platformGradient());
         brush.setTransform(m_state.fillGradient->gradientSpaceTransform());
-        QPainter* shadowPainter = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0;
-        if (shadowPainter) {
+        GraphicsContext* shadowContext = hasShadow() ? shadow->beginShadowLayer(this, normalizedRect) : 0;
+        if (shadowContext) {
+            QPainter* shadowPainter = shadowContext->platformContext();
             shadowPainter->fillRect(normalizedRect, brush);
-            shadowPainter->setCompositionMode(QPainter::CompositionMode_SourceIn);
-            shadowPainter->fillRect(normalizedRect, shadow->m_color);
             shadow->endShadowLayer(this);
         }
         p->fillRect(normalizedRect, brush);
     } else {
         if (hasShadow()) {
-            if (shadow->mustUseContextShadow(this)) {
-                QPainter* shadowPainter = shadow->beginShadowLayer(this, normalizedRect);
-                if (shadowPainter) {
-                    shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
+            if (m_data->mustUseShadowBlur()) {
+                GraphicsContext* shadowContext = shadow->beginShadowLayer(this, normalizedRect);
+                if (shadowContext) {
+                    QPainter* shadowPainter = shadowContext->platformContext();
                     shadowPainter->fillRect(normalizedRect, p->brush());
                     shadow->endShadowLayer(this);
                 }
             } else {
                 // Solid rectangle fill with no blur shadow or transformations applied can be done
                 // faster without using the shadow layer at all.
-                QColor shadowColor = shadow->m_color;
+                QColor shadowColor = m_state.shadowColor;
                 shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
-                p->fillRect(normalizedRect.translated(shadow->offset()), shadowColor);
+                p->fillRect(normalizedRect.translated(QPointF(m_state.shadowOffset.width(), m_state.shadowOffset.height())), shadowColor);
             }
         }
 
@@ -724,16 +733,20 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
     QRectF normalizedRect = rect.normalized();
 
     if (hasShadow()) {
-        ContextShadow* shadow = contextShadow();
-        if (shadow->mustUseContextShadow(this)) {
-            QPainter* shadowPainter = shadow->beginShadowLayer(this, normalizedRect);
-            if (shadowPainter) {
+        ShadowBlur* shadow = shadowBlur();
+        if (m_data->mustUseShadowBlur()) {
+            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, normalizedRect);
+            if (shadowContext) {
+                QPainter* shadowPainter = shadowContext->platformContext();
                 shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
-                shadowPainter->fillRect(normalizedRect, shadow->m_color);
+                shadowPainter->fillRect(normalizedRect, m_state.shadowColor);
                 shadow->endShadowLayer(this);
             }
-        } else
-            p->fillRect(normalizedRect.translated(shadow->offset()), shadow->m_color);
+        } else {
+            QColor shadowColor = m_state.shadowColor;
+            shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
+            p->fillRect(normalizedRect.translated(QPointF(m_state.shadowOffset.width(), m_state.shadowOffset.height())), shadowColor);
+        }
     }
 
     p->fillRect(normalizedRect, m_data->solidColor);
@@ -748,18 +761,20 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
     path.addRoundedRect(rect, topLeft, topRight, bottomLeft, bottomRight);
     QPainter* p = m_data->p();
     if (hasShadow()) {
-        ContextShadow* shadow = contextShadow();
-        if (shadow->mustUseContextShadow(this)) {
-            QPainter* shadowPainter = shadow->beginShadowLayer(this, rect);
-            if (shadowPainter) {
+        ShadowBlur* shadow = shadowBlur();
+        if (m_data->mustUseShadowBlur()) {
+            GraphicsContext* shadowContext = shadow->beginShadowLayer(this, rect);
+            if (shadowContext) {
+                QPainter* shadowPainter = shadowContext->platformContext();
                 shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
-                shadowPainter->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
+                shadowPainter->fillPath(path.platformPath(), QColor(m_state.shadowColor));
                 shadow->endShadowLayer(this);
             }
         } else {
-            p->translate(m_data->shadow.offset());
-            p->fillPath(path.platformPath(), QColor(m_data->shadow.m_color));
-            p->translate(-m_data->shadow.offset());
+            const QPointF shadowOffset(m_state.shadowOffset.width(), m_state.shadowOffset.height());
+            p->translate(shadowOffset);
+            p->fillPath(path.platformPath(), QColor(m_state.shadowColor));
+            p->translate(-shadowOffset);
         }
     }
     p->fillPath(path.platformPath(), QColor(color));
@@ -770,9 +785,9 @@ bool GraphicsContext::inTransparencyLayer() const
     return m_data->layerCount;
 }
 
-ContextShadow* GraphicsContext::contextShadow()
+ShadowBlur* GraphicsContext::shadowBlur()
 {
-    return &m_data->shadow;
+    return m_data->shadow;
 }
 
 void GraphicsContext::clip(const IntRect& rect)
@@ -790,6 +805,18 @@ void GraphicsContext::clip(const FloatRect& rect)
 
     m_data->p()->setClipRect(rect, Qt::IntersectClip);
 }
+IntRect GraphicsContext::clipBounds() const
+{
+    QPainter* p = m_data->p();
+    QRectF clipRect;
+
+    if (p->hasClipping())
+        clipRect = m_data->clipBoundingRect();
+    else
+        clipRect = p->transform().inverted().mapRect(p->window());
+
+    return enclosingIntRect(clipRect);
+}
 
 void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
 {
@@ -926,7 +953,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect, RoundingM
     return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
 }
 
-void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace)
+void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace colorSpace)
 {
     // Qt doesn't support shadows natively, they are drawn manually in the draw*
     // functions
@@ -935,16 +962,14 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const
         // Meaning that this graphics context is associated with a CanvasRenderingContext
         // We flip the height since CG and HTML5 Canvas have opposite Y axis
         m_state.shadowOffset = FloatSize(size.width(), -size.height());
-        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), -size.height()));
-    } else
-        m_data->shadow = ContextShadow(color, blur, FloatSize(size.width(), size.height()));
+    }
 
-    m_data->shadow.setShadowsIgnoreTransforms(m_state.shadowsIgnoreTransforms);
+    m_data->shadow->setShadowValues(FloatSize(m_state.shadowBlur, m_state.shadowBlur), m_state.shadowOffset, color, colorSpace, m_state.shadowsIgnoreTransforms);
 }
 
 void GraphicsContext::clearPlatformShadow()
 {
-    m_data->shadow.clear();
+    m_data->shadow->clear();
 }
 
 void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask)
index 0c8ce9e..41ff8a6 100644 (file)
 
 #include "AffineTransform.h"
 #include "BitmapImage.h"
-#include "ContextShadow.h"
 #include "FloatRect.h"
 #include "GraphicsContext.h"
 #include "ImageObserver.h"
 #include "PlatformString.h"
+#include "ShadowBlur.h"
 #include "StillImageQt.h"
 #include "qwebsettings.h"
 
@@ -224,11 +224,11 @@ void BitmapImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
     CompositeOperator previousOperator = ctxt->compositeOperation();
     ctxt->setCompositeOperation(!image->hasAlpha() && op == CompositeSourceOver ? CompositeCopy : op);
 
-    ContextShadow* shadow = ctxt->contextShadow();
-    if (shadow->m_type != ContextShadow::NoShadow) {
-        QPainter* shadowPainter = shadow->beginShadowLayer(ctxt, normalizedDst);
-        if (shadowPainter) {
-            shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
+    if (ctxt->hasShadow()) {
+        ShadowBlur* shadow = ctxt->shadowBlur();
+        GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst);
+        if (shadowContext) {
+            QPainter* shadowPainter = shadowContext->platformContext();
             shadowPainter->drawPixmap(normalizedDst, *image, normalizedSrc);
             shadow->endShadowLayer(ctxt);
         }
index 3b08995..cb2a442 100644 (file)
@@ -28,9 +28,9 @@
 #include "config.h"
 #include "StillImageQt.h"
 
-#include "ContextShadow.h"
 #include "GraphicsContext.h"
 #include "IntSize.h"
+#include "ShadowBlur.h"
 
 #include <QPainter>
 
@@ -74,11 +74,11 @@ void StillImage::draw(GraphicsContext* ctxt, const FloatRect& dst,
     CompositeOperator previousOperator = ctxt->compositeOperation();
     ctxt->setCompositeOperation(op);
 
-    ContextShadow* shadow = ctxt->contextShadow();
-    if (shadow->m_type != ContextShadow::NoShadow) {
-        QPainter* shadowPainter = shadow->beginShadowLayer(ctxt, normalizedDst);
-        if (shadowPainter) {
-            shadowPainter->setOpacity(static_cast<qreal>(shadow->m_color.alpha()) / 255);
+    if (ctxt->hasShadow()) {
+        ShadowBlur* shadow = ctxt->shadowBlur();
+        GraphicsContext* shadowContext = shadow->beginShadowLayer(ctxt, normalizedDst);
+        if (shadowContext) {
+            QPainter* shadowPainter = shadowContext->platformContext();
             shadowPainter->drawPixmap(normalizedDst, *m_pixmap, normalizedSrc);
             shadow->endShadowLayer(ctxt);
         }