[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

ariya at webkit.org ariya at webkit.org
Wed Dec 22 12:09:43 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit fa215186de9577385e18698a7f78931f206f39cc
Author: ariya at webkit.org <ariya at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Aug 16 14:32:25 2010 +0000

    [Qt] Shadow blur for rectangle fill
    https://bugs.webkit.org/show_bug.cgi?id=44025
    
    Patch by Ariya Hidayat <ariya at sencha.com> on 2010-08-16
    Reviewed by Kenneth Rohde Christiansen.
    
    WebCore:
    
    The blur implementation follows the approximation of Gaussian blur
    with three successive box blurs, working on the alpha channel only.
    (see http://www.w3.org/TR/SVG/filters.html#feGaussianBlur).
    
    * WebCore.pro: Refer to ContexShadow.* files.
    * platform/graphics/qt/ContextShadow.cpp: Added.
    (WebCore::ContextShadow::ContextShadow):
    (WebCore::ContextShadow::clear):
    (WebCore::blurHorizontal): Box blurs in horizontal direction, working
    on QImage (in-place).
    (WebCore::shadowBlur): Main blur function which just calls the
    above blurHorizontal function twice, once with transposed image
    (equivalent as it would have done vertical box blurs).
    (WebCore::ContextShadow::drawShadowRect):
    * platform/graphics/qt/ContextShadow.h: Added.
    (WebCore::ContextShadow::):
    * platform/graphics/qt/GraphicsContextQt.cpp:
    (WebCore::GraphicsContextPlatformPrivate::hasShadow):
    (WebCore::GraphicsContext::restorePlatformState):
    (WebCore::GraphicsContext::fillRect): Use ContextShadow for the shadow.
    (WebCore::GraphicsContext::setPlatformShadow):
    
    LayoutTests:
    
    Update pixel test reference after the blur support.
    
    * platform/qt/fast/box-shadow/basic-shadows-expected.checksum:
    * platform/qt/fast/box-shadow/basic-shadows-expected.png:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65425 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 72f3add..3d473b2 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,15 @@
+2010-08-16  Ariya Hidayat  <ariya at sencha.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Shadow blur for rectangle fill
+        https://bugs.webkit.org/show_bug.cgi?id=44025
+
+        Update pixel test reference after the blur support.
+
+        * platform/qt/fast/box-shadow/basic-shadows-expected.checksum:
+        * platform/qt/fast/box-shadow/basic-shadows-expected.png:
+
 2010-08-13  Steve Block  <steveblock at google.com>
 
         Reviewed by Alexey Proskuryakov.
diff --git a/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.checksum b/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.checksum
index 181ee20..08ccf98 100644
--- a/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.checksum
+++ b/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.checksum
@@ -1 +1 @@
-b4d3c35c842ed05b52fc30be51863f1f
\ No newline at end of file
+5aa5b68d30be16c04417274964e31549
\ No newline at end of file
diff --git a/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.png b/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.png
index e20642a..bc1f431 100644
Binary files a/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.png and b/LayoutTests/platform/qt/fast/box-shadow/basic-shadows-expected.png differ
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 99b4d91..787dbc2 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,32 @@
+2010-08-16  Ariya Hidayat  <ariya at sencha.com>
+
+        Reviewed by Kenneth Rohde Christiansen.
+
+        [Qt] Shadow blur for rectangle fill
+        https://bugs.webkit.org/show_bug.cgi?id=44025
+
+        The blur implementation follows the approximation of Gaussian blur
+        with three successive box blurs, working on the alpha channel only.
+        (see http://www.w3.org/TR/SVG/filters.html#feGaussianBlur).
+
+        * WebCore.pro: Refer to ContexShadow.* files.
+        * platform/graphics/qt/ContextShadow.cpp: Added.
+        (WebCore::ContextShadow::ContextShadow):
+        (WebCore::ContextShadow::clear):
+        (WebCore::blurHorizontal): Box blurs in horizontal direction, working
+        on QImage (in-place).
+        (WebCore::shadowBlur): Main blur function which just calls the
+        above blurHorizontal function twice, once with transposed image
+        (equivalent as it would have done vertical box blurs).
+        (WebCore::ContextShadow::drawShadowRect):
+        * platform/graphics/qt/ContextShadow.h: Added.
+        (WebCore::ContextShadow::):
+        * platform/graphics/qt/GraphicsContextQt.cpp:
+        (WebCore::GraphicsContextPlatformPrivate::hasShadow):
+        (WebCore::GraphicsContext::restorePlatformState):
+        (WebCore::GraphicsContext::fillRect): Use ContextShadow for the shadow.
+        (WebCore::GraphicsContext::setPlatformShadow):
+
 2010-08-16  Andras Becsi  <abecsi at webkit.org>
 
         Rubber-stamped by Gustavo Noronha Silva.
diff --git a/WebCore/WebCore.pro b/WebCore/WebCore.pro
index 444ff36..212096d 100644
--- a/WebCore/WebCore.pro
+++ b/WebCore/WebCore.pro
@@ -1690,6 +1690,7 @@ HEADERS += \
     platform/graphics/PathTraversalState.h \
     platform/graphics/Pattern.h \
     platform/graphics/Pen.h \
+    platform/graphics/qt/ContextShadow.h \
     platform/graphics/qt/FontCustomPlatformData.h \
     platform/graphics/qt/ImageDecoderQt.h \
     platform/graphics/qt/StillImageQt.h \
@@ -2186,6 +2187,7 @@ SOURCES += \
     page/qt/FrameQt.cpp \
     platform/graphics/qt/TransformationMatrixQt.cpp \
     platform/graphics/qt/ColorQt.cpp \
+    platform/graphics/qt/ContextShadow.cpp \
     platform/graphics/qt/FontQt.cpp \
     platform/graphics/qt/FontPlatformDataQt.cpp \
     platform/graphics/qt/FloatPointQt.cpp \
diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/qt/ContextShadow.cpp
new file mode 100644
index 0000000..6eff278
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ContextShadow.cpp
@@ -0,0 +1,235 @@
+/*
+ * 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"
+
+namespace WebCore {
+
+ContextShadow::ContextShadow()
+    : type(NoShadow)
+    , blurRadius(0)
+{
+}
+
+ContextShadow::ContextShadow(const QColor& c, float r, qreal dx, qreal dy)
+    : color(c)
+    , blurRadius(qRound(r))
+    , offset(dx, dy)
+{
+    // The type of shadow is decided by the blur radius, shadow offset, and shadow color.
+    if (!color.isValid() || !color.alpha()) {
+        // Can't paint the shadow with invalid or invisible color.
+        type = NoShadow;
+    } else if (r > 0) {
+        // Shadow is always blurred, even the offset is zero.
+        type = BlurShadow;
+    } else if (offset.isNull()) {
+        // Without blur and zero offset means the shadow is fully hidden.
+        type = NoShadow;
+    } else {
+        if (color.alpha() > 0)
+            type = AlphaSolidShadow;
+        else
+            type = OpaqueSolidShadow;
+    }
+}
+
+void ContextShadow::clear()
+{
+    type = NoShadow;
+    color = QColor();
+    blurRadius = 0;
+    offset = QPointF(0, 0);
+}
+
+// Instead of integer division, we use 18.14 for fixed-point division.
+static const int BlurSumShift = 14;
+
+// Note: image must be RGB32 format
+static void blurHorizontal(QImage& image, int radius, bool swap = false)
+{
+    Q_ASSERT(image.format() == QImage::Format_ARGB32_Premultiplied);
+
+    // See comments in http://webkit.org/b/40793, it seems sensible
+    // to follow Skia's limit of 128 pixels of blur radius
+    radius = qMin(128, radius);
+
+    int imgWidth = image.width();
+    int imgHeight = image.height();
+
+    // Check http://www.w3.org/TR/SVG/filters.html#feGaussianBlur
+    // for the approaches when the box-blur radius is even vs odd.
+    int dmax = radius >> 1;
+    int dmin = qMax(0, dmax - 1 + (radius & 1));
+
+    for (int y = 0; y < imgHeight; ++y) {
+
+        unsigned char* pixels = image.scanLine(y);
+
+        int left;
+        int right;
+        int pixelCount;
+        int prev;
+        int next;
+        int firstAlpha;
+        int lastAlpha;
+        int totalAlpha;
+        unsigned char* target;
+        unsigned char* prevPtr;
+        unsigned char* nextPtr;
+
+        int invCount;
+
+        static const int alphaChannel = 3;
+        static const int blueChannel = 0;
+        static const int greenChannel = 1;
+
+        // For each step, we use sliding window algorithm. This is much more
+        // efficient than computing the sum of each pixels covered by the box
+        // kernel size for each x.
+
+        // As noted in the SVG filter specification, running box blur 3x
+        // approximates a real gaussian blur nicely.
+
+        // Step 1: blur alpha channel and store the result in the blue channel.
+        left = swap ? dmax : dmin;
+        right = swap ? dmin : dmax;
+        pixelCount = left + 1 + right;
+        invCount = (1 << BlurSumShift) / pixelCount;
+        prev = -left;
+        next = 1 + right;
+        firstAlpha = pixels[alphaChannel];
+        lastAlpha = pixels[(imgWidth - 1) * 4 + alphaChannel];
+        totalAlpha = 0;
+        for (int i = 0; i < pixelCount; ++i)
+            totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + alphaChannel];
+        target = pixels + blueChannel;
+        prevPtr = pixels + prev * 4 + alphaChannel;
+        nextPtr = pixels + next * 4 + alphaChannel;
+        for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) {
+            *target = (totalAlpha * invCount) >> BlurSumShift;
+            int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) -
+                        ((prev > 0) ? *prevPtr : firstAlpha);
+            totalAlpha += delta;
+        }
+
+        // Step 2: blur blue channel and store the result in the green channel.
+        left = swap ? dmin : dmax;
+        right = swap ? dmax : dmin;
+        pixelCount = left + 1 + right;
+        invCount = (1 << BlurSumShift) / pixelCount;
+        prev = -left;
+        next = 1 + right;
+        firstAlpha = pixels[blueChannel];
+        lastAlpha = pixels[(imgWidth - 1) * 4 + blueChannel];
+        totalAlpha = 0;
+        for (int i = 0; i < pixelCount; ++i)
+            totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + blueChannel];
+        target = pixels + greenChannel;
+        prevPtr = pixels + prev * 4 + blueChannel;
+        nextPtr = pixels + next * 4 + blueChannel;
+        for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) {
+            *target = (totalAlpha * invCount) >> BlurSumShift;
+            int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) -
+                        ((prev > 0) ? *prevPtr : firstAlpha);
+            totalAlpha += delta;
+        }
+
+        // Step 3: blur green channel and store the result in the alpha channel.
+        left = dmax;
+        right = dmax;
+        pixelCount = left + 1 + right;
+        invCount = (1 << BlurSumShift) / pixelCount;
+        prev = -left;
+        next = 1 + right;
+        firstAlpha = pixels[greenChannel];
+        lastAlpha = pixels[(imgWidth - 1) * 4 + greenChannel];
+        totalAlpha = 0;
+        for (int i = 0; i < pixelCount; ++i)
+            totalAlpha += pixels[qBound(0, i - left, imgWidth - 1) * 4 + greenChannel];
+        target = pixels + alphaChannel;
+        prevPtr = pixels + prev * 4 + greenChannel;
+        nextPtr = pixels + next * 4 + greenChannel;
+        for (int x = 0; x < imgWidth; ++x, ++prev, ++next, target += 4, prevPtr += 4, nextPtr += 4) {
+            *target = (totalAlpha * invCount) >> BlurSumShift;
+            int delta = ((next < imgWidth) ? *nextPtr : lastAlpha) -
+                        ((prev > 0) ? *prevPtr : firstAlpha);
+            totalAlpha += delta;
+        }
+    }
+}
+
+static void shadowBlur(QImage& image, int radius, const QColor& shadowColor)
+{
+    blurHorizontal(image, radius);
+
+    QTransform transform;
+    transform.rotate(90);
+    image = image.transformed(transform);
+    blurHorizontal(image, radius, true);
+    transform.reset();
+    transform.rotate(270);
+    image = image.transformed(transform);
+
+    // "Colorize" with the right shadow color.
+    QPainter p(&image);
+    p.setCompositionMode(QPainter::CompositionMode_SourceIn);
+    p.fillRect(image.rect(), shadowColor.rgb());
+    p.end();
+}
+
+void ContextShadow::drawShadowRect(QPainter* p, const QRectF& rect)
+{
+    if (type == NoShadow)
+        return;
+
+    if (type == BlurShadow) {
+        // We expand the area by the blur radius * 2 to give extra space
+        // for the blur transition.
+        int extra = blurRadius * 2;
+        QRect imageRect = rect.toAlignedRect().adjusted(-extra, -extra, extra, extra);
+
+        QImage shadowImage(imageRect.size(), QImage::Format_ARGB32_Premultiplied);
+        shadowImage.fill(Qt::transparent);
+        QPainter shadowPainter(&shadowImage);
+        shadowPainter.fillRect(rect.x() - imageRect.x(), rect.y() - imageRect.y(),
+                               rect.width(), rect.height(), color);
+        shadowPainter.end();
+
+        shadowBlur(shadowImage, blurRadius, color);
+
+        p->drawImage(imageRect.topLeft() + offset, shadowImage);
+
+        return;
+    }
+
+    p->fillRect(rect.translated(offset), color);
+}
+
+
+}
diff --git a/WebCore/platform/graphics/qt/ContextShadow.h b/WebCore/platform/graphics/qt/ContextShadow.h
new file mode 100644
index 0000000..e114ebc
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ContextShadow.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#ifndef ContextShadow_h
+#define ContextShadow_h
+
+#include <QPainter>
+
+namespace WebCore {
+
+// This is to track and keep the shadow state. We use this rather than
+// using GraphicsContextState to allow possible optimizations (right now
+// only to determine the shadow type, but in future it might covers things
+// like cached scratch image, persistent shader, etc).
+
+// This class should be copyable since GraphicsContextQt keeps a stack of
+// the shadow state for savePlatformState and restorePlatformState.
+
+class ContextShadow {
+public:
+    enum {
+        NoShadow,
+        OpaqueSolidShadow,
+        AlphaSolidShadow,
+        BlurShadow
+    } type;
+
+    QColor color;
+    int blurRadius;
+    QPointF offset;
+
+    ContextShadow();
+    ContextShadow(const QColor& c, float r, qreal dx, qreal dy);
+
+    void clear();
+
+    // Draws the shadow for colored rectangle (can't be filled with pattern
+    // or gradient) according to the shadow parameters.
+    // Note: 'rect' specifies the rectangle which casts the shadow,
+    // NOT the bounding box of the shadow.
+    void drawShadowRect(QPainter* p, const QRectF& rect);
+
+};
+
+} // namespace WebCore
+
+#endif // ContextShadow_h
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index d30ea66..059fc96 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -8,6 +8,7 @@
  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
  * Copyright (C) 2008 Dirk Schulze <vbs85 at gmx.de>
+ * Copyright (C) 2010 Sencha, Inc.
  *
  * All rights reserved.
  *
@@ -42,6 +43,7 @@
 
 #include "AffineTransform.h"
 #include "Color.h"
+#include "ContextShadow.h"
 #include "FloatConversion.h"
 #include "Font.h"
 #include "GraphicsContextPrivate.h"
@@ -256,12 +258,12 @@ public:
     // Only used by SVG for now.
     QPainterPath currentPath;
 
-    ContextShadowParameter shadow;
-    QStack<ContextShadowParameter> shadowStack;
+    ContextShadow shadow;
+    QStack<ContextShadow> shadowStack;
 
     bool hasShadow() const
     {
-        return shadow.type != ContextShadowParameter::NoShadow;
+        return shadow.type != ContextShadow::NoShadow;
     }
 
 private:
@@ -348,7 +350,7 @@ void GraphicsContext::restorePlatformState()
     }
 
     if (m_data->shadowStack.isEmpty())
-        m_data->shadow = ContextShadowParameter();
+        m_data->shadow = ContextShadow();
     else
         m_data->shadow = m_data->shadowStack.pop();
 }
@@ -753,7 +755,7 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
     QPainter* p = m_data->p();
 
     if (m_data->hasShadow())
-        p->fillRect(QRectF(rect).translated(m_data->shadow.offset), m_data->shadow.color);
+        m_data->shadow.drawShadowRect(p, rect);
 
     p->fillRect(rect, m_data->solidColor);
 }
@@ -920,9 +922,9 @@ 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_common->state.shadowSize = FloatSize(size.width(), -size.height());
-        m_data->shadow = ContextShadowParameter(color, blur, size.width(), -size.height());
+        m_data->shadow = ContextShadow(color, blur, size.width(), -size.height());
     } else {
-        m_data->shadow = ContextShadowParameter(color, blur, size.width(), size.height());
+        m_data->shadow = ContextShadow(color, blur, size.width(), size.height());
     }
 }
 

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list