summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/graphicsview/blurpicker/blureffect.cpp19
-rw-r--r--examples/graphicsview/blurpicker/blureffect.h11
-rw-r--r--examples/graphicsview/blurpicker/blurpicker.cpp4
-rw-r--r--examples/graphicsview/lighting/lighting.cpp2
-rw-r--r--examples/graphicsview/lighting/shadoweffect.cpp19
-rw-r--r--examples/graphicsview/lighting/shadoweffect.h11
-rw-r--r--src/gui/graphicsview/qgraphicseffect.cpp234
-rw-r--r--src/gui/graphicsview/qgraphicseffect.h58
-rw-r--r--src/gui/graphicsview/qgraphicseffect_p.h27
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp91
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h2
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h45
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp72
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h5
14 files changed, 297 insertions, 303 deletions
diff --git a/examples/graphicsview/blurpicker/blureffect.cpp b/examples/graphicsview/blurpicker/blureffect.cpp
index 6c2095d..43791c6 100644
--- a/examples/graphicsview/blurpicker/blureffect.cpp
+++ b/examples/graphicsview/blurpicker/blureffect.cpp
@@ -43,28 +43,27 @@
#include <QDebug>
-BlurEffect::BlurEffect()
+BlurEffect::BlurEffect(QGraphicsItem *item)
: QGraphicsBlurEffect()
- , m_baseLine(200)
+ , m_baseLine(200), item(item)
{
}
-void BlurEffect::adjustForItem(const QGraphicsItem *item)
+void BlurEffect::adjustForItem()
{
qreal y = m_baseLine - item->pos().y();
qreal radius = qBound(0.0, y / 32, 16.0);
setBlurRadius(radius);
}
-QRectF BlurEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF BlurEffect::boundingRect() const
{
- adjustForItem(item);
- return QGraphicsBlurEffect::boundingRectFor(item);
+ const_cast<BlurEffect *>(this)->adjustForItem();
+ return QGraphicsBlurEffect::boundingRect();
}
-void BlurEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void BlurEffect::draw(QPainter *painter)
{
- adjustForItem(item);
- QGraphicsBlurEffect::drawItem(item, painter, option, widget);
+ adjustForItem();
+ QGraphicsBlurEffect::draw(painter);
}
diff --git a/examples/graphicsview/blurpicker/blureffect.h b/examples/graphicsview/blurpicker/blureffect.h
index cafd910..2aea8bf 100644
--- a/examples/graphicsview/blurpicker/blureffect.h
+++ b/examples/graphicsview/blurpicker/blureffect.h
@@ -48,21 +48,20 @@
class BlurEffect: public QGraphicsBlurEffect
{
public:
- BlurEffect();
+ BlurEffect(QGraphicsItem *item);
void setBaseLine(qreal y) { m_baseLine = y; }
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+ void draw(QPainter *painter);
private:
- void adjustForItem(const QGraphicsItem *item);
+ void adjustForItem();
private:
qreal m_baseLine;
+ QGraphicsItem *item;
};
#endif // BLUREFFECT_H
diff --git a/examples/graphicsview/blurpicker/blurpicker.cpp b/examples/graphicsview/blurpicker/blurpicker.cpp
index 10ce44f..9904dfa 100644
--- a/examples/graphicsview/blurpicker/blurpicker.cpp
+++ b/examples/graphicsview/blurpicker/blurpicker.cpp
@@ -79,7 +79,7 @@ void BlurPicker::updateIconPositions()
pos -= QPointF(40, 40);
icon->setPos(pos);
baseline = qMax(baseline, ys);
- static_cast<BlurEffect *>(icon->effect())->setBaseLine(baseline);
+ static_cast<BlurEffect *>(icon->graphicsEffect())->setBaseLine(baseline);
}
m_scene.update();
@@ -103,7 +103,7 @@ void BlurPicker::setupScene()
QPixmap pixmap(names[i]);
QGraphicsPixmapItem *icon = m_scene.addPixmap(pixmap);
icon->setZValue(1);
- icon->setGraphicsEffect(new BlurEffect);
+ icon->setGraphicsEffect(new BlurEffect(icon));
m_icons << icon;
}
diff --git a/examples/graphicsview/lighting/lighting.cpp b/examples/graphicsview/lighting/lighting.cpp
index fff2204..63f0a6c 100644
--- a/examples/graphicsview/lighting/lighting.cpp
+++ b/examples/graphicsview/lighting/lighting.cpp
@@ -98,7 +98,7 @@ void Lighting::setupScene()
item->setPen(QPen(Qt::black));
item->setBrush(QBrush(Qt::white));
- item->setGraphicsEffect(new ShadowEffect(m_lightSource));
+ item->setGraphicsEffect(new ShadowEffect(item, m_lightSource));
item->setZValue(1);
item->setPos(i * 80, j * 80);
m_scene.addItem(item);
diff --git a/examples/graphicsview/lighting/shadoweffect.cpp b/examples/graphicsview/lighting/shadoweffect.cpp
index c1d384a..e2dd864 100644
--- a/examples/graphicsview/lighting/shadoweffect.cpp
+++ b/examples/graphicsview/lighting/shadoweffect.cpp
@@ -43,14 +43,14 @@
#include <math.h>
-ShadowEffect::ShadowEffect(QGraphicsItem *source)
+ShadowEffect::ShadowEffect(QGraphicsItem *item, QGraphicsItem *source)
: QGraphicsShadowEffect()
- , m_lightSource(source)
+ , item(item), m_lightSource(source)
{
setBlurRadius(8);
}
-void ShadowEffect::adjustForItem(const QGraphicsItem *item)
+void ShadowEffect::adjustForItem()
{
QPointF delta = item->pos() - m_lightSource->pos();
setShadowOffset(delta.toPoint() / 30);
@@ -61,15 +61,14 @@ void ShadowEffect::adjustForItem(const QGraphicsItem *item)
setOpacity(qBound(0.4, 1 - dd / 200.0, 0.7));
}
-QRectF ShadowEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF ShadowEffect::boundingRect() const
{
- adjustForItem(item);
- return QGraphicsShadowEffect::boundingRectFor(item);
+ const_cast<ShadowEffect *>(this)->adjustForItem();
+ return QGraphicsShadowEffect::boundingRect();
}
-void ShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void ShadowEffect::draw(QPainter *painter)
{
- adjustForItem(item);
- QGraphicsShadowEffect::drawItem(item, painter, option, widget);
+ adjustForItem();
+ QGraphicsShadowEffect::draw(painter);
}
diff --git a/examples/graphicsview/lighting/shadoweffect.h b/examples/graphicsview/lighting/shadoweffect.h
index 09b63e3..d4aa440 100644
--- a/examples/graphicsview/lighting/shadoweffect.h
+++ b/examples/graphicsview/lighting/shadoweffect.h
@@ -48,18 +48,17 @@
class ShadowEffect: public QGraphicsShadowEffect
{
public:
- ShadowEffect(QGraphicsItem *source);
+ ShadowEffect(QGraphicsItem *item, QGraphicsItem *source);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+ void draw(QPainter *painter);
private:
- void adjustForItem(const QGraphicsItem *item);
+ void adjustForItem();
private:
+ QGraphicsItem *item;
QGraphicsItem *m_lightSource;
};
diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp
index c173d1b..8d2c416 100644
--- a/src/gui/graphicsview/qgraphicseffect.cpp
+++ b/src/gui/graphicsview/qgraphicseffect.cpp
@@ -104,83 +104,90 @@
QGraphicsEffect::QGraphicsEffect()
: QObject(*new QGraphicsEffectPrivate, 0)
+{}
+
+/*!
+ \internal
+*/
+QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd)
+ : QObject(dd, 0)
+{}
+
+QGraphicsEffect::~QGraphicsEffect()
{
Q_D(QGraphicsEffect);
- d->parentItem = 0;
+ d->setGraphicsEffectSource(0);
}
-QGraphicsEffect::~QGraphicsEffect()
+QRectF QGraphicsEffect::boundingRect() const
{
+ return sourceBoundingRect();
}
-QRectF QGraphicsEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsEffect::sourceBoundingRect() const
{
- // default is to give the item's bounding rect
- // do NOT call item->effectiveBoundRect() because
- // that function will call this one (infinite loop)
- return item->boundingRect();
+ Q_D(const QGraphicsEffect);
+ if (d->source)
+ return d->source->boundingRect();
+ return QRectF();
}
-/*! \internal
-*/
-QGraphicsEffect::QGraphicsEffect(QGraphicsEffectPrivate &dd)
- : QObject(dd, 0)
+void QGraphicsEffect::drawSource(QPainter *painter)
{
Q_D(QGraphicsEffect);
- d->parentItem = 0;
+ if (d->source)
+ d->source->draw(painter);
}
-// this helper function is only for subclasses of QGraphicsEffect
-// the implementation is trivial, but this allows us to keep
-// QGraphicsScene::drawItem() as a protected function
-// (since QGraphicsEffect is a friend of QGraphicsScene)
-QPixmap* QGraphicsEffect::drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags)
+bool QGraphicsEffect::drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &itemToPixmapTransform)
{
- if (!item->scene())
- return 0;
- return item->scene()->drawItemOnPixmap(painter, item, option, widget, flags);
+ Q_D(QGraphicsEffect);
+ if (d->source)
+ return d->source->drawIntoPixmap(pixmap, itemToPixmapTransform);
+ return false;
}
QGraphicsGrayscaleEffect::QGraphicsGrayscaleEffect()
: QGraphicsEffect(*new QGraphicsGrayscaleEffectPrivate)
-{
-}
+{}
QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect()
-{
-}
+{}
-void QGraphicsGrayscaleEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsGrayscaleEffect::draw(QPainter *painter)
{
Q_D(QGraphicsGrayscaleEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
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, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
+
}
QGraphicsColorizeEffect::QGraphicsColorizeEffect()
: QGraphicsEffect(*new QGraphicsColorizeEffectPrivate)
-{
-}
+{}
QGraphicsColorizeEffect::~QGraphicsColorizeEffect()
-{
-}
+{}
QColor QGraphicsColorizeEffect::color() const
{
@@ -194,25 +201,30 @@ void QGraphicsColorizeEffect::setColor(const QColor &c)
d->filter->setColor(c);
}
-void QGraphicsColorizeEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsColorizeEffect::draw(QPainter *painter)
{
Q_D(QGraphicsColorizeEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
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, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -237,23 +249,28 @@ void QGraphicsPixelizeEffect::setPixelSize(int size)
d->pixelSize = size;
}
-void QGraphicsPixelizeEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsPixelizeEffect::draw(QPainter *painter)
{
Q_D(QGraphicsPixelizeEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap))
return;
// pixelize routine
- QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32);
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32);
if (d->pixelSize > 0) {
int width = img.width();
int height = img.height();
@@ -365,31 +382,42 @@ void QGraphicsBlurEffect::setBlurRadius(int radius)
d->filter->setBlurRadius(radius);
}
-QRectF QGraphicsBlurEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsBlurEffect::boundingRect() const
{
Q_D(const QGraphicsBlurEffect);
- return d->filter->boundingRectFor(item->boundingRect());
+ if (d->source)
+ return d->filter->boundingRectFor(d->source->boundingRect());
+ return QRectF();
}
-void QGraphicsBlurEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsBlurEffect::draw(QPainter *painter)
{
Q_D(QGraphicsBlurEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ // ### 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());
+
+ QPixmap pixmap(effectRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
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, deviceRect.topLeft(), pixmap, pixmap.rect());
painter->setWorldTransform(restoreTransform);
}
@@ -426,13 +454,13 @@ void QGraphicsBloomEffect::setOpacity(qreal alpha)
d->opacity = alpha;
}
-QRectF QGraphicsBloomEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsBloomEffect::boundingRect() const
{
- Q_D(QGraphicsBloomEffect);
+ Q_D(const QGraphicsBloomEffect);
+ if (!d->source)
+ return QRectF();
qreal delta = d->blurRadius * 3;
- QRectF blurRect = item->boundingRect();
- blurRect.adjust(-delta, -delta, delta, delta);
- return blurRect;
+ return d->source->boundingRect().adjusted(-delta, -delta, delta, delta);
}
// Change brightness (positive integer) of each pixel
@@ -466,24 +494,29 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity,
return result;
}
-void QGraphicsBloomEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsBloomEffect::draw(QPainter *painter)
{
Q_D(QGraphicsBloomEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (deviceRect.x() != 0 || deviceRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-deviceRect.x(), -deviceRect.y());
+
+ QPixmap pixmap(deviceRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
// bloom routine
int radius = d->blurRadius;
- QImage img = pixmap->toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
QImage overlay = blurred(img, img.rect(), radius);
overlay = brightened(overlay, 70);
img = composited(img, overlay, d->opacity, QPainter::CompositionMode_Overlay);
@@ -540,31 +573,35 @@ void QGraphicsFrameEffect::setFrameOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsFrameEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsFrameEffect::boundingRect() const
{
- Q_D(QGraphicsFrameEffect);
- QRectF frameRect = item->boundingRect();
- frameRect.adjust(-d->width, -d->width, d->width, d->width);
- return frameRect;
+ Q_D(const QGraphicsFrameEffect);
+ if (!d->source)
+ return QRectF();
+ return d->source->boundingRect().adjusted(-d->width, -d->width, d->width, d->width);
}
-void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsFrameEffect::draw(QPainter *painter)
{
Q_D(QGraphicsFrameEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
+ if (deviceBounds.isEmpty())
return;
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
- 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());
- QRectF frameRect = deviceBounds;
- frameRect.adjust(-d->width, -d->width, d->width, d->width);
+ QPixmap pixmap(frameRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
+ return;
painter->save();
painter->setWorldTransform(QTransform());
@@ -576,7 +613,7 @@ void QGraphicsFrameEffect::drawItem(QGraphicsItem *item, QPainter *painter,
painter->drawRoundedRect(frameRect, 20, 20, Qt::RelativeSize);
painter->restore();
- painter->drawPixmap(frameRect.topLeft(), *pixmap);
+ painter->drawPixmap(frameRect.topLeft(), pixmap);
painter->restore();
}
@@ -626,25 +663,30 @@ void QGraphicsShadowEffect::setOpacity(qreal opacity)
d->alpha = opacity;
}
-QRectF QGraphicsShadowEffect::boundingRectFor(const QGraphicsItem *item)
+QRectF QGraphicsShadowEffect::boundingRect() const
{
- Q_D(QGraphicsShadowEffect);
- QRectF shadowRect = item->boundingRect();
+ 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(item->boundingRect());
+ QRectF totalRect = blurRect.united(srcBrect);
return totalRect;
}
-void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option, QWidget *widget)
+void QGraphicsShadowEffect::draw(QPainter *painter)
{
Q_D(QGraphicsShadowEffect);
+ if (!d->source)
+ return;
// Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(item->boundingRect());
+ QTransform itemToPixmapTransform(painter->worldTransform());
+ QRectF deviceBounds = itemToPixmapTransform.mapRect(d->source->boundingRect());
QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
if (deviceRect.isEmpty())
return;
@@ -654,13 +696,16 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
QRectF blurRect = shadowRect;
qreal delta = d->radius * 3;
blurRect.adjust(-delta, -delta, delta, delta);
- QRectF totalRect = blurRect.united(deviceRect);
+ QRect totalRect = blurRect.united(deviceRect).toRect().adjusted(-1, -1, 1, 1);
- QPixmap *pixmap = QGraphicsEffect::drawItemOnPixmap(painter, item, option, widget, 0);
- if (!pixmap)
+ if (totalRect.x() != 0 || totalRect.y() != 0)
+ itemToPixmapTransform *= QTransform::fromTranslate(-totalRect.x(), -totalRect.y());
+
+ QPixmap pixmap(totalRect.size());
+ if (!d->source->drawIntoPixmap(&pixmap, itemToPixmapTransform))
return;
- QImage img = pixmap->toImage();
+ QImage img = pixmap.toImage();
QImage shadowImage(img.size(), QImage::Format_ARGB32);
shadowImage.fill(qRgba(0, 0, 0, d->alpha * 255));
shadowImage.setAlphaChannel(img.alphaChannel());
@@ -682,10 +727,9 @@ void QGraphicsShadowEffect::drawItem(QGraphicsItem *item, QPainter *painter,
qreal itemx = qMin(blurRect.x(), deviceBounds.x());
qreal itemy = qMin(blurRect.y(), deviceBounds.y());
- painter->drawPixmap(itemx, itemy, *pixmap);
+ painter->drawPixmap(itemx, itemy, pixmap);
painter->setWorldTransform(restoreTransform);
}
-
#endif
diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h
index 9f6e342..74a8430 100644
--- a/src/gui/graphicsview/qgraphicseffect.h
+++ b/src/gui/graphicsview/qgraphicseffect.h
@@ -46,6 +46,7 @@
#include <QtCore/qglobal.h>
#include <QtCore/qpoint.h>
#include <QtCore/qvariant.h>
+#include <QtGui/qtransform.h>
#include <QtGui/qcolor.h>
QT_FORWARD_DECLARE_CLASS(QGraphicsItem);
@@ -71,18 +72,17 @@ public:
QGraphicsEffect();
virtual ~QGraphicsEffect();
- virtual QRectF boundingRectFor(const QGraphicsItem *item);
-
- virtual void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0) = 0;
+ virtual QRectF boundingRect() const;
protected:
QGraphicsEffect(QGraphicsEffectPrivate &d);
- QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags);
+ virtual void draw(QPainter *painter) = 0;
+ void drawSource(QPainter *painter);
+ bool drawSourceIntoPixmap(QPixmap *pixmap, const QTransform &xform = QTransform());
+ QRectF sourceBoundingRect() const;
private:
+ friend class QGraphicsScenePrivate;
friend class QGraphicsItem;
Q_DECLARE_PRIVATE(QGraphicsEffect)
Q_DISABLE_COPY(QGraphicsEffect)
@@ -96,9 +96,8 @@ public:
QGraphicsGrayscaleEffect();
~QGraphicsGrayscaleEffect();
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect)
@@ -115,9 +114,8 @@ public:
QColor color() const;
void setColor(const QColor &c);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsColorizeEffect)
@@ -134,9 +132,8 @@ public:
int pixelSize() const;
void setPixelSize(int pixelSize);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsPixelizeEffect)
@@ -153,11 +150,10 @@ public:
int blurRadius() const;
void setBlurRadius(int blurRadius);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsBlurEffect)
@@ -177,11 +173,10 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsBloomEffect)
@@ -204,11 +199,11 @@ public:
qreal frameOpacity() const;
void setFrameOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
+
+protected:
+ void draw(QPainter *painter);
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
private:
Q_DECLARE_PRIVATE(QGraphicsFrameEffect)
Q_DISABLE_COPY(QGraphicsFrameEffect)
@@ -232,11 +227,10 @@ public:
qreal opacity() const;
void setOpacity(qreal opacity);
- QRectF boundingRectFor(const QGraphicsItem *item);
+ QRectF boundingRect() const;
- void drawItem(QGraphicsItem *item, QPainter *painter,
- const QStyleOptionGraphicsItem *option = 0,
- QWidget *widget = 0);
+protected:
+ void draw(QPainter *painter);
private:
Q_DECLARE_PRIVATE(QGraphicsShadowEffect)
diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h
index 999e013..9204789 100644
--- a/src/gui/graphicsview/qgraphicseffect_p.h
+++ b/src/gui/graphicsview/qgraphicseffect_p.h
@@ -61,12 +61,31 @@
QT_BEGIN_NAMESPACE
+class QGraphicsEffectSource
+{
+public:
+ QGraphicsEffectSource() {}
+ virtual ~QGraphicsEffectSource() {}
+ virtual void detach() = 0;
+ virtual QRectF boundingRect() = 0;
+ virtual void draw(QPainter *p) = 0;
+ virtual bool drawIntoPixmap(QPixmap *, const QTransform & = QTransform()) = 0;
+};
+
class QGraphicsEffectPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsEffect)
public:
- QGraphicsEffectPrivate(): parentItem(0) {}
- QGraphicsItem *parentItem;
+ QGraphicsEffectPrivate() : source(0) {}
+ QGraphicsEffectSource *source;
+ inline void setGraphicsEffectSource(QGraphicsEffectSource *newSource)
+ {
+ if (source) {
+ source->detach();
+ delete source;
+ }
+ source = newSource;
+ }
};
class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate
@@ -106,8 +125,10 @@ class QGraphicsBlurEffectPrivate : public QGraphicsEffectPrivate
{
Q_DECLARE_PUBLIC(QGraphicsBlurEffect)
public:
- QGraphicsBlurEffectPrivate() : blurRadius(4) {}
+ QGraphicsBlurEffectPrivate() : filter(new QPixmapBlurFilter), blurRadius(4) {}
+ ~QGraphicsBlurEffectPrivate() { delete filter; }
+ QPixmapBlurFilter *filter;
int blurRadius;
};
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 3a350e0..1d271c9 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -552,7 +552,6 @@
#ifndef QT_NO_GRAPHICSVIEW
-#include "qgraphicseffect_p.h"
#include "qgraphicsscene.h"
#include "qgraphicsscene_p.h"
#include "qgraphicssceneevent.h"
@@ -1180,8 +1179,7 @@ QGraphicsItem::~QGraphicsItem()
else
d_ptr->setParentItemHelper(0);
- QGraphicsEffect *e = graphicsEffect();
- delete e;
+ delete d_ptr->graphicsEffect;
delete d_ptr->transformData;
delete d_ptr;
@@ -2198,11 +2196,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
*/
QGraphicsEffect *QGraphicsItem::graphicsEffect() const
{
- QGraphicsEffect *fx = 0;
- if (d_ptr->hasEffect)
- fx = d_ptr->extra(QGraphicsItemPrivate::ExtraEffect).value<QGraphicsEffect*>();
-
- return fx;
+ return d_ptr->graphicsEffect;
}
/*!
@@ -2220,30 +2214,29 @@ QGraphicsEffect *QGraphicsItem::graphicsEffect() const
*/
void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
{
- if (effect) {
- if (QGraphicsEffect *currentEffect = this->graphicsEffect()) {
- if (currentEffect != effect) {
- qWarning("QGraphicsItem::setEffect: Attempting to set QGraphicsEffect "
- "%p on %p, which already has an effect", effect, this);
- }
- return;
- }
+ if (d_ptr->graphicsEffect == effect)
+ return;
- if (effect->d_func()->parentItem)
- effect->d_func()->parentItem->setGraphicsEffect(0);
- effect->d_func()->parentItem = this;
- d_ptr->hasEffect = true;
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffect, QVariant::fromValue(effect));
+ if (d_ptr->graphicsEffect && effect) {
+ qWarning("QGraphicsItem::setGraphicsEffect: Attempting to set QGraphicsEffect "
+ "%p on %p, which already has an effect installed", effect, this);
+ return;
+ }
+
+ if (!effect) {
+ // Unset current effect.
+ QGraphicsEffectPrivate *oldEffectPrivate = d_ptr->graphicsEffect->d_func();
+ d_ptr->graphicsEffect = 0;
+ if (oldEffectPrivate)
+ oldEffectPrivate->setGraphicsEffectSource(0); // deletes the current source.
} else {
- d_ptr->hasEffect = false;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffect);
- void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value<void*>();
- QPixmap *pixmap = reinterpret_cast<QPixmap*>(ptr);
- delete pixmap;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraEffectPixmap);
+ // Set new effect.
+ effect->d_func()->setGraphicsEffectSource(new QGraphicsItemEffectSource(this));
+ d_ptr->graphicsEffect = effect;
}
- update();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -2257,10 +2250,8 @@ void QGraphicsItem::setGraphicsEffect(QGraphicsEffect *effect)
*/
QRectF QGraphicsItem::effectiveBoundingRect() const
{
- QGraphicsEffect *fx = graphicsEffect();
- if (fx)
- return fx->boundingRectFor(this);
-
+ if (d_ptr->graphicsEffect)
+ return d_ptr->graphicsEffect->boundingRect();
return boundingRect();
}
@@ -2294,42 +2285,6 @@ QRectF QGraphicsItem::sceneEffectiveBoundingRect() const
}
/*!
- \internal
-
- Used by QGraphicsScene.
-*/
-QPixmap *QGraphicsItem::effectPixmap()
-{
- if (!d_ptr->hasEffect)
- return 0;
-
- // the exact size of the pixmap is not a big deal
- // as long as it contains the effective bounding rect
- // TODO: use smart resizing etc
- // TODO: store per device and do everything in device coordinate?
- // TODO: use layer
- QRect rect = effectiveBoundingRect().toAlignedRect();
-
- void *ptr = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectPixmap).value<void*>();
- QPixmap *pixmap = reinterpret_cast<QPixmap*>(ptr);
- bool avail = true;
- if (!pixmap)
- avail = false;
- if (avail && pixmap->size() != rect.size())
- avail = false;
-
- if (!avail) {
- delete pixmap;
- pixmap = new QPixmap(rect.size());
- pixmap->fill(Qt::transparent);
- ptr = reinterpret_cast<void*>(pixmap);
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraEffectPixmap, QVariant::fromValue(ptr));
- }
-
- return pixmap;
-}
-
-/*!
Returns true if this item can accept drag and drop events; otherwise,
returns false. By default, items do not accept drag and drop events; items
are transparent to drag and drop.
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 0beb07c..0c0b341 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -440,8 +440,6 @@ protected:
void removeFromIndex();
void prepareGeometryChange();
- QPixmap *effectPixmap();
-
private:
Q_DISABLE_COPY(QGraphicsItem)
Q_DECLARE_PRIVATE(QGraphicsItem)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 09f296a..dc875f7 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -57,6 +57,7 @@
#include "qset.h"
#include "qpixmapcache.h"
#include "qgraphicsview_p.h"
+#include "qgraphicseffect_p.h"
#include <QtCore/qpoint.h>
@@ -103,8 +104,6 @@ public:
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
ExtraBoundingRegionGranularity,
- ExtraEffect,
- ExtraEffectPixmap,
ExtraGestures
};
@@ -122,6 +121,7 @@ public:
scene(0),
parent(0),
transformData(0),
+ graphicsEffect(0),
index(-1),
siblingIndex(-1),
depth(0),
@@ -151,7 +151,6 @@ public:
allChildrenDirty(0),
fullUpdatePending(0),
flags(0),
- hasEffect(0),
dirtyChildrenBoundingRect(1),
paintedViewBoundingRectsNeedRepaint(0),
dirtySceneTransform(1),
@@ -409,6 +408,7 @@ public:
QList<QGraphicsItem *> children;
struct TransformData;
TransformData *transformData;
+ QGraphicsEffect *graphicsEffect;
QTransform sceneTransform;
int index;
int siblingIndex;
@@ -443,7 +443,6 @@ public:
// New 32 bits
quint32 fullUpdatePending : 1;
quint32 flags : 12;
- quint32 hasEffect : 1;
quint32 dirtyChildrenBoundingRect : 1;
quint32 paintedViewBoundingRectsNeedRepaint : 1;
quint32 dirtySceneTransform : 1;
@@ -511,6 +510,44 @@ struct QGraphicsItemPrivate::TransformData {
}
};
+class QGraphicsItemEffectSource : public QGraphicsEffectSource
+{
+public:
+ QGraphicsItemEffectSource(QGraphicsItem *i)
+ : QGraphicsEffectSource(), item(i), option(0), widget(0)
+ {}
+
+ inline void detach()
+ { item->setGraphicsEffect(0); }
+
+ inline QRectF boundingRect()
+ { return item->boundingRect(); }
+
+ inline void draw(QPainter *painter)
+ { item->paint(painter, option, widget); }
+
+ 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; }
+
+ void resetPaintInfo()
+ { option = 0; widget = 0; }
+
+private:
+ QGraphicsItem *item;
+ const QStyleOptionGraphicsItem *option;
+ QWidget *widget;
+};
+
/*!
\internal
*/
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index c56f34c..f4fd4ce 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -3928,8 +3928,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
#endif
// Render using effect, works now only for no cache mode
- if (noCache && itemd->hasEffect && item->graphicsEffect()) {
- item->graphicsEffect()->drawItem(item, painter, option, widget);
+ if (noCache && itemd->graphicsEffect) {
+ itemd->graphicsEffect->draw(painter);
return;
}
@@ -4228,62 +4228,6 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
-// FIXME: merge this with drawItems (needs refactoring)
-QPixmap* QGraphicsScene::drawItemOnPixmap(QPainter *painter,
- QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option,
- QWidget *widget,
- int flags)
-{
- // TODO: use for choosing item or device coordinate
- // FIXME: how about source, dest, and exposed rects?
- Q_UNUSED(flags);
-
- // Item's (local) bounding rect, including the effect
- QRectF brect = item->effectiveBoundingRect();
- QRectF adjustedBrect(brect);
- _q_adjustRect(&adjustedBrect);
- if (adjustedBrect.isEmpty())
- return 0;
-
- // Find the item's bounds in device coordinates.
- QRectF deviceBounds = painter->worldTransform().mapRect(brect);
- QRect deviceRect = deviceBounds.toRect().adjusted(-1, -1, 1, 1);
- if (deviceRect.isEmpty())
- return 0;
-
- // If widget, check if it intersects or not
- QRect viewRect = widget ? widget->rect() : QRect();
- if (widget && !viewRect.intersects(deviceRect))
- return 0;
-
- // Create offscreen pixmap
- // TODO: use the pixmap from the layer
- QPixmap *targetPixmap = item->effectPixmap();
- if (!targetPixmap)
- targetPixmap = new QPixmap(deviceRect.size());
-
- // FIXME: this is brute force
- QRegion pixmapExposed;
- pixmapExposed += targetPixmap->rect();
-
- // Construct an item-to-pixmap transform.
- QPointF p = deviceRect.topLeft();
- QTransform itemToPixmap = painter->worldTransform();
- if (!p.isNull())
- itemToPixmap *= QTransform::fromTranslate(-p.x(), -p.y());
-
- // Calculate the style option's exposedRect.
- QStyleOptionGraphicsItem fxOption = *option;
- fxOption.exposedRect = brect.adjusted(-1, -1, 1, 1);
-
- // Render
- _q_paintIntoCache(targetPixmap, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &fxOption, false);
-
- return targetPixmap;
-}
-
void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform,
QRegion *exposedRegion, QWidget *widget)
{
@@ -4412,11 +4356,21 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
painter->setClipPath(item->shape(), Qt::IntersectClip);
painter->setOpacity(opacity);
- if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget && !item->d_ptr->hasEffect)
+ 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)
item->paint(painter, &styleOptionTmp, widget);
else
drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+ if (source)
+ source->resetPaintInfo();
+
if (savePainter)
painter->restore();
}
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 68bd3e1..1606053 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -281,11 +281,6 @@ protected:
const QStyleOptionGraphicsItem options[],
QWidget *widget = 0);
- QPixmap* drawItemOnPixmap(QPainter *painter, QGraphicsItem *item,
- const QStyleOptionGraphicsItem *option, QWidget *widget, int flags);
-
-
-
protected Q_SLOTS:
bool focusNextPrevChild(bool next);