summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:05:15 -0800
commit1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353 (patch)
tree4457a7306ea5acb43fe05bfe0973b1f7faf97ba2 /WebCore/platform/graphics/qt/GraphicsContextQt.cpp
parent9364f22aed35e1a1e9d07c121510f80be3ab0502 (diff)
downloadexternal_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.zip
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.gz
external_webkit-1cbdecfa9fc428ac2d8aca0fa91c9580b3d57353.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'WebCore/platform/graphics/qt/GraphicsContextQt.cpp')
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp390
1 files changed, 313 insertions, 77 deletions
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index cf097c8..600d77c 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -5,6 +5,9 @@
* 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.
*
@@ -32,20 +35,32 @@
#include "config.h"
+#ifdef Q_WS_WIN
+#include <windows.h>
+#endif
+
#include "AffineTransform.h"
-#include "Path.h"
#include "Color.h"
-#include "GraphicsContext.h"
+#include "FloatConversion.h"
#include "Font.h"
+#include "GraphicsContext.h"
+#include "GraphicsContextPrivate.h"
+#include "ImageBuffer.h"
+#include "Path.h"
+#include "Pattern.h"
#include "Pen.h"
#include "NotImplemented.h"
-#include <QStack>
+#include <QDebug>
+#include <QGradient>
#include <QPainter>
-#include <QPolygonF>
-#include <QPainterPath>
#include <QPaintDevice>
-#include <QDebug>
+#include <QPaintEngine>
+#include <QPainterPath>
+#include <QPixmap>
+#include <QPolygonF>
+#include <QStack>
+#include <QVector>
#ifndef M_PI
#define M_PI 3.14159265358979323846
@@ -137,6 +152,22 @@ static Qt::PenStyle toQPenStyle(StrokeStyle style)
return Qt::NoPen;
}
+static inline QGradient applySpreadMethod(QGradient gradient, GradientSpreadMethod spreadMethod)
+{
+ switch (spreadMethod) {
+ case SpreadMethodPad:
+ gradient.setSpread(QGradient::PadSpread);
+ break;
+ case SpreadMethodReflect:
+ gradient.setSpread(QGradient::ReflectSpread);
+ break;
+ case SpreadMethodRepeat:
+ gradient.setSpread(QGradient::RepeatSpread);
+ break;
+ }
+ return gradient;
+}
+
struct TransparencyLayer
{
TransparencyLayer(const QPainter* p, const QRect &rect)
@@ -145,13 +176,15 @@ struct TransparencyLayer
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());
- painter.setCompositionMode(p->compositionMode());
+ if (painter.paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ painter.setCompositionMode(p->compositionMode());
painter.setClipPath(p->clipPath());
}
@@ -168,24 +201,6 @@ private:
TransparencyLayer & operator=(const TransparencyLayer &) { return *this; }
};
-struct TextShadow
-{
- TextShadow()
- : x(0)
- , y(0)
- , blur(0)
- {
- }
-
- bool isNull() { return !x && !y && !blur; }
-
- int x;
- int y;
- int blur;
-
- Color color;
-};
-
class GraphicsContextPlatformPrivate
{
public:
@@ -203,12 +218,12 @@ public:
return &layers.top()->painter;
}
- QPaintDevice* device;
+ bool antiAliasingForRectsAndLines;
QStack<TransparencyLayer *> layers;
QPainter* redirect;
- TextShadow shadow;
+ QBrush solidColor;
// Only used by SVG for now.
QPainterPath currentPath;
@@ -221,12 +236,18 @@ private:
GraphicsContextPlatformPrivate::GraphicsContextPlatformPrivate(QPainter* p)
{
painter = p;
- device = painter ? painter->device() : 0;
redirect = 0;
- // FIXME: Maybe only enable in SVG mode?
- if (painter)
- painter->setRenderHint(QPainter::Antialiasing);
+ solidColor = QBrush(Qt::black);
+
+ if (painter) {
+ // use the default the QPainter was constructed with
+ antiAliasingForRectsAndLines = painter->testRenderHint(QPainter::Antialiasing);
+ // FIXME: Maybe only enable in SVG mode?
+ painter->setRenderHint(QPainter::Antialiasing, true);
+ } else {
+ antiAliasingForRectsAndLines = false;
+ }
}
GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
@@ -386,7 +407,13 @@ void GraphicsContext::drawRect(const IntRect& rect)
if (paintingDisabled())
return;
- m_data->p()->drawRect(rect);
+ QPainter *p = m_data->p();
+ const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
+ p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+
+ p->drawRect(rect);
+
+ p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
// FIXME: Now that this is refactored, it should be shared by all contexts.
@@ -429,8 +456,25 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2)
FloatPoint p1 = point1;
FloatPoint p2 = point2;
+ QPainter *p = m_data->p();
+ const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
+ p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
adjustLineToPixelBoundaries(p1, p2, strokeThickness(), strokeStyle());
- m_data->p()->drawLine(p1, p2);
+
+ IntSize shadowSize;
+ int shadowBlur;
+ Color shadowColor;
+ if (textDrawingMode() == cTextFill && getShadow(shadowSize, shadowBlur, shadowColor)) {
+ p->save();
+ p->translate(shadowSize.width(), shadowSize.height());
+ p->setPen(QColor(shadowColor));
+ p->drawLine(p1, p2);
+ p->restore();
+ }
+
+ p->drawLine(p1, p2);
+
+ p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
// This method is only used to draw the little circles used in lists.
@@ -447,7 +491,13 @@ void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSp
if (paintingDisabled() || strokeStyle() == NoStroke || strokeThickness() <= 0.0f || !strokeColor().alpha())
return;
- m_data->p()->drawArc(rect, startAngle * 16, angleSpan * 16);
+ QPainter *p = m_data->p();
+ const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
+ p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
+
+ p->drawArc(rect, startAngle * 16, angleSpan * 16);
+
+ p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points, bool shouldAntialias)
@@ -470,12 +520,80 @@ void GraphicsContext::drawConvexPolygon(size_t npoints, const FloatPoint* points
p->restore();
}
-void GraphicsContext::fillRect(const IntRect& rect, const Color& c)
+void GraphicsContext::fillPath()
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPainterPath path = m_data->currentPath;
+
+ switch (m_common->state.fillColorSpace) {
+ case SolidColorSpace:
+ if (fillColor().alpha())
+ p->fillPath(path, p->brush());
+ break;
+ case PatternColorSpace:
+ p->fillPath(path, QBrush(m_common->state.fillPattern.get()->createPlatformPattern(getCTM())));
+ break;
+ case GradientColorSpace:
+ QGradient* gradient = m_common->state.fillGradient.get()->platformGradient();
+ *gradient = applySpreadMethod(*gradient, spreadMethod());
+ p->fillPath(path, QBrush(*gradient));
+ break;
+ }
+}
+
+void GraphicsContext::strokePath()
+{
+ if (paintingDisabled())
+ return;
+
+ QPainter *p = m_data->p();
+ QPen pen = p->pen();
+ QPainterPath path = m_data->currentPath;
+
+ switch (m_common->state.strokeColorSpace) {
+ case SolidColorSpace:
+ if (strokeColor().alpha())
+ p->strokePath(path, pen);
+ break;
+ case PatternColorSpace: {
+ pen.setBrush(QBrush(m_common->state.strokePattern.get()->createPlatformPattern(getCTM())));
+ p->setPen(pen);
+ p->strokePath(path, pen);
+ break;
+ }
+ case GradientColorSpace: {
+ QGradient* gradient = m_common->state.strokeGradient.get()->platformGradient();
+ *gradient = applySpreadMethod(*gradient, spreadMethod());
+ pen.setBrush(QBrush(*gradient));
+ p->setPen(pen);
+ p->strokePath(path, pen);
+ break;
+ }
+ }
+}
+
+void GraphicsContext::fillRect(const FloatRect& rect)
{
if (paintingDisabled())
return;
- m_data->p()->fillRect(rect, QColor(c));
+ QPainter *p = m_data->p();
+
+ switch (m_common->state.fillColorSpace) {
+ case SolidColorSpace:
+ if (fillColor().alpha())
+ p->fillRect(rect, p->brush());
+ break;
+ case PatternColorSpace:
+ p->fillRect(rect, QBrush(m_common->state.fillPattern.get()->createPlatformPattern(getCTM())));
+ break;
+ case GradientColorSpace:
+ p->fillRect(rect, QBrush(*(m_common->state.fillGradient.get()->platformGradient())));
+ break;
+ }
}
void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
@@ -483,7 +601,8 @@ void GraphicsContext::fillRect(const FloatRect& rect, const Color& c)
if (paintingDisabled())
return;
- m_data->p()->fillRect(rect, QColor(c));
+ m_data->solidColor.setColor(QColor(c));
+ m_data->p()->fillRect(rect, m_data->solidColor);
}
void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight, const Color& color)
@@ -505,9 +624,9 @@ void GraphicsContext::addPath(const Path& path)
m_data->currentPath = *(path.platformPath());
}
-void GraphicsContext::setFillRule(WindRule rule)
+bool GraphicsContext::inTransparencyLayer() const
{
- m_data->currentPath.setFillRule(rule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+ return !m_data->layers.isEmpty();
}
PlatformPath* GraphicsContext::currentPath()
@@ -515,7 +634,7 @@ PlatformPath* GraphicsContext::currentPath()
return &m_data->currentPath;
}
-void GraphicsContext::clip(const IntRect& rect)
+void GraphicsContext::clip(const FloatRect& rect)
{
if (paintingDisabled())
return;
@@ -531,7 +650,6 @@ void GraphicsContext::clip(const IntRect& rect)
* RenderTheme handles drawing focus on widgets which
* need it.
*/
-void setFocusRingColorChangeFunction(void (*)()) { }
Color focusRingColor() { return Color(0, 0, 0); }
void GraphicsContext::drawFocusRing(const Color& color)
{
@@ -545,6 +663,8 @@ void GraphicsContext::drawFocusRing(const Color& color)
return;
QPainter *p = m_data->p();
+ const bool antiAlias = p->testRenderHint(QPainter::Antialiasing);
+ p->setRenderHint(QPainter::Antialiasing, m_data->antiAliasingForRectsAndLines);
const QPen oldPen = p->pen();
const QBrush oldBrush = p->brush();
@@ -568,6 +688,8 @@ void GraphicsContext::drawFocusRing(const Color& color)
#endif
p->setPen(oldPen);
p->setBrush(oldBrush);
+
+ p->setRenderHint(QPainter::Antialiasing, antiAlias);
}
void GraphicsContext::drawLineForText(const IntPoint& origin, int width, bool printing)
@@ -597,23 +719,16 @@ FloatRect GraphicsContext::roundToDevicePixels(const FloatRect& frect)
return FloatRect(QRectF(result));
}
-void GraphicsContext::setShadow(const IntSize& pos, int blur, const Color &color)
+void GraphicsContext::setPlatformShadow(const IntSize& pos, int blur, const Color &color)
{
- if (paintingDisabled())
- return;
-
- m_data->shadow.x = pos.width();
- m_data->shadow.y = pos.height();
- m_data->shadow.blur = blur;
- m_data->shadow.color = color;
+ // Qt doesn't support shadows natively, they are drawn manually in the draw*
+ // functions
}
-void GraphicsContext::clearShadow()
+void GraphicsContext::clearPlatformShadow()
{
- if (paintingDisabled())
- return;
-
- m_data->shadow = TextShadow();
+ // Qt doesn't support shadows natively, they are drawn manually in the draw*
+ // functions
}
void GraphicsContext::beginTransparencyLayer(float opacity)
@@ -623,20 +738,18 @@ void GraphicsContext::beginTransparencyLayer(float opacity)
int x, y, w, h;
x = y = 0;
- w = m_data->device->width();
- h = m_data->device->height();
-
QPainter *p = m_data->p();
+ const QPaintDevice *device = p->device();
+ w = device->width();
+ h = device->height();
+
QRectF clip = p->clipPath().boundingRect();
- bool ok;
- QTransform transform = p->transform().inverted(&ok);
- if (ok) {
- QRectF deviceClip = transform.mapRect(clip);
- x = int(qBound(qreal(0), deviceClip.x(), (qreal)w));
- y = int(qBound(qreal(0), deviceClip.y(), (qreal)h));
- w = int(qBound(qreal(0), deviceClip.width(), (qreal)w) + 2);
- h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2);
- }
+ QRectF deviceClip = p->transform().mapRect(clip);
+ x = int(qBound(qreal(0), deviceClip.x(), (qreal)w));
+ y = int(qBound(qreal(0), deviceClip.y(), (qreal)h));
+ w = int(qBound(qreal(0), deviceClip.width(), (qreal)w) + 2);
+ h = int(qBound(qreal(0), deviceClip.height(), (qreal)h) + 2);
+
TransparencyLayer * layer = new TransparencyLayer(m_data->p(), QRect(x, y, w, h));
layer->opacity = opacity;
@@ -668,9 +781,11 @@ void GraphicsContext::clearRect(const FloatRect& rect)
QPainter *p = m_data->p();
QPainter::CompositionMode currentCompositionMode = p->compositionMode();
- p->setCompositionMode(QPainter::CompositionMode_Source);
+ if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ p->setCompositionMode(QPainter::CompositionMode_Source);
p->eraseRect(rect);
- p->setCompositionMode(currentCompositionMode);
+ if (p->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ p->setCompositionMode(currentCompositionMode);
}
void GraphicsContext::strokeRect(const FloatRect& rect, float width)
@@ -678,12 +793,12 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
if (paintingDisabled())
return;
- QPainter *p = m_data->p();
QPainterPath path;
path.addRect(rect);
- QPen nPen = p->pen();
- nPen.setWidthF(width);
- p->strokePath(path, nPen);
+ setStrokeThickness(width);
+ m_data->currentPath = path;
+
+ strokePath();
}
void GraphicsContext::setLineCap(LineCap lc)
@@ -697,6 +812,26 @@ void GraphicsContext::setLineCap(LineCap lc)
p->setPen(nPen);
}
+void GraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
+{
+ QPainter* p = m_data->p();
+ QPen pen = p->pen();
+ unsigned dashLength = dashes.size();
+ if (dashLength) {
+ QVector<qreal> pattern;
+ unsigned count = dashLength;
+ if (dashLength % 2)
+ count *= 2;
+
+ for (unsigned i = 0; i < count; i++)
+ pattern.append(dashes[i % dashLength] / narrowPrecisionToFloat(pen.widthF()));
+
+ pen.setDashPattern(pattern);
+ pen.setDashOffset(dashOffset);
+ }
+ p->setPen(pen);
+}
+
void GraphicsContext::setLineJoin(LineJoin lj)
{
if (paintingDisabled())
@@ -732,7 +867,8 @@ void GraphicsContext::setCompositeOperation(CompositeOperator op)
if (paintingDisabled())
return;
- m_data->p()->setCompositionMode(toQtCompositionMode(op));
+ if (m_data->p()->paintEngine()->hasFeature(QPaintEngine::PorterDuff))
+ m_data->p()->setCompositionMode(toQtCompositionMode(op));
}
void GraphicsContext::clip(const Path& path)
@@ -780,7 +916,7 @@ void GraphicsContext::rotate(float radians)
if (paintingDisabled())
return;
- m_data->p()->rotate(radians);
+ m_data->p()->rotate(180/M_PI*radians);
}
void GraphicsContext::scale(const FloatSize& s)
@@ -795,7 +931,7 @@ void GraphicsContext::clipOut(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
QPainter *p = m_data->p();
QRectF clipBounds = p->clipPath().boundingRect();
QPainterPath newClip;
@@ -810,7 +946,7 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
{
if (paintingDisabled())
return;
-
+
QPainter *p = m_data->p();
QRectF clipBounds = p->clipPath().boundingRect();
QPainterPath newClip;
@@ -821,6 +957,11 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
p->setClipPath(newClip, Qt::IntersectClip);
}
+void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
+{
+ notImplemented();
+}
+
void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
int thickness)
{
@@ -872,7 +1013,7 @@ void GraphicsContext::setPlatformStrokeColor(const Color& color)
}
void GraphicsContext::setPlatformStrokeStyle(const StrokeStyle& strokeStyle)
-{
+{
if (paintingDisabled())
return;
QPainter *p = m_data->p();
@@ -905,6 +1046,101 @@ void GraphicsContext::setUseAntialiasing(bool enable)
m_data->p()->setRenderHint(QPainter::Antialiasing, enable);
}
+#ifdef Q_WS_WIN
+#include <windows.h>
+
+HDC GraphicsContext::getWindowsContext(const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ // painting through native HDC is only supported for plugin, where mayCreateBitmap is always TRUE
+ Q_ASSERT(mayCreateBitmap == TRUE);
+
+ if (dstRect.isEmpty())
+ return 0;
+
+ // Create a bitmap DC in which to draw.
+ BITMAPINFO bitmapInfo;
+ bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bitmapInfo.bmiHeader.biWidth = dstRect.width();
+ bitmapInfo.bmiHeader.biHeight = dstRect.height();
+ bitmapInfo.bmiHeader.biPlanes = 1;
+ bitmapInfo.bmiHeader.biBitCount = 32;
+ bitmapInfo.bmiHeader.biCompression = BI_RGB;
+ bitmapInfo.bmiHeader.biSizeImage = 0;
+ bitmapInfo.bmiHeader.biXPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biYPelsPerMeter = 0;
+ bitmapInfo.bmiHeader.biClrUsed = 0;
+ bitmapInfo.bmiHeader.biClrImportant = 0;
+
+ void* pixels = 0;
+ HBITMAP bitmap = ::CreateDIBSection(NULL, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0);
+ if (!bitmap)
+ return 0;
+
+ HDC displayDC = ::GetDC(0);
+ HDC bitmapDC = ::CreateCompatibleDC(displayDC);
+ ::ReleaseDC(0, displayDC);
+
+ ::SelectObject(bitmapDC, bitmap);
+
+ // Fill our buffer with clear if we're going to alpha blend.
+ if (supportAlphaBlend) {
+ BITMAP bmpInfo;
+ GetObject(bitmap, sizeof(bmpInfo), &bmpInfo);
+ int bufferSize = bmpInfo.bmWidthBytes * bmpInfo.bmHeight;
+ memset(bmpInfo.bmBits, 0, bufferSize);
+ }
+
+ // Make sure we can do world transforms.
+ SetGraphicsMode(bitmapDC, GM_ADVANCED);
+
+ // Apply a translation to our context so that the drawing done will be at (0,0) of the bitmap.
+ XFORM xform;
+ xform.eM11 = 1.0f;
+ xform.eM12 = 0.0f;
+ xform.eM21 = 0.0f;
+ xform.eM22 = 1.0f;
+ xform.eDx = -dstRect.x();
+ xform.eDy = -dstRect.y();
+ ::SetWorldTransform(bitmapDC, &xform);
+
+
+ return bitmapDC;
+}
+
+void GraphicsContext::releaseWindowsContext(HDC hdc, const IntRect& dstRect, bool supportAlphaBlend, bool mayCreateBitmap)
+{
+ // painting through native HDC is only supported for plugin, where mayCreateBitmap is always TRUE
+ Q_ASSERT(mayCreateBitmap == TRUE);
+
+ if (hdc) {
+
+ if (!dstRect.isEmpty()) {
+
+ HBITMAP bitmap = static_cast<HBITMAP>(GetCurrentObject(hdc, OBJ_BITMAP));
+ BITMAP info;
+ GetObject(bitmap, sizeof(info), &info);
+ ASSERT(info.bmBitsPixel == 32);
+
+ QPixmap pixmap = QPixmap::fromWinHBITMAP(bitmap, supportAlphaBlend ? QPixmap::PremultipliedAlpha : QPixmap::NoAlpha);
+ m_data->p()->drawPixmap(dstRect, pixmap);
+
+ ::DeleteObject(bitmap);
+ }
+
+ ::DeleteDC(hdc);
+ }
+}
+#endif
+
+void GraphicsContext::setImageInterpolationQuality(InterpolationQuality)
+{
+}
+
+InterpolationQuality GraphicsContext::imageInterpolationQuality() const
+{
+ return InterpolationDefault;
+}
+
}
// vim: ts=4 sw=4 et