Add CachePaintMode, as a temporary local back-port of
QGraphicsItem::CacheMode, which will appear in 4.4. I've chosen names that aren't really good, but they're not misleading, and they don't clash with the API in 4.4. My first KDE submit :-DDD. svn path=/trunk/KDE/kdebase/workspace/libs/plasma/; revision=710738
This commit is contained in:
parent
b42db6a2ea
commit
55e02ca70a
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include <QtCore/QList>
|
#include <QtCore/QList>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QPixmapCache>
|
||||||
|
#include <QStyleOptionGraphicsItem>
|
||||||
|
|
||||||
#include <KDebug>
|
#include <KDebug>
|
||||||
|
|
||||||
@ -43,6 +45,7 @@ class Widget::Private
|
|||||||
std::numeric_limits<qreal>::infinity())
|
std::numeric_limits<qreal>::infinity())
|
||||||
, parent(0)
|
, parent(0)
|
||||||
, opacity(1.0)
|
, opacity(1.0)
|
||||||
|
, cachePaintMode(Widget::NoCacheMode)
|
||||||
{ }
|
{ }
|
||||||
~Private() { }
|
~Private() { }
|
||||||
|
|
||||||
@ -55,6 +58,15 @@ class Widget::Private
|
|||||||
|
|
||||||
qreal opacity;
|
qreal opacity;
|
||||||
|
|
||||||
|
// Replace with CacheMode in 4.4
|
||||||
|
#if QT_VERSION >= 0x040400
|
||||||
|
#warning Replace Plasma::Widget::CachePaintMode with QGraphicsItem::CacheMode
|
||||||
|
#endif
|
||||||
|
Widget::CachePaintMode cachePaintMode;
|
||||||
|
QSize cacheSize;
|
||||||
|
QString cacheKey;
|
||||||
|
QRectF cacheInvalidated;
|
||||||
|
|
||||||
bool shouldPaint(QPainter *painter, const QTransform &transform);
|
bool shouldPaint(QPainter *painter, const QTransform &transform);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,6 +111,35 @@ qreal Widget::opacity() const
|
|||||||
return d->opacity;
|
return d->opacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::setCachePaintMode(CachePaintMode mode, const QSize &size)
|
||||||
|
{
|
||||||
|
d->cachePaintMode = mode;
|
||||||
|
d->cacheSize = size;
|
||||||
|
if (mode == NoCacheMode) {
|
||||||
|
QPixmapCache::remove(d->cacheKey);
|
||||||
|
d->cacheKey.clear();
|
||||||
|
update();
|
||||||
|
} else {
|
||||||
|
if (mode == ItemCoordinateCacheMode) {
|
||||||
|
d->cacheKey = QString("%1").arg(long(this));
|
||||||
|
d->cacheSize = size;
|
||||||
|
}
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget::CachePaintMode Widget::cachePaintMode() const
|
||||||
|
{
|
||||||
|
return d->cachePaintMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::invalidate(const QRectF &rect)
|
||||||
|
{
|
||||||
|
if (d->cachePaintMode != NoCacheMode)
|
||||||
|
d->cacheInvalidated |= rect.isNull() ? boundingRect() : rect;
|
||||||
|
update(rect);
|
||||||
|
}
|
||||||
|
|
||||||
Qt::Orientations Widget::expandingDirections() const
|
Qt::Orientations Widget::expandingDirections() const
|
||||||
{
|
{
|
||||||
return Qt::Horizontal | Qt::Vertical;
|
return Qt::Horizontal | Qt::Vertical;
|
||||||
@ -240,7 +281,98 @@ void Widget::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QW
|
|||||||
painter->setOpacity(d->opacity);
|
painter->setOpacity(d->opacity);
|
||||||
|
|
||||||
if (d->shouldPaint(painter, transform())) {
|
if (d->shouldPaint(painter, transform())) {
|
||||||
paintWidget(painter, option, widget);
|
if (d->cachePaintMode == NoCacheMode) {
|
||||||
|
paintWidget(painter, option, widget);
|
||||||
|
} else {
|
||||||
|
QRectF brect = boundingRect();
|
||||||
|
QRect boundingRectInt = brect.toRect();
|
||||||
|
|
||||||
|
// Fetch the off-screen transparent buffer and exposed area info.
|
||||||
|
QPixmap pix;
|
||||||
|
QPixmapCache::find(d->cacheKey, pix);
|
||||||
|
QRectF exposed = d->cacheInvalidated;
|
||||||
|
|
||||||
|
// Render using item coodinate cache mode.
|
||||||
|
if (d->cachePaintMode == ItemCoordinateCacheMode) {
|
||||||
|
// Recreate the pixmap if it's gone.
|
||||||
|
if (pix.isNull()) {
|
||||||
|
pix = QPixmap(d->cacheSize);
|
||||||
|
pix.fill(Qt::transparent);
|
||||||
|
exposed = brect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for newly invalidated areas.
|
||||||
|
if (!exposed.isNull()) {
|
||||||
|
d->cacheInvalidated = QRectF();
|
||||||
|
|
||||||
|
QStyleOptionGraphicsItem cacheOption = *option;
|
||||||
|
cacheOption.exposedRect = exposed.toRect(); // <- truncation
|
||||||
|
|
||||||
|
QPainter pixmapPainter(&pix);
|
||||||
|
// Fit the item's bounding rect into the pixmap's coordinates.
|
||||||
|
pixmapPainter.scale(pix.width() / brect.width(),
|
||||||
|
pix.height() / brect.height());
|
||||||
|
pixmapPainter.translate(-brect.topLeft());
|
||||||
|
|
||||||
|
// Re-render the invalidated areas of the pixmap. Important: don't
|
||||||
|
// fool the item into using the widget - pass 0 instead of \a
|
||||||
|
// widget.
|
||||||
|
paintWidget(&pixmapPainter, &cacheOption, 0);
|
||||||
|
pixmapPainter.end();
|
||||||
|
|
||||||
|
// Reinsert this pixmap into the cache
|
||||||
|
QPixmapCache::insert(d->cacheKey, pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redraw the exposed area using the transformed painter. Depending on
|
||||||
|
// the hardware, this may be a server-side operation, or an expensive
|
||||||
|
// qpixmap-image-transform-pixmap roundtrip.
|
||||||
|
painter->drawPixmap(brect, pix, QRectF(QPointF(), pix.size()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render using device coordinate cache mode.
|
||||||
|
if (d->cachePaintMode == DeviceCoordinateCacheMode) {
|
||||||
|
QTransform transform = painter->worldTransform();
|
||||||
|
QRect deviceRect = transform.mapRect(brect).toRect();
|
||||||
|
|
||||||
|
// Auto-adjust the pixmap size.
|
||||||
|
if (deviceRect.size() != pix.size()) {
|
||||||
|
pix = QPixmap(deviceRect.size());
|
||||||
|
pix.fill(Qt::transparent);
|
||||||
|
exposed = brect;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for newly invalidated areas.
|
||||||
|
if (!exposed.isNull()) {
|
||||||
|
d->cacheInvalidated = QRectF();
|
||||||
|
|
||||||
|
// Construct the new styleoption, reset the exposed rect.
|
||||||
|
QStyleOptionGraphicsItem cacheOption = *option;
|
||||||
|
cacheOption.exposedRect = exposed.toRect(); // <- truncation
|
||||||
|
|
||||||
|
QPointF viewOrigo = transform.map(QPointF(0, 0));
|
||||||
|
QPointF offset = viewOrigo - deviceRect.topLeft();
|
||||||
|
|
||||||
|
// Transform the painter, and render the item in device coordinates.
|
||||||
|
QPainter pixmapPainter(&pix);
|
||||||
|
pixmapPainter.translate(offset);
|
||||||
|
pixmapPainter.setWorldTransform(transform, true);
|
||||||
|
pixmapPainter.translate(transform.inverted().map(QPointF(0, 0)));
|
||||||
|
paintWidget(&pixmapPainter, &cacheOption, 0);
|
||||||
|
pixmapPainter.end();
|
||||||
|
|
||||||
|
// Reinsert this pixmap into the cache
|
||||||
|
QPixmapCache::insert(d->cacheKey, pix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redraw the exposed area using an untransformed painter. This
|
||||||
|
// effectively becomes a bitblit that does not transform the cache.
|
||||||
|
painter->setWorldTransform(QTransform());
|
||||||
|
painter->drawPixmap(deviceRect.topLeft(), pix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -59,6 +59,11 @@ class PLASMA_EXPORT Widget : public QObject,
|
|||||||
Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity )
|
Q_PROPERTY( qreal opacity READ opacity WRITE setOpacity )
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum CachePaintMode {
|
||||||
|
NoCacheMode,
|
||||||
|
ItemCoordinateCacheMode,
|
||||||
|
DeviceCoordinateCacheMode
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,6 +209,26 @@ public:
|
|||||||
void setOpacity(qreal opacity);
|
void setOpacity(qreal opacity);
|
||||||
qreal opacity() const;
|
qreal opacity() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the widget's cache paint mode and cache size.
|
||||||
|
* @param mode the new cache paint mode
|
||||||
|
* @param mode the new cache size, only applies to ItemCoordinateCacheMode
|
||||||
|
*/
|
||||||
|
void setCachePaintMode(CachePaintMode mode, const QSize &size = QSize());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current cache paint mode.
|
||||||
|
*/
|
||||||
|
CachePaintMode cachePaintMode() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates the widget's cache paint mode for a given item rectangle.
|
||||||
|
* @param rect the optional invalidated rectangle; if null, defaults to boundingRect().
|
||||||
|
*/
|
||||||
|
void invalidate(const QRectF &rect = QRectF());
|
||||||
|
inline void invalidate(qreal _x, qreal _y, qreal w, qreal h)
|
||||||
|
{ invalidate(QRectF(_x, _y, w, h)); }
|
||||||
|
|
||||||
virtual QGraphicsItem* graphicsItem();
|
virtual QGraphicsItem* graphicsItem();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
Reference in New Issue
Block a user