[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