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
findCloseColor(WMScreen * scr,unsigned short red,unsigned short green,unsigned short blue,unsigned short alpha)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
createRGBAColor(WMScreen * scr,unsigned short red,unsigned short green,unsigned short blue,unsigned short alpha)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
WMCreateRGBColor(WMScreen * scr,unsigned short red,unsigned short green,unsigned short blue,Bool exact)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
WMGetRColorFromColor(WMColor * color)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
WMCreateRGBAColor(WMScreen * scr,unsigned short red,unsigned short green,unsigned short blue,unsigned short alpha,Bool exact)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
WMCreateNamedColor(WMScreen * scr,const char * name,Bool exact)125 WMColor *WMCreateNamedColor(WMScreen * scr, const 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
WMRetainColor(WMColor * color)142 WMColor *WMRetainColor(WMColor * color)
143 {
144 assert(color != NULL);
145
146 color->refCount++;
147
148 return color;
149 }
150
WMReleaseColor(WMColor * color)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
WMSetColorAlpha(WMColor * color,unsigned short alpha)163 void WMSetColorAlpha(WMColor * color, unsigned short alpha)
164 {
165 color->alpha = alpha;
166 }
167
WMPaintColorSwatch(WMColor * color,Drawable d,int x,int y,unsigned int width,unsigned int height)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
WMColorPixel(WMColor * color)173 WMPixel WMColorPixel(WMColor * color)
174 {
175 return color->color.pixel;
176 }
177
WMColorGC(WMColor * color)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
WMSetColorInGC(WMColor * color,GC gc)193 void WMSetColorInGC(WMColor * color, GC gc)
194 {
195 XSetForeground(color->screen->display, gc, color->color.pixel);
196 }
197
198 /* "system" colors */
WMWhiteColor(WMScreen * scr)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
WMBlackColor(WMScreen * scr)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
WMGrayColor(WMScreen * scr)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
WMDarkGrayColor(WMScreen * scr)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
WMRedComponentOfColor(WMColor * color)295 unsigned short WMRedComponentOfColor(WMColor * color)
296 {
297 return color->color.red;
298 }
299
WMGreenComponentOfColor(WMColor * color)300 unsigned short WMGreenComponentOfColor(WMColor * color)
301 {
302 return color->color.green;
303 }
304
WMBlueComponentOfColor(WMColor * color)305 unsigned short WMBlueComponentOfColor(WMColor * color)
306 {
307 return color->color.blue;
308 }
309
WMGetColorAlpha(WMColor * color)310 unsigned short WMGetColorAlpha(WMColor * color)
311 {
312 return color->alpha;
313 }
314
WMGetColorRGBDescription(WMColor * color)315 char *WMGetColorRGBDescription(WMColor * color)
316 {
317 char *str = wmalloc(8);
318
319 if (snprintf(str, 8, "#%02x%02x%02x",
320 color->color.red >> 8, color->color.green >> 8, color->color.blue >> 8) >= 8) {
321 wfree(str);
322 return NULL;
323 }
324
325 return str;
326 }
327