fewer pixmaps. same great taste.

svn path=/trunk/KDE/kdelibs/; revision=1178341
This commit is contained in:
Aaron J. Seigo 2010-09-22 19:35:47 +00:00
parent 938880140b
commit 9983bc7dc8
3 changed files with 130 additions and 94 deletions

View File

@ -31,7 +31,9 @@ namespace Plasma
{ {
PixmapTransition::PixmapTransition(QObject *parent) PixmapTransition::PixmapTransition(QObject *parent)
: EasingAnimation(parent) : EasingAnimation(parent),
m_cache(false),
m_dirty(false)
{ {
} }
@ -67,6 +69,16 @@ void PixmapTransition::setTargetPixmap(const QPixmap &pixmap)
updateEffectiveTime(0); updateEffectiveTime(0);
} }
void PixmapTransition::setUsesCache(bool cache)
{
m_cache = cache;
}
bool PixmapTransition::usesCache() const
{
return m_cache;
}
QPixmap PixmapTransition::targetPixmap() const QPixmap PixmapTransition::targetPixmap() const
{ {
return m_targetPixmap; return m_targetPixmap;
@ -74,92 +86,88 @@ QPixmap PixmapTransition::targetPixmap() const
QPixmap PixmapTransition::currentPixmap() const QPixmap PixmapTransition::currentPixmap() const
{ {
return m_currentPixmap; if (m_cache && !m_dirty) {
return m_currentPixmap;
}
QPixmap currentPixmap;
qreal delta = currentTime() / qreal(duration());
if (!m_startPixmap.isNull() && !m_targetPixmap.isNull()) {
//kDebug() << "transitioning";
currentPixmap = Plasma::PaintUtils::transition(m_startPixmap, m_targetPixmap, delta);
} else if (m_startPixmap.isNull()) {
if (qFuzzyCompare(delta, qreal(1.0))) {
currentPixmap = alignedTargetPixmap();
return currentPixmap;
}
if (currentPixmap.isNull()) {
currentPixmap = QPixmap(m_pixmapSize);
}
currentPixmap.fill(QColor(0, 0, 0, (int)(((qreal)255)*delta)));
QPainter p(&currentPixmap);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
//kDebug() << "painting" << m_targetPixmap.rect() << "into" << m_targetRect << "in size" << currentPixmap.size();
p.drawPixmap(m_targetRect, m_targetPixmap);
p.end();
} else if (m_targetPixmap.isNull()) {
currentPixmap = alignedStartPixmap();
if (qFuzzyCompare(delta, qreal(1.0))) {
return currentPixmap;
}
//kDebug() << "painting" << m_startPixmap.rect() << "into" << m_targetRect << "in size" << currentPixmap.size();
QPainter p(&currentPixmap);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(m_currentPixmap.rect(), QColor(0, 0, 0, (int)(254 - ((qreal)254)*delta)));
p.end();
}
if (m_cache) {
const_cast<PixmapTransition *>(this)->m_currentPixmap = currentPixmap;
}
return currentPixmap;
}
QPixmap PixmapTransition::alignedTargetPixmap() const
{
QPixmap pm(m_pixmapSize);
pm.fill(Qt::transparent);
QPainter p(&pm);
p.drawPixmap(m_targetRect, m_targetPixmap);
return pm;
}
QPixmap PixmapTransition::alignedStartPixmap() const
{
QPixmap pm(m_pixmapSize);
pm.fill(Qt::transparent);
QPainter p(&pm);
p.drawPixmap(m_startRect, m_startPixmap);
return pm;
} }
void PixmapTransition::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) void PixmapTransition::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
{ {
QGraphicsWidget *w = targetWidget(); if (oldState == Stopped && newState == Running) {
if (!w) { m_targetRect = m_targetPixmap.rect();
return; m_startRect = m_startPixmap.rect();
m_pixmapSize = m_startRect.size().expandedTo(m_targetRect.size());
QRect actualRect = QRect(QPoint(0,0), m_pixmapSize);
m_targetRect.moveCenter(actualRect.center());
m_startRect.moveCenter(actualRect.center());
} else if (QGraphicsWidget *w = targetWidget()) {
w->update();
} }
if (!m_startPixmap.isNull() && !m_targetPixmap.isNull()) { m_dirty = true;
if (oldState == Stopped && newState == Running) {
Plasma::PaintUtils::centerPixmaps(m_startPixmap, m_targetPixmap);
m_currentPixmap = (direction() == Forward ? m_startPixmap : m_targetPixmap);
} else if (newState == Stopped) {
m_currentPixmap = (direction() == Forward ? m_targetPixmap : m_startPixmap);
}
} else if (m_startPixmap.isNull()) {
if (oldState == Stopped && newState == Running) {
if (direction() == Forward) {
m_currentPixmap = QPixmap(m_targetPixmap.size());
m_currentPixmap.fill(Qt::transparent);
} else {
m_currentPixmap = m_targetPixmap;
}
} else if (newState == Stopped) {
if (direction() == Forward) {
m_currentPixmap = m_targetPixmap;
} else {
m_currentPixmap = QPixmap(m_targetPixmap.size());
m_currentPixmap.fill(Qt::transparent);
}
}
} else if (m_targetPixmap.isNull()) {
if (oldState == Stopped && newState == Running) {
if (direction() == Forward) {
m_currentPixmap = m_targetPixmap;
} else {
m_currentPixmap = QPixmap(m_targetPixmap.size());
m_currentPixmap.fill(Qt::transparent);
}
} else if (newState == Stopped) {
if (direction() == Forward) {
m_currentPixmap = QPixmap(m_targetPixmap.size());
m_currentPixmap.fill(Qt::transparent);
} else {
m_currentPixmap = m_targetPixmap;
}
}
}
w->update();
} }
void PixmapTransition::updateEffectiveTime(int currentTime) void PixmapTransition::updateEffectiveTime(int currentTime)
{ {
m_dirty = true;
QGraphicsWidget *w = targetWidget(); QGraphicsWidget *w = targetWidget();
if (w) {
qreal delta = currentTime / qreal(duration());
if (!m_startPixmap.isNull() && !m_targetPixmap.isNull()) {
m_currentPixmap = Plasma::PaintUtils::transition(m_startPixmap, m_targetPixmap, delta);
} else if (m_startPixmap.isNull()) {
if (qFuzzyCompare(delta, qreal(1.0))) {
m_currentPixmap = m_targetPixmap;
return;
}
if (m_currentPixmap.isNull()) {
m_currentPixmap = QPixmap(m_targetPixmap.size());
}
m_currentPixmap.fill(QColor(0, 0, 0, (int)(((qreal)255)*delta)));
QPainter p(&m_currentPixmap);
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
p.drawPixmap(m_currentPixmap.rect(), m_targetPixmap, m_targetPixmap.rect());
p.end();
} else if (m_targetPixmap.isNull()) {
m_currentPixmap = m_startPixmap;
if (qFuzzyCompare(delta, qreal(1.0))) {
return;
}
QPainter p(&m_currentPixmap);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(m_currentPixmap.rect(), QColor(0, 0, 0, (int)(254 - ((qreal)254)*delta)));
p.end();
}
}
if (w) { if (w) {
w->update(); w->update();
} }

View File

@ -42,6 +42,7 @@ class PixmapTransition : public EasingAnimation
Q_OBJECT Q_OBJECT
Q_PROPERTY(QPixmap startPixmap READ startPixmap WRITE setStartPixmap) Q_PROPERTY(QPixmap startPixmap READ startPixmap WRITE setStartPixmap)
Q_PROPERTY(QPixmap targetPixmap READ targetPixmap WRITE setTargetPixmap) Q_PROPERTY(QPixmap targetPixmap READ targetPixmap WRITE setTargetPixmap)
Q_PROPERTY(QPixmap usesCache READ usesCache WRITE setUsesCache)
Q_PROPERTY(QPixmap currentPixmap READ currentPixmap) Q_PROPERTY(QPixmap currentPixmap READ currentPixmap)
public: public:
@ -50,7 +51,7 @@ public:
virtual ~PixmapTransition(); virtual ~PixmapTransition();
/** /**
* The first pixmap of the animation * @return The first pixmap of the animation
*/ */
QPixmap startPixmap() const; QPixmap startPixmap() const;
@ -70,18 +71,39 @@ public:
void setTargetPixmap(const QPixmap &); void setTargetPixmap(const QPixmap &);
/** /**
* Returns the current pixmap * @return the current pixmap
*/ */
QPixmap currentPixmap() const; QPixmap currentPixmap() const;
/**
* Enable caching of the resulting pixmap, otherwise it will be regenerated on
* each call to currentPixmap; for elements which already have their own caching
* this is not a problem.
*/
void setUsesCache(bool cache);
/**
* @return whether or not caching is on
*/
bool usesCache() const;
protected: protected:
void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState);
void updateEffectiveTime(int currentTime); void updateEffectiveTime(int currentTime);
private:
QPixmap alignedTargetPixmap() const;
QPixmap alignedStartPixmap() const;
private: private:
QPixmap m_startPixmap; QPixmap m_startPixmap;
QPixmap m_targetPixmap; QPixmap m_targetPixmap;
QPixmap m_currentPixmap; QPixmap m_currentPixmap;
QRect m_startRect;
QRect m_targetRect;
QSize m_pixmapSize;
bool m_cache;
bool m_dirty;
}; };
} }

