summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/qt/GraphicsContextQt.cpp')
-rw-r--r--WebCore/platform/graphics/qt/GraphicsContextQt.cpp151
1 files changed, 97 insertions, 54 deletions
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index a840525..b399f4e 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -51,6 +51,7 @@
#include "NotImplemented.h"
#include "Path.h"
#include "Pattern.h"
+#include "Pen.h"
#include "TransparencyLayer.h"
#include <QBrush>
@@ -200,6 +201,9 @@ public:
InterpolationQuality imageInterpolationQuality;
+ // Only used by SVG for now.
+ QPainterPath currentPath;
+
ContextShadow shadow;
QStack<ContextShadow> shadowStack;
@@ -208,6 +212,13 @@ public:
return shadow.m_type != ContextShadow::NoShadow;
}
+ inline void clearCurrentPath()
+ {
+ if (!currentPath.elementCount())
+ return;
+ currentPath = QPainterPath();
+ }
+
QRectF clipBoundingRect() const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
@@ -247,8 +258,8 @@ GraphicsContextPlatformPrivate::~GraphicsContextPlatformPrivate()
if (!platformContextIsOwned)
return;
- QPaintDevice* device = painter->device();
painter->end();
+ QPaintDevice* device = painter->device();
delete painter;
delete device;
}
@@ -308,6 +319,11 @@ void GraphicsContext::restorePlatformState()
m_data->p()->restore();
+ if (!m_data->currentPath.isEmpty() && m_common->state.pathTransform.isInvertible()) {
+ QTransform matrix = m_common->state.pathTransform;
+ m_data->currentPath = m_data->currentPath * matrix;
+ }
+
if (m_data->shadowStack.isEmpty())
m_data->shadow = ContextShadow();
else
@@ -498,40 +514,28 @@ void GraphicsContext::clipConvexPolygon(size_t numPoints, const FloatPoint* poin
p->setRenderHint(QPainter::Antialiasing, painterWasAntialiased);
}
-void GraphicsContext::fillPath(const Path& path)
+void GraphicsContext::fillPath()
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
- QPainterPath platformPath = path.platformPath();
- platformPath.setFillRule(toQtFillRule(fillRule()));
+ QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
+ path.setFillRule(toQtFillRule(fillRule()));
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
if (shadow->m_type != ContextShadow::BlurShadow
&& !m_common->state.fillPattern && !m_common->state.fillGradient)
{
- QPointF offset = shadow->offset();
- const QTransform& transform = p->transform();
- if (transform.isScaling()) {
- // If scaling is required, find the new coord for shadow origin,
- // so that the relative offset to its shape is kept.
- QPointF translatedOffset(offset.x() / transform.m11(),
- offset.y() / transform.m22());
- platformPath.translate(translatedOffset);
- p->fillPath(platformPath, QColor(shadow->m_color));
- platformPath.translate(-translatedOffset);
- } else {
- p->translate(offset);
- p->fillPath(platformPath, QColor(shadow->m_color));
- p->translate(-offset);
- }
+ p->translate(m_data->shadow.offset());
+ p->fillPath(path, QColor(m_data->shadow.m_color));
+ p->translate(-m_data->shadow.offset());
} else {
- QPainter* shadowPainter = shadow->beginShadowLayer(p, platformPath.controlPointRect());
+ QPainter* shadowPainter = shadow->beginShadowLayer(p, path.controlPointRect());
if (shadowPainter) {
shadowPainter->setCompositionMode(QPainter::CompositionMode_Source);
- shadowPainter->fillPath(platformPath, QColor(m_data->shadow.m_color));
+ shadowPainter->fillPath(path, QColor(m_data->shadow.m_color));
shadow->endShadowLayer(p);
}
}
@@ -539,24 +543,26 @@ void GraphicsContext::fillPath(const Path& path)
}
if (m_common->state.fillPattern) {
AffineTransform affine;
- p->fillPath(platformPath, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
+ p->fillPath(path, QBrush(m_common->state.fillPattern->createPlatformPattern(affine)));
} else if (m_common->state.fillGradient) {
QBrush brush(*m_common->state.fillGradient->platformGradient());
brush.setTransform(m_common->state.fillGradient->gradientSpaceTransform());
- p->fillPath(platformPath, brush);
+ p->fillPath(path, brush);
} else
- p->fillPath(platformPath, p->brush());
+ p->fillPath(path, p->brush());
+
+ m_data->clearCurrentPath();
}
-void GraphicsContext::strokePath(const Path& path)
+void GraphicsContext::strokePath()
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
QPen pen(p->pen());
- QPainterPath platformPath = path.platformPath();
- platformPath.setFillRule(toQtFillRule(fillRule()));
+ QPainterPath& path = m_data->currentPath; // Avoid detaching the QPainterPath
+ path.setFillRule(toQtFillRule(fillRule()));
if (m_data->hasShadow()) {
ContextShadow* shadow = contextShadow();
@@ -566,28 +572,16 @@ void GraphicsContext::strokePath(const Path& path)
{
QPen shadowPen(pen);
shadowPen.setColor(m_data->shadow.m_color);
- QPointF offset = shadow->offset();
- const QTransform& transform = p->transform();
- if (transform.isScaling()) {
- // If scaling is required, find the new coord for shadow origin,
- // so that the relative offset to its shape is kept.
- QPointF translatedOffset(offset.x() / transform.m11(),
- offset.y() / transform.m22());
- platformPath.translate(translatedOffset);
- p->strokePath(platformPath, shadowPen);
- platformPath.translate(-translatedOffset);
- } else {
- p->translate(offset);
- p->strokePath(platformPath, shadowPen);
- p->translate(-offset);
- }
+ p->translate(m_data->shadow.offset());
+ p->strokePath(path, shadowPen);
+ p->translate(-m_data->shadow.offset());
} else {
- FloatRect boundingRect = platformPath.controlPointRect();
+ FloatRect boundingRect = path.controlPointRect();
boundingRect.inflate(pen.miterLimit() + pen.widthF());
QPainter* shadowPainter = shadow->beginShadowLayer(p, boundingRect);
if (shadowPainter) {
shadowPainter->setOpacity(static_cast<qreal>(m_data->shadow.m_color.alpha()) / 255);
- shadowPainter->strokePath(platformPath, pen);
+ shadowPainter->strokePath(path, pen);
shadow->endShadowLayer(p);
}
}
@@ -597,15 +591,16 @@ void GraphicsContext::strokePath(const Path& path)
AffineTransform affine;
pen.setBrush(QBrush(m_common->state.strokePattern->createPlatformPattern(affine)));
p->setPen(pen);
- p->strokePath(platformPath, pen);
+ p->strokePath(path, pen);
} else if (m_common->state.strokeGradient) {
QBrush brush(*m_common->state.strokeGradient->platformGradient());
brush.setTransform(m_common->state.strokeGradient->gradientSpaceTransform());
pen.setBrush(brush);
p->setPen(pen);
- p->strokePath(platformPath, pen);
+ p->strokePath(path, pen);
} else
- p->strokePath(platformPath, pen);
+ p->strokePath(path, pen);
+ m_data->clearCurrentPath();
}
static inline void drawRepeatPattern(QPainter* p, QPixmap* image, const FloatRect& rect, const bool repeatX, const bool repeatY)
@@ -721,7 +716,7 @@ void GraphicsContext::fillRect(const FloatRect& rect)
// without using the shadow layer at all.
QColor shadowColor = shadow->m_color;
shadowColor.setAlphaF(shadowColor.alphaF() * p->brush().color().alphaF());
- const QTransform& transform = p->transform();
+ const QTransform transform = p->transform();
if (transform.isScaling()) {
p->fillRect(normalizedRect.translated(static_cast<qreal>(shadow->offset().x()) / transform.m11(),
static_cast<qreal>(shadow->offset().y() / transform.m22())),
@@ -792,11 +787,30 @@ void GraphicsContext::fillRoundedRect(const IntRect& rect, const IntSize& topLef
p->fillPath(path.platformPath(), QColor(color));
}
+void GraphicsContext::beginPath()
+{
+ m_data->clearCurrentPath();
+}
+
+void GraphicsContext::addPath(const Path& path)
+{
+ if (!m_data->currentPath.elementCount()) {
+ m_data->currentPath = path.platformPath();
+ return;
+ }
+ m_data->currentPath.addPath(path.platformPath());
+}
+
bool GraphicsContext::inTransparencyLayer() const
{
return m_data->layerCount;
}
+PlatformPath* GraphicsContext::currentPath()
+{
+ return &m_data->currentPath;
+}
+
ContextShadow* GraphicsContext::contextShadow()
{
return &m_data->shadow;
@@ -810,15 +824,15 @@ void GraphicsContext::clip(const FloatRect& rect)
m_data->p()->setClipRect(rect, Qt::IntersectClip);
}
-void GraphicsContext::clipPath(const Path& path, WindRule clipRule)
+void GraphicsContext::clipPath(WindRule clipRule)
{
if (paintingDisabled())
return;
QPainter* p = m_data->p();
- QPainterPath platformPath = path.platformPath();
- platformPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
- p->setClipPath(platformPath, Qt::IntersectClip);
+ QPainterPath newPath = m_data->currentPath;
+ newPath.setFillRule(clipRule == RULE_EVENODD ? Qt::OddEvenFill : Qt::WindingFill);
+ p->setClipPath(newPath, Qt::IntersectClip);
}
void GraphicsContext::drawFocusRing(const Path& path, int width, int offset, const Color& color)
@@ -1047,10 +1061,12 @@ void GraphicsContext::strokeRect(const FloatRect& rect, float width)
if (paintingDisabled())
return;
- Path path;
+ QPainterPath path;
path.addRect(rect);
setStrokeThickness(width);
- strokePath(path);
+ m_data->currentPath = path;
+
+ strokePath();
}
void GraphicsContext::setLineCap(LineCap lc)
@@ -1170,6 +1186,12 @@ void GraphicsContext::translate(float x, float y)
return;
m_data->p()->translate(x, y);
+
+ if (!m_data->currentPath.isEmpty()) {
+ QTransform matrix;
+ m_data->currentPath = m_data->currentPath * matrix.translate(-x, -y);
+ m_common->state.pathTransform.translate(x, y);
+ }
}
void GraphicsContext::rotate(float radians)
@@ -1178,6 +1200,12 @@ void GraphicsContext::rotate(float radians)
return;
m_data->p()->rotate(180 / M_PI*radians);
+
+ if (!m_data->currentPath.isEmpty()) {
+ QTransform matrix;
+ m_data->currentPath = m_data->currentPath * matrix.rotate(-180 / M_PI*radians);
+ m_common->state.pathTransform.rotate(radians);
+ }
}
void GraphicsContext::scale(const FloatSize& s)
@@ -1186,6 +1214,12 @@ void GraphicsContext::scale(const FloatSize& s)
return;
m_data->p()->scale(s.width(), s.height());
+
+ if (!m_data->currentPath.isEmpty()) {
+ QTransform matrix;
+ m_data->currentPath = m_data->currentPath * matrix.scale(1 / s.width(), 1 / s.height());
+ m_common->state.pathTransform.scaleNonUniform(s.width(), s.height());
+ }
}
void GraphicsContext::clipOut(const IntRect& rect)
@@ -1242,6 +1276,15 @@ void GraphicsContext::concatCTM(const AffineTransform& transform)
return;
m_data->p()->setWorldTransform(transform, true);
+
+ // Transformations to the context shouldn't transform the currentPath.
+ // We have to undo every change made to the context from the currentPath
+ // to avoid wrong drawings.
+ if (!m_data->currentPath.isEmpty() && transform.isInvertible()) {
+ QTransform matrix = transform.inverse();
+ m_data->currentPath = m_data->currentPath * matrix;
+ m_common->state.pathTransform.multiply(transform.toTransformationMatrix());
+ }
}
void GraphicsContext::setURLForRect(const KURL&, const IntRect&)