1 /* libwmf ("player/color.h"): library for wmf conversion
2    Copyright (C) 2000 - various; see CREDITS, ChangeLog, and sources
3 
4    The libwmf Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public License as
6    published by the Free Software Foundation; either version 2 of the
7    License, or (at your option) any later version.
8 
9    The libwmf Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public
15    License along with the libwmf Library; see the file COPYING.  If not,
16    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18 
19 
20 #ifndef WMFPLAYER_COLOR_H
21 #define WMFPLAYER_COLOR_H
22 
23 /* These are the colors defined in the SVG standard (I haven't checked the final recommendation for changes)
24  */
25 wmfRGB wmf_aliceblue		= { 240, 248, 255 };
26 wmfRGB wmf_antiquewhite		= { 250, 235, 215 };
27 wmfRGB wmf_aqua			= {   0, 255, 255 };
28 wmfRGB wmf_aquamarine		= { 127, 255, 212 };
29 wmfRGB wmf_azure		= { 240, 255, 255 };
30 wmfRGB wmf_beige		= { 245, 245, 220 };
31 wmfRGB wmf_bisque		= { 255, 228, 196 };
32 wmfRGB wmf_black		= {   0,   0,   0 };
33 wmfRGB wmf_blanchedalmond	= { 255, 235, 205 };
34 wmfRGB wmf_blue			= {   0,   0, 255 };
35 wmfRGB wmf_blueviolet		= { 138,  43, 226 };
36 wmfRGB wmf_brown		= { 165,  42,  42 };
37 wmfRGB wmf_burlywood		= { 222, 184, 135 };
38 wmfRGB wmf_cadetblue		= {  95, 158, 160 };
39 wmfRGB wmf_chartreuse		= { 127, 255,   0 };
40 wmfRGB wmf_chocolate		= { 210, 105,  30 };
41 wmfRGB wmf_coral		= { 255, 127,  80 };
42 wmfRGB wmf_cornflowerblue	= { 100, 149, 237 };
43 wmfRGB wmf_cornsilk		= { 255, 248, 220 };
44 wmfRGB wmf_crimson		= { 220,  20,  60 };
45 wmfRGB wmf_cyan			= {   0, 255, 255 };
46 wmfRGB wmf_darkblue		= {   0,   0, 139 };
47 wmfRGB wmf_darkcyan		= {   0, 139, 139 };
48 wmfRGB wmf_darkgoldenrod	= { 184, 134,  11 };
49 wmfRGB wmf_darkgray		= { 169, 169, 169 };
50 wmfRGB wmf_darkgreen		= {   0, 100,   0 };
51 wmfRGB wmf_darkgrey		= { 169, 169, 169 };
52 wmfRGB wmf_darkkhaki		= { 189, 183, 107 };
53 wmfRGB wmf_darkmagenta		= { 139,   0, 139 };
54 wmfRGB wmf_darkolivegreen	= {  85, 107,  47 };
55 wmfRGB wmf_darkorange		= { 255, 140,   0 };
56 wmfRGB wmf_darkorchid		= { 153,  50, 204 };
57 wmfRGB wmf_darkred		= { 139,   0,   0 };
58 wmfRGB wmf_darksalmon		= { 233, 150, 122 };
59 wmfRGB wmf_darkseagreen		= { 143, 188, 143 };
60 wmfRGB wmf_darkslateblue	= {  72,  61, 139 };
61 wmfRGB wmf_darkslategray	= {  47,  79,  79 };
62 wmfRGB wmf_darkslategrey	= {  47,  79,  79 };
63 wmfRGB wmf_darkturquoise	= {   0, 206, 209 };
64 wmfRGB wmf_darkviolet		= { 148,   0, 211 };
65 wmfRGB wmf_deeppink		= { 255,  20, 147 };
66 wmfRGB wmf_deepskyblue		= {   0, 191, 255 };
67 wmfRGB wmf_dimgray		= { 105, 105, 105 };
68 wmfRGB wmf_dimgrey		= { 105, 105, 105 };
69 wmfRGB wmf_dodgerblue		= {  30, 144, 255 };
70 wmfRGB wmf_firebrick		= { 178,  34,  34 };
71 wmfRGB wmf_floralwhite		= { 255, 250, 240 };
72 wmfRGB wmf_forestgreen		= {  34, 139,  34 };
73 wmfRGB wmf_fuchsia		= { 255,   0, 255 };
74 wmfRGB wmf_gainsboro		= { 220, 220, 220 };
75 wmfRGB wmf_ghostwhite		= { 248, 248, 255 };
76 wmfRGB wmf_gold			= { 255, 215,   0 };
77 wmfRGB wmf_goldenrod		= { 218, 165,  32 };
78 wmfRGB wmf_gray			= { 128, 128, 128 };
79 wmfRGB wmf_grey			= { 128, 128, 128 };
80 wmfRGB wmf_green		= {   0, 128,   0 };
81 wmfRGB wmf_greenyellow		= { 173, 255,  47 };
82 wmfRGB wmf_honeydew		= { 240, 255, 240 };
83 wmfRGB wmf_hotpink		= { 255, 105, 180 };
84 wmfRGB wmf_indianred		= { 205,  92,  92 };
85 wmfRGB wmf_indigo		= {  75,   0, 130 };
86 wmfRGB wmf_ivory		= { 255, 255, 240 };
87 wmfRGB wmf_khaki		= { 240, 230, 140 };
88 wmfRGB wmf_lavender		= { 230, 230, 250 };
89 wmfRGB wmf_lavenderblush	= { 255, 240, 245 };
90 wmfRGB wmf_lawngreen		= { 124, 252,   0 };
91 wmfRGB wmf_lemonchiffon		= { 255, 250, 205 };
92 wmfRGB wmf_lightblue		= { 173, 216, 230 };
93 wmfRGB wmf_lightcoral		= { 240, 128, 128 };
94 wmfRGB wmf_lightcyan		= { 224, 255, 255 };
95 wmfRGB wmf_lightgoldenrodyellow	= { 250, 250, 210 };
96 wmfRGB wmf_lightgray		= { 211, 211, 211 };
97 wmfRGB wmf_lightgreen		= { 144, 238, 144 };
98 wmfRGB wmf_lightgrey		= { 211, 211, 211 };
99 wmfRGB wmf_lightpink		= { 255, 182, 193 };
100 wmfRGB wmf_lightsalmon		= { 255, 160, 122 };
101 wmfRGB wmf_lightseagreen	= {  32, 178, 170 };
102 wmfRGB wmf_lightskyblue		= { 135, 206, 250 };
103 wmfRGB wmf_lightslategray	= { 119, 136, 153 };
104 wmfRGB wmf_lightslategrey	= { 119, 136, 153 };
105 wmfRGB wmf_lightsteelblue	= { 176, 196, 222 };
106 wmfRGB wmf_lightyellow		= { 255, 255, 224 };
107 wmfRGB wmf_lime			= {   0, 255,   0 };
108 wmfRGB wmf_limegreen		= {  50, 205,  50 };
109 wmfRGB wmf_linen		= { 250, 240, 230 };
110 wmfRGB wmf_magenta		= { 255,   0, 255 };
111 wmfRGB wmf_maroon		= { 128,   0,   0 };
112 wmfRGB wmf_mediumaquamarine	= { 102, 205, 170 };
113 wmfRGB wmf_mediumblue		= {   0,   0, 205 };
114 wmfRGB wmf_mediumorchid		= { 186,  85, 211 };
115 wmfRGB wmf_mediumpurple		= { 147, 112, 219 };
116 wmfRGB wmf_mediumseagreen	= {  60, 179, 113 };
117 wmfRGB wmf_mediumslateblue	= { 123, 104, 238 };
118 wmfRGB wmf_mediumspringgreen	= {   0, 250, 154 };
119 wmfRGB wmf_mediumturquoise	= {  72, 209, 204 };
120 wmfRGB wmf_mediumvioletred	= { 199,  21, 133 };
121 wmfRGB wmf_midnightblue		= {  25,  25, 112 };
122 wmfRGB wmf_mintcream		= { 245, 255, 250 };
123 wmfRGB wmf_mistyrose		= { 255, 228, 225 };
124 wmfRGB wmf_moccasin		= { 255, 228, 181 };
125 wmfRGB wmf_navajowhite		= { 255, 222, 173 };
126 wmfRGB wmf_navy			= {   0,   0, 128 };
127 wmfRGB wmf_oldlace		= { 253, 245, 230 };
128 wmfRGB wmf_olive		= { 128, 128,   0 };
129 wmfRGB wmf_olivedrab		= { 107, 142,  35 };
130 wmfRGB wmf_orange		= { 255, 165,   0 };
131 wmfRGB wmf_orangered		= { 255,  69,   0 };
132 wmfRGB wmf_orchid		= { 218, 112, 214 };
133 wmfRGB wmf_palegoldenrod	= { 238, 232, 170 };
134 wmfRGB wmf_palegreen		= { 152, 251, 152 };
135 wmfRGB wmf_paleturquoise	= { 175, 238, 238 };
136 wmfRGB wmf_palevioletred	= { 219, 112, 147 };
137 wmfRGB wmf_papayawhip		= { 255, 239, 213 };
138 wmfRGB wmf_peachpuff		= { 255, 218, 185 };
139 wmfRGB wmf_peru			= { 205, 133,  63 };
140 wmfRGB wmf_pink			= { 255, 192, 203 };
141 wmfRGB wmf_plum			= { 221, 160, 221 };
142 wmfRGB wmf_powderblue		= { 176, 224, 230 };
143 wmfRGB wmf_purple		= { 128,   0, 128 };
144 wmfRGB wmf_red			= { 255,   0,   0 };
145 wmfRGB wmf_rosybrown		= { 188, 143, 143 };
146 wmfRGB wmf_royalblue		= {  65, 105, 225 };
147 wmfRGB wmf_saddlebrown		= { 139,  69,  19 };
148 wmfRGB wmf_salmon		= { 250, 128, 114 };
149 wmfRGB wmf_sandybrown		= { 244, 164,  96 };
150 wmfRGB wmf_seagreen		= {  46, 139,  87 };
151 wmfRGB wmf_seashell		= { 255, 245, 238 };
152 wmfRGB wmf_sienna		= { 160,  82,  45 };
153 wmfRGB wmf_silver		= { 192, 192, 192 };
154 wmfRGB wmf_skyblue		= { 135, 206, 235 };
155 wmfRGB wmf_slateblue		= { 106,  90, 205 };
156 wmfRGB wmf_slategray		= { 112, 128, 144 };
157 wmfRGB wmf_slategrey		= { 112, 128, 144 };
158 wmfRGB wmf_snow			= { 255, 250, 250 };
159 wmfRGB wmf_springgreen		= {   0, 255, 127 };
160 wmfRGB wmf_steelblue		= {  70, 130, 180 };
161 wmfRGB wmf_tan			= { 210, 180, 140 };
162 wmfRGB wmf_teal			= {   0, 128, 128 };
163 wmfRGB wmf_thistle		= { 216, 191, 216 };
164 wmfRGB wmf_tomato		= { 255,  99,  71 };
165 wmfRGB wmf_turquoise		= {  64, 224, 208 };
166 wmfRGB wmf_violet		= { 238, 130, 238 };
167 wmfRGB wmf_wheat		= { 245, 222, 179 };
168 wmfRGB wmf_white		= { 255, 255, 255 };
169 wmfRGB wmf_whitesmoke		= { 245, 245, 245 };
170 wmfRGB wmf_yellow		= { 255, 255,   0 };
171 wmfRGB wmf_yellowgreen		= { 154, 205,  50 };
172 
173 /* Color table
174  */
175 
176 /**
177  * Initialize internal color table
178  *
179  * @param API the API handle
180  */
wmf_ipa_color_init(wmfAPI * API)181 void wmf_ipa_color_init (wmfAPI* API)
182 {	wmfColorData* color;
183 
184 	API->color_data = wmf_malloc (API,sizeof (wmfColorData));
185 
186 	if (ERR (API))
187 	{	WMF_DEBUG (API,"bailing...");
188 		return;
189 	}
190 
191 	color = (wmfColorData*) API->color_data;
192 
193 	color->max = 32;
194 	color->count = 0;
195 	color->rgb = (wmfRGB*) wmf_malloc (API,color->max * sizeof (wmfRGB));
196 
197 	if (ERR (API))
198 	{	WMF_DEBUG (API,"bailing...");
199 		return;
200 	}
201 
202 	color->rgb[0] = wmf_red; /* not a real entry; don't increment count... */
203 }
204 
205 /**
206  * Add a color to the internal table.
207  *
208  * @param API the API handle
209  * @param rgb pointer to the color to be added
210  */
wmf_ipa_color_add(wmfAPI * API,wmfRGB * rgb)211 void wmf_ipa_color_add (wmfAPI* API,wmfRGB* rgb)
212 {	wmfRGB* more = 0;
213 
214 	wmfColorData* color = (wmfColorData*) API->color_data;
215 
216 	unsigned long i;
217 
218 	int new_color = 1;
219 
220 	for (i = 0; i < color->count; i++)
221 	{	if ( (rgb->r == color->rgb[i].r)
222 		  && (rgb->g == color->rgb[i].g)
223 		  && (rgb->b == color->rgb[i].b))
224 		{	new_color = 0;
225 			break;
226 		}
227 	}
228 	if (!new_color) return;
229 
230 	if (color->count == color->max)
231 	{	more = wmf_realloc (API,color->rgb,(color->max + 32) * sizeof (wmfRGB));
232 
233 		if (ERR (API))
234 		{	WMF_DEBUG (API,"bailing...");
235 			return;
236 		}
237 
238 		color->rgb = more;
239 		color->max += 32;
240 	}
241 
242 	color->rgb[color->count] = (*rgb);
243 	color->count++;
244 }
245 
246 /**
247  * Find closest matching color in internal table and return its index.
248  *
249  * @param API the API handle
250  * @param rgb pointer to the color to be matched
251  *
252  * @return Returns the index of the closest matching color.
253  */
wmf_ipa_color_index(wmfAPI * API,wmfRGB * rgb)254 unsigned long wmf_ipa_color_index (wmfAPI* API,wmfRGB* rgb)
255 {	wmfColorData* color = (wmfColorData*) API->color_data;
256 
257 	unsigned long i;
258 	unsigned long best = 0;
259 
260 	unsigned int dbest = 766;
261 	unsigned int di;
262 	unsigned int dr;
263 	unsigned int dg;
264 	unsigned int db;
265 
266 	if (color->count == 0)
267 	{	if (API->flags & WMF_OPT_IGNORE_NONFATAL)
268 		{	WMF_DEBUG (API,"Color table has no entries!");
269 		}
270 		else
271 		{	WMF_ERROR (API,"Color table has no entries!");
272 			API->err = wmf_E_Glitch;
273 		}
274 		return (best); /* This should dereference safely to red. */
275 	}
276 
277 	/* First check for an exact match...
278 	 */
279 	for (i = 0; i < color->count; i++)
280 	{	if ((rgb->r == color->rgb[i].r)
281 		 && (rgb->g == color->rgb[i].g)
282 		 && (rgb->b == color->rgb[i].b))
283 		{	 best = i;
284 			dbest = 0;
285 			break;
286 		}
287 	}
288 	if (dbest == 0) return (best);
289 
290 	/* Otherwise return best match; I'm going to use minimax rather than r.m.s.
291 	 */
292 	for (i = 0; i < color->count; i++)
293 	{	dr = (unsigned int) ABS (((int) (rgb->r)) - ((int) (color->rgb[i].r)));
294 		dg = (unsigned int) ABS (((int) (rgb->g)) - ((int) (color->rgb[i].g)));
295 		db = (unsigned int) ABS (((int) (rgb->b)) - ((int) (color->rgb[i].b)));
296 
297 		di = MAX (dr,dg);
298 		di = MAX (di,db);
299 
300 		if (di < dbest)
301 		{	 best =  i;
302 			dbest = di;
303 		}
304 	}
305 
306 	return (best);
307 }
308 
309 /**
310  * Get the number of indexed colors.
311  *
312  * @param API the API handle
313  *
314  * @return Returns the number of indexed colors.
315  */
wmf_ipa_color_count(wmfAPI * API)316 unsigned long wmf_ipa_color_count (wmfAPI* API)
317 {	wmfColorData* color = (wmfColorData*) API->color_data;
318 
319 	return (color->count);
320 }
321 
322 /**
323  * Get indexed color.
324  *
325  * @param API   the API handle
326  * @param index the index of the color
327  *
328  * @return Returns pointer to the indexed color.
329  */
wmf_ipa_color(wmfAPI * API,unsigned long index)330 wmfRGB* wmf_ipa_color (wmfAPI* API,unsigned long index)
331 {	wmfColorData* color = (wmfColorData*) API->color_data;
332 
333 	if (index >= color->count)
334 	{	WMF_ERROR (API,"Glitch! Color index out of range!");
335 		API->err = wmf_E_Glitch;
336 		return (&wmf_red);
337 	}
338 
339 	return (color->rgb + index);
340 }
341 
rgb(U16 one,U16 two)342 static wmfRGB rgb (U16 one,U16 two)
343 {	wmfRGB color;
344 
345 	color.r = (unsigned char)  (one & 0x00FF);
346 	color.g = (unsigned char) ((one & 0xFF00) >> 8);
347 	color.b = (unsigned char)  (two & 0x00FF);
348 
349 	return (color);
350 }
351 
352 /**
353  * The color white.
354  *
355  * @param API the API handle
356  *
357  * @return Returns \b wmf_white.
358  */
wmf_rgb_white(void)359 wmfRGB wmf_rgb_white (void)
360 {	return (wmf_white);
361 }
362 
363 /**
364  * The color black.
365  *
366  * @param API the API handle
367  *
368  * @return Returns \b wmf_black.
369  */
wmf_rgb_black(void)370 wmfRGB wmf_rgb_black (void)
371 {	return (wmf_black);
372 }
373 
374 /**
375  * Create a color with specified fractions of red, green and blue.
376  *
377  * @param API   the API handle
378  * @param red   fraction (0 to 1 inclusive) of color red
379  * @param green fraction (0 to 1 inclusive) of color green
380  * @param blue  fraction (0 to 1 inclusive) of color blue
381  *
382  * \b wmf_rgb_color (API,1,1,1) returns \b wmf_white.
383  *
384  * \b wmf_rgb_color (API,0,0,0) returns \b wmf_black.
385  *
386  * @return Returns the color.
387  */
wmf_rgb_color(wmfAPI * API,float red,float green,float blue)388 wmfRGB wmf_rgb_color (wmfAPI* API,float red,float green,float blue)
389 {	(void)API;
390 	wmfRGB color;
391 
392 	int i_red;
393 	int i_green;
394 	int i_blue;
395 
396 	if (red	  > 1) red   = 1;
397 	if (green > 1) green = 1;
398 	if (blue  > 1) blue  = 1;
399 
400 	if (red	  < 0) red   = 0;
401 	if (green < 0) green = 0;
402 	if (blue  < 0) blue  = 0;
403 
404 	i_red   = (int) (red   * (float) 256);
405 	i_green = (int) (green * (float) 256);
406 	i_blue  = (int) (blue  * (float) 256);
407 
408 	if (i_red   > 255) i_red   = 255;
409 	if (i_green > 255) i_green = 255;
410 	if (i_blue  > 255) i_blue  = 255;
411 
412 	if (i_red   < 0) i_red   = 0;
413 	if (i_green < 0) i_green = 0;
414 	if (i_blue  < 0) i_blue  = 0;
415 
416 	color.r = (unsigned char) i_red;
417 	color.g = (unsigned char) i_green;
418 	color.b = (unsigned char) i_blue;
419 
420 	return (color);
421 }
422 
423 #endif /* ! WMFPLAYER_COLOR_H */
424