]> Dogcows Code - chaz/openbox/blob - render/gradient.c
rectangle and diagonal grads yay
[chaz/openbox] / render / gradient.c
1 #include <GL/gl.h>
2 #include <glib.h>
3 #include "render.h"
4 #include "gradient.h"
5 #include "../kernel/openbox.h"
6 #include "color.h"
7
8 void gradient_render(Surface *sf, int w, int h)
9 {
10 pixel32 *data = sf->data.planar.pixel_data;
11 pixel32 current;
12 unsigned int r,g,b;
13 int off, x;
14
15 switch (sf->data.planar.grad) {
16 case Background_Solid: /* already handled */
17 return;
18 case Background_Vertical:
19 gradient_vertical(sf, w, h);
20 break;
21 case Background_Horizontal:
22 gradient_horizontal(sf, w, h);
23 break;
24 case Background_Diagonal:
25 gradient_diagonal(sf, w, h);
26 break;
27 case Background_CrossDiagonal:
28 gradient_crossdiagonal(sf, w, h);
29 break;
30 case Background_Pyramid:
31 gradient_pyramid(sf, w, h);
32 break;
33 case Background_PipeCross:
34 gradient_pipecross(sf, w, h);
35 break;
36 case Background_Rectangle:
37 gradient_rectangle(sf, w, h);
38 break;
39 default:
40 g_message("unhandled gradient");
41 return;
42 }
43
44 if (sf->data.planar.relief == Flat && sf->data.planar.border) {
45 r = sf->data.planar.border_color->r;
46 g = sf->data.planar.border_color->g;
47 b = sf->data.planar.border_color->b;
48 current = (r << default_red_offset)
49 + (g << default_green_offset)
50 + (b << default_blue_offset);
51 for (off = 0, x = 0; x < w; ++x, off++) {
52 *(data + off) = current;
53 *(data + off + ((h-1) * w)) = current;
54 }
55 for (off = 0, x = 0; x < h; ++x, off++) {
56 *(data + (off * w)) = current;
57 *(data + (off * w) + w - 1) = current;
58 }
59 }
60
61 if (sf->data.planar.relief != Flat) {
62 if (sf->data.planar.bevel == Bevel1) {
63 for (off = 1, x = 1; x < w - 1; ++x, off++)
64 highlight(data + off,
65 data + off + (h-1) * w,
66 sf->data.planar.relief==Raised);
67 for (off = 0, x = 0; x < h; ++x, off++)
68 highlight(data + off * w,
69 data + off * w + w - 1,
70 sf->data.planar.relief==Raised);
71 }
72
73 if (sf->data.planar.bevel == Bevel2) {
74 for (off = 2, x = 2; x < w - 2; ++x, off++)
75 highlight(data + off + w,
76 data + off + (h-2) * w,
77 sf->data.planar.relief==Raised);
78 for (off = 1, x = 1; x < h-1; ++x, off++)
79 highlight(data + off * w + 1,
80 data + off * w + w - 2,
81 sf->data.planar.relief==Raised);
82 }
83 }
84 }
85
86
87
88 void gradient_vertical(Surface *sf, int w, int h)
89 {
90 pixel32 *data = sf->data.planar.pixel_data;
91 pixel32 current;
92 float dr, dg, db;
93 unsigned int r,g,b;
94 int x, y;
95
96 dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
97 dr/= (float)h;
98
99 dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
100 dg/= (float)h;
101
102 db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
103 db/= (float)h;
104
105 for (y = 0; y < h; ++y) {
106 r = sf->data.planar.primary->r + (int)(dr * y);
107 g = sf->data.planar.primary->g + (int)(dg * y);
108 b = sf->data.planar.primary->b + (int)(db * y);
109 current = (r << default_red_offset)
110 + (g << default_green_offset)
111 + (b << default_blue_offset);
112 for (x = 0; x < w; ++x, ++data)
113 *data = current;
114 }
115 }
116
117 void gradient_horizontal(Surface *sf, int w, int h)
118 {
119 pixel32 *data = sf->data.planar.pixel_data;
120 pixel32 current;
121 float dr, dg, db;
122 unsigned int r,g,b;
123 int x, y;
124
125 dr = (float)(sf->data.planar.secondary->r - sf->data.planar.primary->r);
126 dr/= (float)w;
127
128 dg = (float)(sf->data.planar.secondary->g - sf->data.planar.primary->g);
129 dg/= (float)w;
130
131 db = (float)(sf->data.planar.secondary->b - sf->data.planar.primary->b);
132 db/= (float)w;
133
134 for (x = 0; x < w; ++x, ++data) {
135 r = sf->data.planar.primary->r + (int)(dr * x);
136 g = sf->data.planar.primary->g + (int)(dg * x);
137 b = sf->data.planar.primary->b + (int)(db * x);
138 current = (r << default_red_offset)
139 + (g << default_green_offset)
140 + (b << default_blue_offset);
141 for (y = 0; y < h; ++y)
142 *(data + y*w) = current;
143 }
144 }
145
146 void gradient_diagonal(Surface *sf, int w, int h)
147 {
148 pixel32 *data = sf->data.planar.pixel_data;
149 pixel32 current;
150 float drx, dgx, dbx, dry, dgy, dby;
151 unsigned int r,g,b;
152 int x, y;
153
154 for (y = 0; y < h; ++y) {
155 drx = (float)(sf->data.planar.secondary->r -
156 sf->data.planar.primary->r);
157 dry = drx/(float)h;
158 drx/= (float)w;
159
160 dgx = (float)(sf->data.planar.secondary->g -
161 sf->data.planar.primary->g);
162 dgy = dgx/(float)h;
163 dgx/= (float)w;
164
165 dbx = (float)(sf->data.planar.secondary->b -
166 sf->data.planar.primary->b);
167 dby = dbx/(float)h;
168 dbx/= (float)w;
169 for (x = 0; x < w; ++x, ++data) {
170 r = sf->data.planar.primary->r +
171 ((int)(drx * x) + (int)(dry * y))/2;
172 g = sf->data.planar.primary->g +
173 ((int)(dgx * x) + (int)(dgy * y))/2;
174 b = sf->data.planar.primary->b +
175 ((int)(dbx * x) + (int)(dby * y))/2;
176 current = (r << default_red_offset)
177 + (g << default_green_offset)
178 + (b << default_blue_offset);
179 *data = current;
180 }
181 }
182 }
183
184 void gradient_crossdiagonal(Surface *sf, int w, int h)
185 {
186 pixel32 *data = sf->data.planar.pixel_data;
187 pixel32 current;
188 float drx, dgx, dbx, dry, dgy, dby;
189 unsigned int r,g,b;
190 int x, y;
191
192 for (y = 0; y < h; ++y) {
193 drx = (float)(sf->data.planar.secondary->r -
194 sf->data.planar.primary->r);
195 dry = drx/(float)h;
196 drx/= (float)w;
197
198 dgx = (float)(sf->data.planar.secondary->g -
199 sf->data.planar.primary->g);
200 dgy = dgx/(float)h;
201 dgx/= (float)w;
202
203 dbx = (float)(sf->data.planar.secondary->b -
204 sf->data.planar.primary->b);
205 dby = dbx/(float)h;
206 dbx/= (float)w;
207 for (x = w; x > 0; --x, ++data) {
208 r = sf->data.planar.primary->r +
209 ((int)(drx * (x-1)) + (int)(dry * y))/2;
210 g = sf->data.planar.primary->g +
211 ((int)(dgx * (x-1)) + (int)(dgy * y))/2;
212 b = sf->data.planar.primary->b +
213 ((int)(dbx * (x-1)) + (int)(dby * y))/2;
214 current = (r << default_red_offset)
215 + (g << default_green_offset)
216 + (b << default_blue_offset);
217 *data = current;
218 }
219 }
220 }
221
222 void highlight(pixel32 *x, pixel32 *y, gboolean raised)
223 {
224 int r, g, b;
225
226 pixel32 *up, *down;
227 if (raised) {
228 up = x;
229 down = y;
230 } else {
231 up = y;
232 down = x;
233 }
234 r = (*up >> default_red_offset) & 0xFF;
235 r += r >> 1;
236 g = (*up >> default_green_offset) & 0xFF;
237 g += g >> 1;
238 b = (*up >> default_blue_offset) & 0xFF;
239 b += b >> 1;
240 if (r > 0xFF) r = 0xFF;
241 if (g > 0xFF) g = 0xFF;
242 if (b > 0xFF) b = 0xFF;
243 *up = (r << default_red_offset) + (g << default_green_offset)
244 + (b << default_blue_offset);
245
246 r = (*down >> default_red_offset) & 0xFF;
247 r = (r >> 1) + (r >> 2);
248 g = (*down >> default_green_offset) & 0xFF;
249 g = (g >> 1) + (g >> 2);
250 b = (*down >> default_blue_offset) & 0xFF;
251 b = (b >> 1) + (b >> 2);
252 *down = (r << default_red_offset) + (g << default_green_offset)
253 + (b << default_blue_offset);
254 }
255
256 static void create_bevel_colors(Appearance *l)
257 {
258 int r, g, b;
259
260 /* light color */
261 r = l->surface.data.planar.primary->r;
262 r += r >> 1;
263 g = l->surface.data.planar.primary->g;
264 g += g >> 1;
265 b = l->surface.data.planar.primary->b;
266 b += b >> 1;
267 if (r > 0xFF) r = 0xFF;
268 if (g > 0xFF) g = 0xFF;
269 if (b > 0xFF) b = 0xFF;
270 g_assert(!l->surface.data.planar.bevel_light);
271 l->surface.data.planar.bevel_light = color_new(r, g, b);
272 color_allocate_gc(l->surface.data.planar.bevel_light);
273
274 /* dark color */
275 r = l->surface.data.planar.primary->r;
276 r = (r >> 1) + (r >> 2);
277 g = l->surface.data.planar.primary->g;
278 g = (g >> 1) + (g >> 2);
279 b = l->surface.data.planar.primary->b;
280 b = (b >> 1) + (b >> 2);
281 g_assert(!l->surface.data.planar.bevel_dark);
282 l->surface.data.planar.bevel_dark = color_new(r, g, b);
283 color_allocate_gc(l->surface.data.planar.bevel_dark);
284 }
285
286 void gradient_solid(Appearance *l, int x, int y, int w, int h)
287 {
288 pixel32 pix;
289 int i, a, b;
290 PlanarSurface *sp = &l->surface.data.planar;
291 int left = x, top = y, right = x + w - 1, bottom = y + h - 1;
292
293 if (sp->primary->gc == None)
294 color_allocate_gc(sp->primary);
295 pix = (sp->primary->r << default_red_offset)
296 + (sp->primary->g << default_green_offset)
297 + (sp->primary->b << default_blue_offset);
298
299 for (a = 0; a < l->area.width; a++)
300 for (b = 0; b < l->area.height; b++)
301 sp->pixel_data[a + b*l->area.width] = pix;
302
303 XFillRectangle(ob_display, l->pixmap, sp->primary->gc,
304 x, y, w, h);
305
306 if (sp->interlaced) {
307 if (sp->secondary->gc == None)
308 color_allocate_gc(sp->secondary);
309 for (i = y; i < h; i += 2)
310 XDrawLine(ob_display, l->pixmap, sp->secondary->gc,
311 x, i, w, i);
312 }
313
314 switch (sp->relief) {
315 case Raised:
316 if (!sp->bevel_dark)
317 create_bevel_colors(l);
318
319 switch (sp->bevel) {
320 case Bevel1:
321 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
322 left, bottom, right, bottom);
323 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
324 right, bottom, right, top);
325
326 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
327 left, top, right, top);
328 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
329 left, bottom, left, top);
330 break;
331 case Bevel2:
332 XDrawLine(ob_display, l->pixmap,
333 sp->bevel_dark->gc,
334 left + 1, bottom - 2, right - 2, bottom - 2);
335 XDrawLine(ob_display, l->pixmap,
336 sp->bevel_dark->gc,
337 right - 2, bottom - 2, right - 2, top + 1);
338
339 XDrawLine(ob_display, l->pixmap,
340 sp->bevel_light->gc,
341 left + 1, top + 1, right - 2, top + 1);
342 XDrawLine(ob_display, l->pixmap,
343 sp->bevel_light->gc,
344 left + 1, bottom - 2, left + 1, top + 1);
345 break;
346 default:
347 g_assert_not_reached(); /* unhandled BevelType */
348 }
349 break;
350 case Sunken:
351 if (!sp->bevel_dark)
352 create_bevel_colors(l);
353
354 switch (sp->bevel) {
355 case Bevel1:
356 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
357 left, bottom, right, bottom);
358 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
359 right, bottom, right, top);
360
361 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
362 left, top, right, top);
363 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
364 left, bottom, left, top);
365 break;
366 case Bevel2:
367 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
368 left + 1, bottom - 2, right - 2, bottom - 2);
369 XDrawLine(ob_display, l->pixmap, sp->bevel_light->gc,
370 right - 2, bottom - 2, right - 2, top + 1);
371
372 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
373 left + 1, top + 1, right - 2, top + 1);
374 XDrawLine(ob_display, l->pixmap, sp->bevel_dark->gc,
375 left + 1, bottom - 2, left + 1, top + 1);
376
377 break;
378 default:
379 g_assert_not_reached(); /* unhandled BevelType */
380 }
381 break;
382 case Flat:
383 if (sp->border) {
384 if (sp->border_color->gc == None)
385 color_allocate_gc(sp->border_color);
386 XDrawRectangle(ob_display, l->pixmap, sp->border_color->gc,
387 left, top, right, bottom);
388 }
389 break;
390 default:
391 g_assert_not_reached(); /* unhandled ReliefType */
392 }
393 }
394
395 void gradient_pyramid(Surface *sf, int inw, int inh)
396 {
397 pixel32 *data = sf->data.planar.pixel_data;
398 pixel32 *end = data + inw*inh - 1;
399 pixel32 current;
400 float drx, dgx, dbx, dry, dgy, dby;
401 unsigned int r,g,b;
402 int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
403 for (y = 0; y < h; ++y) {
404 drx = (float)(sf->data.planar.secondary->r -
405 sf->data.planar.primary->r);
406 dry = drx/(float)h;
407 drx/= (float)w;
408
409 dgx = (float)(sf->data.planar.secondary->g -
410 sf->data.planar.primary->g);
411 dgy = dgx/(float)h;
412 dgx/= (float)w;
413
414 dbx = (float)(sf->data.planar.secondary->b -
415 sf->data.planar.primary->b);
416 dby = dbx/(float)h;
417 dbx/= (float)w;
418 for (x = 0; x < w; ++x, data) {
419 r = sf->data.planar.primary->r +
420 ((int)(drx * x) + (int)(dry * y))/2;
421 g = sf->data.planar.primary->g +
422 ((int)(dgx * x) + (int)(dgy * y))/2;
423 b = sf->data.planar.primary->b +
424 ((int)(dbx * x) + (int)(dby * y))/2;
425 current = (r << default_red_offset)
426 + (g << default_green_offset)
427 + (b << default_blue_offset);
428 *(data+x) = current;
429 *(data+inw-x) = current;
430 *(end-x) = current;
431 *(end-(inw-x)) = current;
432 }
433 data+=inw;
434 end-=inw;
435 }
436 }
437
438 void gradient_rectangle(Surface *sf, int inw, int inh)
439 {
440 pixel32 *data = sf->data.planar.pixel_data;
441 pixel32 *end = data + inw*inh - 1;
442 pixel32 current;
443 float drx, dgx, dbx, dry, dgy, dby;
444 unsigned int r,g,b;
445 int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
446 int val;
447
448 for (y = 0; y < h; ++y) {
449 drx = (float)(sf->data.planar.primary->r -
450 sf->data.planar.secondary->r);
451 dry = drx/(float)h;
452 drx/= (float)w;
453
454 dgx = (float)(sf->data.planar.primary->g -
455 sf->data.planar.secondary->g);
456 dgy = dgx/(float)h;
457 dgx/= (float)w;
458
459 dbx = (float)(sf->data.planar.primary->b -
460 sf->data.planar.secondary->b);
461 dby = dbx/(float)h;
462 dbx/= (float)w;
463 for (x = 0; x < w; ++x, data) {
464 if ((float)x/(float)w < (float)y/(float)h) val = (int)(drx * x);
465 else val = (int)(dry * y);
466
467 r = sf->data.planar.secondary->r + val;
468 g = sf->data.planar.secondary->g + val;
469 b = sf->data.planar.secondary->b + val;
470 current = (r << default_red_offset)
471 + (g << default_green_offset)
472 + (b << default_blue_offset);
473 *(data+x) = current;
474 *(data+inw-x) = current;
475 *(end-x) = current;
476 *(end-(inw-x)) = current;
477 }
478 data+=inw;
479 end-=inw;
480 }
481 }
482
483 void gradient_pipecross(Surface *sf, int inw, int inh)
484 {
485 pixel32 *data = sf->data.planar.pixel_data;
486 pixel32 *end = data + inw*inh - 1;
487 pixel32 current;
488 float drx, dgx, dbx, dry, dgy, dby;
489 unsigned int r,g,b;
490 int x, y, h=(inh/2) + 1, w=(inw/2) + 1;
491 int val;
492
493 for (y = 0; y < h; ++y) {
494 drx = (float)(sf->data.planar.secondary->r -
495 sf->data.planar.primary->r);
496 dry = drx/(float)h;
497 drx/= (float)w;
498
499 dgx = (float)(sf->data.planar.secondary->g -
500 sf->data.planar.primary->g);
501 dgy = dgx/(float)h;
502 dgx/= (float)w;
503
504 dbx = (float)(sf->data.planar.secondary->b -
505 sf->data.planar.primary->b);
506 dby = dbx/(float)h;
507 dbx/= (float)w;
508 for (x = 0; x < w; ++x, data) {
509 if ((float)x/(float)w > (float)y/(float)h) val = (int)(drx * x);
510 else val = (int)(dry * y);
511
512 r = sf->data.planar.primary->r + val;
513 g = sf->data.planar.primary->g + val;
514 b = sf->data.planar.primary->b + val;
515 current = (r << default_red_offset)
516 + (g << default_green_offset)
517 + (b << default_blue_offset);
518 *(data+x) = current;
519 *(data+inw-x) = current;
520 *(end-x) = current;
521 *(end-(inw-x)) = current;
522 }
523 data+=inw;
524 end-=inw;
525 }
526 }
527 #ifdef USE_GL
528 void render_gl_gradient(Surface *sf, int x, int y, int w, int h)
529 {
530 float pr,pg,pb;
531 float sr, sg, sb;
532 float ar, ag, ab;
533
534 pr = (float)sf->data.planar.primary->r/255.0;
535 pg = (float)sf->data.planar.primary->g/255.0;
536 pb = (float)sf->data.planar.primary->b/255.0;
537 if (sf->data.planar.secondary) {
538 sr = (float)sf->data.planar.secondary->r/255.0;
539 sg = (float)sf->data.planar.secondary->g/255.0;
540 sb = (float)sf->data.planar.secondary->b/255.0;
541 }
542 switch (sf->data.planar.grad) {
543 case Background_Solid: /* already handled */
544 glBegin(GL_TRIANGLES);
545 glColor3f(pr, pg, pb);
546 glVertex3i(x, y, 0);
547 glVertex3i(x+w, y, 0);
548 glVertex3i(x+w, y+h, 0);
549
550 glVertex3i(x+w, y+h, 0);
551 glVertex3i(x, y+h, 0);
552 glVertex3i(x, y, 0);
553 glEnd();
554 return;
555 case Background_Horizontal:
556 glBegin(GL_TRIANGLES);
557 glColor3f(pr, pg, pb);
558 glVertex3i(x, y, 0);
559 glColor3f(sr, sg, sb);
560 glVertex3i(x+w, y, 0);
561 glVertex3i(x+w, y+h, 0);
562
563 glVertex3i(x+w, y+h, 0);
564 glColor3f(pr, pg, pb);
565 glVertex3i(x, y+h, 0);
566 glVertex3i(x, y, 0);
567 glEnd();
568 break;
569 case Background_Vertical:
570 glBegin(GL_TRIANGLES);
571 glColor3f(pr, pg, pb);
572 glVertex3i(x, y, 0);
573 glVertex3i(x+w, y, 0);
574 glColor3f(sr, sg, sb);
575 glVertex3i(x+w, y+h, 0);
576
577 glVertex3i(x+w, y+h, 0);
578 glVertex3i(x, y+h, 0);
579 glColor3f(pr, pg, pb);
580 glVertex3i(x, y, 0);
581 glEnd();
582 break;
583 case Background_Diagonal:
584 ar = (pr + sr) / 2.0;
585 ag = (pg + sg) / 2.0;
586 ab = (pb + sb) / 2.0;
587 glBegin(GL_TRIANGLES);
588 glColor3f(ar, ag, ab);
589 glVertex3i(x, y, 0);
590 glColor3f(pr, pg, pb);
591 glVertex3i(x+w, y, 0);
592 glColor3f(ar, ag, ab);
593 glVertex3i(x+w, y+h, 0);
594
595 glColor3f(ar, ag, ab);
596 glVertex3i(x+w, y+h, 0);
597 glColor3f(sr, sg, sb);
598 glVertex3i(x, y+h, 0);
599 glColor3f(ar, ag, ab);
600 glVertex3i(x, y, 0);
601 glEnd();
602 break;
603 case Background_CrossDiagonal:
604 ar = (pr + sr) / 2.0;
605 ag = (pg + sg) / 2.0;
606 ab = (pb + sb) / 2.0;
607 glBegin(GL_TRIANGLES);
608 glColor3f(pr, pg, pb);
609 glVertex3i(x, y, 0);
610 glColor3f(ar, ag, ab);
611 glVertex3i(x+w, y, 0);
612 glColor3f(sr, sg, sb);
613 glVertex3i(x+w, y+h, 0);
614
615 glColor3f(sr, sg, sb);
616 glVertex3i(x+w, y+h, 0);
617 glColor3f(ar, ag, ab);
618 glVertex3i(x, y+h, 0);
619 glColor3f(pr, pg, pb);
620 glVertex3i(x, y, 0);
621 glEnd();
622 break;
623 case Background_Pyramid:
624 printf("pyramid\n");
625 break;
626 case Background_PipeCross:
627 break;
628 case Background_Rectangle:
629 glBegin(GL_TRIANGLES);
630 glColor3f(pr, pg, pb);
631 glVertex3i(x, y, 0);
632 glColor3f(sr, sg, sb);
633 glVertex3i(x+w/2, y+h/2, 0);
634 glColor3f(pr, pg, pb);
635 glVertex3i(x, y+h, 0);
636
637 glVertex3i(x, y+h, 0);
638 glColor3f(sr, sg, sb);
639 glVertex3i(x+w/2, y+h/2, 0);
640 glColor3f(pr, pg, pb);
641 glVertex3i(x+w, y+h, 0);
642
643 glVertex3i(x+w, y+h, 0);
644 glColor3f(sr, sg, sb);
645 glVertex3i(x+w/2, y+h/2, 0);
646 glColor3f(pr, pg, pb);
647 glVertex3i(x+w, y, 0);
648
649 glVertex3i(x+w, y, 0);
650 glColor3f(sr, sg, sb);
651 glVertex3i(x+w/2, y+h/2, 0);
652 glColor3f(pr, pg, pb);
653 glVertex3i(x, y, 0);
654
655 glEnd();
656 break;
657 default:
658 g_message("unhandled gradient");
659 return;
660 }
661 }
662 #endif /* USE_GL */
This page took 0.075329 seconds and 5 git commands to generate.