]> Dogcows Code - chaz/openbox/blob - render/color.c
use the new color hash to cache RrColors
[chaz/openbox] / 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 /*XXX same color could be pointed to twice, this might have to be a refcount*/
69
70 void RrColorFree(RrColor *c)
71 {
72 if (c) {
73 if (--c->refcount < 1) {
74 g_hash_table_remove(RrColorHash(c->inst), &c->key);
75 if (c->pixel) XFreeColors(RrDisplay(c->inst), RrColormap(c->inst),
76 &c->pixel, 1, 0);
77 if (c->gc) XFreeGC(RrDisplay(c->inst), c->gc);
78 g_free(c);
79 }
80 }
81 }
82
83 void RrReduceDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
84 {
85 int r, g, b;
86 int x,y;
87 RrPixel32 *p32 = (RrPixel32 *) im->data;
88 RrPixel16 *p16 = (RrPixel16 *) im->data;
89 unsigned char *p8 = (unsigned char *)im->data;
90 switch (im->bits_per_pixel) {
91 case 32:
92 if ((RrRedOffset(inst) != RrDefaultRedOffset) ||
93 (RrBlueOffset(inst) != RrDefaultBlueOffset) ||
94 (RrGreenOffset(inst) != RrDefaultGreenOffset)) {
95 for (y = 0; y < im->height; y++) {
96 for (x = 0; x < im->width; x++) {
97 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
98 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
99 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
100 p32[x] = (r << RrRedOffset(inst))
101 + (g << RrGreenOffset(inst))
102 + (b << RrBlueOffset(inst));
103 }
104 data += im->width;
105 p32 += im->width;
106 }
107 } else im->data = (char*) data;
108 break;
109 case 16:
110 for (y = 0; y < im->height; y++) {
111 for (x = 0; x < im->width; x++) {
112 r = (data[x] >> RrDefaultRedOffset) & 0xFF;
113 r = r >> RrRedShift(inst);
114 g = (data[x] >> RrDefaultGreenOffset) & 0xFF;
115 g = g >> RrGreenShift(inst);
116 b = (data[x] >> RrDefaultBlueOffset) & 0xFF;
117 b = b >> RrBlueShift(inst);
118 p16[x] = (r << RrRedOffset(inst))
119 + (g << RrGreenOffset(inst))
120 + (b << RrBlueOffset(inst));
121 }
122 data += im->width;
123 p16 += im->bytes_per_line/2;
124 }
125 break;
126 case 8:
127 g_assert(RrVisual(inst)->class != TrueColor);
128 for (y = 0; y < im->height; y++) {
129 for (x = 0; x < im->width; x++) {
130 p8[x] = RrPickColor(inst,
131 data[x] >> RrDefaultRedOffset,
132 data[x] >> RrDefaultGreenOffset,
133 data[x] >> RrDefaultBlueOffset)->pixel;
134 }
135 data += im->width;
136 p8 += im->bytes_per_line;
137 }
138
139 break;
140 default:
141 g_warning("your bit depth is currently unhandled\n");
142 }
143 }
144
145 XColor *RrPickColor(const RrInstance *inst, gint r, gint g, gint b)
146 {
147 r = (r & 0xff) >> (8-RrPseudoBPC(inst));
148 g = (g & 0xff) >> (8-RrPseudoBPC(inst));
149 b = (b & 0xff) >> (8-RrPseudoBPC(inst));
150 return &RrPseudoColors(inst)[(r << (2*RrPseudoBPC(inst))) +
151 (g << (1*RrPseudoBPC(inst))) +
152 b];
153 }
154
155 static void swap_byte_order(XImage *im)
156 {
157 int x, y, di;
158
159 di = 0;
160 for (y = 0; y < im->height; ++y) {
161 for (x = 0; x < im->height; ++x) {
162 char *c = &im->data[di + x * im->bits_per_pixel / 8];
163 char t;
164
165 switch (im->bits_per_pixel) {
166 case 32:
167 t = c[2];
168 c[2] = c[3];
169 c[3] = t;
170 case 16:
171 t = c[0];
172 c[0] = c[1];
173 c[1] = t;
174 case 8:
175 break;
176 default:
177 g_warning("your bit depth is currently unhandled");
178 }
179 }
180 di += im->bytes_per_line;
181 }
182
183 if (im->byte_order == LSBFirst)
184 im->byte_order = MSBFirst;
185 else
186 im->byte_order = LSBFirst;
187 }
188
189 void RrIncreaseDepth(const RrInstance *inst, RrPixel32 *data, XImage *im)
190 {
191 int r, g, b;
192 int x,y;
193 RrPixel32 *p32 = (RrPixel32 *) im->data;
194 RrPixel16 *p16 = (RrPixel16 *) im->data;
195 unsigned char *p8 = (unsigned char *)im->data;
196
197 if (im->byte_order != LSBFirst)
198 swap_byte_order(im);
199
200 switch (im->bits_per_pixel) {
201 case 32:
202 for (y = 0; y < im->height; y++) {
203 for (x = 0; x < im->width; x++) {
204 r = (p32[x] >> RrRedOffset(inst)) & 0xff;
205 g = (p32[x] >> RrGreenOffset(inst)) & 0xff;
206 b = (p32[x] >> RrBlueOffset(inst)) & 0xff;
207 data[x] = (r << RrDefaultRedOffset)
208 + (g << RrDefaultGreenOffset)
209 + (b << RrDefaultBlueOffset)
210 + (0xff << RrDefaultAlphaOffset);
211 }
212 data += im->width;
213 p32 += im->bytes_per_line/4;
214 }
215 break;
216 case 16:
217 for (y = 0; y < im->height; y++) {
218 for (x = 0; x < im->width; x++) {
219 r = (p16[x] & RrRedMask(inst)) >>
220 RrRedOffset(inst) <<
221 RrRedShift(inst);
222 g = (p16[x] & RrGreenMask(inst)) >>
223 RrGreenOffset(inst) <<
224 RrGreenShift(inst);
225 b = (p16[x] & RrBlueMask(inst)) >>
226 RrBlueOffset(inst) <<
227 RrBlueShift(inst);
228 data[x] = (r << RrDefaultRedOffset)
229 + (g << RrDefaultGreenOffset)
230 + (b << RrDefaultBlueOffset)
231 + (0xff << RrDefaultAlphaOffset);
232 }
233 data += im->width;
234 p16 += im->bytes_per_line/2;
235 }
236 break;
237 case 8:
238 g_warning("this image bit depth is currently unhandled");
239 break;
240 case 1:
241 for (y = 0; y < im->height; y++) {
242 for (x = 0; x < im->width; x++) {
243 if (!(((p8[x / 8]) >> (x % 8)) & 0x1))
244 data[x] = 0xff << RrDefaultAlphaOffset; /* black */
245 else
246 data[x] = 0xffffffff; /* white */
247 }
248 data += im->width;
249 p8 += im->bytes_per_line;
250 }
251 break;
252 default:
253 g_warning("this image bit depth is currently unhandled");
254 }
255 }
256
257 int RrColorRed(const RrColor *c)
258 {
259 return c->r;
260 }
261
262 int RrColorGreen(const RrColor *c)
263 {
264 return c->g;
265 }
266
267 int RrColorBlue(const RrColor *c)
268 {
269 return c->b;
270 }
271
272 gulong RrColorPixel(const RrColor *c)
273 {
274 return c->pixel;
275 }
276
277 GC RrColorGC(RrColor *c) /* XXX make this const RrColor* when the GCs are in
278 a cache.. if possible? */
279 {
280 if (!c->gc)
281 RrColorAllocateGC(c);
282 return c->gc;
283 }
This page took 0.053842 seconds and 5 git commands to generate.