diff options
author | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-07-29 05:30:28 (GMT) |
---|---|---|
committer | Bjørn Erik Nilsen <bjorn.nilsen@nokia.com> | 2009-07-29 06:48:50 (GMT) |
commit | a23977d78827ecf464f8f0aef96f7a9cb2abacd4 (patch) | |
tree | e28a8647e35df349b85d256bda12f65909997347 /src/gui | |
parent | a79b31aba0405b0a24e210a2479d4b1df729c608 (diff) | |
download | Qt-a23977d78827ecf464f8f0aef96f7a9cb2abacd4.zip Qt-a23977d78827ecf464f8f0aef96f7a9cb2abacd4.tar.gz Qt-a23977d78827ecf464f8f0aef96f7a9cb2abacd4.tar.bz2 |
QGraphicsEffect optimizations for pixmap based items.
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/graphicsview/qgraphicseffect.cpp | 116 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicseffect.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicseffect_p.h | 1 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsitem_p.h | 6 |
4 files changed, 93 insertions, 31 deletions
diff --git a/src/gui/graphicsview/qgraphicseffect.cpp b/src/gui/graphicsview/qgraphicseffect.cpp index f3f7f22..d98ea3c 100644 --- a/src/gui/graphicsview/qgraphicseffect.cpp +++ b/src/gui/graphicsview/qgraphicseffect.cpp @@ -124,6 +124,9 @@ void QGraphicsEffectSource::draw(QPainter *painter) void QGraphicsEffectSource::update() { d_func()->update(); } +bool QGraphicsEffectSource::isPixmap() const +{ return d_func()->isPixmap(); } + QPixmap QGraphicsEffectSource::pixmap(Qt::CoordinateSystem system, QPoint *offset) const { return d_func()->pixmap(system, offset); } @@ -145,7 +148,6 @@ QGraphicsEffect::~QGraphicsEffect() QRectF QGraphicsEffect::boundingRect() const { Q_D(const QGraphicsEffect); - // return d->boundingRect; if (d->source) return boundingRectFor(d->source->boundingRect()); return QRectF(); @@ -214,9 +216,15 @@ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *so { Q_D(QGraphicsGrayscaleEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // Draw pixmap in device coordinates to avoid pixmap scaling; + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap, pixmap.rect()); @@ -247,9 +255,15 @@ void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *sou { Q_D(QGraphicsColorizeEffect); QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // Draw pixmap in deviceCoordinates to avoid pixmap scaling. + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap, pixmap.rect()); @@ -277,36 +291,54 @@ void QGraphicsPixelizeEffect::setPixelSize(int size) d->pixelSize = size; } +static inline void pixelize(QImage *image, int pixelSize) +{ + Q_ASSERT(pixelSize > 0); + Q_ASSERT(image); + int width = image->width(); + int height = image->height(); + for (int y = 0; y < height; y += pixelSize) { + int ys = qMin(height - 1, y + pixelSize / 2); + QRgb *sbuf = reinterpret_cast<QRgb*>(image->scanLine(ys)); + for (int x = 0; x < width; x += pixelSize) { + int xs = qMin(width - 1, x + pixelSize / 2); + QRgb color = sbuf[xs]; + for (int yi = 0; yi < qMin(pixelSize, height - y); ++yi) { + QRgb *buf = reinterpret_cast<QRgb*>(image->scanLine(y + yi)); + for (int xi = 0; xi < qMin(pixelSize, width - x); ++xi) + buf[x + xi] = color; + } + } + } +} + void QGraphicsPixelizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsPixelizeEffect); + if (d->pixelSize <= 0) { + source->draw(painter); + return; + } + QPoint offset; + if (source->isPixmap()) { + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + pixelize(&image, d->pixelSize); + painter->drawImage(offset, image); + return; + } + + // Draw pixmap in device coordinates to avoid pixmap scaling. const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // pixelize routine - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - if (d->pixelSize > 0) { - int width = img.width(); - int height = img.height(); - for (int y = 0; y < height; y += d->pixelSize) { - int ys = qMin(height - 1, y + d->pixelSize / 2); - QRgb *sbuf = reinterpret_cast<QRgb*>(img.scanLine(ys)); - for (int x = 0; x < width; x += d->pixelSize) { - int xs = qMin(width - 1, x + d->pixelSize / 2); - QRgb color = sbuf[xs]; - for (int yi = 0; yi < qMin(d->pixelSize, height - y); ++yi) { - QRgb *buf = reinterpret_cast<QRgb*>(img.scanLine(y + yi)); - for (int xi = 0; xi < qMin(d->pixelSize, width - x); ++xi) - buf[x + xi] = color; - } - } - } - } + QImage image = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); + pixelize(&image, d->pixelSize); - // Draw using an untransformed painter. QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); - painter->drawImage(offset, img); + painter->drawImage(offset, image); painter->setWorldTransform(restoreTransform); } @@ -403,16 +435,20 @@ QRectF QGraphicsBlurEffect::boundingRectFor(const QRectF &rect) const return d->filter->boundingRectFor(rect); } -// return d->filter->boundingRectFor(rect); -//} - void QGraphicsBlurEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBlurEffect); + QPoint offset; - const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + d->filter->draw(painter, offset, pixmap, pixmap.rect()); + return; + } - // Draw the pixmap with the filter using an untransformed painter. + // Draw pixmap in device coordinates to avoid pixmap scaling. + const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); QTransform restoreTransform = painter->worldTransform(); painter->setWorldTransform(QTransform()); d->filter->draw(painter, offset, pixmap, pixmap.rect()); @@ -494,11 +530,29 @@ static QImage composited(const QImage& img1, const QImage& img2, qreal opacity, void QGraphicsBloomEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsBloomEffect); + QPoint offset; + const int radius = d->blurRadius; + const int delta = radius * 3; + + if (source->isPixmap()) { + // No point in drawing in device coordinates (pixmap will be scaled anyways). + const QPixmap pixmap = source->pixmap(Qt::LogicalCoordinates, &offset); + + // bloom routine + 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); + + painter->drawImage(offset - QPoint(delta, delta), img); + return; + } + + // Draw pixmap in device coordinates to avoid pixmap scaling. const QPixmap pixmap = source->pixmap(Qt::DeviceCoordinates, &offset); // bloom routine - const int radius = d->blurRadius; QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied); QImage overlay = blurred(img, img.rect(), radius); overlay = brightened(overlay, 70); diff --git a/src/gui/graphicsview/qgraphicseffect.h b/src/gui/graphicsview/qgraphicseffect.h index 1db8b6e..9714d3e 100644 --- a/src/gui/graphicsview/qgraphicseffect.h +++ b/src/gui/graphicsview/qgraphicseffect.h @@ -75,6 +75,7 @@ public: const QStyleOption *styleOption() const; void draw(QPainter *painter); void update(); + bool isPixmap() const; QRectF boundingRect(Qt::CoordinateSystem coordinateSystem = Qt::LogicalCoordinates) const; QPixmap pixmap(Qt::CoordinateSystem system = Qt::LogicalCoordinates, QPoint *offset = 0) const; diff --git a/src/gui/graphicsview/qgraphicseffect_p.h b/src/gui/graphicsview/qgraphicseffect_p.h index 7ebfe07..6a0bb3f 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 void update() = 0; + virtual bool isPixmap() const = 0; virtual QPixmap pixmap(Qt::CoordinateSystem system, QPoint *offset = 0) const = 0; friend class QGraphicsScenePrivate; friend class QGraphicsItem; diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 8a2dae9..ff1ca09 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -546,6 +546,12 @@ public: inline void update() { item->update(); } + inline bool isPixmap() const + { + return (item->type() == QGraphicsPixmapItem::Type); + //|| (item->d_ptr->isObject && qobject_cast<QFxImage *>(q_func())); + } + inline const QStyleOption *styleOption() const { return info ? info->option : 0; } |