remove bad comment
[mikachu/openbox.git] / render / color.c
1 #include "render.h"
2 #include "color.h"
3 #include "instance.h"
4
5 #include <X11/Xlib.h>
6 #include <X11/Xutil.h>
7 #include <string.h>
8
9 void RrColorAllocateGC(RrColor *in)
10 {
11     XGCValues gcv;
12
13     gcv.foreground = in->pixel;
14     gcv.cap_style = CapProjecting;
15     in->gc = XCreateGC(RrDisplay(in->inst),
16                        RrRootWindow(in->inst),
17                        GCForeground | GCCapStyle, &gcv);
18 }
19
20 RrColor *RrColorParse(const RrInstance *inst, gchar *colorname)
21 {
22     XColor xcol;
23
24     g_assert(colorname != NULL);
25     /* get rgb values from colorname */
26
27     xcol.red = 0;
28     xcol.green = 0;
29     xcol.blue = 0;
30     xcol.pixel = 0;
31     if (!XParseColor(RrDisplay(inst), RrColormap(inst), colorname, &xcol)) {
32         g_warning("unable to parse color '%s'", colorname);
33         return NULL;
34     }
35     return RrColorNew(inst, xcol.red >> 8, xcol.green >> 8, xcol.blue >> 8);
36 }
37
38 RrColor *RrColorNew(const RrInstance *inst, gint r, gint g, gint b)
39 {
40     /* this should be replaced with something far cooler */
41     RrColor *out = NULL;
42     XColor xcol;
43     gint key;
44
45     key = (r << 24) + (g << 16) + (b << 8);
46     if ((out = g_hash_table_lookup(RrColorHash(inst), &key))) {
47         out->refcount++;
48     } else {
49         xcol.red = (r << 8) | r;
50         xcol.green = (g << 8) | g;
51         xcol.blue = (b << 8) | b;
52         if (XAllocColor(RrDisplay(inst), RrColormap(inst), &xcol)) {
53             out = g_new(RrColor, 1);
54             out->inst = inst;
55             out->r = xcol.red >> 8;
56             out->g = xcol.green >> 8;
57             out->b = xcol.blue >> 8;
58             out->gc = None;
59             out->pixel = xcol.pixel;
60             out->key = key;
61             out->refcount = 1;
62             g_hash_table_replace(RrColorHash(inst), &out->key, out);
63         }
64     }
65     return out;
66 }
67
68 void RrColorFree(RrColor *c)
69 {
70     if (c) {
71         if (--c->refcount < 1) {
72             g_hash_table_remove(RrColorHash(c->inst), &c->key);
73             if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst),
74                                       &c->pixel, 1, 0);
75             if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc);
76             g_free(c);
77         }
78     }
79 }
80
81 void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
82 {
83     int r, g, b;
84     int x,y;
85     RrPixel32 *p32 = (RrPixel32 *) im->data;
86     RrPixel16 *p16 = (RrPixel16 *) im->data;
87     unsigned char *p8 = (unsigned char *)im->data;
88     switch (im->bits_per_pixel) {
89     case 32:
90         if ((RrRedOffset(inst) != RrDefaultRedOffset) ||
91             (RrBlueOffset(inst) != RrDefaultBlueOffset) ||
92             (RrGreenOffset(inst) != RrDefaultGreenOffset)) {
93             for (y = 0; y < im->height; y++) {
94                 for (x = 0; x < im->width; x++) {
95                     r = (data[x] >> RrDefaultRedOffset) & 0xFF;
96                     g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
97                     b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
98                     p32[x] = (r << RrRedOffset(inst))
99                            + (g << RrGreenOffset(inst))
100                            + (b << RrBlueOffset(inst));
101                 }
102                 data += im->width;
103                 p32 += im->width;
104             } 
105         } else im->data = (char*) data;
106         break;
107     case 16:
108         for (y = 0; y < im->height; y++) {
109             for (x = 0; x < im->width; x++) {
110                 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
111                 r = r >> RrRedShift(inst);
112                 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
113                 g = g >> RrGreenShift(inst);
114                 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
115                 b = b >> RrBlueShift(inst);
116                 p16[x] = (r << RrRedOffset(inst))
117                        + (g << RrGreenOffset(inst))
118                        + (b << RrBlueOffset(inst));
119             }
120             data += im->width;
121             p16 += im->bytes_per_line/2;
122         }
123     break;
124     case 8:
125         g_assert(RrVisual(inst)->class != TrueColor);
126         for (y = 0; y < im->height; y++) {
127             for (x = 0; x < im->width; x++) {
128                 p8[x] = RrPickColor(inst,
129                                     data[x] >> RrDefaultRedOffset,
130                                     data[x] >> RrDefaultGreenOffset,
131                                     data[x] >> RrDefaultBlueOffset)->pixel;
132         }
133         data += im->width;
134         p8 += im->bytes_per_line;
135   }
136
137     break;
138     default:
139         g_warning("your bit depth is currently unhandled\n");
140     }
141 }
142
143 XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b) 
144 {
145   r = (r & 0xff) >> (8-RrPseudoBPC(inst));
146   g = (g & 0xff) >> (8-RrPseudoBPC(inst));
147   b = (b & 0xff) >> (8-RrPseudoBPC(inst));
148   return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) +
149                                (g << (1*RrPseudoBPC(inst))) +
150                                b];
151 }
152
153 static void swap_byte_order(XImage *im)
154 {
155     int x, y, di;
156
157     di = 0;
158     for (y = 0; y < im->height; ++y) {
159         for (x = 0; x < im->height; ++x) {
160             char *c = &im->data[di + x * im->bits_per_pixel / 8];
161             char t;
162
163             switch (im->bits_per_pixel) {
164             case 32:
165                 t = c[2];
166                 c[2] = c[3];
167                 c[3] = t;
168             case 16:
169                 t = c[0];
170                 c[0] = c[1];
171                 c[1] = t;
172             case 8:
173                 break;
174             default:
175                 g_warning("your bit depth is currently unhandled");
176             }
177         }
178         di += im->bytes_per_line;
179     }
180
181     if (im->byte_order == LSBFirst)
182         im->byte_order = MSBFirst;
183     else
184         im->byte_order = LSBFirst;
185 }
186
187 void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
188 {
189     int r, g, b;
190     int x,y;
191     RrPixel32 *p32 = (RrPixel32 *) im->data;
192     RrPixel16 *p16 = (RrPixel16 *) im->data;
193     unsigned char *p8 = (unsigned char *)im->data;
194
195     if (im->byte_order != LSBFirst)
196         swap_byte_order(im);
197
198     switch (im->bits_per_pixel) {
199     case 32:
200         for (y = 0; y < im->height; y++) {
201             for (x = 0; x < im->width; x++) {
202                 r = (p32[x] >> RrRedOffset(inst)) & 0xff;
203                 g = (p32[x] >> RrGreenOffset(inst)) & 0xff;
204                 b = (p32[x] >> RrBlueOffset(inst)) & 0xff;
205                 data[x] = (r << RrDefaultRedOffset)
206                     + (g << RrDefaultGreenOffset)
207                     + (b << RrDefaultBlueOffset)
208                     + (0xff << RrDefaultAlphaOffset);
209             }
210             data += im->width;
211             p32 += im->bytes_per_line/4;
212         }
213         break;
214     case 16:
215         for (y = 0; y < im->height; y++) {
216             for (x = 0; x < im->width; x++) {
217                 r = (p16[x] & RrRedMask(inst)) >>
218                     RrRedOffset(inst) <<
219                     RrRedShift(inst);
220                 g = (p16[x] & RrGreenMask(inst)) >>
221                     RrGreenOffset(inst) <<
222                     RrGreenShift(inst);
223                 b = (p16[x] & RrBlueMask(inst)) >>
224                     RrBlueOffset(inst) <<
225                     RrBlueShift(inst);
226                 data[x] = (r << RrDefaultRedOffset)
227                     + (g << RrDefaultGreenOffset)
228                     + (b << RrDefaultBlueOffset)
229                     + (0xff << RrDefaultAlphaOffset);
230             }
231             data += im->width;
232             p16 += im->bytes_per_line/2;
233         }
234         break;
235     case 8:
236         g_warning("this image bit depth is currently unhandled");
237         break;
238     case 1:
239         for (y = 0; y < im->height; y++) {
240             for (x = 0; x < im->width; x++) {
241                 if (!(((p8[x / 8]) >> (x % 8)) & 0x1))
242                     data[x] = 0xff << RrDefaultAlphaOffset; /* black */
243                 else
244                     data[x] = 0xffffffff; /* white */
245             }
246             data += im->width;
247             p8 += im->bytes_per_line;
248         }
249         break;
250     default:
251         g_warning("this image bit depth is currently unhandled");
252     }
253 }
254
255 int RrColorRed(const RrColor *c)
256 {
257     return c->r;
258 }
259
260 int RrColorGreen(const RrColor *c)
261 {
262     return c->g;
263 }
264
265 int RrColorBlue(const RrColor *c)
266 {
267     return c->b;
268 }
269
270 gulong RrColorPixel(const RrColor *c)
271 {
272     return c->pixel;
273 }
274
275 GC RrColorGC(RrColor *c)
276 {
277     if (!c->gc)
278         RrColorAllocateGC(c);
279     return c->gc;
280 }