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