summaryrefslogtreecommitdiff
path: root/noncore/styles/theme/ogfxeffect.cpp
Unidiff
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 @@
1/* This file is part of the KDE libraries
2 Copyright (C) 1998, 1999 Christian Tibirna <ctibirna@total.net>
3 (C) 1998, 1999 Daniel M. Duley <mosfet@kde.org>
4 (C) 1998, 1999 Dirk A. Mueller <mueller@kde.org>
5
6*/
7
8// $Id$
9
10#include <qimage.h>
11#include <qpainter.h>
12
13#include "ogfxeffect.h"
14
15
16//======================================================================
17//
18// Gradient effects
19//
20//======================================================================
21
22
23QPixmap& OGfxEffect::gradient(QPixmap &pixmap, const QColor &ca,
24 const QColor &cb, GradientType eff, int ncols)
25{
26 if(pixmap.depth() > 8 &&
27 (eff == VerticalGradient || eff == HorizontalGradient)) {
28
29 int rDiff, gDiff, bDiff;
30 int rca, gca, bca /*, rcb, gcb, bcb*/;
31
32 register int x, y;
33
34 rDiff = (/*rcb = */ cb.red()) - (rca = ca.red());
35 gDiff = (/*gcb = */ cb.green()) - (gca = ca.green());
36 bDiff = (/*bcb = */ cb.blue()) - (bca = ca.blue());
37
38 register int rl = rca << 16;
39 register int gl = gca << 16;
40 register int bl = bca << 16;
41
42 int rcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * rDiff;
43 int gcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * gDiff;
44 int bcdelta = ((1<<16) / (eff == VerticalGradient ? pixmap.height() : pixmap.width())) * bDiff;
45
46 QPainter p(&pixmap);
47
48 // these for-loops could be merged, but the if's in the inner loop
49 // would make it slow
50 switch(eff) {
51 case VerticalGradient:
52 for ( y = 0; y < pixmap.height(); y++ ) {
53 rl += rcdelta;
54 gl += gcdelta;
55 bl += bcdelta;
56
57 p.setPen(QColor(rl>>16, gl>>16, bl>>16));
58 p.drawLine(0, y, pixmap.width()-1, y);
59 }
60 break;
61 case HorizontalGradient:
62 for( x = 0; x < pixmap.width(); x++) {
63 rl += rcdelta;
64 gl += gcdelta;
65 bl += bcdelta;
66
67 p.setPen(QColor(rl>>16, gl>>16, bl>>16));
68 p.drawLine(x, 0, x, pixmap.height()-1);
69 }
70 break;
71 default:
72 ;
73 }
74 }
75 else {
76// QImage image = OGfxEffect::gradient(pixmap.size(), ca, cb,
77// (OGfxEffect::GradientType) eff, ncols);
78// pixmap.convertFromImage(image);
79 }
80
81 return pixmap;
82}
83
84
85//======================================================================
86//
87// Blend effects
88//
89//======================================================================
90
91
92QPixmap& OGfxEffect::blend(QPixmap &pixmap, float initial_intensity,
93 const QColor &bgnd, GradientType eff,
94 bool anti_dir, int ncols)
95{
96 QImage image = pixmap.convertToImage();
97 OGfxEffect::blend(image, initial_intensity, bgnd, eff, anti_dir);
98
99 unsigned int tmp;
100
101 if ( pixmap. depth ( ) <= 8 )
102 image. convertDepth ( pixmap. depth ( ));
103
104 pixmap.convertFromImage(image);
105
106 return pixmap;
107}
108
109
110QImage& OGfxEffect::blend(QImage &image, float initial_intensity,
111 const QColor &bgnd, GradientType eff,
112 bool anti_dir)
113{
114 if (image.width() == 0 || image.height() == 0) {
115 qDebug ( "Invalid image\n" );
116 return image;
117 }
118
119 int r_bgnd = bgnd.red(), g_bgnd = bgnd.green(), b_bgnd = bgnd.blue();
120 int r, g, b;
121 int ind;
122
123 unsigned int xi, xf, yi, yf;
124 unsigned int a;
125
126 // check the boundaries of the initial intesity param
127 float unaffected = 1;
128 if (initial_intensity > 1) initial_intensity = 1;
129 if (initial_intensity < -1) initial_intensity = -1;
130 if (initial_intensity < 0) {
131 unaffected = 1. + initial_intensity;
132 initial_intensity = 0;
133 }
134
135
136 float intensity = initial_intensity;
137 float var = 1. - initial_intensity;
138
139 if (anti_dir) {
140 initial_intensity = intensity = 1.;
141 var = -var;
142 }
143
144 register int x, y;
145
146 unsigned int *data = (unsigned int *)image.bits();
147
148 if( eff == VerticalGradient || eff == HorizontalGradient ) {
149
150 // set the image domain to apply the effect to
151 xi = 0, xf = image.width();
152 yi = 0, yf = image.height();
153 if (eff == VerticalGradient) {
154 if (anti_dir) yf = (int)(image.height() * unaffected);
155 else yi = (int)(image.height() * (1 - unaffected));
156 }
157 else {
158 if (anti_dir) xf = (int)(image.width() * unaffected);
159 else xi = (int)(image.height() * (1 - unaffected));
160 }
161
162 var /= (eff == VerticalGradient?yf-yi:xf-xi);
163
164 for (y = yi; y < (int)yf; y++) {
165 intensity = eff == VerticalGradient? intensity + var :
166 initial_intensity;
167 for (x = xi; x < (int)xf ; x++) {
168 if (eff == HorizontalGradient) intensity += var;
169 ind = x + image.width() * y ;
170 r = qRed (data[ind]) + (int)(intensity *
171 (r_bgnd - qRed (data[ind])));
172 g = qGreen(data[ind]) + (int)(intensity *
173 (g_bgnd - qGreen(data[ind])));
174 b = qBlue (data[ind]) + (int)(intensity *
175 (b_bgnd - qBlue (data[ind])));
176 if (r > 255) r = 255; if (r < 0 ) r = 0;
177 if (g > 255) g = 255; if (g < 0 ) g = 0;
178 if (b > 255) b = 255; if (b < 0 ) b = 0;
179 a = qAlpha(data[ind]);
180 data[ind] = qRgba(r, g, b, a);
181 }
182 }
183 }
184 else if (eff == DiagonalGradient || eff == CrossDiagonalGradient) {
185 float xvar = var / 2 / image.width(); // / unaffected;
186 float yvar = var / 2 / image.height(); // / unaffected;
187 float tmp;
188
189 for (x = 0; x < image.width() ; x++) {
190 tmp = xvar * (eff == DiagonalGradient? x : image.width()-x-1);
191 for (y = 0; y < image.height() ; y++) {
192 intensity = initial_intensity + tmp + yvar * y;
193 ind = x + image.width() * y ;
194 r = qRed (data[ind]) + (int)(intensity *
195 (r_bgnd - qRed (data[ind])));
196 g = qGreen(data[ind]) + (int)(intensity *
197 (g_bgnd - qGreen(data[ind])));
198 b = qBlue (data[ind]) + (int)(intensity *
199 (b_bgnd - qBlue (data[ind])));
200 if (r > 255) r = 255; if (r < 0 ) r = 0;
201 if (g > 255) g = 255; if (g < 0 ) g = 0;
202 if (b > 255) b = 255; if (b < 0 ) b = 0;
203 a = qAlpha(data[ind]);
204 data[ind] = qRgba(r, g, b, a);
205 }
206 }
207 }
208
209 else if (eff == RectangleGradient || eff == EllipticGradient) {
210 float xvar;
211 float yvar;
212
213 for (x = 0; x < image.width() / 2 + image.width() % 2; x++) {
214 xvar = var / image.width() * (image.width() - x*2/unaffected-1);
215 for (y = 0; y < image.height() / 2 + image.height() % 2; y++) {
216 yvar = var / image.height() * (image.height() - y*2/unaffected -1);
217
218 if (eff == RectangleGradient)
219 intensity = initial_intensity + QMAX(xvar, yvar);
220 else
221 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
222 if (intensity > 1) intensity = 1;
223 if (intensity < 0) intensity = 0;
224
225 //NW
226 ind = x + image.width() * y ;
227 r = qRed (data[ind]) + (int)(intensity *
228 (r_bgnd - qRed (data[ind])));
229 g = qGreen(data[ind]) + (int)(intensity *
230 (g_bgnd - qGreen(data[ind])));
231 b = qBlue (data[ind]) + (int)(intensity *
232 (b_bgnd - qBlue (data[ind])));
233 if (r > 255) r = 255; if (r < 0 ) r = 0;
234 if (g > 255) g = 255; if (g < 0 ) g = 0;
235 if (b > 255) b = 255; if (b < 0 ) b = 0;
236 a = qAlpha(data[ind]);
237 data[ind] = qRgba(r, g, b, a);
238
239 //NE
240 ind = image.width() - x - 1 + image.width() * y ;
241 r = qRed (data[ind]) + (int)(intensity *
242 (r_bgnd - qRed (data[ind])));
243 g = qGreen(data[ind]) + (int)(intensity *
244 (g_bgnd - qGreen(data[ind])));
245 b = qBlue (data[ind]) + (int)(intensity *
246 (b_bgnd - qBlue (data[ind])));
247 if (r > 255) r = 255; if (r < 0 ) r = 0;
248 if (g > 255) g = 255; if (g < 0 ) g = 0;
249 if (b > 255) b = 255; if (b < 0 ) b = 0;
250 a = qAlpha(data[ind]);
251 data[ind] = qRgba(r, g, b, a);
252 }
253 }
254
255 //CT loop is doubled because of stupid central row/column issue.
256 // other solution?
257 for (x = 0; x < image.width() / 2; x++) {
258 xvar = var / image.width() * (image.width() - x*2/unaffected-1);
259 for (y = 0; y < image.height() / 2; y++) {
260 yvar = var / image.height() * (image.height() - y*2/unaffected -1);
261
262 if (eff == RectangleGradient)
263 intensity = initial_intensity + QMAX(xvar, yvar);
264 else
265 intensity = initial_intensity + sqrt(xvar * xvar + yvar * yvar);
266 if (intensity > 1) intensity = 1;
267 if (intensity < 0) intensity = 0;
268
269 //SW
270 ind = x + image.width() * (image.height() - y -1) ;
271 r = qRed (data[ind]) + (int)(intensity *
272 (r_bgnd - qRed (data[ind])));
273 g = qGreen(data[ind]) + (int)(intensity *
274 (g_bgnd - qGreen(data[ind])));
275 b = qBlue (data[ind]) + (int)(intensity *
276 (b_bgnd - qBlue (data[ind])));
277 if (r > 255) r = 255; if (r < 0 ) r = 0;
278 if (g > 255) g = 255; if (g < 0 ) g = 0;
279 if (b > 255) b = 255; if (b < 0 ) b = 0;
280 a = qAlpha(data[ind]);
281 data[ind] = qRgba(r, g, b, a);
282
283 //SE
284 ind = image.width()-x-1 + image.width() * (image.height() - y - 1) ;
285 r = qRed (data[ind]) + (int)(intensity *
286 (r_bgnd - qRed (data[ind])));
287 g = qGreen(data[ind]) + (int)(intensity *
288 (g_bgnd - qGreen(data[ind])));
289 b = qBlue (data[ind]) + (int)(intensity *
290 (b_bgnd - qBlue (data[ind])));
291 if (r > 255) r = 255; if (r < 0 ) r = 0;
292 if (g > 255) g = 255; if (g < 0 ) g = 0;
293 if (b > 255) b = 255; if (b < 0 ) b = 0;
294 a = qAlpha(data[ind]);
295 data[ind] = qRgba(r, g, b, a);
296 }
297 }
298 }
299
300 else
301 qDebug ( "not implemented\n" );
302
303 return image;
304}
305
306#if 0
307// Not very efficient as we create a third big image...
308//
309QImage& KQGfxEffect::blend(QImage &image1, QImage &image2,
310 GradientType gt, int xf, int yf)
311{
312 if (image1.width() == 0 || image1.height() == 0 ||
313 image2.width() == 0 || image2.height() == 0)
314 return image1;
315
316 QImage image3;
317
318 image3 = KQGfxEffect::unbalancedGradient(image1.size(),
319 QColor(0,0,0), QColor(255,255,255),
320 gt, xf, yf, 0);
321
322 return blend(image1,image2,image3, Red); // Channel to use is arbitrary
323}
324#endif