simply the render interface by not requiring the setting of all the areas. only take...
[mikachu/openbox.git] / render / image.c
1 #include <glib.h>
2 #include "../kernel/geom.h"
3 #include "image.h"
4
5 void image_draw(pixel32 *target, TextureRGBA *rgba, Rect *area)
6 {
7     pixel32 *draw = rgba->data;
8     guint c, i, e, t, sfw, sfh;
9     sfw = area->width;
10     sfh = area->height;
11
12     g_assert(rgba->data != NULL);
13
14     if ((rgba->width != sfw || rgba->height != sfh) &&
15         (rgba->width != rgba->cwidth || rgba->height != rgba->cheight)) {
16         double dx = rgba->width / (double)sfw;
17         double dy = rgba->height / (double)sfh;
18         double px = 0.0;
19         double py = 0.0;
20         int iy = 0;
21
22         /* scale it and cache it */
23         if (rgba->cache != NULL)
24             g_free(rgba->cache);
25         rgba->cache = g_new(pixel32, sfw * sfh);
26         rgba->cwidth = sfw;
27         rgba->cheight = sfh;
28         for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
29             rgba->cache[i] = rgba->data[(int)px + iy];
30             if (++c >= sfw) {
31                 c = 0;
32                 px = 0;
33                 py += dy;
34                 iy = (int)py * rgba->width;
35             } else
36                 px += dx;
37         }
38
39         /* do we use the cache we may have just created, or the original? */
40         if (rgba->width != sfw || rgba->height != sfh)
41             draw = rgba->cache;
42
43         /* apply the alpha channel */
44         for (i = 0, c = 0, t = area->x, e = sfw*sfh; i < e; ++i, ++t) {
45             guchar alpha, r, g, b, bgr, bgg, bgb;
46
47             alpha = draw[i] >> default_alpha_offset;
48             r = draw[i] >> default_red_offset;
49             g = draw[i] >> default_green_offset;
50             b = draw[i] >> default_blue_offset;
51
52             if (c >= sfw) {
53                 c = 0;
54                 t += area->width - sfw;
55             }
56
57             /* background color */
58             bgr = target[t] >> default_red_offset;
59             bgg = target[t] >> default_green_offset;
60             bgb = target[t] >> default_blue_offset;
61
62             r = bgr + (((r - bgr) * alpha) >> 8);
63             g = bgg + (((g - bgg) * alpha) >> 8);
64             b = bgb + (((b - bgb) * alpha) >> 8);
65
66             target[t] = (r << default_red_offset)
67                       | (g << default_green_offset)
68                       | (b << default_blue_offset);
69         }
70     }
71 }