summaryrefslogtreecommitdiff
path: root/noncore/styles/theme/ogfxeffect.cpp
Side-by-side diff
Diffstat (limited to 'noncore/styles/theme/ogfxeffect.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/styles/theme/ogfxeffect.cpp324
1 files changed, 324 insertions, 0 deletions
diff --git a/noncore/styles/theme/ogfxeffect.cpp b/noncore/styles/theme/ogfxeffect.cpp
new file mode 100644
index 0000000..a991728
--- a/dev/null
+++ b/noncore/styles/theme/ogfxeffect.cpp
@@ -0,0 +1,324 @@
+/* This file is part of the KDE libraries
+ Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
+ (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
+ (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
+
+*/
+
+// $Id$
+
+#include <qimage.h>
+#include <qpainter.h>
+
+#include "ogfxeffect.h"
+
+
+//======================================================================
+//
+// Gradient effects
+//
+//======================================================================
+
+
+QPixmap& OGfxEffect::gradient(QPixmap &pixmap, const QColor &ca,
+ const QColor &cb, GradientType eff, int ncols)
+{
+ if(pixmap.depth() > 8 &&
+ (eff == VerticalGradient || eff == HorizontalGradient)) {
+
+ int rDiff, gDiff, bDiff;
+ int rca, gca, bca /*, rcb, gcb, bcb*/;
+
+ register int x, y;
+
+ rDiff = (/*rcb = */ cb.red()) - (rca = ca.red());
+ gDiff = (/*gcb = */ cb.green()) - (gca = ca.green());
+ bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue());
+
+ register int rl = rca << 16;
+ register int gl = gca << 16;
+ register int bl = bca << 16;
+
+ int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff;
+ int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff;
+ int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff;
+
+ QPainter p(&pixmap);
+
+ // these for-loops could be merged, but the if's in the inner loop
+ // would make it slow
+ switch(eff) {
+ case VerticalGradient:
+ for ( y = 0; y < pixmap.height(); y++ ) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(0, y, pixmap.width()-1, y);
+ }
+ break;
+ case HorizontalGradient:
+ for( x = 0; x < pixmap.width(); x++) {
+ rl += rcdelta;
+ gl += gcdelta;
+ bl += bcdelta;
+
+ p.setPen(QColor(rl>>16, gl>>16, bl>>16));
+ p.drawLine(x, 0, x, pixmap.height()-1);
+ }
+ break;
+ default:
+ ;
+ }
+ }
+ else {
+// QImage image = OGfxEffect::gradient(pixmap.size(), ca, cb,
+// (OGfxEffect::GradientType) eff, ncols);
+// pixmap.convertFromImage(image);
+ }
+
+ return pixmap;
+}
+
+
+//======================================================================
+//
+// Blend effects
+//
+//======================================================================
+
+
+QPixmap& OGfxEffect::blend(QPixmap &pixmap, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir, int ncols)
+{
+ QImage image = pixmap.convertToImage();
+ OGfxEffect::blend(image, initial_intensity, bgnd, eff, anti_dir);
+
+ unsigned int tmp;
+
+ if ( pixmap. depth ( ) <= 8 )
+ image. convertDepth ( pixmap. depth ( ));
+
+ pixmap.convertFromImage(image);
+
+ return pixmap;
+}
+
+
+QImage& OGfxEffect::blend(QImage &image, float initial_intensity,
+ const QColor &bgnd, GradientType eff,
+ bool anti_dir)
+{
+ if (image.width() == 0 || image.height() == 0) {
+ qDebug ( "Invalid image\n" );
+ return image;
+ }
+
+ int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
+ int r, g, b;
+ int ind;
+
+ unsigned int xi, xf, yi, yf;
+ unsigned int a;
+
+ // check the boundaries of the initial intesity param
+ float unaffected = 1;
+ if (initial_intensity > 1) initial_intensity = 1;
+ if (initial_intensity < -1) initial_intensity = -1;
+ if (initial_intensity < 0) {
+ unaffected = 1. + initial_intensity;
+ initial_intensity = 0;
+ }
+
+
+ float intensity = initial_intensity;
+ float var = 1. - initial_intensity;
+
+ if (anti_dir) {
+ initial_intensity = intensity = 1.;
+ var = -var;
+ }
+
+ register int x, y;
+
+ unsigned int *data = (unsigned int *)image.bits();
+
+ if( eff == VerticalGradient || eff == HorizontalGradient ) {
+
+ // set the image domain to apply the effect to
+ xi = 0, xf = image.width();
+ yi = 0, yf = image.height();
+ if (eff == VerticalGradient) {
+ if (anti_dir) yf = (int)(image.height() * unaffected);
+ else yi = (int)(image.height() * (1 - unaffected));
+ }
+ else {
+ if (anti_dir) xf = (int)(image.width() * unaffected);
+ else xi = (int)(image.height() * (1 - unaffected));
+ }
+
+ var /= (eff == VerticalGradient?yf-yi:xf-xi);
+
+ for (y = yi; y < (int)yf; y++) {
+ intensity = eff == VerticalGradient? intensity + var :
+ initial_intensity;
+ for (x = xi; x < (int)xf ; x++) {
+ if (eff == HorizontalGradient) intensity += var;
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+ else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
+ float xvar = var / 2 / image.width(); // / unaffected;
+ float yvar = var / 2 / image.height(); // / unaffected;
+ float tmp;
+
+ for (x = 0; x < image.width() ; x++) {
+ tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
+ for (y = 0; y < image.height() ; y++) {
+ intensity = initial_intensity + tmp + yvar * y;
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+
+ else if (eff == RectangleGradient || eff == EllipticGradient) {
+ float xvar;
+ float yvar;
+
+ for (x = 0; x < image.width() / 2 + image.width() % 2; x++) {
+ xvar = var / image.width() * (image.width() - x*2/unaffected-1);
+ for (y = 0; y < image.height() / 2 + image.height() % 2; y++) {
+ yvar = var / image.height() * (image.height() - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //NW
+ ind = x + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //NE
+ ind = image.width() - x - 1 + image.width() * y ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+
+ //CT loop is doubled because of stupid central row/column issue.
+ // other solution?
+ for (x = 0; x < image.width() / 2; x++) {
+ xvar = var / image.width() * (image.width() - x*2/unaffected-1);
+ for (y = 0; y < image.height() / 2; y++) {
+ yvar = var / image.height() * (image.height() - y*2/unaffected -1);
+
+ if (eff == RectangleGradient)
+ intensity = initial_intensity + QMAX(xvar, yvar);
+ else
+ intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
+ if (intensity > 1) intensity = 1;
+ if (intensity < 0) intensity = 0;
+
+ //SW
+ ind = x + image.width() * (image.height() - y -1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+
+ //SE
+ ind = image.width()-x-1 + image.width() * (image.height() - y - 1) ;
+ r = qRed (data[ind]) + (int)(intensity *
+ (r_bgnd - qRed (data[ind])));
+ g = qGreen(data[ind]) + (int)(intensity *
+ (g_bgnd - qGreen(data[ind])));
+ b = qBlue (data[ind]) + (int)(intensity *
+ (b_bgnd - qBlue (data[ind])));
+ if (r > 255) r = 255; if (r < 0 ) r = 0;
+ if (g > 255) g = 255; if (g < 0 ) g = 0;
+ if (b > 255) b = 255; if (b < 0 ) b = 0;
+ a = qAlpha(data[ind]);
+ data[ind] = qRgba(r, g, b, a);
+ }
+ }
+ }
+
+ else
+ qDebug ( "not implemented\n" );
+
+ return image;
+}
+
+#if 0
+// Not very efficient as we create a third big image...
+//
+QImage& KQGfxEffect::blend(QImage &image1, QImage &image2,
+ GradientType gt, int xf, int yf)
+{
+ if (image1.width() == 0 || image1.height() == 0 ||
+ image2.width() == 0 || image2.height() == 0)
+ return image1;
+
+ QImage image3;
+
+ image3 = KQGfxEffect::unbalancedGradient(image1.size(),
+ QColor(0,0,0), QColor(255,255,255),
+ gt, xf, yf, 0);
+
+ return blend(image1,image2,image3, Red); // Channel to use is arbitrary
+}
+#endif