add rgba icon support
[mikachu/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   default:
30     g_message("unhandled gradient");
31     return;
32   }
33   
34   if (sf->data.planar.relief == Flat && sf->data.planar.border) {
35     r = sf->data.planar.border_color->r;
36     g = sf->data.planar.border_color->g;
37     b = sf->data.planar.border_color->b;
38     current = (r << default_red_shift)
39             + (g << default_green_shift)
40             + (b << default_blue_shift);
41     for (off = 0, x = 0; x < w; ++x, off++) {
42       *(data + off) = current;
43       *(data + off + ((h-1) * w)) = current;
44     }
45     for (off = 0, x = 0; x < h; ++x, off++) {
46       *(data + (off * w)) = current;
47       *(data + (off * w) + w - 1) = current;
48     }
49   }
50
51   if (sf->data.planar.relief != Flat) {
52     if (sf->data.planar.bevel == Bevel1) {
53       for (off = 1, x = 1; x < w - 1; ++x, off++)
54         highlight(data + off,
55                   data + off + (h-1) * w,
56                   sf->data.planar.relief==Raised);
57       for (off = 0, x = 0; x < h; ++x, off++)
58         highlight(data + off * w,
59                   data + off * w + w - 1,
60                   sf->data.planar.relief==Raised);
61     }
62
63     if (sf->data.planar.bevel == Bevel2) {
64       for (off = 2, x = 2; x < w - 2; ++x, off++)
65         highlight(data + off + w,
66                   data + off + (h-2) * w,
67                   sf->data.planar.relief==Raised);
68       for (off = 1, x = 1; x < h-1; ++x, off++)
69         highlight(data + off * w + 1,
70                   data + off * w + w - 2,
71                   sf->data.planar.relief==Raised);
72     }
73   }
74 }
75
76
77
78 void gradient_vertical(Surface *sf, int w, int h)
79 {
80   pixel32 *data = sf->data.planar.pixel_data;
81   pixel32 current;
82   float dr, dg, db;
83   unsigned int r,g,b;
84   int x, y;
85
86   dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
87   dr/= (float)h;
88
89   dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
90   dg/= (float)h;
91
92   db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
93   db/= (float)h;
94
95   for (y = 0; y < h; ++y) {
96     r = sf->data.planar.primary->r + (int)(dr * y);
97     g = sf->data.planar.primary->g + (int)(dg * y);
98     b = sf->data.planar.primary->b + (int)(db * y);
99     current = (r << default_red_shift)
100             + (g << default_green_shift)
101             + (b << default_blue_shift);
102     for (x = 0; x < w; ++x, ++data)
103       *data = current;
104   }
105 }
106
107 void gradient_horizontal(Surface *sf, int w, int h)
108 {
109   pixel32 *data = sf->data.planar.pixel_data;
110   pixel32 current;
111   float dr, dg, db;
112   unsigned int r,g,b;
113   int x, y;
114
115   dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
116   dr/= (float)w;
117
118   dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
119   dg/= (float)w;
120
121   db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
122   db/= (float)w;
123
124   for (x = 0; x < w; ++x, ++data) {
125     r = sf->data.planar.primary->r + (int)(dr * x);
126     g = sf->data.planar.primary->g + (int)(dg * x);
127     b = sf->data.planar.primary->b + (int)(db * x);
128     current = (r << default_red_shift)
129             + (g << default_green_shift)
130             + (b << default_blue_shift);
131     for (y = 0; y < h; ++y)
132       *(data + y*w) = current;
133   }
134 }
135
136 void gradient_diagonal(Surface *sf, int w, int h)
137 {
138   pixel32 *data = sf->data.planar.pixel_data;
139   pixel32 current;
140   float drx, dgx, dbx, dry, dgy, dby;
141   unsigned int r,g,b;
142   int x, y;
143
144   for (y = 0; y < h; ++y) {
145     drx = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
146     dry = drx/(float)h;
147     drx/= (float)w;
148
149     dgx = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
150     dgy = dgx/(float)h;
151     dgx/= (float)w;
152
153     dbx = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
154     dby = dbx/(float)h;
155     dbx/= (float)w;
156     for (x = 0; x < w; ++x, ++data) {
157       r = sf->data.planar.primary->r + ((int)(drx * x) + (int)(dry * y))/2;
158       g = sf->data.planar.primary->g + ((int)(dgx * x) + (int)(dgy * y))/2;
159       b = sf->data.planar.primary->b + ((int)(dbx * x) + (int)(dby * y))/2;
160       current = (r << default_red_shift)
161               + (g << default_green_shift)
162               + (b << default_blue_shift);
163       *data = current;
164     }
165   }
166 }
167
168 void gradient_crossdiagonal(Surface *sf, int w, int h)
169 {
170   pixel32 *data = sf->data.planar.pixel_data;
171   pixel32 current;
172   float drx, dgx, dbx, dry, dgy, dby;
173   unsigned int r,g,b;
174   int x, y;
175
176   for (y = 0; y < h; ++y) {
177     drx = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
178     dry = drx/(float)h;
179     drx/= (float)w;
180
181     dgx = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
182     dgy = dgx/(float)h;
183     dgx/= (float)w;
184
185     dbx = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
186     dby = dbx/(float)h;
187     dbx/= (float)w;
188     for (x = w; x > 0; --x, ++data) {
189       r = sf->data.planar.primary->r + ((int)(drx * (x-1)) + (int)(dry * y))/2;
190       g = sf->data.planar.primary->g + ((int)(dgx * (x-1)) + (int)(dgy * y))/2;
191       b = sf->data.planar.primary->b + ((int)(dbx * (x-1)) + (int)(dby * y))/2;
192       current = (r << default_red_shift)
193               + (g << default_green_shift)
194               + (b << default_blue_shift);
195       *data = current;
196     }
197   }
198 }
199
200 void highlight(pixel32 *x, pixel32 *y, gboolean raised)
201 {
202   int r, g, b;
203
204   pixel32 *up, *down;
205   if (raised) {
206     up = x;
207     down = y;
208   } else {
209     up = y;
210     down = x;
211   }
212   r = (*up >> default_red_shift) & 0xFF;
213   r += r >> 1;
214   g = (*up >> default_green_shift) & 0xFF;
215   g += g >> 1;
216   b = (*up >> default_blue_shift) & 0xFF;
217   b += b >> 1;
218   if (r > 255) r = 255;
219   if (g > 255) g = 255;
220   if (b > 255) b = 255;
221   *up = (r << default_red_shift) + (g << default_green_shift)
222       + (b << default_blue_shift);
223   
224   r = (*down >> default_red_shift) & 0xFF;
225   r = (r >> 1) + (r >> 2);
226   g = (*down >> default_green_shift) & 0xFF;
227   g = (g >> 1) + (g >> 2);
228   b = (*down >> default_blue_shift) & 0xFF;
229   b = (b >> 1) + (b >> 2);
230   *down = (r << default_red_shift) + (g << default_green_shift)
231         + (b << default_blue_shift);
232 }
233
234 void gradient_solid(Appearance *l, int x, int y, int w, int h) 
235 {
236   int i;
237   PlanarSurface *sp = &l->surface.data.planar;
238   int left = x, top = y, right = w - 1, bottom = h - 1;
239
240   if (sp->primary->gc == None)
241     color_allocate_gc(sp->primary);
242   XFillRectangle(ob_display, l->pixmap, sp->primary->gc
243                  , x, y, w, h);
244
245   if (l->surface.data.planar.interlaced) {
246     if (sp->secondary->gc == None)
247       color_allocate_gc(sp->secondary);
248     for (i = y; i < h; i += 2)
249       XDrawLine(ob_display, l->pixmap, sp->secondary->gc,
250                 x, i, w, i);
251   }
252 /*
253   switch (texture.relief()) {
254   case RenderTexture::Raised:
255     switch (texture.bevel()) {
256     case RenderTexture::Bevel1:
257       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
258                 left, bottom, right, bottom);
259       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
260                 right, bottom, right, top);
261                 
262       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
263                 left, top, right, top);
264       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
265                 left, bottom, left, top);
266       break;
267     case RenderTexture::Bevel2:
268       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
269                 left + 1, bottom - 2, right - 2, bottom - 2);
270       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
271                 right - 2, bottom - 2, right - 2, top + 1);
272
273       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
274                 left + 1, top + 1, right - 2, top + 1);
275       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
276                 left + 1, bottom - 2, left + 1, top + 1);
277       break;
278     default:
279       assert(false); // unhandled RenderTexture::BevelType   
280     }
281     break;
282   case RenderTexture::Sunken:
283     switch (texture.bevel()) {
284     case RenderTexture::Bevel1:
285       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
286                 left, bottom, right, bottom);
287       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
288                 right, bottom, right, top);
289       
290       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
291                 left, top, right, top);
292       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
293                 left, bottom, left, top);
294       break;
295     case RenderTexture::Bevel2:
296       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
297                 left + 1, bottom - 2, right - 2, bottom - 2);
298       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
299                 right - 2, bottom - 2, right - 2, top + 1);
300       
301       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
302                 left + 1, top + 1, right - 2, top + 1);
303       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
304                 left + 1, bottom - 2, left + 1, top + 1);
305
306       break;
307     default:
308       assert(false); // unhandled RenderTexture::BevelType   
309     }
310     break;
311   case RenderTexture::Flat:
312     if (texture.border())
313       XDrawRectangle(**display, sf.pixmap(), texture.borderColor().gc(),
314                      left, top, right, bottom);
315     break;
316   default:  
317     assert(false); // unhandled RenderTexture::ReliefType
318   }
319 */
320 }