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