kwin/effects/shadow.cpp
Luboš Luňák e6069e9cf6 Arghl. Again a stupid bug caused by float having poor precision.
Reverting r700026 and changing floats to doubles again. I'd probably like
to change even the ones interfacing with OpenGL which I've left for now.


svn path=/trunk/KDE/kdebase/workspace/; revision=707987
2007-09-03 15:00:43 +00:00

139 lines
5.2 KiB
C++

/*****************************************************************
KWin - the KDE window manager
This file is part of the KDE project.
Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
You can Freely distribute this program under the GNU General Public
License. See the file "COPYING" for the exact licensing terms.
******************************************************************/
#include "shadow.h"
#include <kwinglutils.h>
#include <kconfiggroup.h>
#include <KStandardDirs>
namespace KWin
{
KWIN_EFFECT( shadow, ShadowEffect )
ShadowEffect::ShadowEffect()
{
KConfigGroup conf = effects->effectConfig("Shadow");
shadowXOffset = conf.readEntry( "XOffset", 10 );
shadowYOffset = conf.readEntry( "YOffset", 10 );
shadowOpacity = conf.readEntry( "Opacity", 0.2 );
shadowFuzzyness = conf.readEntry( "Fuzzyness", 10 );
QString shadowtexture = KGlobal::dirs()->findResource("data", "kwin/shadow-texture.png");
mShadowTexture = new GLTexture(shadowtexture);
}
QRect ShadowEffect::shadowRectangle(const QRect& windowRectangle) const
{
return windowRectangle.adjusted( shadowXOffset - shadowFuzzyness - 20, shadowYOffset - shadowFuzzyness - 20,
shadowXOffset + shadowFuzzyness + 20, shadowYOffset + shadowFuzzyness + 20);
}
void ShadowEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
{
data.mask |= PAINT_WINDOW_TRANSLUCENT;
data.paint |= QRegion( shadowRectangle( ( QRegion( w->geometry()) & data.paint ).boundingRect() ));
effects->prePaintWindow( w, data, time );
}
void ShadowEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
{
if( !w->isDeleted() && !w->isDesktop() && !w->isDock() )
drawShadow( w, mask, region, data );
effects->paintWindow( w, mask, region, data );
}
void ShadowEffect::postPaintWindow( EffectWindow* w )
{
effects->postPaintWindow( w );
}
QRect ShadowEffect::transformWindowDamage( EffectWindow* w, const QRect& r )
{
QRect r2 = r | shadowRectangle( r );
return effects->transformWindowDamage( w, r2 );
}
void ShadowEffect::addQuadVertices(QVector<float>& verts, float x1, float y1, float x2, float y2) const
{
verts << x1 << y1;
verts << x1 << y2;
verts << x2 << y2;
verts << x2 << y1;
}
void ShadowEffect::drawShadow( EffectWindow* window, int mask, QRegion region, WindowPaintData& data )
{
if(( mask & PAINT_WINDOW_TRANSLUCENT ) == 0 )
return;
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT );
glEnable( GL_BLEND );
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
int fuzzy = shadowFuzzyness;
// Shadow's size must be a least 2*fuzzy in both directions (or the corners will be broken)
int w = qMax(fuzzy*2, window->width());
int h = qMax(fuzzy*2, window->height());
glPushMatrix();
if( mask & PAINT_WINDOW_TRANSFORMED )
glTranslatef( data.xTranslate, data.yTranslate, 0 );
glTranslatef( window->x() + shadowXOffset - qMax(0, w - window->width()) / 2.0,
window->y() + shadowYOffset - qMax(0, h - window->height()) / 2.0, 0 );
if(( mask & PAINT_WINDOW_TRANSFORMED ) && ( data.xScale != 1 || data.yScale != 1 ))
glScalef( data.xScale, data.yScale, 1 );
QVector<float> verts, texcoords;
// center
addQuadVertices(verts, 0 + fuzzy, 0 + fuzzy, w - fuzzy, h - fuzzy);
addQuadVertices(texcoords, 0.5, 0.5, 0.5, 0.5);
// sides
// left
addQuadVertices(verts, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy, h - fuzzy);
addQuadVertices(texcoords, 0.0, 0.5, 0.5, 0.5);
// top
addQuadVertices(verts, 0 + fuzzy, 0 - fuzzy, w - fuzzy, 0 + fuzzy);
addQuadVertices(texcoords, 0.5, 0.0, 0.5, 0.5);
// right
addQuadVertices(verts, w - fuzzy, 0 + fuzzy, w + fuzzy, h - fuzzy);
addQuadVertices(texcoords, 0.5, 0.5, 1.0, 0.5);
// bottom
addQuadVertices(verts, 0 + fuzzy, h - fuzzy, w - fuzzy, h + fuzzy);
addQuadVertices(texcoords, 0.5, 0.5, 0.5, 1.0);
// corners
// top-left
addQuadVertices(verts, 0 - fuzzy, 0 - fuzzy, 0 + fuzzy, 0 + fuzzy);
addQuadVertices(texcoords, 0.0, 0.0, 0.5, 0.5);
// top-right
addQuadVertices(verts, w - fuzzy, 0 - fuzzy, w + fuzzy, 0 + fuzzy);
addQuadVertices(texcoords, 0.5, 0.0, 1.0, 0.5);
// bottom-left
addQuadVertices(verts, 0 - fuzzy, h - fuzzy, 0 + fuzzy, h + fuzzy);
addQuadVertices(texcoords, 0.0, 0.5, 0.5, 1.0);
// bottom-right
addQuadVertices(verts, w - fuzzy, h - fuzzy, w + fuzzy, h + fuzzy);
addQuadVertices(texcoords, 0.5, 0.5, 1.0, 1.0);
mShadowTexture->bind();
// Take the transparency settings and window's transparency into account.
// Also make the shadow more transparent if we've made it bigger
glColor4f(0, 0, 0, shadowOpacity * data.opacity * (window->width() / (double)w) * (window->height() / (double)h));
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// We have two elements per vertex in the verts array
int verticesCount = verts.count() / 2;
renderGLGeometry( mask, region, verticesCount, verts.data(), texcoords.data() );
mShadowTexture->unbind();
glPopMatrix();
glPopAttrib();
}
} // namespace