~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to kwin/clients/oxygen/oxygendecohelper.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2008 Long Huynh Huu <long.upcase@googlemail.com>
 
3
 * Copyright 2007 Matthew Woehlke <mw_triad@users.sourceforge.net>
 
4
 * Copyright 2007 Casper Boemann <cbr@boemann.dk>
 
5
 *
 
6
 * This library is free software; you can redistribute it and/or
 
7
 * modify it under the terms of the GNU Library General Public
 
8
 * License version 2 as published by the Free Software Foundation.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Library General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Library General Public License
 
16
 * along with this library; see the file COPYING.LIB.  If not, write to
 
17
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 
18
 * Boston, MA 02110-1301, USA.
 
19
 */
 
20
 
 
21
#include "oxygendecohelper.h"
 
22
 
 
23
#include <QtGui/QPainter>
 
24
#include <KColorUtils>
 
25
#include <KDebug>
 
26
 
 
27
#include <cmath>
 
28
 
 
29
namespace Oxygen
 
30
{
 
31
 
 
32
    //______________________________________________________________________________
 
33
    DecoHelper::DecoHelper(const QByteArray &componentName):
 
34
        Helper(componentName),
 
35
        _debugArea( KDebug::registerArea( "Oxygen (decoration)" ) )
 
36
 
 
37
    {}
 
38
 
 
39
    //______________________________________________________________________________
 
40
    void DecoHelper::invalidateCaches( void )
 
41
    {
 
42
        // base class call
 
43
        Helper::invalidateCaches();
 
44
 
 
45
        // local caches
 
46
        _titleBarTextColorCache.clear();
 
47
        _buttonTextColorCache.clear();
 
48
 
 
49
    }
 
50
 
 
51
    //______________________________________________________________________________
 
52
    QPixmap DecoHelper::windecoButton(const QColor &color, bool pressed, int size)
 
53
    {
 
54
        const quint64 key( (quint64(color.rgba()) << 32) | (size << 1) | (int)pressed );
 
55
        QPixmap *pixmap( windecoButtonCache().object(key) );
 
56
 
 
57
        if( !pixmap )
 
58
        {
 
59
            pixmap = new QPixmap(size, size);
 
60
            pixmap->fill(Qt::transparent);
 
61
 
 
62
            const QColor light( calcLightColor(color) );
 
63
            const QColor dark( calcDarkColor(color) );
 
64
 
 
65
            QPainter p( pixmap );
 
66
            p.setRenderHints(QPainter::Antialiasing);
 
67
            p.setPen(Qt::NoPen);
 
68
            qreal u = size/18.0;
 
69
            p.translate( 0.5*u, (0.5-0.668)*u );
 
70
 
 
71
            {
 
72
                //plain background
 
73
                QLinearGradient lg( 0, u*1.665, 0, u*(12.33+1.665) );
 
74
                if( pressed )
 
75
                {
 
76
                    lg.setColorAt( 1, light );
 
77
                    lg.setColorAt( 0, dark );
 
78
                } else {
 
79
                    lg.setColorAt( 0, light );
 
80
                    lg.setColorAt( 1, dark );
 
81
                }
 
82
 
 
83
                const QRectF r( u*0.5*(17-12.33), u*1.665, u*12.33, u*12.33 );
 
84
                p.setBrush( lg );
 
85
                p.drawEllipse( r );
 
86
            }
 
87
 
 
88
            {
 
89
                // outline circle
 
90
                const qreal penWidth( 0.7 );
 
91
                QLinearGradient lg( 0, u*1.665, 0, u*(2.0*12.33+1.665) );
 
92
                lg.setColorAt( 0, light );
 
93
                lg.setColorAt( 1, dark );
 
94
                const QRectF r( u*0.5*(17-12.33+penWidth), u*(1.665+penWidth), u*(12.33-penWidth), u*(12.33-penWidth) );
 
95
                p.setPen( QPen( lg, penWidth*u ) );
 
96
                p.setBrush( Qt::NoBrush );
 
97
                p.drawEllipse( r );
 
98
                p.end();
 
99
            }
 
100
 
 
101
            windecoButtonCache().insert( key, pixmap );
 
102
        }
 
103
 
 
104
        return *pixmap;
 
105
    }
 
106
 
 
107
    //_______________________________________________________________________
 
108
    QPixmap DecoHelper::windecoButtonGlow(const QColor &color, int size)
 
109
    {
 
110
        const quint64 key( (quint64(color.rgba()) << 32) | size );
 
111
        QPixmap *pixmap( windecoButtonGlowCache().object(key) );
 
112
 
 
113
        if( !pixmap )
 
114
        {
 
115
            pixmap = new QPixmap(size, size);
 
116
            pixmap->fill(Qt::transparent);
 
117
 
 
118
            // right now the same color is used for the two shadows
 
119
            const QColor& light( color );
 
120
            const QColor& dark( color );
 
121
 
 
122
            QPainter p(pixmap);
 
123
            p.setRenderHints(QPainter::Antialiasing);
 
124
            p.setPen(Qt::NoPen);
 
125
            qreal u = size/18.0;
 
126
            p.translate( 0.5*u, (0.5-0.668)*u );
 
127
 
 
128
            {
 
129
 
 
130
                // outer shadow
 
131
                QRadialGradient rg( u*8.5, u*8.5, u*8.5 );
 
132
 
 
133
                static const int nPoints(5);
 
134
                const qreal x[5] = { 0.61, 0.72, 0.81, 0.9, 1};
 
135
                const qreal values[5] = { 255-172, 255-178, 255-210, 255-250, 0 };
 
136
                QColor c = dark;
 
137
                for( int i = 0; i<nPoints; i++ )
 
138
                { c.setAlpha( values[i] ); rg.setColorAt( x[i], c ); }
 
139
 
 
140
                QRectF r( pixmap->rect() );
 
141
                p.setBrush( rg );
 
142
                p.drawRect( r );
 
143
            }
 
144
 
 
145
            {
 
146
                // inner shadow
 
147
                QRadialGradient rg( u*8.5, u*8.5, u*8.5 );
 
148
 
 
149
                static const int nPoints(6);
 
150
                const qreal x[6] = { 0.61, 0.67, 0.7, 0.74, 0.78, 1 };
 
151
                const qreal values[6] = { 255-92, 255-100, 255-135, 255-205, 255-250, 0 };
 
152
                QColor c = light;
 
153
                for( int i = 0; i<nPoints; i++ )
 
154
                { c.setAlpha( values[i] ); rg.setColorAt( x[i], c ); }
 
155
 
 
156
                QRectF r( pixmap->rect() );
 
157
                p.setBrush( rg );
 
158
                p.drawRect( r );
 
159
            }
 
160
 
 
161
            windecoButtonGlowCache().insert( key, pixmap );
 
162
 
 
163
        }
 
164
 
 
165
        return *pixmap;
 
166
    }
 
167
 
 
168
    //_______________________________________________________________________
 
169
    QRegion DecoHelper::decoRoundedMask( const QRect& r, int left, int right, int top, int bottom ) const
 
170
    {
 
171
        // get rect geometry
 
172
        int x, y, w, h;
 
173
        r.getRect(&x, &y, &w, &h);
 
174
 
 
175
        QRegion mask(x + 3*left, y + 0*top, w-3*(left+right), h-0*(top+bottom));
 
176
        mask += QRegion(x + 0*left, y + 3*top, w-0*(left+right), h-3*(top+bottom));
 
177
        mask += QRegion(x + 1*left, y + 1*top, w-1*(left+right), h-1*(top+bottom));
 
178
 
 
179
        return mask;
 
180
    }
 
181
 
 
182
    //______________________________________________________________________________
 
183
    const QColor& DecoHelper::inactiveTitleBarTextColor( const QPalette& palette )
 
184
    {
 
185
 
 
186
        const quint32 key( palette.color(QPalette::Active, QPalette::Window).rgba() );
 
187
        QColor* out( _titleBarTextColorCache.object( key ) );
 
188
        if( !out )
 
189
        {
 
190
 
 
191
            // todo: reimplement cache
 
192
            const QColor ab = palette.color(QPalette::Active, QPalette::Window);
 
193
            const QColor af = palette.color(QPalette::Active, QPalette::WindowText);
 
194
            const QColor nb = palette.color(QPalette::Inactive, QPalette::Window);
 
195
            const QColor nf = palette.color(QPalette::Inactive, QPalette::WindowText);
 
196
            out = new QColor( reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))) );
 
