summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/effects/qgraphicseffect.cpp22
-rw-r--r--src/gui/effects/qgraphicseffect.h10
-rw-r--r--src/gui/effects/qgraphicseffect_p.h3
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp31
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h9
-rw-r--r--src/gui/kernel/qwidget.cpp18
-rw-r--r--src/gui/kernel/qwidget_p.h3
-rw-r--r--tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp99
8 files changed, 177 insertions, 18 deletions
diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp
index f20480b..647fd1b 100644
--- a/src/gui/effects/qgraphicseffect.cpp
+++ b/src/gui/effects/qgraphicseffect.cpp
@@ -97,6 +97,7 @@
*/
#include "qgraphicseffect_p.h"
+#include <QtGui/qgraphicsitem.h>
#include <QtGui/qimage.h>
#include <QtGui/qpainter.h>
@@ -248,16 +249,22 @@ bool QGraphicsEffectSource::isPixmap() const
\sa QGraphicsEffect::draw(), boundingRect(), deviceRect()
*/
-QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset, PixmapPadMode mode) const
{
Q_D(const QGraphicsEffectSource);
+ // Shortcut, no cache for childless pixmap items...
+ const QGraphicsItem *item = graphicsItem();
+ if (system == Qt::LogicalCoordinates && mode == NoExpandPadMode && item && isPixmap()) {
+ return ((QGraphicsPixmapItem *) item)->pixmap();
+ }
+
QPixmap pm;
if (d->m_cachedSystem == system)
QPixmapCache::find(d->m_cacheKey, &pm);
if (pm.isNull()) {
- pm = d->pixmap(system, &d->m_cachedOffset);
+ pm = d->pixmap(system, &d->m_cachedOffset, mode);
d->m_cachedSystem = system;
d->invalidateCache();
@@ -565,7 +572,8 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou
QPoint offset;
if (source->isPixmap()) {
// No point in drawing in device coordinates (pixmap will be scaled anyways).
- const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset,
+ QGraphicsEffectSource::NoExpandPadMode);
d->filter->draw(painter, offset, pixmap);
return;
}
@@ -776,6 +784,8 @@ void QGraphicsDropShadowEffect::setOffset(const QPointF &offset)
By default, the horizontal shadow offset is 8 pixels.
+
+
\sa yOffset(), offset()
*/
@@ -1029,7 +1039,8 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour
if (source->isPixmap()) {
// No point in drawing in device coordinates (pixmap will be scaled anyways).
if (!d->hasOpacityMask) {
- const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset);
+ const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset,
+ QGraphicsEffectSource::NoExpandPadMode);
painter->drawPixmap(offset, pixmap);
} else {
QRect srcBrect = source->boundingRect().toAlignedRect();
@@ -1050,7 +1061,8 @@ void QGraphicsOpacityEffect::draw(QPainter *painter, QGraphicsEffectSource *sour
} else {
// Draw pixmap in device coordinates to avoid pixmap scaling;
if (!d->hasOpacityMask) {
- const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset);
+ const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset,
+ QGraphicsEffectSource::NoExpandPadMode);
painter->setWorldTransform(QTransform());
painter->drawPixmap(offset, pixmap);
} else {
diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h
index 019e808..abf03b3 100644
--- a/src/gui/effects/qgraphicseffect.h
+++ b/src/gui/effects/qgraphicseffect.h
@@ -64,6 +64,12 @@ class Q_GUI_EXPORT QGraphicsEffectSource : public QObject
{
Q_OBJECT
public:
+ enum PixmapPadMode {
+ NoExpandPadMode,
+ ExpandToTransparentBorderPadMode,
+ ExpandToEffectRectPadMode
+ };
+
~QGraphicsEffectSource();
const QGraphicsItem *graphicsItem() const;
const QWidget *widget() const;
@@ -75,7 +81,9 @@ public:
QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const;
QRect deviceRect() const;
- QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const;
+ QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates,
+ QPoint *offset = 0,
+ PixmapPadMode mode = ExpandToEffectRectPadMode) const;
protected:
QGraphicsEffectSource(QGraphicsEffectSourcePrivate &dd, QObject *parent = 0);
diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h
index 24d8696..dff84a1 100644
--- a/src/gui/effects/qgraphicseffect_p.h
+++ b/src/gui/effects/qgraphicseffect_p.h
@@ -77,7 +77,8 @@ public:
virtual void draw(QPainter *p) = 0;
virtual void update() = 0;
virtual bool isPixmap() const = 0;
- virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0;
+ virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0,
+ QGraphicsEffectSource::PixmapPadMode mode = QGraphicsEffectSource::ExpandToTransparentBorderPadMode) const = 0;
virtual void effectBoundingRectChanged() = 0;
void invalidateCache() const { QPixmapCache::remove(m_cacheKey); }
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index f892bb4..97357a7 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -1657,7 +1657,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->scene->d_func()->index->itemChange(this, ItemFlagsChange, quint32(flags));
// Flags that alter the geometry of the item (or its children).
- const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
+ const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations | ItemIsSelectable);
bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
if (fullUpdate)
d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
@@ -9138,10 +9138,14 @@ void QGraphicsPixmapItem::setOffset(const QPointF &offset)
QRectF QGraphicsPixmapItem::boundingRect() const
{
Q_D(const QGraphicsPixmapItem);
- qreal pw = 1.0;
if (d->pixmap.isNull())
return QRectF();
- return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
+ if (d->flags & ItemIsSelectable) {
+ qreal pw = 1.0;
+ return QRectF(d->offset, d->pixmap.size()).adjusted(-pw/2, -pw/2, pw/2, pw/2);
+ } else {
+ return QRectF(d->offset, d->pixmap.size());
+ }
}
/*!
@@ -10660,7 +10664,8 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
}
-QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffectSource::PixmapPadMode mode) const
{
const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
if (!info && deviceCoordinates) {
@@ -10674,7 +10679,16 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
QGraphicsScenePrivate *scened = item->d_ptr->scene->d_func();
const QRectF sourceRect = boundingRect(system);
- QRect effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ QRect effectRect;
+
+ if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) {
+ effectRect = item->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+ } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) {
+ effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
+ } else {
+ effectRect = sourceRect.toAlignedRect();
+ }
+
if (offset)
*offset = effectRect.topLeft();
@@ -10702,10 +10716,15 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
effectRect.setBottom(deviceHeight -1);
}
-
if (effectRect.isEmpty())
return QPixmap();
+ if (system == Qt::LogicalCoordinates
+ && effectRect.size() == sourceRect.size()
+ && isPixmap()) {
+ return static_cast<QGraphicsPixmapItem *>(item)->pixmap();
+ }
+
QPixmap pixmap(effectRect.size());
pixmap.fill(Qt::transparent);
QPainter pixmapPainter(&pixmap);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 7c3c4f0..183e95b 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -61,6 +61,7 @@
#include <private/qgraphicstransform_p.h>
#include <private/qgraphicseffect_p.h>
+#include <qgraphicseffect.h>
#include <QtCore/qpoint.h>
@@ -603,7 +604,9 @@ public:
inline bool isPixmap() const
{
- return (item->type() == QGraphicsPixmapItem::Type);
+ return item->type() == QGraphicsPixmapItem::Type
+ && !(item->flags() & QGraphicsItem::ItemIsSelectable)
+ && item->d_ptr->children.size() == 0;
//|| (item->d_ptr->isObject && qobject_cast<QFxImage *>(q_func()));
}
@@ -621,7 +624,9 @@ public:
QRectF boundingRect(Qt::CoordinateSystem system) const;
void draw(QPainter *);
- QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const;
+ QPixmap pixmap(Qt::CoordinateSystem system,
+ QPoint *offset,
+ QGraphicsEffectSource::PixmapPadMode mode) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 5fa9a92..27e73e0 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -5437,7 +5437,8 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter)
context->sharedPainter, context->backingStore);
}
-QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset) const
+QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffectSource::PixmapPadMode mode) const
{
const bool deviceCoordinates = (system == Qt::DeviceCoordinates);
if (!context && deviceCoordinates) {
@@ -5455,7 +5456,20 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *
pixmapOffset = painterTransform.map(pixmapOffset);
}
- QRect effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+
+ QRect effectRect;
+
+ if (mode == QGraphicsEffectSource::ExpandToEffectRectPadMode) {
+ effectRect = m_widget->graphicsEffect()->boundingRectFor(sourceRect).toAlignedRect();
+
+ } else if (mode == QGraphicsEffectSource::ExpandToTransparentBorderPadMode) {
+ effectRect = sourceRect.adjusted(-1, -1, 1, 1).toAlignedRect();
+
+ } else {
+ effectRect = sourceRect.toAlignedRect();
+
+ }
+
if (offset)
*offset = effectRect.topLeft();
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 159a3f2..616a972 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -819,7 +819,8 @@ public:
QRectF boundingRect(Qt::CoordinateSystem system) const;
void draw(QPainter *p);
- QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset) const;
+ QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset,
+ QGraphicsEffectSource::PixmapPadMode mode) const;
QWidget *m_widget;
QWidgetPaintContext *context;
diff --git a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
index 855950b..0635989 100644
--- a/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
+++ b/tests/auto/qgraphicseffectsource/tst_qgraphicseffectsource.cpp
@@ -166,6 +166,9 @@ private slots:
void deviceRect();
void pixmap();
+ void pixmapPadding_data();
+ void pixmapPadding();
+
private:
QGraphicsView *view;
QGraphicsScene *scene;
@@ -318,6 +321,102 @@ void tst_QGraphicsEffectSource::pixmap()
QCOMPARE(pixmap1, pixmap2);
}
+class PaddingEffect : public QGraphicsEffect
+{
+public:
+ PaddingEffect(QObject *parent) : QGraphicsEffect(parent)
+ {
+ }
+
+ QRectF boundingRectFor(const QRectF &src) const {
+ return src.adjusted(-10, -10, 10, 10);
+ }
+
+ void draw(QPainter *p, QGraphicsEffectSource *source) {
+ pix = source->pixmap(coordinateMode, &offset, padMode);
+ }
+
+ QPixmap pix;
+ QPoint offset;
+ QGraphicsEffectSource::PixmapPadMode padMode;
+ Qt::CoordinateSystem coordinateMode;
+};
+
+void tst_QGraphicsEffectSource::pixmapPadding_data()
+{
+ QTest::addColumn<int>("coordinateMode");
+ QTest::addColumn<int>("padMode");
+ QTest::addColumn<QSize>("size");
+ QTest::addColumn<QPoint>("offset");
+ QTest::addColumn<uint>("ulPixel");
+
+ QTest::newRow("log,nopad") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffectSource::NoPadMode)
+ << QSize(10, 10) << QPoint(0, 0)
+ << 0xffff0000u;
+
+ QTest::newRow("log,transparent") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffectSource::ExpandToTransparentBorderPadMode)
+ << QSize(12, 12) << QPoint(-1, -1)
+ << 0x00000000u;
+
+ QTest::newRow("log,effectrect") << int(Qt::LogicalCoordinates)
+ << int(QGraphicsEffectSource::ExpandToEffectRectPadMode)
+ << QSize(30, 30) << QPoint(-10, -10)
+ << 0x00000000u;
+
+ QTest::newRow("dev,nopad") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffectSource::NoPadMode)
+ << QSize(20, 20) << QPoint(40, 40)
+ << 0xffff0000u;
+
+ QTest::newRow("dev,transparent") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffectSource::ExpandToTransparentBorderPadMode)
+ << QSize(22, 22) << QPoint(39, 39)
+ << 0x00000000u;
+
+ QTest::newRow("dev,effectrect") << int(Qt::DeviceCoordinates)
+ << int(QGraphicsEffectSource::ExpandToEffectRectPadMode)
+ << QSize(40, 40) << QPoint(30, 30)
+ << 0x00000000u;
+
+}
+
+void tst_QGraphicsEffectSource::pixmapPadding()
+{
+ QPixmap dummyTarget(100, 100);
+ QPainter dummyPainter(&dummyTarget);
+ dummyPainter.translate(40, 40);
+ dummyPainter.scale(2, 2);
+
+ QPixmap pm(10, 10);
+ pm.fill(Qt::red);
+
+ QGraphicsScene *scene = new QGraphicsScene();
+ PaddingEffect *effect = new PaddingEffect(scene);
+ QGraphicsPixmapItem *pmItem = new QGraphicsPixmapItem(pm);
+ scene->addItem(pmItem);
+ pmItem->setGraphicsEffect(effect);
+
+ QFETCH(int, coordinateMode);
+ QFETCH(int, padMode);
+ QFETCH(QPoint, offset);
+ QFETCH(QSize, size);
+ QFETCH(uint, ulPixel);
+
+ effect->padMode = (QGraphicsEffectSource::PixmapPadMode) padMode;
+ effect->coordinateMode = (Qt::CoordinateSystem) coordinateMode;
+
+ scene->render(&dummyPainter, scene->itemsBoundingRect(), scene->itemsBoundingRect());
+
+ QCOMPARE(effect->pix.size(), size);
+ QCOMPARE(effect->offset, offset);
+ QCOMPARE(effect->pix.toImage().pixel(0, 0), ulPixel);
+
+ // ### Fix corruption in scene destruction, then enable...
+ // delete scene;
+}
+
QTEST_MAIN(tst_QGraphicsEffectSource)
#include "tst_qgraphicseffectsource.moc"