00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "helper.h"
00022
00023 #include <KGlobalSettings>
00024 #include <KColorUtils>
00025 #include <KColorScheme>
00026
00027 #include <QtGui/QWidget>
00028 #include <QtGui/QPainter>
00029
00030 #include <math.h>
00031
00032 const double OxygenHelper::_shadowGain = 1.5;
00033
00034
00035
00036
00037
00038 OxygenHelper::OxygenHelper(const QByteArray &componentName)
00039 : _componentData(componentName, 0, KComponentData::SkipMainComponentRegistration)
00040 {
00041 _config = _componentData.config();
00042 _contrast = KGlobalSettings::contrastF(_config);
00043 _bgcontrast = 0.3;
00044
00045 m_backgroundCache.setMaxCost(64);
00046 m_windecoButtonCache.setMaxCost(64);
00047 }
00048
00049 KSharedConfigPtr OxygenHelper::config() const
00050 {
00051 return _config;
00052 }
00053
00054 void OxygenHelper::reloadConfig()
00055 {
00056 double old_contrast = _contrast;
00057
00058 _config->reparseConfiguration();
00059 _contrast = KGlobalSettings::contrastF(_config);
00060
00061 if (_contrast != old_contrast)
00062 invalidateCaches();
00063 }
00064
00065 void OxygenHelper::renderWindowBackground(QPainter *p, const QRect &clipRect, const QWidget *widget, const QPalette & pal)
00066 {
00067 const QWidget* window = widget->window();
00068
00069 const QWidget* w = widget;
00070 int x = 0, y = 0;
00071 while (!w->isWindow()) {
00072 x += w->geometry().x();
00073 y += w->geometry().y();
00074 w = w->parentWidget();
00075 }
00076
00077 if (clipRect.isValid()) {
00078 p->save();
00079 p->setClipRegion(clipRect,Qt::IntersectClip);
00080 }
00081 QRect r = window->rect();
00082 QColor color = pal.color(window->backgroundRole());
00083 int splitY = qMin(300, 3*r.height()/4);
00084
00085 QRect upperRect = QRect(-x, -y, r.width(), splitY);
00086 QPixmap tile = verticalGradient(color, splitY);
00087 p->drawTiledPixmap(upperRect, tile);
00088
00089 QRect lowerRect = QRect(-x, splitY-y, r.width(), r.height() - splitY);
00090 p->fillRect(lowerRect, backgroundBottomColor(color));
00091
00092 int radialW = qMin(600, r.width());
00093 int frameH = 32;
00094 QRect radialRect = QRect((r.width() - radialW) / 2-x, -y, radialW, 64-frameH);
00095 if (clipRect.intersects(radialRect))
00096 {
00097 tile = radialGradient(color, radialW);
00098 p->drawPixmap(radialRect, tile, QRect(0, frameH, radialW, 64-frameH));
00099 }
00100
00101 if (clipRect.isValid())
00102 p->restore();
00103 }
00104
00105 void OxygenHelper::invalidateCaches()
00106 {
00107 m_backgroundCache.clear();
00108 m_windecoButtonCache.clear();
00109 }
00110
00111 bool OxygenHelper::lowThreshold(const QColor &color)
00112 {
00113 QColor darker = KColorScheme::shade(color, KColorScheme::MidShade, 0.5);
00114 return KColorUtils::luma(darker) > KColorUtils::luma(color);
00115 }
00116
00117 QColor OxygenHelper::alphaColor(QColor color, double alpha)
00118 {
00119 if (alpha >= 1.0)
00120 return color;
00121 color.setAlphaF(qMax(0.0, alpha) * color.alphaF());
00122 return color;
00123 }
00124
00125 QColor OxygenHelper::backgroundRadialColor(const QColor &color) const
00126 {
00127 if (lowThreshold(color))
00128 return KColorScheme::shade(color, KColorScheme::LightShade, 0.0);
00129 else
00130 return KColorScheme::shade(color, KColorScheme::LightShade, _bgcontrast);
00131 }
00132
00133 QColor OxygenHelper::backgroundTopColor(const QColor &color) const
00134 {
00135 if (lowThreshold(color))
00136 return KColorScheme::shade(color, KColorScheme::MidlightShade, 0.0);
00137 else
00138 return KColorScheme::shade(color, KColorScheme::MidlightShade, _bgcontrast);
00139 }
00140
00141 QColor OxygenHelper::backgroundBottomColor(const QColor &color) const
00142 {
00143 QColor midColor = KColorScheme::shade(color, KColorScheme::MidShade, 0.0);
00144 if (lowThreshold(color))
00145 return midColor;
00146
00147 double by = KColorUtils::luma(color), my = KColorUtils::luma(midColor);
00148 return KColorUtils::shade(color, (my - by) * _bgcontrast);
00149 }
00150
00151 QColor OxygenHelper::calcLightColor(const QColor &color) const
00152 {
00153 return KColorScheme::shade(color, KColorScheme::LightShade, _contrast);
00154 }
00155
00156 QColor OxygenHelper::calcDarkColor(const QColor &color) const
00157 {
00158 if (lowThreshold(color))
00159 return KColorUtils::mix(calcLightColor(color), color, 0.2 + 0.8 * _contrast);
00160 else
00161 return KColorScheme::shade(color, KColorScheme::MidShade, _contrast);
00162 }
00163
00164 QColor OxygenHelper::calcShadowColor(const QColor &color) const
00165 {
00166 return KColorScheme::shade(KColorUtils::mix(QColor(255,255,255),color, color.alpha()*(1/255.0)),
00167 KColorScheme::ShadowShade, _contrast);
00168
00169 }
00170
00171 QColor OxygenHelper::backgroundColor(const QColor &color, int height, int y)
00172 {
00173 double h = height * 0.5;
00174 if (y > height>>1) {
00175 double a = double(y) / h;
00176 return KColorUtils::mix(backgroundTopColor(color), color, a);
00177 }
00178 else {
00179 double a = (double(y) - h) / h;
00180 return KColorUtils::mix(color, backgroundBottomColor(color), a);
00181 }
00182 }
00183
00184 QPixmap OxygenHelper::verticalGradient(const QColor &color, int height)
00185 {
00186 quint64 key = (quint64(color.rgba()) << 32) | height | 0x8000;
00187 QPixmap *pixmap = m_backgroundCache.object(key);
00188
00189 if (!pixmap)
00190 {
00191 pixmap = new QPixmap(32, height);
00192
00193 QLinearGradient gradient(0, 0, 0, height);
00194 gradient.setColorAt(0.0, backgroundTopColor(color));
00195 gradient.setColorAt(0.5, color);
00196 gradient.setColorAt(1.0, backgroundBottomColor(color));
00197
00198 QPainter p(pixmap);
00199 p.setCompositionMode(QPainter::CompositionMode_Source);
00200 p.fillRect(pixmap->rect(), gradient);
00201
00202 m_backgroundCache.insert(key, pixmap);
00203 }
00204
00205 return *pixmap;
00206 }
00207
00208 QPixmap OxygenHelper::radialGradient(const QColor &color, int width)
00209 {
00210 quint64 key = (quint64(color.rgba()) << 32) | width | 0xb000;
00211 QPixmap *pixmap = m_backgroundCache.object(key);
00212
00213 if (!pixmap)
00214 {
00215
00216 pixmap = new QPixmap(width, 64);
00217 pixmap->fill(QColor(0,0,0,0));
00218 QColor radialColor = backgroundRadialColor(color);
00219 radialColor.setAlpha(255);
00220 QRadialGradient gradient(64, 0, 64);
00221 gradient.setColorAt(0, radialColor);
00222 radialColor.setAlpha(101);
00223 gradient.setColorAt(0.5, radialColor);
00224 radialColor.setAlpha(37);
00225 gradient.setColorAt(0.75, radialColor);
00226 radialColor.setAlpha(0);
00227 gradient.setColorAt(1, radialColor);
00228
00229 QPainter p(pixmap);
00230 p.scale(width/128.0,1);
00231 p.fillRect(QRect(0,0,128,64), gradient);
00232
00233 m_backgroundCache.insert(key, pixmap);
00234 }
00235
00236 return *pixmap;
00237 }
00238
00239 void OxygenHelper::drawShadow(QPainter &p, const QColor &color, int size) const
00240 {
00241 double m = double(size-2)*0.5;
00242
00243 const double offset = 0.8;
00244 double k0 = (m-4.0) / m;
00245 QRadialGradient shadowGradient(m+1.0, m+offset+1.0, m);
00246 for (int i = 0; i < 8; i++) {
00247 double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00248 double a = (cos(3.14159 * i * 0.125) + 1.0) * 0.25;
00249 shadowGradient.setColorAt(k1, alphaColor(color, a * _shadowGain));
00250 }
00251 shadowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00252 p.setBrush(shadowGradient);
00253 p.drawEllipse(QRectF(0, 0, size, size));
00254 }
00255
00256 QLinearGradient OxygenHelper::decoGradient(const QRect &r, const QColor &color)
00257 {
00258 QColor light = KColorScheme::shade(color, KColorScheme::LightShade, _contrast * 0.7);
00259 QColor dark = KColorScheme::shade(color, KColorScheme::DarkShade, _contrast * 0.7);
00260 double y = KColorUtils::luma(color);
00261 double yd = KColorUtils::luma(dark);
00262 double yl = KColorUtils::luma(light);
00263
00264 QLinearGradient gradient(r.topLeft(), r.bottomLeft());
00265 if (yd > y)
00266 {
00267 gradient.setColorAt(0.2, color);
00268 gradient.setColorAt(0.8, dark);
00269 }
00270 else if (yl < y)
00271 {
00272 gradient.setColorAt(0.2, light);
00273 gradient.setColorAt(0.8, color);
00274 }
00275 else
00276 {
00277 gradient.setColorAt(0.2, dark);
00278 gradient.setColorAt(0.5, color);
00279 gradient.setColorAt(0.8, light);
00280 }
00281
00282 return gradient;
00283 }
00284
00285 QPixmap OxygenHelper::windecoButton(const QColor &color, bool pressed, int size)
00286 {
00287 quint64 key = (quint64(color.rgba()) << 32) | (size << 1) | pressed;
00288 QPixmap *pixmap = m_windecoButtonCache.object(key);
00289
00290 if (!pixmap)
00291 {
00292 pixmap = new QPixmap(size, size);
00293 pixmap->fill(Qt::transparent);
00294
00295 QPainter p(pixmap);
00296 p.setRenderHints(QPainter::Antialiasing);
00297 p.setPen(Qt::NoPen);
00298 p.setWindow(0,0,21,21);
00299
00300 QColor light = alphaColor(calcLightColor(color), 0.2);
00301 QColor dark = alphaColor(calcShadowColor(color), 0.2);
00302
00303
00304 int penWidth = 1 / (size / 21.0);
00305
00306
00307 QLinearGradient innerGradient(0, 0, 0, 21);
00308 if (!pressed) {
00309 innerGradient.setColorAt(0.0, Qt::transparent);
00310 innerGradient.setColorAt(1.0, alphaColor(color, 0.1));
00311 } else {
00312 innerGradient.setColorAt(0.0, alphaColor(color, 0.1));
00313 innerGradient.setColorAt(1.0, Qt::transparent);
00314 }
00315 p.setBrush(innerGradient);
00316 p.drawEllipse(QRectF(3.0,3.0,15.0,15.0));
00317
00318
00319 QLinearGradient darklg(QPoint(0,0), QPoint(21,0));
00320 darklg.setColorAt(0.0, Qt::transparent);
00321 darklg.setColorAt(0.5, dark);
00322 darklg.setColorAt(1.0, Qt::transparent);
00323
00324 QLinearGradient lightlg(QPoint(0,0), QPoint(21,0));
00325 lightlg.setColorAt(0.0, Qt::transparent);
00326 lightlg.setColorAt(0.5, light);
00327 lightlg.setColorAt(1.0, Qt::transparent);
00328
00329 p.setPen(QPen(darklg, 1.5*penWidth));
00330 for(int i = 0; i < 2; ++i)
00331 p.drawEllipse(QRectF(3.0,2.7,15.0,15.0));
00332 p.setPen(QPen(lightlg, 1.0*penWidth));
00333 for(int i = 0; i < 8; ++i)
00334 p.drawEllipse(QRectF(3.0,4.0,15.0,15.0));
00335
00336 m_windecoButtonCache.insert(key, pixmap);
00337 }
00338
00339 return *pixmap;
00340 }
00341
00342 QPixmap OxygenHelper::glow(const QColor &color, int size, int rsize)
00343 {
00344 QPixmap pixmap(rsize, rsize);
00345 pixmap.fill(QColor(0,0,0,0));
00346
00347 QPainter p(&pixmap);
00348 p.setRenderHints(QPainter::Antialiasing);
00349 p.setPen(Qt::NoPen);
00350 p.setWindow(0,0,size,size);
00351
00352 QRectF r(0, 0, size, size);
00353 double m = double(size)*0.5;
00354
00355 const double width = 3.0;
00356 const double bias = _glowBias * double(size) / double(rsize);
00357 double k0 = (m-width+bias) / m;
00358 QRadialGradient glowGradient(m, m, m);
00359 for (int i = 0; i < 8; i++) {
00360 double k1 = (k0 * double(8 - i) + double(i)) * 0.125;
00361 double a = 1.0 - sqrt(i * 0.125);
00362 glowGradient.setColorAt(k1, alphaColor(color, a));
00363 }
00364 glowGradient.setColorAt(1.0, alphaColor(color, 0.0));
00365
00366
00367 p.setBrush(glowGradient);
00368 p.drawEllipse(r);
00369
00370
00371 p.setCompositionMode(QPainter::CompositionMode_DestinationOut);
00372 p.setBrush(QBrush(Qt::black));
00373 p.drawEllipse(r.adjusted(width, width, -width, -width));
00374
00375 p.end();
00376
00377 return pixmap;
00378 }
00379
00380 void OxygenHelper::drawFloatFrame(QPainter *p, const QRect r, const QColor &color) const
00381 {
00382 p->setRenderHint(QPainter::Antialiasing);
00383 QRect frame = r;
00384 frame.adjust(1,1,-1,-1);
00385 int x,y,w,h;
00386 frame.getRect(&x, &y, &w, &h);
00387
00388 QColor light = calcLightColor(backgroundTopColor(color));
00389 QColor dark = calcDarkColor(color);
00390
00391 p->setBrush(Qt::NoBrush);
00392
00393 if (0) {
00394 QColor shadow = calcShadowColor(color);
00395 p->setPen(alphaColor(shadow, 0.1));
00396 p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00397 p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00398 p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00399 p->setPen(alphaColor(shadow, 0.3));
00400 p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h));
00401 p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h));
00402 p->setPen(alphaColor(shadow, 0.4));
00403 p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00404 p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00405 p->setPen(alphaColor(shadow, 0.55));
00406 p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00407 }
00408 else if (1) {
00409 QColor shadow = KColorUtils::darken(color, 0.0, 0.0);
00410 p->setPen(KColorUtils::darken(shadow, 0.1));
00411 p->drawLine(QPointF(x+4, y-0.5), QPointF(x+w-4, y-0.5));
00412 p->drawArc(QRectF(x-0.5, y-0.5, 11, 11),90*16, 90*16);
00413 p->drawArc(QRectF(x+w-11+0.5, y-0.5, 11, 11), 0, 90*16);
00414 p->setPen(KColorUtils::darken(shadow, 0.3));
00415 p->drawLine(QPointF(x-0.5, y+4), QPointF(x-0.5, y+h-4));
00416 p->drawLine(QPointF(x+w+0.5, y+4), QPointF(x+w+0.5, y+h-4));
00417 p->setPen(KColorUtils::darken(shadow, 0.4));
00418 p->drawArc(QRectF(0.5, y+h-11+0.5, 11, 11),180*16, 90*16);
00419 p->drawArc(QRectF(x+w-11+0.5, y+h-11+0.5, 11, 11),270*16, 90*16);
00420 p->setPen(KColorUtils::darken(shadow, 0.55));
00421 p->drawLine(QPointF(x+4, y+h+0.5), QPointF(x+w-4, y+h+0.5));
00422 }
00423
00424 p->setPen(QPen(light, 1.2));
00425 p->drawLine(QPointF(x+4, y+0.6), QPointF(x+w-4, y+0.6));
00426 QLinearGradient lg = QLinearGradient(0.0, 1.5, 0.0, 4.5);
00427 lg.setColorAt(0, light);
00428 light = calcLightColor(backgroundBottomColor(color));
00429 lg.setColorAt(1, light);
00430 p->setPen(QPen(lg, 1.2));
00431 p->drawArc(QRectF(x+0.6, y+0.6, 9, 9),90*16, 90*16);
00432 p->drawArc(QRectF(x+w-9-0.6, y+0.6, 9, 9), 0, 90*16);
00433 p->drawLine(QPointF(x+0.6, y+4), QPointF(x+0.6, y+h-4));
00434 p->drawLine(QPointF(x+w-0.6, y+4), QPointF(x+w-0.6, y+h-4));
00435
00436 return;
00437 }