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