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
This commit is contained in:
Martin Gräßlin 2010-08-07 14:08:34 +00:00
parent b5377e5834
commit eabad32cfb
9 changed files with 184 additions and 5 deletions

View file

@ -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();

View file

@ -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 );
}

View file

@ -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()

View file

@ -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;
};
/**

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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() )

View file

@ -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: