add shit that i made in the last week!
[dana/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 *position,
6                 Rect *surarea)
7 {
8     gulong *draw = rgba->data;
9     guint c, i, e, t, sfw, sfh;
10     sfw = position->width;
11     sfh = position->height;
12
13     /* it would be nice if this worked, but this function is well broken in
14        these circumstances. */
15     g_assert(position->width == surarea->width &&
16              position->height == surarea->height);
17
18     g_assert(rgba->data != NULL);
19
20     if ((rgba->width != sfw || rgba->height != sfh) &&
21         (rgba->width != rgba->cwidth || rgba->height != rgba->cheight)) {
22         double dx = rgba->width / (double)sfw;
23         double dy = rgba->height / (double)sfh;
24         double px = 0.0;
25         double py = 0.0;
26         int iy = 0;
27
28         /* scale it and cache it */
29         if (rgba->cache != NULL)
30             g_free(rgba->cache);
31         rgba->cache = g_new(unsigned long, sfw * sfh);
32         rgba->cwidth = sfw;
33         rgba->cheight = sfh;
34         for (i = 0, c = 0, e = sfw*sfh; i < e; ++i) {
35             rgba->cache[i] = rgba->data[(int)px + iy];
36             if (++c >= sfw) {
37                 c = 0;
38                 px = 0;
39                 py += dy;
40                 iy = (int)py * rgba->width;
41             } else
42                 px += dx;
43         }
44
45         /* do we use the cache we may have just created, or the original? */
46         if (rgba->width != sfw || rgba->height != sfh)
47             draw = rgba->cache;
48
49         /* apply the alpha channel */
50         for (i = 0, c = 0, t = position->x, e = sfw*sfh; i < e; ++i, ++t) {
51             guchar alpha, r, g, b, bgr, bgg, bgb;
52
53             alpha = draw[i] >> 24;
54             r = draw[i] >> 16;
55             g = draw[i] >> 8;
56             b = draw[i];
57
58             if (c >= sfw) {
59                 c = 0;
60                 t += surarea->width - sfw;
61             }
62
63             /* background color */
64             bgr = target[t] >> default_red_shift;
65             bgg = target[t] >> default_green_shift;
66             bgb = target[t] >> default_blue_shift;
67
68             r = bgr + (((r - bgr) * alpha) >> 8);
69             g = bgg + (((g - bgg) * alpha) >> 8);
70             b = bgb + (((b - bgb) * alpha) >> 8);
71
72             target[t] = (r << default_red_shift) | (g << default_green_shift) |
73                 (b << default_blue_shift);
74         }
75     }
76 }