]>
Dogcows Code - chaz/openbox/blob - otk_c/color.c
1 // -*- mode: C; indent-tabs-mode: nil; -*-
6 #include "screeninfo.h"
12 static Bool cleancache
= False
;
13 static PyObject
*colorcache
;
15 // global color allocator/deallocator
22 static void rgb_dealloc(PyObject
* self
)
27 static int rgb_compare(PyObject
*py1
, PyObject
*py2
)
35 p1
= (r1
->screen
<< 24 | r1
->r
<< 16 | r1
->g
<< 8 | r1
->b
) & 0x00ffffff;
36 p2
= (r2
->screen
<< 24 | r2
->r
<< 16 | r2
->g
<< 8 | r2
->b
) & 0x00ffffff;
47 static PyTypeObject RGB_Type
= {
48 PyObject_HEAD_INIT(NULL
)
53 rgb_dealloc
, /*tp_dealloc*/
57 rgb_compare
, /*tp_compare*/
65 static PyObject
*RGB_New(int screen
, int r
, int g
, int b
) {
66 RGB
*self
= (RGB
*) PyObject_New(RGB
, &RGB_Type
);
67 self
->screen
= screen
;
71 return (PyObject
*)self
;
74 typedef struct PixelRef
{
79 static PixelRef
*PixelRef_New(unsigned long p
) {
80 PixelRef
* self
= malloc(sizeof(PixelRef
));
86 static void OtkColor_ParseColorName(OtkColor
*self
) {
89 if (!self
->colorname
) {
90 fprintf(stderr
, "OtkColor: empty colorname, cannot parse (using black)\n");
91 OtkColor_SetRGB(self
, 0, 0, 0);
94 // get rgb values from colorname
100 if (!XParseColor(OBDisplay
->display
, self
->colormap
,
101 PyString_AsString(self
->colorname
), &xcol
)) {
102 fprintf(stderr
, "BColor::allocate: color parse error: \"%s\"\n",
103 PyString_AsString(self
->colorname
));
104 OtkColor_SetRGB(self
, 0, 0, 0);
108 OtkColor_SetRGB(self
, xcol
.red
>> 8, xcol
.green
>> 8, xcol
.blue
>> 8);
111 static void OtkColor_DoCacheCleanup() {
112 unsigned long *pixels
;
115 PyObject
*rgb
, *pixref
;
118 // ### TODO - support multiple displays!
119 if (!PyDict_Size(colorcache
)) {
124 pixels
= malloc(sizeof(unsigned long) * PyDict_Size(colorcache
));
126 for (i
= 0; i
< ScreenCount(OBDisplay
->display
); i
++) {
130 while (PyDict_Next(colorcache
, &ppos
, &rgb
, &pixref
)) {
131 if (((PixelRef
*)pixref
)->count
!= 0 || ((RGB
*)rgb
)->screen
!= i
)
134 pixels
[count
++] = ((PixelRef
*)pixref
)->p
;
135 PyDict_DelItem(colorcache
, rgb
);
136 free(pixref
); // not really a PyObject, it just pretends
137 --ppos
; // back up one in the iteration
141 XFreeColors(OBDisplay
->display
,
142 OtkDisplay_ScreenInfo(OBDisplay
, i
)->colormap
,
150 static void OtkColor_Allocate(OtkColor
*self
) {
152 PyObject
*rgb
, *pixref
;
154 if (!OtkColor_IsValid(self
)) {
155 if (!self
->colorname
) {
156 fprintf(stderr
, "BColor: cannot allocate invalid color (using black)\n");
157 OtkColor_SetRGB(self
, 0, 0, 0);
159 OtkColor_ParseColorName(self
);
163 // see if we have allocated this color before
164 rgb
= RGB_New(self
->screen
, self
->red
, self
->green
, self
->blue
);
165 pixref
= PyDict_GetItem((PyObject
*)colorcache
, rgb
);
168 self
->allocated
= True
;
169 self
->pixel
= ((PixelRef
*)pixref
)->p
;
170 ((PixelRef
*)pixref
)->count
++;
174 // allocate color from rgb values
175 xcol
.red
= self
->red
| self
->red
<< 8;
176 xcol
.green
= self
->green
| self
->green
<< 8;
177 xcol
.blue
= self
->blue
| self
->blue
<< 8;
180 if (!XAllocColor(OBDisplay
->display
, self
->colormap
, &xcol
)) {
181 fprintf(stderr
, "BColor::allocate: color alloc error: rgb:%x/%x/%x\n",
182 self
->red
, self
->green
, self
->blue
);
186 self
->pixel
= xcol
.pixel
;
187 self
->allocated
= True
;
189 PyDict_SetItem(colorcache
, rgb
, (PyObject
*)PixelRef_New(self
->pixel
));
192 OtkColor_DoCacheCleanup();
195 static void OtkColor_Deallocate(OtkColor
*self
) {
196 PyObject
*rgb
, *pixref
;
198 if (!self
->allocated
)
201 rgb
= RGB_New(self
->screen
, self
->red
, self
->green
, self
->blue
);
202 pixref
= PyDict_GetItem(colorcache
, rgb
);
204 if (((PixelRef
*)pixref
)->count
>= 1)
205 ((PixelRef
*)pixref
)->count
--;
209 OtkColor_DoCacheCleanup();
211 self
->allocated
= False
;
215 OtkColor
*OtkColor_New(int screen
)
217 OtkColor
*self
= malloc(sizeof(OtkColor
));
219 self
->allocated
= False
;
224 self
->screen
= screen
;
225 self
->colorname
= NULL
;
226 self
->colormap
= OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
;
231 OtkColor
*OtkColor_FromRGB(int r
, int g
, int b
, int screen
)
233 OtkColor
*self
= malloc(sizeof(OtkColor
));
235 self
->allocated
= False
;
240 self
->screen
= screen
;
241 self
->colorname
= NULL
;
242 self
->colormap
= OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
;
247 OtkColor
*OtkColor_FromName(const char *name
, int screen
)
249 OtkColor
*self
= malloc(sizeof(OtkColor
));
251 self
->allocated
= False
;
256 self
->screen
= screen
;
257 self
->colorname
= PyString_FromString(name
);
258 self
->colormap
= OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
;
263 void OtkColor_Destroy(OtkColor
*self
)
266 Py_DECREF(self
->colorname
);
270 void OtkColor_SetRGB(OtkColor
*self
, int r
, int g
, int b
)
272 OtkColor_Deallocate(self
);
278 void OtkColor_SetScreen(OtkColor
*self
, int screen
)
280 if (screen
== self
->screen
) {
285 Otk_Deallocate(self
);
287 self
->colormap
= OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
;
289 self
->screen
= screen
;
295 Bool
OtkColor_IsValid(OtkColor
*self
)
297 return self
->red
!= -1 && self
->blue
!= -1 && self
->green
!= -1;
300 unsigned long OtkColor_Pixel(OtkColor
*self
)
302 if (!self
->allocated
)
303 OtkColor_Allocate(self
);
307 void OtkColor_InitializeCache()
309 colorcache
= PyDict_New();
312 void OtkColor_DestroyCache()
314 Py_DECREF(colorcache
);
318 void OtkColor_CleanupColorCache()
This page took 0.050827 seconds and 5 git commands to generate.