diff --git a/animations/pixmaptransition.cpp b/animations/pixmaptransition.cpp index 53fb6301b..2be6efa71 100644 --- a/animations/pixmaptransition.cpp +++ b/animations/pixmaptransition.cpp @@ -31,7 +31,9 @@ namespace Plasma { 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); } +void PixmapTransition::setUsesCache(bool cache) +{ + m_cache = cache; +} + +bool PixmapTransition::usesCache() const +{ + return m_cache; +} + QPixmap PixmapTransition::targetPixmap() const { return m_targetPixmap; @@ -74,92 +86,88 @@ QPixmap PixmapTransition::targetPixmap() 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(¤tPixmap); + 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(¤tPixmap); + 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(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) { - QGraphicsWidget *w = targetWidget(); - if (!w) { - return; + if (oldState == Stopped && newState == Running) { + m_targetRect = m_targetPixmap.rect(); + 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()) { - 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(); + m_dirty = true; } void PixmapTransition::updateEffectiveTime(int currentTime) { + m_dirty = true; 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) { w->update(); } diff --git a/animations/pixmaptransition_p.h b/animations/pixmaptransition_p.h index a8d6c07ff..2de36ba8b 100644 --- a/animations/pixmaptransition_p.h +++ b/animations/pixmaptransition_p.h @@ -42,6 +42,7 @@ class PixmapTransition : public EasingAnimation Q_OBJECT Q_PROPERTY(QPixmap startPixmap READ startPixmap WRITE setStartPixmap) Q_PROPERTY(QPixmap targetPixmap READ targetPixmap WRITE setTargetPixmap) + Q_PROPERTY(QPixmap usesCache READ usesCache WRITE setUsesCache) Q_PROPERTY(QPixmap currentPixmap READ currentPixmap) public: @@ -50,7 +51,7 @@ public: virtual ~PixmapTransition(); /** - * The first pixmap of the animation + * @return The first pixmap of the animation */ QPixmap startPixmap() const; @@ -70,18 +71,39 @@ public: void setTargetPixmap(const QPixmap &); /** - * Returns the current pixmap + * @return the current pixmap */ 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: void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState); void updateEffectiveTime(int currentTime); +private: + QPixmap alignedTargetPixmap() const; + QPixmap alignedStartPixmap() const; + private: QPixmap m_startPixmap; QPixmap m_targetPixmap; QPixmap m_currentPixmap; + QRect m_startRect; + QRect m_targetRect; + QSize m_pixmapSize; + bool m_cache; + bool m_dirty; }; } diff --git a/paintutils.cpp b/paintutils.cpp index 75d30f129..0dd614f62 100644 --- a/paintutils.cpp +++ b/paintutils.cpp @@ -82,8 +82,7 @@ QPixmap shadowText(QString text, const QFont &font, QColor textColor, QColor sha p.end(); //Draw blurred shadow - QImage img(textRect.size() + QSize(radius * 2, radius * 2), - QImage::Format_ARGB32_Premultiplied); + QImage img(textRect.size() + QSize(radius * 2, radius * 2), QImage::Format_ARGB32_Premultiplied); img.fill(0); p.begin(&img); 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()) { return; } + QRect fromRect(from.rect()); QRect toRect(to.rect()); @@ -181,16 +181,16 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount) return from; } - QPixmap startPixmap(from); - QPixmap targetPixmap(to); - - if (from.size() != to.size() || !from.hasAlphaChannel() || !to.hasAlphaChannel()) { - centerPixmaps(startPixmap, targetPixmap); - } + QRect startRect(from.rect()); + QRect targetRect(to.rect()); + QSize pixmapSize = startRect.size().expandedTo(targetRect.size()); + QRect toRect = QRect(QPoint(0,0), pixmapSize); + targetRect.moveCenter(toRect.center()); + startRect.moveCenter(toRect.center()); + QPixmap startPixmap(pixmapSize); + QPixmap targetPixmap(pixmapSize); //paint to in the center of from - QRect toRect = to.rect(); - QColor color; color.setAlphaF(amount); @@ -203,15 +203,17 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount) QPainter p; p.begin(&targetPixmap); + p.drawPixmap(targetRect, from); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); - p.fillRect(targetPixmap.rect(), color); + p.fillRect(targetRect, color); p.end(); p.begin(&startPixmap); + p.drawPixmap(startRect, from); p.setCompositionMode(QPainter::CompositionMode_DestinationOut); - p.fillRect(startPixmap.rect(), color); + p.fillRect(startRect, color); p.setCompositionMode(QPainter::CompositionMode_Plus); - p.drawPixmap(toRect.topLeft(), targetPixmap); + p.drawPixmap(targetRect, to); p.end(); return startPixmap; @@ -266,18 +268,22 @@ QPixmap transition(const QPixmap &from, const QPixmap &to, qreal amount) #endif else { // Fall back to using QRasterPaintEngine to do the transition. - QImage under = startPixmap.toImage(); - QImage over = targetPixmap.toImage(); + QImage under(pixmapSize, QImage::Format_ARGB32_Premultiplied);// = startPixmap.toImage(); + under.fill(Qt::transparent); + QImage over(pixmapSize, QImage::Format_ARGB32_Premultiplied);// = targetPixmap.toImage(); + over.fill(Qt::transparent); QPainter p; p.begin(&over); + p.drawPixmap(targetRect, to); p.setCompositionMode(QPainter::CompositionMode_DestinationIn); p.fillRect(over.rect(), color); p.end(); p.begin(&under); + p.drawPixmap(startRect, from); p.setCompositionMode(QPainter::CompositionMode_DestinationOut); - p.fillRect(under.rect(), color); + p.fillRect(startRect, color); p.setCompositionMode(QPainter::CompositionMode_Plus); p.drawImage(toRect.topLeft(), over); p.end();