added flakey parentrel for solids and some mean spirited asserts
[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   pixel32 pix;
237   int i, a, b;
238   PlanarSurface *sp = &l->surface.data.planar;
239   int left = x, top = y, right = w - 1, bottom = h - 1;
240
241 assert(x+w < l->area.width);
242 assert(y+h < l->area.height);
243
244   if (sp->primary->gc == None)
245     color_allocate_gc(sp->primary);
246   pix = (sp->primary->r << default_red_shift)
247       + (sp->primary->g << default_green_shift)
248       + (sp->primary->b << default_blue_shift);
249 printf("x = %d : y = %d : w = %d : h = %d (%d:%d\n", x,y,w,h, 
250 l->area.width, l->area.height);
251   for (a = 0; a < l->area.width; a++)
252     for (b = 0; b < l->area.height; b++)
253       sp->pixel_data[a + b*l->area.width] = pix;
254
255   XFillRectangle(ob_display, l->pixmap, sp->primary->gc
256                  , x, y, w, h);
257
258   if (l->surface.data.planar.interlaced) {
259     if (sp->secondary->gc == None)
260       color_allocate_gc(sp->secondary);
261     for (i = y; i < h; i += 2)
262       XDrawLine(ob_display, l->pixmap, sp->secondary->gc,
263                 x, i, w, i);
264   }
265 /*
266   switch (texture.relief()) {
267   case RenderTexture::Raised:
268     switch (texture.bevel()) {
269     case RenderTexture::Bevel1:
270       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
271                 left, bottom, right, bottom);
272       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
273                 right, bottom, right, top);
274                 
275       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
276                 left, top, right, top);
277       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
278                 left, bottom, left, top);
279       break;
280     case RenderTexture::Bevel2:
281       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
282                 left + 1, bottom - 2, right - 2, bottom - 2);
283       XDrawLine(ob_display, l->pixmap, texture.bevelDarkColor().gc(),
284                 right - 2, bottom - 2, right - 2, top + 1);
285
286       XDrawLine(ob_display, l->pixmap, texture.bevelLightColor().gc(),
287                 left + 1, top + 1, right - 2, top + 1);
288       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
289                 left + 1, bottom - 2, left + 1, top + 1);
290       break;
291     default:
292       assert(false); // unhandled RenderTexture::BevelType   
293     }
294     break;
295   case RenderTexture::Sunken:
296     switch (texture.bevel()) {
297     case RenderTexture::Bevel1:
298       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
299                 left, bottom, right, bottom);
300       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
301                 right, bottom, right, top);
302       
303       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
304                 left, top, right, top);
305       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
306                 left, bottom, left, top);
307       break;
308     case RenderTexture::Bevel2:
309       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
310                 left + 1, bottom - 2, right - 2, bottom - 2);
311       XDrawLine(**display, sf.pixmap(), texture.bevelLightColor().gc(),
312                 right - 2, bottom - 2, right - 2, top + 1);
313       
314       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
315                 left + 1, top + 1, right - 2, top + 1);
316       XDrawLine(**display, sf.pixmap(), texture.bevelDarkColor().gc(),
317                 left + 1, bottom - 2, left + 1, top + 1);
318
319       break;
320     default:
321       assert(false); // unhandled RenderTexture::BevelType   
322     }
323     break;
324   case RenderTexture::Flat:
325     if (texture.border())
326       XDrawRectangle(**display, sf.pixmap(), texture.borderColor().gc(),
327                      left, top, right, bottom);
328     break;
329   default:  
330     assert(false); // unhandled RenderTexture::ReliefType
331   }
332 */
333 }