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