View File

@ -82,8 +82,7 @@ QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor sha
p.end(); p.end();
//Draw blurred shadow //Draw blurred shadow
QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied);
QImage::Format_ARGB32_Premultiplied);
img.fill(0); img.fill(0);
p.begin(&img); p.begin(&img);
p.drawImage(QPoint(radius, radius), textPixmap.toImage()); p.drawImage(QPoint(radius, radius), textPixmap.toImage());
@ -147,6 +146,7 @@ void centerPixmaps(QPixmap &from, QPixmap &to)
if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) { if (from.size() == to.size() && from.hasAlphaChannel() && to.hasAlphaChannel()) {
return; return;
} }
QRect fromRect(from.rect()); QRect fromRect(from.rect());
QRect toRect(to.rect()); QRect toRect(to.rect());
@ -181,16 +181,16 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
return from; return from;
} }
QPixmap startPixmap(from); QRect startRect(from.rect());
QPixmap targetPixmap(to); QRect targetRect(to.rect());
QSize pixmapSize = startRect.size().expandedTo(targetRect.size());
if (from.size() != to.size() || !from.hasAlphaChannel() || !to.hasAlphaChannel()) { QRect toRect = QRect(QPoint(0,0), pixmapSize);
centerPixmaps(startPixmap, targetPixmap); targetRect.moveCenter(toRect.center());
} startRect.moveCenter(toRect.center());
QPixmap startPixmap(pixmapSize);
QPixmap targetPixmap(pixmapSize);
//paint to in the center of from //paint to in the center of from
QRect toRect = to.rect();
QColor color; QColor color;
color.setAlphaF(amount); color.setAlphaF(amount);
@ -203,15 +203,17 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
QPainter p; QPainter p;
p.begin(&targetPixmap); p.begin(&targetPixmap);
p.drawPixmap(targetRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(targetPixmap.rect(), color); p.fillRect(targetRect, color);
p.end(); p.end();
p.begin(&startPixmap); p.begin(&startPixmap);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut); p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(startPixmap.rect(), color); p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus); p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawPixmap(toRect.topLeft(), targetPixmap); p.drawPixmap(targetRect, to);
p.end(); p.end();
return startPixmap; return startPixmap;
@ -266,18 +268,22 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount)
#endif #endif
else { else {
// Fall back to using QRasterPaintEngine to do the transition. // Fall back to using QRasterPaintEngine to do the transition.
QImage under = startPixmap.toImage(); QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);// = startPixmap.toImage();
QImage over = targetPixmap.toImage(); under.fill(Qt::transparent);
QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);// = targetPixmap.toImage();
over.fill(Qt::transparent);
QPainter p; QPainter p;
p.begin(&over); p.begin(&over);
p.drawPixmap(targetRect, to);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(over.rect(), color); p.fillRect(over.rect(), color);
p.end(); p.end();
p.begin(&under); p.begin(&under);
p.drawPixmap(startRect, from);
p.setCompositionMode(QPainter::CompositionMode_DestinationOut); p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
p.fillRect(under.rect(), color); p.fillRect(startRect, color);
p.setCompositionMode(QPainter::CompositionMode_Plus); p.setCompositionMode(QPainter::CompositionMode_Plus);
p.drawImage(toRect.topLeft(), over); p.drawImage(toRect.topLeft(), over);
p.end(); p.end();