summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/qt
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/qt')
-rw-r--r--WebCore/platform/graphics/qt/ContextShadow.cpp256
-rw-r--r--WebCore/platform/graphics/qt/ContextShadow.h71
-rw-r--r--WebCore/platform/graphics/qt/FontCacheQt.cpp2
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp9
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp208
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferData.h4
-rw-r--r--WebCore/platform/graphics/qt/ImageBufferQt.cpp53
-rw-r--r--WebCore/platform/graphics/qt/ImageDecoderQt.cpp25
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp4
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp66
-rw-r--r--WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h10
-rw-r--r--WebCore/platform/graphics/qt/PathQt.cpp27
-rw-r--r--WebCore/platform/graphics/qt/TransparencyLayer.h89
13 files changed, 628 insertions, 196 deletions
diff --git a/WebCore/platform/graphics/qt/ContextShadow.cpp b/WebCore/platform/graphics/qt/ContextShadow.cpp
new file mode 100644
index 0000000..0511218
--- /dev/null
+++ b/WebCore/platform/graphics/qt/ContextShadow.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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) {
+ QRectF shadowRect = rect.translated(offset);
+
+ // We expand the area by the blur radius * 2 to give extra space
+ // for the blur transition.
+ int extra = blurRadius * 2;
+ QRectF bufferRect = shadowRect.adjusted(-extra, -extra, extra, extra);
+ QRect alignedBufferRect = bufferRect.toAlignedRect();
+
+ QRect clipRect;
+ if (p->hasClipping())
+ clipRect = p->clipRegion().boundingRect();
+ else
+ clipRect = p->transform().inverted().mapRect(p->window());
+
+ if (!clipRect.contains(alignedBufferRect)) {
+
+ // No need to have the buffer larger that the clip.
+ alignedBufferRect = alignedBufferRect.intersected(clipRect);
+ if (alignedBufferRect.isEmpty())
+ return;
+
+ // We adjust again because the pixels at the borders are still
+ // potentially affected by the pixels outside the buffer.
+ alignedBufferRect.adjust(-extra, -extra, extra, extra);
+ }
+
+ QImage shadowImage(alignedBufferRect.size(), QImage::Format_ARGB32_Premultiplied);
+ shadowImage.fill(Qt::transparent);
+ QPainter shadowPainter(&shadowImage);
+
+ shadowPainter.fillRect(shadowRect.translated(-alignedBufferRect.topLeft()), color);
+ shadowPainter.end();
+
+ shadowBlur(shadowImage, blurRadius, color);
+
+ p->drawImage(alignedBufferRect.topLeft(), 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/FontCacheQt.cpp b/WebCore/platform/graphics/qt/FontCacheQt.cpp
index bfcc5c3..c59c523 100644
--- a/WebCore/platform/graphics/qt/FontCacheQt.cpp
+++ b/WebCore/platform/graphics/qt/FontCacheQt.cpp
@@ -29,10 +29,10 @@
#include "FontPlatformData.h"
#include "Font.h"
#include "PlatformString.h"
-#include "StringHash.h"
#include <utility>
#include <wtf/ListHashSet.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringHash.h>
#include <QFont>
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 273e2dd..d5e7b3f 100644
--- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -512,15 +512,6 @@ void GraphicsContext3D::makeContextCurrent()
m_internal->m_glWidget->makeCurrent();
}
-void GraphicsContext3D::beginPaint(CanvasRenderingContext* context)
-{
- paintRenderingResultsToCanvas();
-}
-
-void GraphicsContext3D::endPaint()
-{
-}
-
void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
{
m_internal->m_glWidget->makeCurrent();
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index d4a145f..1632804 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@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"
@@ -50,6 +52,7 @@
#include "Path.h"
#include "Pattern.h"
#include "Pen.h"
+#include "TransparencyLayer.h"
#include <QBrush>
#include <QDebug>
@@ -166,48 +169,6 @@ static inline Qt::FillRule toQtFillRule(WindRule rule)
return Qt::OddEvenFill;
}
-struct TransparencyLayer : FastAllocBase {
- TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask)
- : pixmap(rect.width(), rect.height())
- , opacity(opacity)
- , alphaMask(alphaMask)
- , saveCounter(1) // see the comment for saveCounter
- {
- offset = rect.topLeft();
- pixmap.fill(Qt::transparent);
- painter.begin(&pixmap);
- painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing));
- painter.translate(-offset);
- painter.setPen(p->pen());
- painter.setBrush(p->brush());
- painter.setTransform(p->transform(), true);
- painter.setOpacity(p->opacity());
- painter.setFont(p->font());
- if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff))
- painter.setCompositionMode(p->compositionMode());
- // if the path is an empty region, this assignment disables all painting
- if (!p->clipPath().isEmpty())
- painter.setClipPath(p->clipPath());
- }
-
- TransparencyLayer()
- {
- }
-
- QPixmap pixmap;
- QPoint offset;
- QPainter painter;
- qreal opacity;
- // for clipToImageBuffer
- QPixmap alphaMask;
- // saveCounter is only used in combination with alphaMask
- // otherwise, its value is unspecified
- int saveCounter;
-private:
- TransparencyLayer(const TransparencyLayer &) {}
- TransparencyLayer & operator=(const TransparencyLayer &) { return *this; }
-};
-
class GraphicsContextPlatformPrivate : public Noncopyable {
public:
GraphicsContextPlatformPrivate(QPainter* painter);
@@ -240,6 +201,14 @@ public:
// Only used by SVG for now.
QPainterPath currentPath;
+ ContextShadow shadow;
+ QStack<ContextShadow> shadowStack;
+
+ bool hasShadow() const
+ {
+ return shadow.type != ContextShadow::NoShadow;
+ }
+
private:
QPainter* painter;
};
@@ -307,6 +276,7 @@ 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()
@@ -321,9 +291,16 @@ void GraphicsContext::restorePlatformState()
QTransform matrix = m_common->state.pathTransform;
m_data->currentPath = m_data->currentPath * matrix;
}
+
+ if (m_data->shadowStack.isEmpty())
+ m_data->shadow = ContextShadow();
+ else
+ m_data->shadow = m_data->shadowStack.pop();
}
// Draws a filled rectangle with a stroked border.
+// This is only used to draw borders (real fill is done via fillRect), and
+// thus it must not cast any shadow.
void GraphicsContext::drawRect(const IntRect& rect)
{
if (paintingDisabled())
@@ -333,24 +310,13 @@ void GraphicsContext::drawRect(const IntRect& rect)
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
- if (m_common->state.shadowColor.isValid()) {
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (getShadow(shadowSize, shadowBlur, shadowColor)) {
- IntRect shadowRect = rect;
- shadowRect.move(shadowSize.width(), shadowSize.height());
- shadowRect.inflate(static_cast<int>(p->pen().widthF()));
- p->fillRect(shadowRect, QColor(shadowColor));
- }
- }
-
p->drawRect(rect);
p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
// This is only used to draw borders.
+// Must not cast any shadow.
void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
{
if (paintingDisabled())
@@ -372,17 +338,6 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
adjustLineToPixelBoundaries(p1, p2, width, style);
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) {
- p->save();
- p->translate(shadowSize.width(), shadowSize.height());
- p->setPen(shadowColor);
- p->drawLine(p1, p2);
- p->restore();
- }
-
int patWidth = 0;
switch (style) {
case NoStroke:
@@ -474,16 +429,14 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
p->setRenderHint(QPainter::Antialiasing, true);
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
startAngle *= 16;
angleSpan *= 16;
- if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+
+ if (m_data->hasShadow()) {
p->save();
- p->translate(shadowSize.width(), shadowSize.height());
+ p->translate(m_data->shadow.offset);
QPen pen(p->pen());
- pen.setColor(shadowColor);
+ pen.setColor(m_data->shadow.color);
p->setPen(pen);
p->drawArc(rect, startAngle, angleSpan);
p->restore();
@@ -509,17 +462,14 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
QPainter* p = m_data->p();
p->save();
p->setRenderHint(QPainter::Antialiasing, shouldAntialias);
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (getShadow(shadowSize, shadowBlur, shadowColor)) {
+ if (m_data->hasShadow()) {
p->save();
- p->translate(shadowSize.width(), shadowSize.height());
+ p->translate(m_data->shadow.offset);
if (p->brush().style() != Qt::NoBrush)
- p->setBrush(QBrush(shadowColor));
+ p->setBrush(QBrush(m_data->shadow.color));
QPen pen(p->pen());
if (pen.style() != Qt::NoPen) {
- pen.setColor(shadowColor);
+ pen.setColor(m_data->shadow.color);
p->setPen(pen);
}
p->drawConvexPolygon(polygon);
@@ -553,18 +503,6 @@ QPen GraphicsContext::pen()
return p->pen();
}
-static void inline drawFilledShadowPath(GraphicsContext* context, QPainter* p, const QPainterPath& path)
-{
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
- p->translate(shadowSize.width(), shadowSize.height());
- p->fillPath(path, QBrush(shadowColor));
- p->translate(-shadowSize.width(), -shadowSize.height());
- }
-}
-
void GraphicsContext::fillPath()
{
if (paintingDisabled())
@@ -574,7 +512,11 @@ void GraphicsContext::fillPath()
QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
path.setFillRule(toQtFillRule(fillRule()));
- drawFilledShadowPath(this, p, path);
+ if (m_data->hasShadow()) {
+ p->translate(m_data->shadow.offset);
+ p->fillPath(path, m_data->shadow.color);
+ p->translate(-m_data->shadow.offset);
+ }
if (m_common->state.fillPattern) {
AffineTransform affine;
p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
@@ -598,16 +540,12 @@ void GraphicsContext::strokePath()
QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
path.setFillRule(toQtFillRule(fillRule()));
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (getShadow(shadowSize, shadowBlur, shadowColor)) {
- QTransform t(p->worldTransform());
- p->translate(shadowSize.width(), shadowSize.height());
+ if (m_data->hasShadow()) {
+ p->translate(m_data->shadow.offset);
QPen shadowPen(pen);
- shadowPen.setColor(shadowColor);
+ shadowPen.setColor(m_data->shadow.color);
p->strokePath(path, shadowPen);
- p->setWorldTransform(t);
+ p->translate(-m_data->shadow.offset);
}
if (m_common->state.strokePattern) {
AffineTransform affine;
@@ -625,18 +563,6 @@ void GraphicsContext::strokePath()
m_data->currentPath = QPainterPath();
}
-static inline void drawBorderlessRectShadow(GraphicsContext* context, QPainter* p, const FloatRect& rect)
-{
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- if (context->getShadow(shadowSize, shadowBlur, shadowColor)) {
- FloatRect shadowRect(rect);
- shadowRect.move(shadowSize.width(), shadowSize.height());
- p->fillRect(shadowRect, QColor(shadowColor));
- }
-}
-
static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY)
{
// Patterns must be painted so that the top left of the first image is anchored at
@@ -712,22 +638,18 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QPainter* p = m_data->p();
FloatRect normalizedRect = rect.normalized();
- FloatSize shadowSize;
- float shadowBlur;
- Color shadowColor;
- bool hasShadow = getShadow(shadowSize, shadowBlur, shadowColor);
- FloatRect shadowDestRect;
+ QRectF shadowDestRect;
QImage* shadowImage = 0;
QPainter* pShadow = 0;
- if (hasShadow) {
+ if (m_data->hasShadow()) {
shadowImage = new QImage(roundedIntSize(normalizedRect.size()), QImage::Format_ARGB32_Premultiplied);
pShadow = new QPainter(shadowImage);
shadowDestRect = normalizedRect;
- shadowDestRect.move(shadowSize.width(), shadowSize.height());
+ shadowDestRect.translate(m_data->shadow.offset);
pShadow->setCompositionMode(QPainter::CompositionMode_Source);
- pShadow->fillRect(shadowImage->rect(), shadowColor);
+ pShadow->fillRect(shadowImage->rect(), m_data->shadow.color);
pShadow->setCompositionMode(QPainter::CompositionMode_DestinationIn);
}
@@ -737,7 +659,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QBrush brush(m_common->state.fillPattern->createPlatformPattern(affine));
QPixmap* image = m_common->state.fillPattern->tileImage()->nativeImageForCurrentFrame();
- if (hasShadow) {
+ if (m_data->hasShadow()) {
drawRepeatPattern(pShadow, image, FloatRect(static_cast<QRectF>(shadowImage->rect())), m_common->state.fillPattern->repeatX(), m_common->state.fillPattern->repeatY());
pShadow->end();
p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect());
@@ -747,14 +669,14 @@ void GraphicsContext::fillRect(const FloatRect& rect)
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- if (hasShadow) {
+ if (m_data->hasShadow()) {
pShadow->fillRect(shadowImage->rect(), brush);
pShadow->end();
p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect());
}
p->fillRect(normalizedRect, brush);
} else {
- if (hasShadow) {
+ if (m_data->hasShadow()) {
pShadow->fillRect(shadowImage->rect(), p->brush());
pShadow->end();
p->drawImage(shadowDestRect, *shadowImage, shadowImage->rect());
@@ -774,8 +696,10 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& color, ColorS
m_data->solidColor.setColor(color);
QPainter* p = m_data->p();
- if (m_common->state.shadowColor.isValid())
- drawBorderlessRectShadow(this, p, rect);
+
+ if (m_data->hasShadow())
+ m_data->shadow.drawShadowRect(p, rect);
+
p->fillRect(rect, m_data->solidColor);
}
@@ -786,7 +710,11 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
Path path = Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight);
QPainter* p = m_data->p();
- drawFilledShadowPath(this, p, path.platformPath());
+ if (m_data->hasShadow()) {
+ p->translate(m_data->shadow.offset);
+ p->fillPath(path.platformPath(), m_data->shadow.color);
+ p->translate(-m_data->shadow.offset);
+ }
p->fillPath(path.platformPath(), QColor(color));
}
@@ -928,7 +856,7 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
return FloatRect(roundedOrigin, roundedLowerRight - roundedOrigin);
}
-void GraphicsContext::setPlatformShadow(const FloatSize& size, float, const Color&, ColorSpace)
+void GraphicsContext::setPlatformShadow(const FloatSize& size, float blur, const Color& color, ColorSpace)
{
// Qt doesn't support shadows natively, they are drawn manually in the draw*
// functions
@@ -937,13 +865,20 @@ void GraphicsContext::setPlatformShadow(const FloatSize& size, float, const Colo
// 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 = ContextShadow(color, blur, size.width(), -size.height());
+ } else {
+ m_data->shadow = ContextShadow(color, blur, size.width(), size.height());
}
}
void GraphicsContext::clearPlatformShadow()
{
- // Qt doesn't support shadows natively, they are drawn manually in the draw*
- // functions
+ m_data->shadow.clear();
+}
+
+void GraphicsContext::pushTransparencyLayerInternal(const QRect &rect, qreal opacity, QPixmap& alphaMask)
+{
+ m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -1226,23 +1161,6 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
}
}
-void GraphicsContext::clipToImageBuffer(const FloatRect& floatRect, const ImageBuffer* image)
-{
- if (paintingDisabled())
- return;
-
- QPixmap* nativeImage = image->image()->nativeImageForCurrentFrame();
- if (!nativeImage)
- return;
-
- IntRect rect(floatRect);
- QPixmap alphaMask = *nativeImage;
- if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
- alphaMask = alphaMask.scaled(rect.width(), rect.height());
-
- m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
-}
-
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
int thickness)
{
diff --git a/WebCore/platform/graphics/qt/ImageBufferData.h b/WebCore/platform/graphics/qt/ImageBufferData.h
index 222dabe..aa32253 100644
--- a/WebCore/platform/graphics/qt/ImageBufferData.h
+++ b/WebCore/platform/graphics/qt/ImageBufferData.h
@@ -26,6 +26,9 @@
#ifndef ImageBufferData_h
#define ImageBufferData_h
+#include "Image.h"
+#include <wtf/RefPtr.h>
+
#include <QPainter>
#include <QPixmap>
@@ -41,6 +44,7 @@ public:
QPixmap m_pixmap;
OwnPtr<QPainter> m_painter;
+ RefPtr<Image> m_image;
};
} // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 761a4fe..11ca377 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -33,6 +33,7 @@
#include "ImageData.h"
#include "MIMETypeRegistry.h"
#include "StillImageQt.h"
+#include "TransparencyLayer.h"
#include <wtf/text/CString.h>
#include <QBuffer>
@@ -74,6 +75,8 @@ ImageBufferData::ImageBufferData(const IntSize& size)
brush.setColor(Qt::black);
painter->setBrush(brush);
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ m_image = StillImage::createForRendering(&m_pixmap);
}
ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success)
@@ -98,24 +101,50 @@ GraphicsContext* ImageBuffer::context() const
return m_context.get();
}
-Image* ImageBuffer::imageForRendering() const
+bool ImageBuffer::drawsUsingCopy() const
{
- if (!m_image)
- m_image = StillImage::createForRendering(&m_data.m_pixmap);
+ return false;
+}
- return m_image.get();
+PassRefPtr<Image> ImageBuffer::copyImage() const
+{
+ return StillImage::create(m_data.m_pixmap);
}
-Image* ImageBuffer::image() const
+void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+ CompositeOperator op, bool useLowQualityScale)
{
- if (!m_image) {
- // It's assumed that if image() is called, the actual rendering to the
- // GraphicsContext must be done.
- ASSERT(context());
- m_image = StillImage::create(m_data.m_pixmap);
- }
+ if (destContext == context()) {
+ // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
+ RefPtr<Image> copy = copyImage();
+ destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
+ } else
+ destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
+ const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+ if (destContext == context()) {
+ // We're drawing into our own buffer. In order for this to work, we need to copy the source buffer first.
+ RefPtr<Image> copy = copyImage();
+ copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+ } else
+ m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+}
+
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect) const
+{
+ QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame();
+ if (!nativeImage)
+ return;
+
+ IntRect rect(floatRect);
+ QPixmap alphaMask = *nativeImage;
+ if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
+ alphaMask = alphaMask.scaled(rect.width(), rect.height());
- return m_image.get();
+ context->pushTransparencyLayerInternal(rect, 1.0, alphaMask);
}
void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index fb3d621..858cc44 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -78,6 +78,9 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
m_buffer->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
m_reader.set(new QImageReader(m_buffer.get(), m_format));
+ // This will force the JPEG decoder to use JDCT_IFAST
+ m_reader->setQuality(49);
+
// QImageReader only allows retrieving the format before reading the image
m_format = m_reader->format();
}
@@ -186,20 +189,16 @@ void ImageDecoderQt::internalReadImage(size_t frameIndex)
bool ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
{
QPixmap pixmap;
- bool pixmapLoaded;
- const int imageCount = m_reader->imageCount();
- if (imageCount == 0 || imageCount == 1)
- pixmapLoaded = pixmap.loadFromData((const uchar*)(m_data->data()), m_data->size(), m_format);
- else {
- QImage img;
- const bool imageLoaded = m_reader->read(&img);
- if (imageLoaded) {
- pixmap = QPixmap::fromImage(img);
- pixmapLoaded = true;
- }
- }
- if (!pixmapLoaded) {
+#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
+ pixmap = QPixmap::fromImageReader(m_reader.get());
+#else
+ QImage img;
+ if (m_reader->read(&img))
+ pixmap = QPixmap::fromImage(img);
+#endif
+
+ if (pixmap.isNull()) {
frameCount();
repetitionCount();
clearPointers();
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
index 3c6c5aa..08eb816 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivatePhonon.cpp
@@ -534,7 +534,11 @@ void MediaPlayerPrivate::aboutToFinish()
void MediaPlayerPrivate::totalTimeChanged(qint64 totalTime)
{
+#if OS(WINDOWS)
+ LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%I64d)", totalTime);
+#else
LOG(Media, "MediaPlayerPrivatePhonon::totalTimeChanged(%lld)", totalTime);
+#endif
LOG_MEDIAOBJECT();
}
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
index 525aaf4..4ad5571 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.cpp
@@ -25,6 +25,7 @@
#include "GraphicsContext.h"
#include "HTMLMediaElement.h"
#include "HTMLVideoElement.h"
+#include "NotImplemented.h"
#include "TimeRanges.h"
#include "Widget.h"
#include "qwebframe.h"
@@ -95,6 +96,7 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
, m_isSeeking(false)
, m_composited(false)
, m_queuedSeek(-1)
+ , m_preload(MediaPlayer::Auto)
{
m_mediaPlayer->bind(m_videoItem);
m_videoScene->addItem(m_videoItem);
@@ -106,6 +108,8 @@ MediaPlayerPrivate::MediaPlayerPrivate(MediaPlayer* player)
this, SLOT(stateChanged(QMediaPlayer::State)));
connect(m_mediaPlayer, SIGNAL(error(QMediaPlayer::Error)),
this, SLOT(handleError(QMediaPlayer::Error)));
+ connect(m_mediaPlayer, SIGNAL(bufferStatusChanged(int)),
+ this, SLOT(bufferStatusChanged(int)));
connect(m_mediaPlayer, SIGNAL(durationChanged(qint64)),
this, SLOT(durationChanged(qint64)));
connect(m_mediaPlayer, SIGNAL(positionChanged(qint64)),
@@ -145,6 +149,20 @@ bool MediaPlayerPrivate::hasAudio() const
void MediaPlayerPrivate::load(const String& url)
{
+ m_mediaUrl = url;
+
+ // QtMultimedia does not have an API to throttle loading
+ // so we handle this ourselves by delaying the load
+ if (m_preload == MediaPlayer::None) {
+ m_delayingLoad = true;
+ return;
+ }
+
+ commitLoad(url);
+}
+
+void MediaPlayerPrivate::commitLoad(const String& url)
+{
// We are now loading
if (m_networkState != MediaPlayer::Loading) {
m_networkState = MediaPlayer::Loading;
@@ -208,6 +226,21 @@ void MediaPlayerPrivate::load(const String& url)
// engine which does.
m_mediaPlayer->setMuted(element->muted());
m_mediaPlayer->setVolume(static_cast<int>(element->volume() * 100.0));
+
+ // Setting a media source will start loading the media, but we need
+ // to pre-roll as well to get video size-hints and buffer-status
+ if (element->paused())
+ m_mediaPlayer->pause();
+ else
+ m_mediaPlayer->play();
+}
+
+void MediaPlayerPrivate::resumeLoad()
+{
+ m_delayingLoad = false;
+
+ if (!m_mediaUrl.isNull())
+ commitLoad(m_mediaUrl);
}
void MediaPlayerPrivate::cancelLoad()
@@ -216,6 +249,12 @@ void MediaPlayerPrivate::cancelLoad()
updateStates();
}
+void MediaPlayerPrivate::prepareToPlay()
+{
+ if (m_mediaPlayer->media().isNull() || m_delayingLoad)
+ resumeLoad();
+}
+
void MediaPlayerPrivate::play()
{
if (m_mediaPlayer->state() != QMediaPlayer::PlayingState)
@@ -322,24 +361,11 @@ float MediaPlayerPrivate::maxTimeSeekable() const
unsigned MediaPlayerPrivate::bytesLoaded() const
{
- unsigned percentage = m_mediaPlayer->bufferStatus();
-
- if (percentage == 100) {
- if (m_networkState != MediaPlayer::Idle) {
- m_networkState = MediaPlayer::Idle;
- m_player->networkStateChanged();
- }
- if (m_readyState != MediaPlayer::HaveEnoughData) {
- m_readyState = MediaPlayer::HaveEnoughData;
- m_player->readyStateChanged();
- }
- }
-
QLatin1String bytesLoadedKey("bytes-loaded");
if (m_mediaPlayer->availableExtendedMetaData().contains(bytesLoadedKey))
return m_mediaPlayer->extendedMetaData(bytesLoadedKey).toInt();
- return percentage;
+ return m_mediaPlayer->bufferStatus();
}
unsigned MediaPlayerPrivate::totalBytes() const
@@ -350,6 +376,13 @@ unsigned MediaPlayerPrivate::totalBytes() const
return 100;
}
+void MediaPlayerPrivate::setPreload(MediaPlayer::Preload preload)
+{
+ m_preload = preload;
+ if (m_delayingLoad && m_preload != MediaPlayer::None)
+ resumeLoad();
+}
+
void MediaPlayerPrivate::setRate(float rate)
{
m_mediaPlayer->setPlaybackRate(rate);
@@ -439,6 +472,11 @@ void MediaPlayerPrivate::positionChanged(qint64)
}
}
+void MediaPlayerPrivate::bufferStatusChanged(int)
+{
+ notImplemented();
+}
+
void MediaPlayerPrivate::durationChanged(qint64)
{
m_player->durationChanged();
diff --git a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
index d72404c..165efde 100644
--- a/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
+++ b/WebCore/platform/graphics/qt/MediaPlayerPrivateQt.h
@@ -50,10 +50,13 @@ public:
bool hasAudio() const;
void load(const String &url);
+ void commitLoad(const String& url);
+ void resumeLoad();
void cancelLoad();
void play();
void pause();
+ void prepareToPlay();
bool paused() const;
bool seeking() const;
@@ -68,6 +71,8 @@ public:
bool supportsMuting() const;
void setMuted(bool);
+ void setPreload(MediaPlayer::Preload);
+
MediaPlayer::NetworkState networkState() const;
MediaPlayer::ReadyState readyState() const;
@@ -103,6 +108,7 @@ private slots:
void seekTimeout();
void positionChanged(qint64);
void durationChanged(qint64);
+ void bufferStatusChanged(int);
void volumeChanged(int);
void mutedChanged(bool);
void repaint();
@@ -127,6 +133,10 @@ private:
bool m_isSeeking;
bool m_composited;
qint64 m_queuedSeek;
+ MediaPlayer::Preload m_preload;
+ bool m_delayingLoad;
+ String m_mediaUrl;
+
};
}
diff --git a/WebCore/platform/graphics/qt/PathQt.cpp b/WebCore/platform/graphics/qt/PathQt.cpp
index de9de07..ce5da2e 100644
--- a/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/WebCore/platform/graphics/qt/PathQt.cpp
@@ -51,6 +51,7 @@
namespace WebCore {
Path::Path()
+ : m_lastMoveToIndex(0)
{
}
@@ -60,12 +61,14 @@ Path::~Path()
Path::Path(const Path& other)
: m_path(other.m_path)
+ , m_lastMoveToIndex(other.m_lastMoveToIndex)
{
}
Path& Path::operator=(const Path& other)
{
m_path = other.m_path;
+ m_lastMoveToIndex = other.m_lastMoveToIndex;
return *this;
}
@@ -180,6 +183,7 @@ FloatRect Path::strokeBoundingRect(StrokeStyleApplier* applier)
void Path::moveTo(const FloatPoint& point)
{
+ m_lastMoveToIndex = m_path.elementCount();
m_path.moveTo(point);
}
@@ -260,7 +264,26 @@ void Path::addArcTo(const FloatPoint& p1, const FloatPoint& p2, float radius)
void Path::closeSubpath()
{
- m_path.closeSubpath();
+ const int elementCount = m_path.elementCount();
+
+ if (!elementCount)
+ return;
+
+ QPointF lastMoveToPoint = m_path.elementAt(m_lastMoveToIndex);
+ int elementsInLastSubpath = 0;
+
+ for (int i = m_lastMoveToIndex; i < elementCount; ++i) {
+ QPainterPath::Element element = m_path.elementAt(i);
+ if (element.isLineTo() || element.isCurveTo()) {
+ // All we need to know is if there are 1 or more elements in the last subpath.
+ if (++elementsInLastSubpath == 2) {
+ m_path.lineTo(lastMoveToPoint);
+ return;
+ }
+ }
+ }
+
+ moveTo(lastMoveToPoint);
}
#define DEGREES(t) ((t) * 180.0 / M_PI)
@@ -440,7 +463,7 @@ void Path::transform(const AffineTransform& transform)
// QTransform.map doesn't handle the MoveTo element because of the isEmpty issue
if (m_path.isEmpty() && m_path.elementCount()) {
QPointF point = qTransform.map(m_path.currentPosition());
- m_path.moveTo(point);
+ moveTo(point);
} else
#endif
m_path = qTransform.map(m_path);
diff --git a/WebCore/platform/graphics/qt/TransparencyLayer.h b/WebCore/platform/graphics/qt/TransparencyLayer.h
new file mode 100644
index 0000000..0d9c121
--- /dev/null
+++ b/WebCore/platform/graphics/qt/TransparencyLayer.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2006 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Zack Rusin <zack@kde.org>
+ * Copyright (C) 2006 George Staikos <staikos@kde.org>
+ * Copyright (C) 2006 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <sandfeld@kde.org>
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * 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@gmx.de>
+ *
+ * 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 TransparencyLayer_h
+#define TransparencyLayer_h
+
+#include <QPaintEngine>
+#include <QPainter>
+#include <QPixmap>
+
+namespace WebCore {
+
+struct TransparencyLayer : FastAllocBase {
+ TransparencyLayer(const QPainter* p, const QRect &rect, qreal opacity, QPixmap& alphaMask)
+ : pixmap(rect.width(), rect.height())
+ , opacity(opacity)
+ , alphaMask(alphaMask)
+ , saveCounter(1) // see the comment for saveCounter
+ {
+ offset = rect.topLeft();
+ pixmap.fill(Qt::transparent);
+ painter.begin(&pixmap);
+ painter.setRenderHint(QPainter::Antialiasing, p->testRenderHint(QPainter::Antialiasing));
+ painter.translate(-offset);
+ painter.setPen(p->pen());
+ painter.setBrush(p->brush());
+ painter.setTransform(p->transform(), true);
+ painter.setOpacity(p->opacity());
+ painter.setFont(p->font());
+ if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ painter.setCompositionMode(p->compositionMode());
+ // if the path is an empty region, this assignment disables all painting
+ if (!p->clipPath().isEmpty())
+ painter.setClipPath(p->clipPath());
+ }
+
+ TransparencyLayer()
+ {
+ }
+
+ QPixmap pixmap;
+ QPoint offset;
+ QPainter painter;
+ qreal opacity;
+ // for clipToImageBuffer
+ QPixmap alphaMask;
+ // saveCounter is only used in combination with alphaMask
+ // otherwise, its value is unspecified
+ int saveCounter;
+private:
+ TransparencyLayer(const TransparencyLayer &) {}
+ TransparencyLayer & operator=(const TransparencyLayer &) { return *this; }
+};
+
+} // namespace WebCore
+
+#endif // TransparencyLayer_h