197
            _titleBarTextColorCache.insert( key, out );
 
198
        }
 
199
 
 
200
        return *out;
 
201
    }
 
202
 
 
203
 
 
204
    //______________________________________________________________________________
 
205
    const QColor& DecoHelper::inactiveButtonTextColor( const QPalette& palette )
 
206
    {
 
207
 
 
208
        const quint32 key( palette.color(QPalette::Active, QPalette::Window).rgba() );
 
209
        QColor* out( _buttonTextColorCache.object( key ) );
 
210
        if( !out )
 
211
        {
 
212
 
 
213
            // todo: reimplement cache
 
214
            const QColor ab = palette.color(QPalette::Active, QPalette::Button);
 
215
            const QColor af = palette.color(QPalette::Active, QPalette::ButtonText);
 
216
            const QColor nb = palette.color(QPalette::Inactive, QPalette::Button);
 
217
            const QColor nf = palette.color(QPalette::Inactive, QPalette::ButtonText);
 
218
            out = new QColor( reduceContrast(nb, nf, qMax(qreal(2.5), KColorUtils::contrastRatio(ab, KColorUtils::mix(ab, af, 0.4)))) );
 
219
            _buttonTextColorCache.insert( key, out );
 
220
        }
 
221
 
 
222
        return *out;
 
223
    }
 
224
 
 
225
    //_________________________________________________________
 
226
    QColor DecoHelper::reduceContrast(const QColor &c0, const QColor &c1, double t) const
 
227
    {
 
228
        const double s( KColorUtils::contrastRatio(c0, c1) );
 
229
        if( s < t ) return c1;
 
230
 
 
231
        double l(0);
 
232
        double h(1.0);
 
233
        double x(s);
 
234
        double a;
 
235
        QColor r( c1 );
 
236
        for (int maxiter = 16; maxiter; --maxiter)
 
237
        {
 
238
 
 
239
            a = 0.5 * (l + h);
 
240
            r = KColorUtils::mix(c0, c1, a);
 
241
            x = KColorUtils::contrastRatio(c0, r);
 
242
 
 
243
            if ( std::abs(x - t) < 0.01) break;
 
244
            if (x > t) h = a;
 
245
            else l = a;
 
246
        }
 
247
 
 
248
        return r;
 
249
    }
 
250
 
 
251
}