From 72debacc7f57b9ea9115e549170341a9ad11bf0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= Date: Tue, 28 Jul 2009 12:24:32 +0200 Subject: Add QGraphicsEffectSource::pixmap. We need a convenient way of getting the pixmap representation of the source. --- examples/graphicsview/blurpicker/blureffect.cpp | 4 +-- examples/graphicsview/blurpicker/blureffect.h | 2 +- src/gui/graphicsview/qgraphicseffect.cpp | 31 ++++++++++++++++----- src/gui/graphicsview/qgraphicseffect.h | 8 +++++- src/gui/graphicsview/qgraphicseffect_p.h | 6 +++- src/gui/graphicsview/qgraphicsitem.cpp | 29 ++++++++++++++++++- src/gui/graphicsview/qgraphicsitem_p.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 37 ++++++++++++++++--------- src/gui/graphicsview/qgraphicsscene_p.h | 6 ++-- 9 files changed, 95 insertions(+), 29 deletions(-) diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp index 43791c6..82be44f 100644 --- a/examples/graphicsview/blurpicker/blureffect.cpp +++ b/examples/graphicsview/blurpicker/blureffect.cpp @@ -62,8 +62,8 @@ QRectF BlurEffect::boundingRect() const return QGraphicsBlurEffect::boundingRect(); } -void BlurEffect::draw(QPainter *painter) +void BlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { adjustForItem(); - QGraphicsBlurEffect::draw(painter); + QGraphicsBlurEffect::draw(painter, source); } diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h index 2aea8bf..89694b6 100644 --- a/examples/graphicsview/blurpicker/blureffect.h +++ b/examples/graphicsview/blurpicker/blureffect.h @@ -54,7 +54,7 @@ public: QRectF boundingRect() const; - void draw(QPainter *painter); + void draw(QPainter *painter, QGraphicsEffectSource *source); private: void adjustForItem(); diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index ed529db..1281847 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -124,6 +124,8 @@ void QGraphicsEffectSource::draw(QPainter *painter) bool QGraphicsEffectSource::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) { return d_func()->drawIntoPixmap(pixmap, offset); } +QPixmap QGraphicsEffectSource::pixmap(bool deviceCoordinates, QPoint *offset) const +{ return d_func()->pixmap(deviceCoordinates, offset); } QGraphicsEffect::QGraphicsEffect() : QObject(*new QGraphicsEffectPrivate, 0) @@ -151,6 +153,25 @@ QRectF QGraphicsEffect::boundingRect() const return QRectF(); } +void QGraphicsEffect::setSourcePixmap(const QPixmap &pixmap) +{ + Q_D(QGraphicsEffect); + d->sourcePixmap = pixmap; + d->hasSourcePixmap = !pixmap.isNull(); +} + +QPixmap QGraphicsEffect::sourcePixmap() const +{ + Q_D(const QGraphicsEffect); + return d->sourcePixmap; +} + +bool QGraphicsEffect::hasSourcePixmap() const +{ + Q_D(const QGraphicsEffect); + return d->hasSourcePixmap; +} + QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const { return rect; @@ -398,17 +419,13 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); - const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true); - const QRect effectRect = d->filter->boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1); - - QPixmap pixmap(effectRect.size()); - if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft())) - return; + QPoint offset; + const QPixmap pixmap = source->pixmap(true, &offset); // Draw the pixmap with the filter using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect()); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); painter->setWorldTransform(restoreTransform); } diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index c13461e..77eebd6 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -65,6 +65,7 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW class QGraphicsEffectSourcePrivate; +class QStyleOption; class Q_GUI_EXPORT QGraphicsEffectSource : public QObject { Q_OBJECT @@ -75,6 +76,7 @@ public: const QStyleOption *styleOption() const; void draw(QPainter *painter); bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset = QPoint()); + QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const; protected: QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0); @@ -97,9 +99,13 @@ public: virtual ~QGraphicsEffect(); QRectF boundingRect() const; + void setSourcePixmap(const QPixmap &pixmap); + QPixmap sourcePixmap() const; + bool hasSourcePixmap() const; + virtual QRectF boundingRectFor(const QRectF &rect) const; + protected: QGraphicsEffect(QGraphicsEffectPrivate &d); - virtual QRectF boundingRectFor(const QRectF &rect) const; virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0; private: diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index ce90193..a575d3b 100644 --- a/src/gui/graphicsview/qgraphicseffect_p.h +++ b/src/gui/graphicsview/qgraphicseffect_p.h @@ -73,6 +73,7 @@ public: virtual const QStyleOption *styleOption() const = 0; virtual void draw(QPainter *p) = 0; virtual bool drawIntoPixmap(QPixmap *, const QPoint &offset = QPoint()) = 0; + virtual QPixmap pixmap(bool deviceCoordinates, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; friend class QGraphicsItemPrivate; @@ -82,7 +83,7 @@ class QGraphicsEffectPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QGraphicsEffect) public: - QGraphicsEffectPrivate() : source(0) {} + QGraphicsEffectPrivate() : source(0), hasSourcePixmap(0) {} QGraphicsEffectSource *source; inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource) { @@ -93,6 +94,9 @@ public: source = newSource; } QRectF boundingRect; + QPixmap sourcePixmap; + quint32 hasSourcePixmap : 1; + quint32 padding : 31; // feel free to use }; class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index b46abd4..425031f 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -9944,6 +9944,33 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter) info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); } +QPixmap QGraphicsItemEffectSourcePrivate::pixmap(bool deviceCoordinates, QPoint *offset) const +{ + const QRectF sourceRect = boundingRect(deviceCoordinates); + const QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect(); + if (offset) + *offset = sourceRect.toAlignedRect().topLeft(); + + const QTransform translateTransform = QTransform::fromTranslate(-effectRect.x(), + -effectRect.y()); + QTransform effectTransform = deviceCoordinates ? translateTransform + : info->transformPtr->inverted(); + if (!deviceCoordinates) + effectTransform *= translateTransform; + *info->transformPtr *= effectTransform; + + QPixmap pixmap(effectRect.size()); + pixmap.fill(Qt::transparent); + QPainter pixmapPainter(&pixmap); + pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); + + QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); + scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, + info->widget, info->opacity, &effectTransform, info->wasDirtySceneTransform, + info->drawItem); + return pixmap; +} + bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset) { QPoint effectOffset(offset); @@ -9969,7 +9996,7 @@ bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPo pixmapPainter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing); QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func(); scened->draw(item, &pixmapPainter, &viewTransform, info->transformPtr, &exposedRegion, - info->widget, info->opacity, &effectOffset, info->wasDirtySceneTransform, + info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem); return true; } diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 0823e51..db79e07 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -548,6 +548,7 @@ public: QRectF boundingRect(bool deviceCoordinates) const; void draw(QPainter *); bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset); + QPixmap pixmap(bool deviceCoordinates, QPoint *offset) const; QGraphicsItem *item; QGraphicsItemPaintInfo *info; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 31ec1ba..3a899ff 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4232,7 +4232,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget, - qreal parentOpacity, QPoint *effectOffset) + qreal parentOpacity, const QTransform *const effectTransform) { Q_ASSERT(item); @@ -4285,10 +4285,8 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect() : transformPtr->mapRect(brect).toRect(); - if (widget) { - item->d_ptr->paintedViewBoundingRects.insert(widget, effectOffset ? - viewBoundingRect.translated(*effectOffset) : viewBoundingRect); - } + if (widget) + item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect); viewBoundingRect.adjust(-1, -1, 1, 1); drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty(); if (!drawItem) { @@ -4306,6 +4304,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * ENSURE_TRANSFORM_PTR; if (item->d_ptr->graphicsEffect) { + if (item->type() == 7) { + item->d_ptr->graphicsEffect->setSourcePixmap(static_cast(item) + ->pixmap()); + } ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp, opacity, wasDirtyParentSceneTransform, drawItem); @@ -4319,13 +4321,13 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * painter->setWorldTransform(restoreTransform); } else { draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity, - effectOffset, wasDirtyParentSceneTransform, drawItem); + effectTransform, wasDirtyParentSceneTransform, drawItem); } } void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const QTransform *const viewTransform, - const QTransform *const transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, - QPoint *effectOffset, bool wasDirtyParentSceneTransform, bool drawItem) + QTransform *transformPtr, QRegion *exposedRegion, QWidget *widget, qreal opacity, + const QTransform *effectTransform, bool wasDirtyParentSceneTransform, bool drawItem) { const bool itemIsFullyTransparent = (opacity < 0.0001); const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape); @@ -4338,6 +4340,8 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q if (itemClipsChildrenToShape) { painter->save(); Q_ASSERT(transformPtr); + if (effectTransform) + *transformPtr *= *effectTransform; painter->setWorldTransform(*transformPtr); painter->setClipPath(item->shape(), Qt::IntersectClip); } @@ -4351,7 +4355,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q break; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); } } @@ -4368,8 +4372,11 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q if (savePainter) painter->save(); - if (!itemHasChildren || !itemClipsChildrenToShape) + if (!itemHasChildren || !itemClipsChildrenToShape) { + if (effectTransform) + *transformPtr *= *effectTransform; painter->setWorldTransform(*transformPtr); + } if (itemClipsToShape) painter->setClipPath(item->shape(), Qt::IntersectClip); @@ -4392,7 +4399,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q child->d_ptr->dirtySceneTransform = 1; if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)) continue; - drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset); + drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectTransform); } } @@ -4475,8 +4482,12 @@ void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, b item->d_ptr->ignoreOpacity = 1; QGraphicsItem *p = item->d_ptr->parent; - while (p && !p->d_ptr->dirtyChildren) { + while (p) { p->d_ptr->dirtyChildren = 1; + if (p->d_ptr->graphicsEffect) { + p->d_ptr->dirty = 1; + p->d_ptr->fullUpdatePending = 1; + } p = p->d_ptr->parent; } } @@ -4585,7 +4596,7 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool // Process item. if (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint) { const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask); - const QRectF itemBoundingRect = adjustedItemBoundingRect(item); + const QRectF itemBoundingRect = adjustedItemEffectiveBoundingRect(item); if (useCompatUpdate && !itemIsUntransformable && qFuzzyIsNull(item->boundingRegionGranularity())) { // This block of code is kept for compatibility. Since 4.5, by default diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index b602758..f380ced 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -201,9 +201,9 @@ public: void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const, QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0), - QPoint *effectOffset = 0); - void draw(QGraphicsItem *, QPainter *, const QTransform *const, const QTransform *const, - QRegion *, QWidget *, qreal, QPoint *, bool, bool); + const QTransform *const effectTransform = 0); + void draw(QGraphicsItem *, QPainter *, const QTransform *const, QTransform *, + QRegion *, QWidget *, qreal, const QTransform *const, bool, bool); void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false, bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false, -- cgit v0.12