]> icculus.org git repositories - dana/openbox.git/blob - render/gradient.c
remove debug prints
[dana/openbox.git] / render / gradient.c
1 #include <glib.h>
2 #include "render.h"
3 #include "gradient.h"
4 #include "../kernel/openbox.h"
5 #include "color.h"
6
7 void gradient_render(Surface *sf, int w, int h)
8 {
9     pixel32 *data = sf->data.planar.pixel_data;
10     pixel32 current;
11     unsigned int r,g,b;
12     int off, x;
13
14     switch (sf->data.planar.grad) {
15     case Background_Solid: /* already handled */
16         return;
17     case Background_Vertical:
18         gradient_vertical(sf, w, h);
19         break;
20     case Background_Horizontal:
21         gradient_horizontal(sf, w, h);
22         break;
23     case Background_Diagonal:
24         gradient_diagonal(sf, w, h);
25         break;
26     case Background_CrossDiagonal:
27         gradient_crossdiagonal(sf, w, h);
28         break;
29     case Background_Pyramid:
30         gradient_pyramid(sf, w, h);
31         break;
32     case Background_PipeCross:
33         gradient_pipecross(sf, w, h);
34         break;
35     case Background_Rectangle:
36         gradient_rectangle(sf, w, h);
37         break;
38     default:
39         g_message("unhandled gradient");
40         return;
41     }
42   
43     if (sf->data.planar.relief == Flat && sf->data.planar.border) {
44         r = sf->data.planar.border_color->r;
45         g = sf->data.planar.border_color->g;
46         b = sf->data.planar.border_color->b;
47         current = (r << default_red_offset)
48             + (g << default_green_offset)
49             + (b << default_blue_offset);
50         for (off = 0, x = 0; x < w; ++x, off++) {
51             *(data + off) = current;
52             *(data + off + ((h-1) * w)) = current;
53         }
54         for (off = 0, x = 0; x < h; ++x, off++) {
55             *(data + (off * w)) = current;
56             *(data + (off * w) + w - 1) = current;
57         }
58     }
59
60     if (sf->data.planar.relief != Flat) {
61         if (sf->data.planar.bevel == Bevel1) {
62             for (off = 1, x = 1; x < w - 1; ++x, off++)
63                 highlight(data + off,
64                           data + off + (h-1) * w,
65                           sf->data.planar.relief==Raised);
66             for (off = 0, x = 0; x < h; ++x, off++)
67                 highlight(data + off * w,
68                           data + off * w + w - 1,
69                           sf->data.planar.relief==Raised);
70         }
71
72         if (sf->data.planar.bevel == Bevel2) {
73             for (off = 2, x = 2; x < w - 2; ++x, off++)
74                 highlight(data + off + w,
75                           data + off + (h-2) * w,
76                           sf->data.planar.relief==Raised);
77             for (off = 1, x = 1; x < h-1; ++x, off++)
78                 highlight(data + off * w + 1,
79                           data + off * w + w - 2,
80                           sf->data.planar.relief==Raised);
81         }
82     }
83 }
84
85
86
87 void gradient_vertical(Surface *sf, int w, int h)
88 {
89     pixel32 *data = sf->data.planar.pixel_data;
90     pixel32 current;
91     float dr, dg, db;
92     unsigned int r,g,b;
93     int x, y;
94
95     dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
96     dr/= (float)h;
97
98     dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
99     dg/= (float)h;
100
101     db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
102     db/= (float)h;
103
104     for (y = 0; y < h; ++y) {
105         r = sf->data.planar.primary->r + (int)(dr * y);
106         g = sf->data.planar.primary->g + (int)(dg * y);
107         b = sf->data.planar.primary->b + (int)(db * y);
108         current = (r << default_red_offset)
109             + (g << default_green_offset)
110             + (b << default_blue_offset);
111         for (x = 0; x < w; ++x, ++data)
112             *data = current;
113     }
114 }
115
116 void gradient_horizontal(Surface *sf, int w, int h)
117 {
118     pixel32 *data = sf->data.planar.pixel_data;
119     pixel32 current;
120     float dr, dg, db;
121     unsigned int r,g,b;
122     int x, y;
123
124     dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
125     dr/= (float)w;
126
127     dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
128     dg/= (float)w;
129
130     db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
131     db/= (float)w;
132
133     for (x = 0; x < w; ++x, ++data) {
134         r = sf->data.planar.primary->r + (int)(dr * x);
135         g = sf->data.planar.primary->g + (int)(dg * x);
136         b = sf->data.planar.primary->b + (int)(db * x);
137         current = (r << default_red_offset)
138             + (g << default_green_offset)
139             + (b << default_blue_offset);
140         for (y = 0; y < h; ++y)
141             *(data + y*w) = current;
142     }
143 }
144
145 void gradient_diagonal(Surface *sf, int w, int h)
146 {
147     pixel32 *data = sf->data.planar.pixel_data;
148     pixel32 current;
149     float drx, dgx, dbx, dry, dgy, dby;
150     unsigned int r,g,b;
151     int x, y;
152
153     for (y = 0; y < h; ++y) {
154         drx = (float)(sf->data.planar.secondary->r -
155                       sf->data.planar.primary->r);
156         dry = drx/(float)h;
157         drx/= (float)w;
158
159         dgx = (float)(sf->data.planar.secondary->g -
160                       sf->data.planar.primary->g);
161         dgy = dgx/(float)h;
162         dgx/= (float)w;
163
164         dbx = (float)(sf->data.planar.secondary->b -
165                       sf->data.planar.primary->b);
166         dby = dbx/(float)h;
167         dbx/= (float)w;
168         for (x = 0; x < w; ++x, ++data) {
169             r = sf->data.planar.primary->r +
170                 ((int)(drx * x) + (int)(dry * y))/2;
171             g = sf->data.planar.primary->g +
172                 ((int)(dgx * x) + (int)(dgy * y))/2;
173             b = sf->data.planar.primary->b +
174                 ((int)(dbx * x) + (int)(dby * y))/2;
175             current = (r << default_red_offset)
176                 + (g << default_green_offset)
177                 + (b << default_blue_offset);
178             *data = current;
179         }
180     }
181 }
182
183 void gradient_crossdiagonal(Surface *sf, int w, int h)
184 {
185     pixel32 *data = sf->data.planar.pixel_data;
186     pixel32 current;
187     float drx, dgx, dbx, dry, dgy, dby;
188     unsigned int r,g,b;
189     int x, y;
190
191     for (y = 0; y < h; ++y) {
192         drx = (float)(sf->data.planar.secondary->r -
193                       sf->data.planar.primary->r);
194         dry = drx/(float)h;
195         drx/= (float)w;
196
197         dgx = (float)(sf->data.planar.secondary->g -
198                       sf->data.planar.primary->g);
199         dgy = dgx/(float)h;
200         dgx/= (float)w;
201
202         dbx = (float)(sf->data.planar.secondary->b -
203                       sf->data.planar.primary->b);
204         dby = dbx/(float)h;
205         dbx/= (float)w;
206         for (x = w; x > 0; --x, ++data) {
207             r = sf->data.planar.primary->r +
208                 ((int)(drx * (x-1)) + (int)(dry * y))/2;
209             g = sf->data.planar.primary->g +
210                 ((int)(dgx * (x-1)) + (int)(dgy * y))/2;
211             b = sf->data.planar.primary->b +
212                 ((int)(dbx * (x-1)) + (int)(dby * y))/2;
213             current = (r << default_red_offset)
214                 + (g << default_green_offset)
215                 + (b << default_blue_offset);
216             *data = current;
217         }
218     }
219 }
220
221 void highlight(pixel32 *x, pixel32 *y, gboolean raised)
222 {
223     int r, g, b;
224
225     pixel32 *up, *down;
226     if (raised) {
227         up = x;
228         down = y;
229     } else {
230         up = y;
231         down = x;
232     }
233     r = (*up >> default_red_offset) & 0xFF;
234     r += r >> 1;
235     g = (*up >> default_green_offset) & 0xFF;
236     g += g >> 1;
237     b = (*up >> default_blue_offset) & 0xFF;
238     b += b >> 1;
239     if (r > 0xFF) r = 0xFF;
240     if (g > 0xFF) g = 0xFF;
241     if (b > 0xFF) b = 0xFF;
242     *up = (r << default_red_offset) + (g << default_green_offset)
243         + (b << default_blue_offset);
244   
245     r = (*down >> default_red_offset) & 0xFF;
246     r = (r >> 1) + (r >> 2);
247     g = (*down >> default_green_offset) & 0xFF;
248     g = (g >> 1) + (g >> 2);
249     b = (*down >> default_blue_offset) & 0xFF;
250     b = (b >> 1) + (b >> 2);
251     *down = (r << default_red_offset) + (g << default_green_offset)
252         + (b << default_blue_offset);
253 }
254
255 static void create_bevel_colors(Appearance *l)
256 {
257     int r, g, b;
258
259     /* light color */
260     r = l->surface.data.planar.primary->r;
261     r += r >> 1;
262     g = l->surface.data.planar.primary->g;
263     g += g >> 1;
264     b = l->surface.data.planar.primary->b;
265     b += b >> 1;
266     if (r > 0xFF) r = 0xFF;
267     if (g > 0xFF) g = 0xFF;
268     if (b > 0xFF) b = 0xFF;
269     g_assert(!l->surface.data.planar.bevel_light);
270     l->surface.data.planar.bevel_light = color_new(r, g, b);
271     color_allocate_gc(l->surface.data.planar.bevel_light);
272
273     /* dark color */
274     r = l->surface.data.planar.primary->r;
275     r = (r >> 1) + (r >> 2);
276     g = l->surface.data.planar.primary->g;
277     g = (g >> 1) + (g >> 2);
278     b = l->surface.data.planar.primary->b;
279     b = (b >> 1) + (b >> 2);
280     g_assert(!l->surface.data.planar.bevel_dark);
281     l->surface.data.planar.bevel_dark = color_new(r, g, b);
282     color_allocate_gc(l->surface.data.planar.bevel_dark);
283 }
284
285 void gradient_solid(Appearance *l, int x, int y, int w, int h) 
286 {
287     pixel32 pix;
288     int i, a, b;
289     PlanarSurface *sp = &l->surface.data.planar;
290     int left = x, top = y, right = x + w - 1, bottom = y + h - 1;
291
292     if (sp->primary->gc == None)
293         color_allocate_gc(sp->primary);
294     pix = (sp->primary->r << default_red_offset)
295         + (sp->primary->g << default_green_offset)
296         + (sp->primary->b << default_blue_offset);
297
298     for (a = 0; a < l->area.width; a++)
299         for (b = 0; b < l->area.height; b++)
300             sp->pixel_data[a + b*l->area.width] = pix;
301
302     XFillRectangle(ob_display, l->pixmap, sp->primary->gc,
303                    x, y, w, h);
304
305     if (sp->interlaced) {
306         if (sp->secondary->gc == None)
307             color_allocate_gc(sp->secondary);
308         for (i = y; i < h; i += 2)
309             XDrawLine(ob_display, l->pixmap, sp->secondary->gc,
310                       x, i, w, i);
311     }
312
313     switch (sp->relief) {
314     case Raised:
315         if (!sp->bevel_dark)
316             create_bevel_colors(l);
317
318         switch (sp->bevel) {
319         case Bevel1:
320             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
321                       left, bottom, right, bottom);
322             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
323                       right, bottom, right, top);
324                 
325             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
326                       left, top, right, top);
327             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
328                       left, bottom, left, top);
329             break;
330         case Bevel2:
331             XDrawLine(ob_display, l->pixmap,
332                       sp->bevel_dark->gc,
333                       left + 1, bottom - 2, right - 2, bottom - 2);
334             XDrawLine(ob_display, l->pixmap,
335                       sp->bevel_dark->gc,
336                       right - 2, bottom - 2, right - 2, top + 1);
337
338             XDrawLine(ob_display, l->pixmap,
339                       sp->bevel_light->gc,
340                       left + 1, top + 1, right - 2, top + 1);
341             XDrawLine(ob_display, l->pixmap,
342                       sp->bevel_light->gc,
343                       left + 1, bottom - 2, left + 1, top + 1);
344             break;
345         default:
346             g_assert_not_reached(); /* unhandled BevelType */
347         }
348         break;
349     case Sunken:
350         if (!sp->bevel_dark)
351             create_bevel_colors(l);
352
353         switch (sp->bevel) {
354         case Bevel1:
355             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
356                       left, bottom, right, bottom);
357             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
358                       right, bottom, right, top);
359       
360             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
361                       left, top, right, top);
362             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
363                       left, bottom, left, top);
364             break;
365         case Bevel2:
366             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
367                       left + 1, bottom - 2, right - 2, bottom - 2);
368             XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
369                       right - 2, bottom - 2, right - 2, top + 1);
370       
371             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
372                       left + 1, top + 1, right - 2, top + 1);
373             XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
374                       left + 1, bottom - 2, left + 1, top + 1);
375
376             break;
377         default:
378             g_assert_not_reached(); /* unhandled BevelType */
379         }
380         break;
381     case Flat:
382         if (sp->border)
383             XDrawRectangle(ob_display, l->pixmap, sp->border_color->gc,
384                            left, top, right, bottom);
385         break;
386     default:  
387         g_assert_not_reached(); /* unhandled ReliefType */
388     }
389 }
390
391 void gradient_pyramid(Surface *sf, int inw, int inh)
392 {
393     pixel32 *data = sf->data.planar.pixel_data;
394     pixel32 *end = data + inw*inh;
395     pixel32 current;
396     float drx, dgx, dbx, dry, dgy, dby;
397     unsigned int r,g,b;
398     int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
399     for (y = 0; y < h; ++y) {
400         drx = (float)(sf->data.planar.secondary->r -
401                       sf->data.planar.primary->r);
402         dry = drx/(float)h;
403         drx/= (float)w;
404
405         dgx = (float)(sf->data.planar.secondary->g -
406                       sf->data.planar.primary->g);
407         dgy = dgx/(float)h;
408         dgx/= (float)w;
409
410         dbx = (float)(sf->data.planar.secondary->b -
411                       sf->data.planar.primary->b);
412         dby = dbx/(float)h;
413         dbx/= (float)w;
414         for (x = 0; x < w; ++x, data) {
415             r = sf->data.planar.primary->r +
416                 ((int)(drx * x) + (int)(dry * y))/2;
417             g = sf->data.planar.primary->g +
418                 ((int)(dgx * x) + (int)(dgy * y))/2;
419             b = sf->data.planar.primary->b +
420                 ((int)(dbx * x) + (int)(dby * y))/2;
421             current = (r << default_red_offset)
422                 + (g << default_green_offset)
423                 + (b << default_blue_offset);
424             *(data+x) = current;
425             *(data+inw-x) = current;
426             *(end-x) = current;
427             *(end-(inw-x)) = current;
428         }
429         data+=inw;
430         end-=inw;
431     }
432 }
433
434 void gradient_rectangle(Surface *sf, int inw, int inh)
435 {
436     pixel32 *data = sf->data.planar.pixel_data;
437     pixel32 *end = data + inw*inh;
438     pixel32 current;
439     float drx, dgx, dbx, dry, dgy, dby;
440     unsigned int r,g,b;
441     int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
442     int val;
443
444     for (y = 0; y < h; ++y) {
445         drx = (float)(sf->data.planar.primary->r -
446                       sf->data.planar.secondary->r);
447         dry = drx/(float)h;
448         drx/= (float)w;
449
450         dgx = (float)(sf->data.planar.primary->g -
451                       sf->data.planar.secondary->g);
452         dgy = dgx/(float)h;
453         dgx/= (float)w;
454
455         dbx = (float)(sf->data.planar.primary->b -
456                       sf->data.planar.secondary->b);
457         dby = dbx/(float)h;
458         dbx/= (float)w;
459         for (x = 0; x < w; ++x, data) {
460             if ((float)x/(float)w < (float)y/(float)h) val = (int)(drx * x);
461             else val = (int)(dry * y);
462
463             r = sf->data.planar.secondary->r + val;
464             g = sf->data.planar.secondary->g + val;
465             b = sf->data.planar.secondary->b + val;
466             current = (r << default_red_offset)
467                 + (g << default_green_offset)
468                 + (b << default_blue_offset);
469             *(data+x) = current;
470             *(data+inw-x) = current;
471             *(end-x) = current;
472             *(end-(inw-x)) = current;
473         }
474         data+=inw;
475         end-=inw;
476     }
477 }
478
479 void gradient_pipecross(Surface *sf, int inw, int inh)
480 {
481     pixel32 *data = sf->data.planar.pixel_data;
482     pixel32 *end = data + inw*inh;
483     pixel32 current;
484     float drx, dgx, dbx, dry, dgy, dby;
485     unsigned int r,g,b;
486     int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
487     int val;
488
489     for (y = 0; y < h; ++y) {
490         drx = (float)(sf->data.planar.secondary->r -
491                       sf->data.planar.primary->r);
492         dry = drx/(float)h;
493         drx/= (float)w;
494
495         dgx = (float)(sf->data.planar.secondary->g -
496                       sf->data.planar.primary->g);
497         dgy = dgx/(float)h;
498         dgx/= (float)w;
499
500         dbx = (float)(sf->data.planar.secondary->b -
501                       sf->data.planar.primary->b);
502         dby = dbx/(float)h;
503         dbx/= (float)w;
504         for (x = 0; x < w; ++x, data) {
505             if ((float)x/(float)w > (float)y/(float)h) val = (int)(drx * x);
506             else val = (int)(dry * y);
507
508             r = sf->data.planar.primary->r + val;
509             g = sf->data.planar.primary->g + val;
510             b = sf->data.planar.primary->b + val;
511             current = (r << default_red_offset)
512                 + (g << default_green_offset)
513                 + (b << default_blue_offset);
514             *(data+x) = current;
515             *(data+inw-x) = current;
516             *(end-x) = current;
517             *(end-(inw-x)) = current;
518         }
519         data+=inw;
520         end-=inw;
521     }
522 }
523