1 // -*- mode: C; indent-tabs-mode: nil; -*-
6 #include "screeninfo.h"
12 static Bool cleancache
= False
;
13 static PyObject
*colorcache
= NULL
;
15 static void otkcolor_dealloc(OtkColor
* self
)
17 // when this is called, the color has already been cleaned out of the cache
18 PyObject_Del((PyObject
*)self
);
21 static int otkcolor_compare(OtkColor
*c1
, OtkColor
*c2
)
26 p1
= c1
->red
<< 16 | c1
->green
<< 8 | c1
->blue
;
27 p2
= c2
->red
<< 16 | c2
->green
<< 8 | c2
->blue
;
38 static PyObject
*otkcolor_repr(OtkColor
*self
)
40 return PyString_FromFormat("rgb:%x/%x/%x", self
->red
, self
->green
,
44 static long otkcolor_hash(OtkColor
*self
)
46 return self
->screen
<< 24 | self
->red
<< 16 | self
->green
<< 8 | self
->blue
;
49 static PyTypeObject OtkColor_Type
= {
50 PyObject_HEAD_INIT(NULL
)
55 (destructor
)otkcolor_dealloc
, /*tp_dealloc*/
59 (cmpfunc
)otkcolor_compare
, /*tp_compare*/
60 (reprfunc
)otkcolor_repr
, /*tp_repr*/
64 (hashfunc
)otkcolor_hash
, /*tp_hash */
68 static void parseColorName(OtkColor
*self
, const char *name
) {
71 // get rgb values from colorname
77 if (!XParseColor(OBDisplay
->display
,
78 OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
,
80 fprintf(stderr
, "OtkColor: color parse error: \"%s\"\n", name
);
81 self
->red
= self
->green
= self
->blue
= 0;
83 self
->red
= xcol
.red
>> 8;
84 self
->green
= xcol
.green
>> 8;
85 self
->blue
= xcol
.blue
>> 8;
90 static void doCacheCleanup() {
91 unsigned long *pixels
;
94 PyObject
*key
; // this is a color too, but i dont need to use it as such
97 // ### TODO - support multiple displays!
98 if (!PyDict_Size(colorcache
)) return; // nothing to do
100 printf("Cleaning Cache...\n");
102 pixels
= malloc(sizeof(unsigned long) * PyDict_Size(colorcache
));
104 for (i
= 0; i
< ScreenCount(OBDisplay
->display
); i
++) {
105 printf("Screen %d\n", i
);
109 while (PyDict_Next(colorcache
, &ppos
, &key
, (PyObject
**)&color
)) {
110 // get the screen from the hash
111 if (color
->screen
!= i
) continue; // wrong screen
113 printf("has %d refs\n", color
->ob_refcnt
);
115 // does someone other than the cache have a reference? (the cache gets 2)
116 if (color
->ob_refcnt
> 2)
119 printf("ppos: %d\n", ppos
);
120 printf("Cleaning pixel: %lx Count: %d\n", color
->pixel
, count
+1);
122 pixels
[count
++] = color
->pixel
;
123 printf("pixref references before: %d\n", color
->ob_refcnt
);
124 PyDict_DelItem(colorcache
, key
);
125 printf("pixref references after: %d\n", color
->ob_refcnt
);
126 --ppos
; // back up one in the iteration
130 XFreeColors(OBDisplay
->display
,
131 OtkDisplay_ScreenInfo(OBDisplay
, i
)->colormap
,
133 printf("Done Cleaning Cache. Cleaned %d pixels\n", count
);
140 static void allocate(OtkColor
*self
) {
143 assert(!self
->allocated
);
145 printf("allocating! %d\n", cleancache
);
147 // allocate color from rgb values
148 xcol
.red
= self
->red
| self
->red
<< 8;
149 xcol
.green
= self
->green
| self
->green
<< 8;
150 xcol
.blue
= self
->blue
| self
->blue
<< 8;
153 if (!XAllocColor(OBDisplay
->display
,
154 OtkDisplay_ScreenInfo(OBDisplay
, self
->screen
)->colormap
,
156 fprintf(stderr
, "OtkColor: color alloc error: rgb:%x/%x/%x\n",
157 self
->red
, self
->green
, self
->blue
);
161 self
->pixel
= xcol
.pixel
;
162 self
->allocated
= True
;
168 PyObject
*OtkColor_FromRGB(int r
, int g
, int b
, int screen
)
170 OtkColor
*self
= PyObject_New(OtkColor
, &OtkColor_Type
);
173 assert(screen
>= 0); assert(r
>= 0); assert(g
>= 0); assert(b
>= 0);
174 assert(r
<= 0xff); assert(g
<= 0xff); assert(b
<= 0xff);
176 if (!colorcache
) colorcache
= PyDict_New();
178 self
->allocated
= False
;
183 self
->screen
= screen
;
185 // does this color already exist in the cache?
186 cached
= PyDict_GetItem(colorcache
, (PyObject
*)self
);
192 // add it to the cache
193 PyDict_SetItem(colorcache
, (PyObject
*)self
, (PyObject
*)self
);
194 return (PyObject
*)self
;
197 PyObject
*OtkColor_FromName(const char *name
, int screen
)
199 OtkColor
*self
= PyObject_New(OtkColor
, &OtkColor_Type
);
202 assert(screen
>= 0); assert(name
);
204 if (!colorcache
) colorcache
= PyDict_New();
206 self
->allocated
= False
;
211 self
->screen
= screen
;
213 parseColorName(self
, name
);
215 // does this color already exist in the cache?
216 cached
= PyDict_GetItem(colorcache
, (PyObject
*)self
);
222 // add it to the cache
223 PyDict_SetItem(colorcache
, (PyObject
*)self
, (PyObject
*)self
);
224 return (PyObject
*)self
;
227 unsigned long OtkColor_Pixel(OtkColor
*self
)
229 if (!self
->allocated
)
234 void OtkColor_CleanupColorCache()