summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
authorBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-07-29 08:41:15 +0200
committerBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-07-29 08:41:17 +0200
commit854acb3478651312dbe84d9b4ef971b46485fe1f (patch)
tree069cf9d1774eafe1a235e26f74e43f59085bbd33 /src/gui/graphicsview
parente646d08593dc18cad4e59176c2fe8c10fa5b9497 (diff)
Add QGraphicsSourceEffect.
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/qgraphicseffect.cpp304
-rw-r--r--src/gui/graphicsview/qgraphicseffect.h64
-rw-r--r--src/gui/graphicsview/qgraphicseffect_p.h19
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp64
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h1
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h56
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp73
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h6
9 files changed, 333 insertions, 255 deletions
diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp
index 8d2c416740..ed529dbe49 100644
--- a/src/gui/graphicsview/qgraphicseffect.cpp
+++ b/src/gui/graphicsview/qgraphicseffect.cpp
@@ -102,6 +102,29 @@
*/
+QGraphicsEffectSource::QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{}
+
+QGraphicsEffectSource::~QGraphicsEffectSource()
+{}
+
+QRectF QGraphicsEffectSource::boundingRect(bool deviceCoordinates) const
+{ return d_func()->boundingRect(deviceCoordinates); }
+
+const QGraphicsItem *QGraphicsEffectSource::graphicsItem() const
+{ return d_func()->graphicsItem(); }
+
+const QStyleOption *QGraphicsEffectSource::styleOption() const
+{ return d_func()->styleOption(); }
+
+void QGraphicsEffectSource::draw(QPainter *painter)
+{ d_func()->draw(painter); }
+
+bool QGraphicsEffectSource::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset)
+{ return d_func()->drawIntoPixmap(pixmap, offset); }
+
+
QGraphicsEffect::QGraphicsEffect()
: QObject(*new QGraphicsEffectPrivate, 0)
{}
@@ -121,31 +144,40 @@ QGraphicsEffect::~QGraphicsEffect()
QRectF QGraphicsEffect::boundingRect() const
{
- return sourceBoundingRect();
-}
-
-QRectF QGraphicsEffect::sourceBoundingRect() const
-{
Q_D(const QGraphicsEffect);
+ // return d->boundingRect;
if (d->source)
- return d->source->boundingRect();
+ return boundingRectFor(d->source->boundingRect());
return QRectF();
}
-void QGraphicsEffect::drawSource(QPainter *painter)
+QRectF QGraphicsEffect::boundingRectFor(const QRectF &rect) const
{
- Q_D(QGraphicsEffect);
- if (d->source)
- d->source->draw(painter);
+ return rect;
}
-bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform)
-{
- Q_D(QGraphicsEffect);
- if (d->source)
- return d->source->drawIntoPixmap(pixmap, itemToPixmapTransform);
- return false;
-}
+//QRectF QGraphicsEffect::sourceBoundingRect(bool deviceCoordinates) const
+//{
+// Q_D(const QGraphicsEffect);
+// if (d->source)
+// return d->source->boundingRect(deviceCoordinates);
+// return QRectF();
+//}
+
+//void QGraphicsEffect::drawSource(QPainter *painter)
+//{
+// Q_D(QGraphicsEffect);
+// if (d->source)
+// d->source->d_func()->draw(painter);
+//}
+
+//bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QPoint &offset)
+//{
+// Q_D(QGraphicsEffect);
+// if (d->source)
+// return d->source->d_func()->drawIntoPixmap(pixmap, offset);
+// return false;
+//}
QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect()
: QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate)
@@ -154,30 +186,20 @@ QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect()
QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect()
{}
-void QGraphicsGrayscaleEffect::draw(QPainter *painter)
+void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsGrayscaleEffect);
- if (!d->source)
- return;
-
// Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
-
- if (deviceRect.x() != 0 || deviceRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
-
- QPixmap pixmap(deviceRect.size());
- if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true)
+ .toRect().adjusted(-1, -1, 1, 1);
+ QPixmap pixmap(sourceRect.size());
+ if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft()))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
+ d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -201,30 +223,19 @@ void QGraphicsColorizeEffect::setColor(const QColor &c)
d->filter->setColor(c);
}
-void QGraphicsColorizeEffect::draw(QPainter *painter)
+void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsColorizeEffect);
- if (!d->source)
- return;
-
- // Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
-
- if (deviceRect.x() != 0 || deviceRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
-
- QPixmap pixmap(deviceRect.size());
- if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true)
+ .toRect().adjusted(-1, -1, 1, 1);
+ QPixmap pixmap(sourceRect.size());
+ if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft()))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
+ d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -249,24 +260,14 @@ void QGraphicsPixelizeEffect::setPixelSize(int size)
d->pixelSize = size;
}
-void QGraphicsPixelizeEffect::draw(QPainter *painter)
+void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsPixelizeEffect);
- if (!d->source)
- return;
-
// Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
-
- if (deviceRect.x() != 0 || deviceRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
-
- QPixmap pixmap(deviceRect.size());
- if (!d->source->drawIntoPixmap(&pixmap))
+ const QRect sourceRect = source->boundingRect(/*deviceCoordinates=*/true)
+ .toRect().adjusted(-1, -1, 1, 1);
+ QPixmap pixmap(sourceRect.size());
+ if (!source->drawIntoPixmap(&pixmap, sourceRect.topLeft()))
return;
// pixelize routine
@@ -292,7 +293,7 @@ void QGraphicsPixelizeEffect::draw(QPainter *painter)
// Draw using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- painter->drawImage(deviceRect.topLeft(), img);
+ painter->drawImage(sourceRect.topLeft(), img);
painter->setWorldTransform(restoreTransform);
}
@@ -382,42 +383,32 @@ void QGraphicsBlurEffect::setBlurRadius(int radius)
d->filter->setBlurRadius(radius);
}
-QRectF QGraphicsBlurEffect::boundingRect() const
+QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
{
Q_D(const QGraphicsBlurEffect);
- if (d->source)
- return d->filter->boundingRectFor(d->source->boundingRect());
- return QRectF();
+ return d->filter->boundingRectFor(rect);
}
-void QGraphicsBlurEffect::draw(QPainter *painter)
+//QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const
+//{
+// Q_D(const QGraphicsBlurEffect);
+// return d->filter->boundingRectFor(rect);
+//}
+
+void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsBlurEffect);
- if (!d->source)
- return;
-
- // Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
-
- // ### Potentially big rect; must be clipped to the viewport rect.
- const qreal delta = d->blurRadius * 3;
- const QRect effectRect = deviceBounds.adjusted(-delta, -delta, delta, delta)
- .toRect().adjusted(-1, -1, 1, 1);
- if (effectRect.x() != 0 || effectRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-effectRect.x(), -effectRect.y());
+ 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 (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft()))
return;
// Draw the pixmap with the filter using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- d->filter->draw(painter, deviceRect.topLeft(), pixmap, pixmap.rect());
+ d->filter->draw(painter, sourceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -454,13 +445,20 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha)
d->opacity = alpha;
}
-QRectF QGraphicsBloomEffect::boundingRect() const
+//QRectF QGraphicsBloomEffect::boundingRectFor(nst QGraphicsEffectSource *source) const
+//{
+// Q_D(const QGraphicsBloomEffect);
+// if (!d->source)
+// return QRectF();
+// const qreal delta = d->blurRadius * 3;
+// return sourceBoundingRect().adjusted(-delta, -delta, delta, delta);
+//}
+
+QRectF QGraphicsBloomEffect::boundingRectFor(const QRectF &rect) const
{
Q_D(const QGraphicsBloomEffect);
- if (!d->source)
- return QRectF();
- qreal delta = d->blurRadius * 3;
- return d->source->boundingRect().adjusted(-delta, -delta, delta, delta);
+ const qreal delta = d->blurRadius * 3;
+ return rect.adjusted(-delta, -delta, delta, delta);
}
// Change brightness (positive integer) of each pixel
@@ -494,24 +492,14 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity,
return result;
}
-void QGraphicsBloomEffect::draw(QPainter *painter)
+void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsBloomEffect);
- if (!d->source)
- return;
-
- // Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
-
- if (deviceRect.x() != 0 || deviceRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+ const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true);
+ const QRect effectRect = boundingRectFor(sourceRect).toRect().adjusted(-1, -1, 1, 1);
- QPixmap pixmap(deviceRect.size());
- if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ QPixmap pixmap(effectRect.size());
+ if (!source->drawIntoPixmap(&pixmap, effectRect.topLeft()))
return;
// bloom routine
@@ -524,7 +512,7 @@ void QGraphicsBloomEffect::draw(QPainter *painter)
// Draw using an untransformed painter.
QTransform restoreTransform = painter->worldTransform();
painter->setWorldTransform(QTransform());
- painter->drawImage(deviceRect.topLeft() - QPointF(radius * 3, radius * 3), img);
+ painter->drawImage(effectRect.topLeft(), img);
painter->setWorldTransform(restoreTransform);
}
@@ -573,49 +561,31 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsFrameEffect::boundingRect() const
+//QRectF QGraphicsFrameEffect::boundingRect() const
+//{
+// Q_D(const QGraphicsFrameEffect);
+// if (!d->source)
+// return QRectF();
+// return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width);
+//}
+
+QRectF QGraphicsFrameEffect::boundingRectFor(const QRectF &rect) const
{
Q_D(const QGraphicsFrameEffect);
- if (!d->source)
- return QRectF();
- return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width);
+ return rect.adjusted(-d->width, -d->width, d->width, d->width);
}
-void QGraphicsFrameEffect::draw(QPainter *painter)
+void QGraphicsFrameEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsFrameEffect);
- if (!d->source)
- return;
-
- // Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- if (deviceBounds.isEmpty())
- return;
-
- QRect frameRect = deviceBounds.adjusted(-d->width, -d->width, d->width, d->width)
- .toRect().adjusted(-1, -1, 1, 1);
-
- if (frameRect.x() != 0 || frameRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-frameRect.x(), -frameRect.y());
-
- QPixmap pixmap(frameRect.size());
- if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
- return;
-
- painter->save();
- painter->setWorldTransform(QTransform());
-
painter->save();
painter->setOpacity(painter->opacity() * d->alpha);
painter->setPen(Qt::NoPen);
painter->setBrush(d->color);
- painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize);
+ painter->drawRoundedRect(boundingRect(), 20, 20, Qt::RelativeSize);
painter->restore();
- painter->drawPixmap(frameRect.topLeft(), pixmap);
-
- painter->restore();
+ source->draw(painter);
}
QGraphicsShadowEffect::QGraphicsShadowEffect()
@@ -663,46 +633,50 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsShadowEffect::boundingRect() const
+//QRectF QGraphicsShadowEffect::boundingRect() const
+//{
+// Q_D(const QGraphicsShadowEffect);
+// if (!d->source)
+// return QRectF();
+// const QRectF srcBrect = d->source->boundingRect();
+// QRectF shadowRect = srcBrect;
+// shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y());
+// QRectF blurRect = shadowRect;
+// qreal delta = d->radius * 3;
+// blurRect.adjust(-delta, -delta, delta, delta);
+// QRectF totalRect = blurRect.united(srcBrect);
+// return totalRect;
+//}
+
+QRectF QGraphicsShadowEffect::boundingRectFor(const QRectF &rect) const
{
Q_D(const QGraphicsShadowEffect);
- if (!d->source)
- return QRectF();
- const QRectF srcBrect = d->source->boundingRect();
- QRectF shadowRect = srcBrect;
+ QRectF shadowRect = rect;
shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y());
QRectF blurRect = shadowRect;
qreal delta = d->radius * 3;
blurRect.adjust(-delta, -delta, delta, delta);
- QRectF totalRect = blurRect.united(srcBrect);
+ QRectF totalRect = blurRect.united(rect);
return totalRect;
}
-void QGraphicsShadowEffect::draw(QPainter *painter)
+void QGraphicsShadowEffect::draw(QPainter *painter, QGraphicsEffectSource *source)
{
Q_D(QGraphicsShadowEffect);
if (!d->source)
return;
- // Find the item's bounds in device coordinates.
- QTransform itemToPixmapTransform(painter->worldTransform());
- QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return;
+ const QRectF sourceRect = source->boundingRect(/*deviceCoordinates=*/true);
- QRectF shadowRect = deviceBounds;
+ QRectF shadowRect = sourceRect;
shadowRect.adjust(d->offset.x(), d->offset.y(), d->offset.x(), d->offset.y());
QRectF blurRect = shadowRect;
qreal delta = d->radius * 3;
blurRect.adjust(-delta, -delta, delta, delta);
- QRect totalRect = blurRect.united(deviceRect).toRect().adjusted(-1, -1, 1, 1);
-
- if (totalRect.x() != 0 || totalRect.y() != 0)
- itemToPixmapTransform *= QTransform::fromTranslate(-totalRect.x(), -totalRect.y());
+ QRect totalRect = blurRect.united(sourceRect).toRect().adjusted(-1, -1, 1, 1);
QPixmap pixmap(totalRect.size());
- if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ if (!source->drawIntoPixmap(&pixmap, totalRect.topLeft()))
return;
QImage img = pixmap.toImage();
@@ -719,14 +693,14 @@ void QGraphicsShadowEffect::draw(QPainter *painter)
qreal shadowx = blurRect.x() + delta;
qreal shadowy = blurRect.y() + delta;
- if (blurRect.x() < deviceRect.x())
- shadowx = blurRect.x() + d->offset.x();
- if (blurRect.y() < deviceRect.y())
+ if (blurRect.x() < sourceRect.x())
+ shadowx = sourceRect.x() + d->offset.x();
+ if (blurRect.y() < sourceRect.y())
shadowy = blurRect.y() + d->offset.y();
painter->drawImage(shadowx, shadowy, shadowImage);
- qreal itemx = qMin(blurRect.x(), deviceBounds.x());
- qreal itemy = qMin(blurRect.y(), deviceBounds.y());
+ qreal itemx = qMin(blurRect.x(), sourceRect.x());
+ qreal itemy = qMin(blurRect.y(), sourceRect.y());
painter->drawPixmap(itemx, itemy, pixmap);
painter->setWorldTransform(restoreTransform);
diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h
index 74a843046a..c13461e3ff 100644
--- a/src/gui/graphicsview/qgraphicseffect.h
+++ b/src/gui/graphicsview/qgraphicseffect.h
@@ -64,6 +64,30 @@ QT_MODULE(Gui)
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+class QGraphicsEffectSourcePrivate;
+class Q_GUI_EXPORT QGraphicsEffectSource : public QObject
+{
+ Q_OBJECT
+public:
+ ~QGraphicsEffectSource();
+ QRectF boundingRect(bool deviceCoordinates = false) const;
+ const QGraphicsItem *graphicsItem() const;
+ const QStyleOption *styleOption() const;
+ void draw(QPainter *painter);
+ bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset = QPoint());
+
+protected:
+ QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0);
+
+private:
+ Q_DECLARE_PRIVATE(QGraphicsEffectSource);
+ Q_DISABLE_COPY(QGraphicsEffectSource);
+ friend class QGraphicsEffect;
+ friend class QGraphicsEffectPrivate;
+ friend class QGraphicsScenePrivate;
+ friend class QGraphicsItem;
+};
+
class QGraphicsEffectPrivate;
class Q_GUI_EXPORT QGraphicsEffect : public QObject
{
@@ -71,21 +95,19 @@ class Q_GUI_EXPORT QGraphicsEffect : public QObject
public:
QGraphicsEffect();
virtual ~QGraphicsEffect();
-
- virtual QRectF boundingRect() const;
+ QRectF boundingRect() const;
protected:
QGraphicsEffect(QGraphicsEffectPrivate &d);
- virtual void draw(QPainter *painter) = 0;
- void drawSource(QPainter *painter);
- bool drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &xform = QTransform());
- QRectF sourceBoundingRect() const;
+ virtual QRectF boundingRectFor(const QRectF &rect) const;
+ virtual void draw(QPainter *painter, QGraphicsEffectSource *source) = 0;
private:
- friend class QGraphicsScenePrivate;
- friend class QGraphicsItem;
Q_DECLARE_PRIVATE(QGraphicsEffect)
Q_DISABLE_COPY(QGraphicsEffect)
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+ friend class QGraphicsScenePrivate;
};
class QGraphicsGrayscaleEffectPrivate;
@@ -97,7 +119,7 @@ public:
~QGraphicsGrayscaleEffect();
protected:
- void draw(QPainter *painter);
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect)
@@ -115,7 +137,7 @@ public:
void setColor(const QColor &c);
protected:
- void draw(QPainter *painter);
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsColorizeEffect)
@@ -133,7 +155,7 @@ public:
void setPixelSize(int pixelSize);
protected:
- void draw(QPainter *painter);
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect)
@@ -150,10 +172,11 @@ public:
int blurRadius() const;
void setBlurRadius(int blurRadius);
- QRectF boundingRect() const;
+ // QRectF boundingRect() const;
protected:
- void draw(QPainter *painter);
+ QRectF boundingRectFor(const QRectF &rect) const;
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsBlurEffect)
@@ -173,10 +196,11 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRect() const;
+ // QRectF boundingRect() const;
protected:
- void draw(QPainter *painter);
+ QRectF boundingRectFor(const QRectF &rect) const;
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsBloomEffect)
@@ -199,10 +223,11 @@ public:
qreal frameOpacity() const;
void setFrameOpacity(qreal opacity);
- QRectF boundingRect() const;
+ // QRectF boundingRect() const;
protected:
- void draw(QPainter *painter);
+ QRectF boundingRectFor(const QRectF &rect) const;
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsFrameEffect)
@@ -227,10 +252,11 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRect() const;
+ // QRectF boundingRect() const;
protected:
- void draw(QPainter *painter);
+ QRectF boundingRectFor(const QRectF &rect) const;
+ void draw(QPainter *painter, QGraphicsEffectSource *source);
private:
Q_DECLARE_PRIVATE(QGraphicsShadowEffect)
diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h
index 92047897aa..ce90193e43 100644
--- a/src/gui/graphicsview/qgraphicseffect_p.h
+++ b/src/gui/graphicsview/qgraphicseffect_p.h
@@ -61,15 +61,21 @@
QT_BEGIN_NAMESPACE
-class QGraphicsEffectSource
+class QGraphicsEffectSourcePrivate : public QObjectPrivate
{
+ Q_DECLARE_PUBLIC(QGraphicsEffectSource)
public:
- QGraphicsEffectSource() {}
- virtual ~QGraphicsEffectSource() {}
+ QGraphicsEffectSourcePrivate() : QObjectPrivate() {}
+ virtual ~QGraphicsEffectSourcePrivate() {}
virtual void detach() = 0;
- virtual QRectF boundingRect() = 0;
+ virtual QRectF boundingRect(bool deviceCoordinates = false) const = 0;
+ virtual const QGraphicsItem *graphicsItem() const = 0;
+ virtual const QStyleOption *styleOption() const = 0;
virtual void draw(QPainter *p) = 0;
- virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0;
+ virtual bool drawIntoPixmap(QPixmap *, const QPoint &offset = QPoint()) = 0;
+ friend class QGraphicsScenePrivate;
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
};
class QGraphicsEffectPrivate : public QObjectPrivate
@@ -81,11 +87,12 @@ public:
inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
{
if (source) {
- source->detach();
+ source->d_func()->detach();
delete source;
}
source = newSource;
}
+ QRectF boundingRect;
};
class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 1d271c9edc..b46abd496a 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1016,10 +1016,10 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
*/
void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
{
- if (!dirtyChildrenBoundingRect) {
- *rect |= x->mapRect(childrenBoundingRect);
- return;
- }
+ // if (!dirtyChildrenBoundingRect) {
+ // *rect |= x->mapRect(childrenBoundingRect);
+ // return;
+ // }
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *child = children.at(i);
@@ -2231,7 +2231,9 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
} else {
// Set new effect.
- effect->d_func()->setGraphicsEffectSource(new QGraphicsItemEffectSource(this));
+ QGraphicsEffectSourcePrivate *sourced = new QGraphicsItemEffectSourcePrivate(this);
+ QGraphicsEffectSource *source = new QGraphicsEffectSource(*sourced);
+ effect->d_func()->setGraphicsEffectSource(source);
d_ptr->graphicsEffect = effect;
}
@@ -3843,8 +3845,8 @@ void QGraphicsItem::setZValue(qreal z)
*/
QRectF QGraphicsItem::childrenBoundingRect() const
{
- if (!d_ptr->dirtyChildrenBoundingRect)
- return d_ptr->childrenBoundingRect;
+ // if (!d_ptr->dirtyChildrenBoundingRect)
+ // return d_ptr->childrenBoundingRect;
QRectF childRect;
QTransform x;
@@ -9924,6 +9926,54 @@ int QGraphicsItemGroup::type() const
return Type;
}
+QRectF QGraphicsItemEffectSourcePrivate::boundingRect(bool deviceCoordinates) const
+{
+ QRectF rect = item->boundingRect();
+ rect |= item->childrenBoundingRect();
+ if (deviceCoordinates && info) {
+ Q_ASSERT(info->transformPtr);
+ return info->transformPtr->mapRect(rect);
+ }
+ return rect;
+}
+
+void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
+{
+ QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
+ scened->draw(item, painter, info->viewTransform, info->transformPtr, info->exposedRegion,
+ info->widget, info->opacity, 0, info->wasDirtySceneTransform, info->drawItem);
+}
+
+bool QGraphicsItemEffectSourcePrivate::drawIntoPixmap(QPixmap *pixmap, const QPoint &offset)
+{
+ QPoint effectOffset(offset);
+
+ QTransform viewTransform(Qt::Uninitialized);
+ if (info->viewTransform) {
+ viewTransform = *info->viewTransform;
+ viewTransform *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y());
+ } else {
+ viewTransform = QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y());
+ }
+
+ *info->transformPtr *= QTransform::fromTranslate(-effectOffset.x(), -effectOffset.y());
+
+ QRegion exposedRegion;
+ if (info->exposedRegion) {
+ exposedRegion = *info->exposedRegion;
+ exposedRegion.translate(-effectOffset.x(), -effectOffset.y());
+ }
+
+ 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, &viewTransform, info->transformPtr, &exposedRegion,
+ info->widget, info->opacity, &effectOffset, info->wasDirtySceneTransform,
+ info->drawItem);
+ return true;
+}
+
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, QGraphicsItem *item)
{
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 0c0b341cd3..0c2082951c 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -457,6 +457,7 @@ private:
friend class QGraphicsSceneIndexPrivate;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
+ friend class QGraphicsItemEffectSourcePrivate;
friend class ::tst_QGraphicsItem;
friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index dc875f7ec7..0823e5181b 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -510,44 +510,50 @@ struct QGraphicsItemPrivate::TransformData {
}
};
-class QGraphicsItemEffectSource : public QGraphicsEffectSource
+struct QGraphicsItemPaintInfo
+{
+ inline QGraphicsItemPaintInfo(const QTransform *const xform1, QTransform *xform2,
+ QRegion *r, QWidget *w, QStyleOptionGraphicsItem *opt,
+ qreal o, bool b1, bool b2)
+ : viewTransform(xform1), transformPtr(xform2), exposedRegion(r), widget(w),
+ option(opt), opacity(o), wasDirtySceneTransform(b1), drawItem(b2)
+ {}
+
+ const QTransform *viewTransform;
+ QTransform *transformPtr;
+ QRegion *exposedRegion;
+ QWidget *widget;
+ QStyleOptionGraphicsItem *option;
+ qreal opacity;
+ quint32 wasDirtySceneTransform : 1;
+ quint32 drawItem : 1;
+};
+
+class QGraphicsItemEffectSourcePrivate : public QGraphicsEffectSourcePrivate
{
public:
- QGraphicsItemEffectSource(QGraphicsItem *i)
- : QGraphicsEffectSource(), item(i), option(0), widget(0)
+ QGraphicsItemEffectSourcePrivate(QGraphicsItem *i)
+ : QGraphicsEffectSourcePrivate(), item(i), info(0)
{}
inline void detach()
{ item->setGraphicsEffect(0); }
- inline QRectF boundingRect()
- { return item->boundingRect(); }
+ inline const QGraphicsItem *graphicsItem() const
+ { return item; }
- inline void draw(QPainter *painter)
- { item->paint(painter, option, widget); }
+ inline const QStyleOption *styleOption() const
+ { return info ? info->option : 0; }
- inline bool drawIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform)
- {
- pixmap->fill(Qt::transparent);
- QPainter pixmapPainter(pixmap);
- if (!itemToPixmapTransform.isIdentity())
- pixmapPainter.setWorldTransform(itemToPixmapTransform);
- item->paint(&pixmapPainter, option, widget);
- return true;
- }
-
- inline void setPaintInfo(const QStyleOptionGraphicsItem *o, QWidget *w)
- { option = o; widget = w; }
+ QRectF boundingRect(bool deviceCoordinates) const;
+ void draw(QPainter *);
+ bool drawIntoPixmap(QPixmap *pixmap, const QPoint &offset);
- void resetPaintInfo()
- { option = 0; widget = 0; }
-
-private:
QGraphicsItem *item;
- const QStyleOptionGraphicsItem *option;
- QWidget *widget;
+ QGraphicsItemPaintInfo *info;
};
+
/*!
\internal
*/
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index f4fd4ce441..31ec1ba127 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -208,7 +208,7 @@
#ifndef QT_NO_GRAPHICSVIEW
-#include "qgraphicseffect.h"
+#include "qgraphicseffect_p.h"
#include "qgraphicsitem.h"
#include "qgraphicsitem_p.h"
#include "qgraphicslayout.h"
@@ -3920,19 +3920,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
QGraphicsItemPrivate *itemd = item->d_ptr;
QGraphicsItem::CacheMode cacheMode = QGraphicsItem::CacheMode(itemd->cacheMode);
- bool noCache = cacheMode == QGraphicsItem::NoCache ||
-#ifdef Q_WS_X11
- !X11->use_xrender;
-#else
- false;
-#endif
-
- // Render using effect, works now only for no cache mode
- if (noCache && itemd->graphicsEffect) {
- itemd->graphicsEffect->draw(painter);
- return;
- }
-
// Render directly, using no cache.
if (cacheMode == QGraphicsItem::NoCache
#ifdef Q_WS_X11
@@ -4245,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)
+ qreal parentOpacity, QPoint *effectOffset)
{
Q_ASSERT(item);
@@ -4298,7 +4285,10 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
ENSURE_TRANSFORM_PTR
QRect viewBoundingRect = translateOnlyTransform ? brect.translated(transformPtr->dx(), transformPtr->dy()).toRect()
: transformPtr->mapRect(brect).toRect();
- item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ if (widget) {
+ item->d_ptr->paintedViewBoundingRects.insert(widget, effectOffset ?
+ viewBoundingRect.translated(*effectOffset) : viewBoundingRect);
+ }
viewBoundingRect.adjust(-1, -1, 1, 1);
drawItem = exposedRegion ? exposedRegion->intersects(viewBoundingRect) : !viewBoundingRect.isEmpty();
if (!drawItem) {
@@ -4312,13 +4302,42 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
}
} // else we know for sure this item has children we must process.
+ if (itemHasChildren && itemClipsChildrenToShape)
+ ENSURE_TRANSFORM_PTR;
+
+ if (item->d_ptr->graphicsEffect) {
+ ENSURE_TRANSFORM_PTR;
+ QGraphicsItemPaintInfo info(viewTransform, transformPtr, exposedRegion, widget, &styleOptionTmp,
+ opacity, wasDirtyParentSceneTransform, drawItem);
+ QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source;
+ QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *>
+ (source->d_func());
+ sourced->info = &info;
+ const QTransform restoreTransform = painter->worldTransform();
+ painter->setWorldTransform(*transformPtr);
+ item->d_ptr->graphicsEffect->draw(painter, source);
+ painter->setWorldTransform(restoreTransform);
+ } else {
+ draw(item, painter, viewTransform, transformPtr, exposedRegion, widget, opacity,
+ effectOffset, 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)
+{
+ const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ const bool itemHasChildren = !item->d_ptr->children.isEmpty();
+
int i = 0;
if (itemHasChildren) {
item->d_ptr->ensureSortedChildren();
if (itemClipsChildrenToShape) {
painter->save();
- ENSURE_TRANSFORM_PTR
+ Q_ASSERT(transformPtr);
painter->setWorldTransform(*transformPtr);
painter->setClipPath(item->shape(), Qt::IntersectClip);
}
@@ -4332,15 +4351,15 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
break;
if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
continue;
- drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity);
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset);
}
}
// Draw item
if (drawItem) {
Q_ASSERT(!itemIsFullyTransparent);
- Q_ASSERT(itemHasContents);
- ENSURE_TRANSFORM_PTR
+ Q_ASSERT(!(item->d_ptr->flags & QGraphicsItem::ItemHasNoContents));
+ Q_ASSERT(transformPtr);
item->d_ptr->initStyleOption(&styleOptionTmp, *transformPtr, exposedRegion
? *exposedRegion : QRegion(), exposedRegion == 0);
@@ -4356,21 +4375,11 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
painter->setClipPath(item->shape(), Qt::IntersectClip);
painter->setOpacity(opacity);
- QGraphicsItemEffectSource *source = item->d_ptr->graphicsEffect
- ? static_cast<QGraphicsItemEffectSource *>
- (item->d_ptr->graphicsEffect->d_func()->source)
- : 0;
- if (source)
- source->setPaintInfo(&styleOptionTmp, widget);
-
- if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !source)
+ if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
item->paint(painter, &styleOptionTmp, widget);
else
drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
- if (source)
- source->resetPaintInfo();
-
if (savePainter)
painter->restore();
}
@@ -4383,7 +4392,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
child->d_ptr->dirtySceneTransform = 1;
if (itemIsFullyTransparent && !(child->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity))
continue;
- drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity);
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget, opacity, effectOffset);
}
}
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 16060535a2..813e0003ef 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -306,6 +306,7 @@ private:
friend class QGraphicsSceneIndexPrivate;
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
+ friend class QGraphicsItemEffectSourcePrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers)
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 38f5682726..b60275875a 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -200,7 +200,11 @@ public:
QRegion *exposedRegion, QWidget *widget);
void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform *const,
- QRegion *exposedRegion, QWidget *widget, qreal parentOpacity = qreal(1.0));
+ 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);
+
void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
bool removingItemFromScene = false);