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