From eabad32cfb06d1adddc3860719cfedd2e830fca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Gr=C3=A4=C3=9Flin?= Date: Sat, 7 Aug 2010 14:08:34 +0000 Subject: [PATCH] Add cross fade support for text and icon to EffectFrame. This allows an effect to fade between old and new text/icon. As an example it's added to CoverSwitch. Currently only supported in OpenGL. XRender might be added, but I'm missing an idea for an effect to add it. Most effects using EffectFrame require OpenGL anyway. svn path=/trunk/KDE/kdebase/workspace/; revision=1160252 --- effects.cpp | 8 ++++ effects/coverswitch/coverswitch.cpp | 3 ++ lib/kwineffects.cpp | 45 ++++++++++++++++++ lib/kwineffects.h | 42 +++++++++++++++++ scene.h | 2 + scene_opengl.cpp | 72 +++++++++++++++++++++++++++-- scene_opengl.h | 5 ++ scene_xrender.cpp | 10 ++++ scene_xrender.h | 2 + 9 files changed, 184 insertions(+), 5 deletions(-) diff --git a/effects.cpp b/effects.cpp index 1114e37afa..708acca521 100644 --- a/effects.cpp +++ b/effects.cpp @@ -1761,6 +1761,10 @@ const QPixmap& EffectFrameImpl::icon() const void EffectFrameImpl::setIcon( const QPixmap& icon ) { m_icon = icon; + if( isCrossFade() ) + { + m_sceneFrame->crossFadeIcon(); + } if( m_iconSize.isEmpty() ) // Set a size if we don't already have one { setIconSize( m_icon.size() ); @@ -1838,6 +1842,10 @@ void EffectFrameImpl::setText( const QString& text ) { return; } + if( isCrossFade() ) + { + m_sceneFrame->crossFadeText(); + } m_text = text; QRect oldGeom = m_geometry; autoResize(); diff --git a/effects/coverswitch/coverswitch.cpp b/effects/coverswitch/coverswitch.cpp index 299e0b0925..9124bbb18f 100644 --- a/effects/coverswitch/coverswitch.cpp +++ b/effects/coverswitch/coverswitch.cpp @@ -63,6 +63,7 @@ CoverSwitchEffect::CoverSwitchEffect() captionFont.setBold( true ); captionFont.setPointSize( captionFont.pointSize() * 2 ); captionFrame->setFont( captionFont ); + captionFrame->enableCrossFade( true ); } CoverSwitchEffect::~CoverSwitchEffect() @@ -328,6 +329,8 @@ void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& opacity = timeLine.value(); else if( stop ) opacity = 1.0 - timeLine.value(); + if( animation ) + captionFrame->setCrossFadeProgress( timeLine.value() ); captionFrame->render( region, opacity ); } diff --git a/lib/kwineffects.cpp b/lib/kwineffects.cpp index f97c251bbf..67c33f3dd7 100644 --- a/lib/kwineffects.cpp +++ b/lib/kwineffects.cpp @@ -1291,15 +1291,60 @@ EffectWindow* WindowMotionManager::windowAtPoint( QPoint point, bool useStacking return NULL; } +/*************************************************************** + EffectFramePrivate +***************************************************************/ +class EffectFramePrivate + { + public: + EffectFramePrivate(); + ~EffectFramePrivate(); + + bool crossFading; + qreal crossFadeProgress; + }; + +EffectFramePrivate::EffectFramePrivate() + : crossFading( false ) + , crossFadeProgress( 1.0 ) + { + } + +EffectFramePrivate::~EffectFramePrivate() + { + } + /*************************************************************** EffectFrame ***************************************************************/ EffectFrame::EffectFrame() + : d( new EffectFramePrivate ) { } EffectFrame::~EffectFrame() { + delete d; + } + +qreal EffectFrame::crossFadeProgress() const + { + return d->crossFadeProgress; + } + +void EffectFrame::setCrossFadeProgress( qreal progress ) + { + d->crossFadeProgress = progress; + } + +bool EffectFrame::isCrossFade() const + { + return d->crossFading; + } + +void EffectFrame::enableCrossFade( bool enable ) + { + d->crossFading = enable; } QColor EffectFrame::styledTextColor() diff --git a/lib/kwineffects.h b/lib/kwineffects.h index 24edcc74da..1f44c2f064 100644 --- a/lib/kwineffects.h +++ b/lib/kwineffects.h @@ -57,6 +57,7 @@ namespace KWin class EffectWindow; class EffectWindowGroup; class EffectFrame; +class EffectFramePrivate; class Effect; class WindowQuad; class GLRenderTarget; @@ -1767,6 +1768,47 @@ class KWIN_EXPORT EffectFrame * The foreground text color as specified by the default Plasma theme. */ static QColor styledTextColor(); + + /** + * If @p enable is @c true cross fading between icons and text is enabled + * By default disabled. Use setCrossFadeProgress to cross fade. + * Cross Fading is currently only available if OpenGL is used. + * @param enable @c true enables cross fading, @c false disables it again + * @see isCrossFade + * @see setCrossFadeProgress + * @since 4.6 + **/ + void enableCrossFade( bool enable ); + /** + * @returns @c true if cross fading is enabled, @c false otherwise + * @see enableCrossFade + * @since 4.6 + **/ + bool isCrossFade() const; + /** + * Sets the current progress for cross fading the last used icon/text + * with current icon/text to @p progress. + * A value of 0.0 means completely old icon/text, a value of 1.0 means + * completely current icon/text. + * Default value is 1.0. You have to enable cross fade before using it. + * Cross Fading is currently only available if OpenGL is used. + * @see enableCrossFade + * @see isCrossFade + * @see crossFadeProgress + * @since 4.6 + **/ + void setCrossFadeProgress( qreal progress ); + /** + * @returns The current progress for cross fading + * @see setCrossFadeProgress + * @see enableCrossFade + * @see isCrossFade + * @since 4.6 + **/ + qreal crossFadeProgress() const; + + private: + EffectFramePrivate* const d; }; /** diff --git a/scene.h b/scene.h index e2b1e2f474..7d08d6cbac 100644 --- a/scene.h +++ b/scene.h @@ -226,6 +226,8 @@ class Scene::EffectFrame virtual void freeIconFrame() = 0; virtual void freeTextFrame() = 0; virtual void freeSelection() = 0; + virtual void crossFadeIcon() = 0; + virtual void crossFadeText() = 0; protected: EffectFrameImpl* m_effectFrame; diff --git a/scene_opengl.cpp b/scene_opengl.cpp index a0cd32305f..a15948b099 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -1920,7 +1920,9 @@ SceneOpenGL::EffectFrame::EffectFrame( EffectFrameImpl* frame ) : Scene::EffectFrame( frame ) , m_texture( NULL ) , m_textTexture( NULL ) + , m_oldTextTexture( NULL ) , m_iconTexture( NULL ) + , m_oldIconTexture( NULL ) , m_selectionTexture( NULL ) , m_unstyledVBO( NULL ) { @@ -1934,7 +1936,9 @@ SceneOpenGL::EffectFrame::~EffectFrame() { delete m_texture; delete m_textTexture; + delete m_oldTextTexture; delete m_iconTexture; + delete m_oldIconTexture; delete m_selectionTexture; delete m_unstyledVBO; } @@ -1951,6 +1955,10 @@ void SceneOpenGL::EffectFrame::free() m_selectionTexture = NULL; delete m_unstyledVBO; m_unstyledVBO = NULL; + delete m_oldIconTexture; + m_oldIconTexture = NULL; + delete m_oldTextTexture; + m_oldTextTexture = NULL; } void SceneOpenGL::EffectFrame::freeIconFrame() @@ -1971,6 +1979,20 @@ void SceneOpenGL::EffectFrame::freeSelection() m_selectionTexture = NULL; } +void SceneOpenGL::EffectFrame::crossFadeIcon() + { + delete m_oldIconTexture; + m_oldIconTexture = m_iconTexture; + m_iconTexture = NULL; + } + +void SceneOpenGL::EffectFrame::crossFadeText() + { + delete m_oldTextTexture; + m_oldTextTexture = m_textTexture; + m_textTexture = NULL; + } + void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double frameOpacity ) { if( m_effectFrame->geometry().isEmpty() ) @@ -2144,17 +2166,35 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr } } - if( shader ) - shader->setUniform( "opacity", (float)opacity ); - else - glColor4f( 1.0, 1.0, 1.0, opacity ); - // Render icon if( !m_effectFrame->icon().isNull() && !m_effectFrame->iconSize().isEmpty() ) { QPoint topLeft( m_effectFrame->geometry().x(), m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2 ); + if( m_effectFrame->isCrossFade() && m_oldIconTexture ) + { + if( shader ) + shader->setUniform( "opacity", (float)opacity * (1.0f - (float)m_effectFrame->crossFadeProgress()) ); + else + glColor4f( 1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress()) ); + + m_oldIconTexture->bind(); + m_oldIconTexture->render( region, QRect( topLeft, m_effectFrame->iconSize() )); + m_oldIconTexture->unbind(); + if( shader ) + shader->setUniform( "opacity", (float)opacity * (float)m_effectFrame->crossFadeProgress() ); + else + glColor4f( 1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress() ); + } + else + { + if( shader ) + shader->setUniform( "opacity", (float)opacity ); + else + glColor4f( 1.0, 1.0, 1.0, opacity ); + } + if( !m_iconTexture ) // lazy creation { m_iconTexture = new Texture( m_effectFrame->icon().handle(), @@ -2169,6 +2209,28 @@ void SceneOpenGL::EffectFrame::render( QRegion region, double opacity, double fr // Render text if( !m_effectFrame->text().isEmpty() ) { + if( m_effectFrame->isCrossFade() && m_oldTextTexture ) + { + if( shader ) + shader->setUniform( "opacity", (float)opacity * (1.0f - (float)m_effectFrame->crossFadeProgress()) ); + else + glColor4f( 1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress()) ); + + m_oldTextTexture->bind(); + m_oldTextTexture->render( region, m_effectFrame->geometry() ); + m_oldTextTexture->unbind(); + if( shader ) + shader->setUniform( "opacity", (float)opacity * (float)m_effectFrame->crossFadeProgress() ); + else + glColor4f( 1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress() ); + } + else + { + if( shader ) + shader->setUniform( "opacity", (float)opacity ); + else + glColor4f( 1.0, 1.0, 1.0, opacity ); + } if( !m_textTexture ) // Lazy creation updateTextTexture(); m_textTexture->bind(); diff --git a/scene_opengl.h b/scene_opengl.h index d429b1804d..6b53aafae5 100644 --- a/scene_opengl.h +++ b/scene_opengl.h @@ -180,6 +180,9 @@ class SceneOpenGL::EffectFrame virtual void render(QRegion region, double opacity, double frameOpacity); + virtual void crossFadeIcon(); + virtual void crossFadeText(); + static void cleanup(); private: @@ -188,7 +191,9 @@ class SceneOpenGL::EffectFrame GLTexture* m_texture; GLTexture* m_textTexture; + GLTexture* m_oldTextTexture; GLTexture* m_iconTexture; + GLTexture* m_oldIconTexture; GLTexture* m_selectionTexture; GLVertexBuffer* m_unstyledVBO; diff --git a/scene_xrender.cpp b/scene_xrender.cpp index 28b474b996..99c952fe65 100644 --- a/scene_xrender.cpp +++ b/scene_xrender.cpp @@ -896,6 +896,16 @@ void SceneXrender::EffectFrame::freeSelection() m_selectionPicture = NULL; } +void SceneXrender::EffectFrame::crossFadeIcon() + { + // TODO: implement me + } + +void SceneXrender::EffectFrame::crossFadeText() + { + // TODO: implement me + } + void SceneXrender::EffectFrame::render( QRegion region, double opacity, double frameOpacity ) { if( m_effectFrame->geometry().isEmpty() ) diff --git a/scene_xrender.h b/scene_xrender.h index c2280493ee..95fa75495d 100644 --- a/scene_xrender.h +++ b/scene_xrender.h @@ -104,6 +104,8 @@ class SceneXrender::EffectFrame virtual void freeIconFrame(); virtual void freeTextFrame(); virtual void freeSelection(); + virtual void crossFadeIcon(); + virtual void crossFadeText(); virtual void render( QRegion region, double opacity, double frameOpacity ); private: