]> Dogcows Code - chaz/openbox/blob - otk_c/color.c
remove the debug shit
[chaz/openbox] / otk_c / color.c
1 // -*- mode: C; indent-tabs-mode: nil; -*-
2
3 #include "../config.h"
4 #include "color.h"
5 #include "display.h"
6 #include "screeninfo.h"
7
8 #ifdef HAVE_STDLIB_H
9 # include <stdlib.h>
10 #endif
11
12 static Bool cleancache = False;
13 static PyObject *colorcache = NULL;
14
15 static void otkcolor_dealloc(OtkColor* self)
16 {
17 // when this is called, the color has already been cleaned out of the cache
18 PyObject_Del((PyObject*)self);
19 }
20
21 static int otkcolor_compare(OtkColor *c1, OtkColor *c2)
22 {
23 long result;
24 unsigned long p1, p2;
25
26 p1 = c1->red << 16 | c1->green << 8 | c1->blue;
27 p2 = c2->red << 16 | c2->green << 8 | c2->blue;
28
29 if (p1 < p2)
30 result = -1;
31 else if (p1 > p2)
32 result = 1;
33 else
34 result = 0;
35 return result;
36 }
37
38 static PyObject *otkcolor_repr(OtkColor *self)
39 {
40 return PyString_FromFormat("rgb:%x/%x/%x", self->red, self->green,
41 self->blue);
42 }
43
44 static long otkcolor_hash(OtkColor *self)
45 {
46 return self->screen << 24 | self->red << 16 | self->green << 8 | self->blue;
47 }
48
49 static PyTypeObject OtkColor_Type = {
50 PyObject_HEAD_INIT(NULL)
51 0,
52 "Color",
53 sizeof(OtkColor),
54 0,
55 (destructor)otkcolor_dealloc, /*tp_dealloc*/
56 0, /*tp_print*/
57 0, /*tp_getattr*/
58 0, /*tp_setattr*/
59 (cmpfunc)otkcolor_compare, /*tp_compare*/
60 (reprfunc)otkcolor_repr, /*tp_repr*/
61 0, /*tp_as_number*/
62 0, /*tp_as_sequence*/
63 0, /*tp_as_mapping*/
64 (hashfunc)otkcolor_hash, /*tp_hash */
65 };
66
67
68 static void parseColorName(OtkColor *self, const char *name) {
69 XColor xcol;
70
71 // get rgb values from colorname
72 xcol.red = 0;
73 xcol.green = 0;
74 xcol.blue = 0;
75 xcol.pixel = 0;
76
77 if (!XParseColor(OBDisplay->display,
78 OtkDisplay_ScreenInfo(OBDisplay, self->screen)->colormap,
79 name, &xcol)) {
80 fprintf(stderr, "OtkColor: color parse error: \"%s\"\n", name);
81 self->red = self->green = self->blue = 0;
82 } else {
83 self->red = xcol.red >> 8;
84 self->green = xcol.green >> 8;
85 self->blue = xcol.blue >> 8;
86 }
87 }
88
89 static void doCacheCleanup() {
90 unsigned long *pixels;
91 int i, ppos;
92 unsigned int count;
93 PyObject *key; // this is a color too, but i dont need to use it as such
94 OtkColor *color;
95
96 // ### TODO - support multiple displays!
97 if (!PyDict_Size(colorcache)) return; // nothing to do
98
99 pixels = malloc(sizeof(unsigned long) * PyDict_Size(colorcache));
100
101 for (i = 0; i < ScreenCount(OBDisplay->display); i++) {
102 count = 0;
103 ppos = 0;
104
105 while (PyDict_Next(colorcache, &ppos, &key, (PyObject**)&color)) {
106 // get the screen from the hash
107 if (color->screen != i) continue; // wrong screen
108
109 // does someone other than the cache have a reference? (the cache gets 2)
110 if (color->ob_refcnt > 2)
111 continue;
112
113 pixels[count++] = color->pixel;
114 PyDict_DelItem(colorcache, key);
115 --ppos; // back up one in the iteration
116 }
117
118 if (count > 0)
119 XFreeColors(OBDisplay->display,
120 OtkDisplay_ScreenInfo(OBDisplay, i)->colormap,
121 pixels, count, 0);
122 }
123
124 free(pixels);
125 cleancache = False;
126 }
127
128 static void allocate(OtkColor *self) {
129 XColor xcol;
130
131 assert(!self->allocated);
132
133 // allocate color from rgb values
134 xcol.red = self->red | self->red << 8;
135 xcol.green = self->green | self->green << 8;
136 xcol.blue = self->blue | self->blue << 8;
137 xcol.pixel = 0;
138
139 if (!XAllocColor(OBDisplay->display,
140 OtkDisplay_ScreenInfo(OBDisplay, self->screen)->colormap,
141 &xcol)) {
142 fprintf(stderr, "OtkColor: color alloc error: rgb:%x/%x/%x\n",
143 self->red, self->green, self->blue);
144 xcol.pixel = 0;
145 }
146
147 self->pixel = xcol.pixel;
148 self->allocated = True;
149
150 if (cleancache)
151 doCacheCleanup();
152 }
153
154 PyObject *OtkColor_FromRGB(int r, int g, int b, int screen)
155 {
156 OtkColor *self = PyObject_New(OtkColor, &OtkColor_Type);
157 PyObject *cached;
158
159 assert(screen >= 0); assert(r >= 0); assert(g >= 0); assert(b >= 0);
160 assert(r <= 0xff); assert(g <= 0xff); assert(b <= 0xff);
161
162 if (!colorcache) colorcache = PyDict_New();
163
164 self->allocated = False;
165 self->red = r;
166 self->green = g;
167 self->blue = b;
168 self->pixel = 0;
169 self->screen = screen;
170
171 // does this color already exist in the cache?
172 cached = PyDict_GetItem(colorcache, (PyObject*)self);
173 if (cached) {
174 Py_INCREF(cached);
175 return cached;
176 }
177
178 // add it to the cache
179 PyDict_SetItem(colorcache, (PyObject*)self, (PyObject*)self);
180 return (PyObject*)self;
181 }
182
183 PyObject *OtkColor_FromName(const char *name, int screen)
184 {
185 OtkColor *self = PyObject_New(OtkColor, &OtkColor_Type);
186 PyObject *cached;
187
188 assert(screen >= 0); assert(name);
189
190 if (!colorcache) colorcache = PyDict_New();
191
192 self->allocated = False;
193 self->red = -1;
194 self->green = -1;
195 self->blue = -1;
196 self->pixel = 0;
197 self->screen = screen;
198
199 parseColorName(self, name);
200
201 // does this color already exist in the cache?
202 cached = PyDict_GetItem(colorcache, (PyObject*)self);
203 if (cached) {
204 Py_INCREF(cached);
205 return cached;
206 }
207
208 // add it to the cache
209 PyDict_SetItem(colorcache, (PyObject*)self, (PyObject*)self);
210 return (PyObject*)self;
211 }
212
213 unsigned long OtkColor_Pixel(OtkColor *self)
214 {
215 if (!self->allocated)
216 allocate(self);
217 return self->pixel;
218 }
219
220 void OtkColor_CleanupColorCache()
221 {
222 cleancache = True;
223 }
This page took 0.046658 seconds and 4 git commands to generate.