]> Dogcows Code - chaz/openbox/blob - render/gradient.c
of by one error in pyramid, rectangle, and crosspipe
[chaz/openbox] / 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 - 1;
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 - 1;
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 - 1;
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
This page took 0.068115 seconds and 5 git commands to generate.