Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / wcolor.c
1
2 #include "WINGsP.h"
3
4 #include "wconfig.h"
5
6 #include <wraster.h>
7
8 #define LIGHT_STIPPLE_WIDTH 4
9 #define LIGHT_STIPPLE_HEIGHT 4
10 static char LIGHT_STIPPLE_BITS[] = {
11         0x05, 0x0a, 0x05, 0x0a
12 };
13
14 #define DARK_STIPPLE_WIDTH 4
15 #define DARK_STIPPLE_HEIGHT 4
16 static char DARK_STIPPLE_BITS[] = {
17         0x0a, 0x04, 0x0a, 0x01
18 };
19
20 static WMColor *createRGBAColor(WMScreen * scr, unsigned short red,
21                                 unsigned short green, unsigned short blue, unsigned short alpha);
22
23 /*
24  * TODO: make the color creation code return the same WMColor for the
25  * same colors.
26  * make findCloseColor() find the closest color in the RContext pallette
27  * or in the other colors allocated by WINGs.
28  */
29
30 static WMColor *findCloseColor(WMScreen * scr, unsigned short red, unsigned short green,
31                                unsigned short blue, unsigned short alpha)
32 {
33         WMColor *color;
34         XColor xcolor;
35         RColor rcolor;
36
37         rcolor.red = red >> 8;
38         rcolor.green = green >> 8;
39         rcolor.blue = blue >> 8;
40         rcolor.alpha = alpha >> 8;
41
42         if (!RGetClosestXColor(scr->rcontext, &rcolor, &xcolor))
43                 return NULL;
44
45         if (!XAllocColor(scr->display, scr->colormap, &xcolor))
46                 return NULL;
47
48         color = wmalloc(sizeof(WMColor));
49
50         color->screen = scr;
51         color->refCount = 1;
52         color->color = xcolor;
53         color->alpha = alpha;
54         color->flags.exact = 1;
55         color->gc = NULL;
56
57         return color;
58 }
59
60 static WMColor *createRGBAColor(WMScreen * scr, unsigned short red, unsigned short green,
61                                 unsigned short blue, unsigned short alpha)
62 {
63         WMColor *color;
64         XColor xcolor;
65
66         xcolor.red = red;
67         xcolor.green = green;
68         xcolor.blue = blue;
69         xcolor.flags = DoRed | DoGreen | DoBlue;
70         if (!XAllocColor(scr->display, scr->colormap, &xcolor))
71                 return NULL;
72
73         color = wmalloc(sizeof(WMColor));
74
75         color->screen = scr;
76         color->refCount = 1;
77         color->color = xcolor;
78         color->alpha = alpha;
79         color->flags.exact = 1;
80         color->gc = NULL;
81
82         return color;
83 }
84
85 WMColor *WMCreateRGBColor(WMScreen * scr, unsigned short red, unsigned short green,
86                           unsigned short blue, Bool exact)
87 {
88         WMColor *color = NULL;
89
90         if (!exact || !(color = createRGBAColor(scr, red, green, blue, 0xffff))) {
91                 color = findCloseColor(scr, red, green, blue, 0xffff);
92         }
93         if (!color)
94                 color = WMBlackColor(scr);
95
96         return color;
97 }
98
99 RColor WMGetRColorFromColor(WMColor * color)
100 {
101         RColor rcolor;
102
103         rcolor.red = color->color.red >> 8;
104         rcolor.green = color->color.green >> 8;
105         rcolor.blue = color->color.blue >> 8;
106         rcolor.alpha = color->alpha >> 8;
107
108         return rcolor;
109 }
110
111 WMColor *WMCreateRGBAColor(WMScreen * scr, unsigned short red, unsigned short green,
112                            unsigned short blue, unsigned short alpha, Bool exact)
113 {
114         WMColor *color = NULL;
115
116         if (!exact || !(color = createRGBAColor(scr, red, green, blue, alpha))) {
117                 color = findCloseColor(scr, red, green, blue, alpha);
118         }
119         if (!color)
120                 color = WMBlackColor(scr);
121
122         return color;
123 }
124
125 WMColor *WMCreateNamedColor(WMScreen * scr, char *name, Bool exact)
126 {
127         WMColor *color;
128         XColor xcolor;
129
130         if (!XParseColor(scr->display, scr->colormap, name, &xcolor))
131                 return NULL;
132
133         if (scr->visual->class == TrueColor)
134                 exact = True;
135
136         if (!exact || !(color = createRGBAColor(scr, xcolor.red, xcolor.green, xcolor.blue, 0xffff))) {
137                 color = findCloseColor(scr, xcolor.red, xcolor.green, xcolor.blue, 0xffff);
138         }
139         return color;
140 }
141
142 WMColor *WMRetainColor(WMColor * color)
143 {
144         assert(color != NULL);
145
146         color->refCount++;
147
148         return color;
149 }
150
151 void WMReleaseColor(WMColor * color)
152 {
153         color->refCount--;
154
155         if (color->refCount < 1) {
156                 XFreeColors(color->screen->display, color->screen->colormap, &(color->color.pixel), 1, 0);
157                 if (color->gc)
158                         XFreeGC(color->screen->display, color->gc);
159                 wfree(color);
160         }
161 }
162
163 void WMSetColorAlpha(WMColor * color, unsigned short alpha)
164 {
165         color->alpha = alpha;
166 }
167
168 void WMPaintColorSwatch(WMColor * color, Drawable d, int x, int y, unsigned int width, unsigned int height)
169 {
170         XFillRectangle(color->screen->display, d, WMColorGC(color), x, y, width, height);
171 }
172
173 WMPixel WMColorPixel(WMColor * color)
174 {
175         return color->color.pixel;
176 }
177
178 GC WMColorGC(WMColor * color)
179 {
180         if (!color->gc) {
181                 XGCValues gcv;
182                 WMScreen *scr = color->screen;
183
184                 gcv.foreground = color->color.pixel;
185                 gcv.graphics_exposures = False;
186                 color->gc = XCreateGC(scr->display, scr->rcontext->drawable,
187                                       GCForeground | GCGraphicsExposures, &gcv);
188         }
189
190         return color->gc;
191 }
192
193 void WMSetColorInGC(WMColor * color, GC gc)
194 {
195         XSetForeground(color->screen->display, gc, color->color.pixel);
196 }
197
198 /* "system" colors */
199 WMColor *WMWhiteColor(WMScreen * scr)
200 {
201         if (!scr->white) {
202                 scr->white = WMCreateRGBColor(scr, 0xffff, 0xffff, 0xffff, True);
203                 if (!scr->white->flags.exact)
204                         wwarning(_("could not allocate %s color"), _("white"));
205         }
206         return WMRetainColor(scr->white);
207 }
208
209 WMColor *WMBlackColor(WMScreen * scr)
210 {
211         if (!scr->black) {
212                 scr->black = WMCreateRGBColor(scr, 0, 0, 0, True);
213                 if (!scr->black->flags.exact)
214                         wwarning(_("could not allocate %s color"), _("black"));
215         }
216         return WMRetainColor(scr->black);
217 }
218
219 WMColor *WMGrayColor(WMScreen * scr)
220 {
221         if (!scr->gray) {
222                 WMColor *color;
223
224                 if (scr->depth == 1) {
225                         Pixmap stipple;
226                         WMColor *white = WMWhiteColor(scr);
227                         WMColor *black = WMBlackColor(scr);
228                         XGCValues gcv;
229
230                         stipple = XCreateBitmapFromData(scr->display, W_DRAWABLE(scr),
231                                                         LIGHT_STIPPLE_BITS, LIGHT_STIPPLE_WIDTH,
232                                                         LIGHT_STIPPLE_HEIGHT);
233
234                         color = createRGBAColor(scr, 0xffff, 0xffff, 0xffff, 0xffff);
235
236                         gcv.foreground = white->color.pixel;
237                         gcv.background = black->color.pixel;
238                         gcv.fill_style = FillStippled;
239                         gcv.stipple = stipple;
240                         color->gc = XCreateGC(scr->display, W_DRAWABLE(scr), GCForeground
241                                               | GCBackground | GCStipple | GCFillStyle
242                                               | GCGraphicsExposures, &gcv);
243
244                         XFreePixmap(scr->display, stipple);
245                         WMReleaseColor(white);
246                         WMReleaseColor(black);
247                 } else {
248                         color = WMCreateRGBColor(scr, 0xaeba, 0xaaaa, 0xaeba, True);
249                         if (!color->flags.exact)
250                                 wwarning(_("could not allocate %s color"), _("gray"));
251                 }
252                 scr->gray = color;
253         }
254         return WMRetainColor(scr->gray);
255 }
256
257 WMColor *WMDarkGrayColor(WMScreen * scr)
258 {
259         if (!scr->darkGray) {
260                 WMColor *color;
261
262                 if (scr->depth == 1) {
263                         Pixmap stipple;
264                         WMColor *white = WMWhiteColor(scr);
265                         WMColor *black = WMBlackColor(scr);
266                         XGCValues gcv;
267
268                         stipple = XCreateBitmapFromData(scr->display, W_DRAWABLE(scr),
269                                                         DARK_STIPPLE_BITS, DARK_STIPPLE_WIDTH,
270                                                         DARK_STIPPLE_HEIGHT);
271
272                         color = createRGBAColor(scr, 0, 0, 0, 0xffff);
273
274                         gcv.foreground = white->color.pixel;
275                         gcv.background = black->color.pixel;
276                         gcv.fill_style = FillStippled;
277                         gcv.stipple = stipple;
278                         color->gc = XCreateGC(scr->display, W_DRAWABLE(scr), GCForeground
279                                               | GCBackground | GCStipple | GCFillStyle
280                                               | GCGraphicsExposures, &gcv);
281
282                         XFreePixmap(scr->display, stipple);
283                         WMReleaseColor(white);
284                         WMReleaseColor(black);
285                 } else {
286                         color = WMCreateRGBColor(scr, 0x5144, 0x5555, 0x5144, True);
287                         if (!color->flags.exact)
288                                 wwarning(_("could not allocate %s color"), _("dark gray"));
289                 }
290                 scr->darkGray = color;
291         }
292         return WMRetainColor(scr->darkGray);
293 }
294
295 unsigned short WMRedComponentOfColor(WMColor * color)
296 {
297         return color->color.red;
298 }
299
300 unsigned short WMGreenComponentOfColor(WMColor * color)
301 {
302         return color->color.green;
303 }
304
305 unsigned short WMBlueComponentOfColor(WMColor * color)
306 {
307         return color->color.blue;
308 }
309
310 unsigned short WMGetColorAlpha(WMColor * color)
311 {
312         return color->alpha;
313 }
314
315 char *WMGetColorRGBDescription(WMColor * color)
316 {
317         char *str = wmalloc(32);
318
319         sprintf(str, "#%02x%02x%02x", color->color.red >> 8, color->color.green >> 8, color->color.blue >> 8);
320
321         return str;
322 }