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