diff options
Diffstat (limited to 'WebCore/platform/graphics/qt')
-rw-r--r-- | WebCore/platform/graphics/qt/GraphicsContextQt.cpp | 151 |
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&) |