Code

adapt includes to glib 2.9 changes
[inkscape.git] / src / svg / svg-color.cpp
1 #define __SP_SVG_COLOR_C__
3 /*
4  * SVG data parser
5  *
6  * Authors:
7  *   Lauris Kaplinski <lauris@kaplinski.com>
8  *
9  * Copyright (C) 1999-2002 Lauris Kaplinski
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include "config.h"
16 #endif
18 #include <math.h>
19 #include <glib/gstrfuncs.h>
20 #include <glib/ghash.h>
22 #include <glib/gutils.h>
23 #if GLIB_CHECK_VERSION(2,9,0)
24 #else
25 # include <glib/gprintf.h>
26 #endif
28 #include "svg.h"
30 struct SPSVGColor {
31         unsigned long rgb;
32         char const *name;
33 };
35 /*
36  * These are the colors defined in the SVG standard
37  */
38 static SPSVGColor sp_svg_color_named[] = {
39         { 0xF0F8FF, "aliceblue" },
40         { 0xFAEBD7, "antiquewhite" },
41         { 0x00FFFF, "aqua" },
42         { 0x7FFFD4, "aquamarine" },
43         { 0xF0FFFF, "azure" },
44         { 0xF5F5DC, "beige" },
45         { 0xFFE4C4, "bisque" },
46         { 0x000000, "black" },
47         { 0xFFEBCD, "blanchedalmond" },
48         { 0x0000FF, "blue" },
49         { 0x8A2BE2, "blueviolet" },
50         { 0xA52A2A, "brown" },
51         { 0xDEB887, "burlywood" },
52         { 0x5F9EA0, "cadetblue" },
53         { 0x7FFF00, "chartreuse" },
54         { 0xD2691E, "chocolate" },
55         { 0xFF7F50, "coral" },
56         { 0x6495ED, "cornflowerblue" },
57         { 0xFFF8DC, "cornsilk" },
58         { 0xDC143C, "crimson" },
59         { 0x00FFFF, "cyan" },
60         { 0x00008B, "darkblue" },
61         { 0x008B8B, "darkcyan" },
62         { 0xB8860B, "darkgoldenrod" },
63         { 0xA9A9A9, "darkgray" },
64         { 0x006400, "darkgreen" },
65         { 0xA9A9A9, "darkgrey" },
66         { 0xBDB76B, "darkkhaki" },
67         { 0x8B008B, "darkmagenta" },
68         { 0x556B2F, "darkolivegreen" },
69         { 0xFF8C00, "darkorange" },
70         { 0x9932CC, "darkorchid" },
71         { 0x8B0000, "darkred" },
72         { 0xE9967A, "darksalmon" },
73         { 0x8FBC8F, "darkseagreen" },
74         { 0x483D8B, "darkslateblue" },
75         { 0x2F4F4F, "darkslategray" },
76         { 0x2F4F4F, "darkslategrey" },
77         { 0x00CED1, "darkturquoise" },
78         { 0x9400D3, "darkviolet" },
79         { 0xFF1493, "deeppink" },
80         { 0x00BFFF, "deepskyblue" },
81         { 0x696969, "dimgray" },
82         { 0x696969, "dimgrey" },
83         { 0x1E90FF, "dodgerblue" },
84         { 0xB22222, "firebrick" },
85         { 0xFFFAF0, "floralwhite" },
86         { 0x228B22, "forestgreen" },
87         { 0xFF00FF, "fuchsia" },
88         { 0xDCDCDC, "gainsboro" },
89         { 0xF8F8FF, "ghostwhite" },
90         { 0xFFD700, "gold" },
91         { 0xDAA520, "goldenrod" },
92         { 0x808080, "gray" },
93         { 0x808080, "grey" },
94         { 0x008000, "green" },
95         { 0xADFF2F, "greenyellow" },
96         { 0xF0FFF0, "honeydew" },
97         { 0xFF69B4, "hotpink" },
98         { 0xCD5C5C, "indianred" },
99         { 0x4B0082, "indigo" },
100         { 0xFFFFF0, "ivory" },
101         { 0xF0E68C, "khaki" },
102         { 0xE6E6FA, "lavender" },
103         { 0xFFF0F5, "lavenderblush" },
104         { 0x7CFC00, "lawngreen" },
105         { 0xFFFACD, "lemonchiffon" },
106         { 0xADD8E6, "lightblue" },
107         { 0xF08080, "lightcoral" },
108         { 0xE0FFFF, "lightcyan" },
109         { 0xFAFAD2, "lightgoldenrodyellow" },
110         { 0xD3D3D3, "lightgray" },
111         { 0x90EE90, "lightgreen" },
112         { 0xD3D3D3, "lightgrey" },
113         { 0xFFB6C1, "lightpink" },
114         { 0xFFA07A, "lightsalmon" },
115         { 0x20B2AA, "lightseagreen" },
116         { 0x87CEFA, "lightskyblue" },
117         { 0x778899, "lightslategray" },
118         { 0x778899, "lightslategrey" },
119         { 0xB0C4DE, "lightsteelblue" },
120         { 0xFFFFE0, "lightyellow" },
121         { 0x00FF00, "lime" },
122         { 0x32CD32, "limegreen" },
123         { 0xFAF0E6, "linen" },
124         { 0xFF00FF, "magenta" },
125         { 0x800000, "maroon" },
126         { 0x66CDAA, "mediumaquamarine" },
127         { 0x0000CD, "mediumblue" },
128         { 0xBA55D3, "mediumorchid" },
129         { 0x9370DB, "mediumpurple" },
130         { 0x3CB371, "mediumseagreen" },
131         { 0x7B68EE, "mediumslateblue" },
132         { 0x00FA9A, "mediumspringgreen" },
133         { 0x48D1CC, "mediumturquoise" },
134         { 0xC71585, "mediumvioletred" },
135         { 0x191970, "midnightblue" },
136         { 0xF5FFFA, "mintcream" },
137         { 0xFFE4E1, "mistyrose" },
138         { 0xFFE4B5, "moccasin" },
139         { 0xFFDEAD, "navajowhite" },
140         { 0x000080, "navy" },
141         { 0xFDF5E6, "oldlace" },
142         { 0x808000, "olive" },
143         { 0x6B8E23, "olivedrab" },
144         { 0xFFA500, "orange" },
145         { 0xFF4500, "orangered" },
146         { 0xDA70D6, "orchid" },
147         { 0xEEE8AA, "palegoldenrod" },
148         { 0x98FB98, "palegreen" },
149         { 0xAFEEEE, "paleturquoise" },
150         { 0xDB7093, "palevioletred" },
151         { 0xFFEFD5, "papayawhip" },
152         { 0xFFDAB9, "peachpuff" },
153         { 0xCD853F, "peru" },
154         { 0xFFC0CB, "pink" },
155         { 0xDDA0DD, "plum" },
156         { 0xB0E0E6, "powderblue" },
157         { 0x800080, "purple" },
158         { 0xFF0000, "red" },
159         { 0xBC8F8F, "rosybrown" },
160         { 0x4169E1, "royalblue" },
161         { 0x8B4513, "saddlebrown" },
162         { 0xFA8072, "salmon" },
163         { 0xF4A460, "sandybrown" },
164         { 0x2E8B57, "seagreen" },
165         { 0xFFF5EE, "seashell" },
166         { 0xA0522D, "sienna" },
167         { 0xC0C0C0, "silver" },
168         { 0x87CEEB, "skyblue" },
169         { 0x6A5ACD, "slateblue" },
170         { 0x708090, "slategray" },
171         { 0x708090, "slategrey" },
172         { 0xFFFAFA, "snow" },
173         { 0x00FF7F, "springgreen" },
174         { 0x4682B4, "steelblue" },
175         { 0xD2B48C, "tan" },
176         { 0x008080, "teal" },
177         { 0xD8BFD8, "thistle" },
178         { 0xFF6347, "tomato" },
179         { 0x40E0D0, "turquoise" },
180         { 0xEE82EE, "violet" },
181         { 0xF5DEB3, "wheat" },
182         { 0xFFFFFF, "white" },
183         { 0xF5F5F5, "whitesmoke" },
184         { 0xFFFF00, "yellow" },
185         { 0x9ACD32, "yellowgreen" }
186 };
188 #define SP_SVG_NUMCOLORS (sizeof (sp_svg_color_named) / sizeof (sp_svg_color_named[0]))
190 static GHashTable *sp_svg_create_color_hash (void);
192 guint32
193 sp_svg_read_color (const gchar *str, guint32 def)
195         static GHashTable *colors = NULL;
196         gchar c[32];
197         guint32 val = 0;
199         /* 
200          * todo: handle the rgb (r, g, b) and rgb ( r%, g%, b%), syntax 
201          * defined in http://www.w3.org/TR/REC-CSS2/syndata.html#color-units 
202          */
204         if (str == NULL) return def;
205         while ((*str <= ' ') && *str) str++;
206         if (!*str) return def;
208         if (str[0] == '#') {
209                 gint i;
210                 for (i = 1; str[i]; i++) {
211                         int hexval;
212                         if (str[i] >= '0' && str[i] <= '9')
213                                 hexval = str[i] - '0';
214                         else if (str[i] >= 'A' && str[i] <= 'F')
215                                 hexval = str[i] - 'A' + 10;
216                         else if (str[i] >= 'a' && str[i] <= 'f')
217                                 hexval = str[i] - 'a' + 10;
218                         else
219                                 break;
220                         val = (val << 4) + hexval;
221                 }
222                 /* handle #rgb case */
223                 if (i == 1 + 3) {
224                         val = ((val & 0xf00) << 8) |
225                                 ((val & 0x0f0) << 4) |
226                                 (val & 0x00f);
227                         val |= val << 4;
228                 } else if (i != 1 + 6) {
229                         /* must be either 3 or 6 digits. */
230                         return def;
231                 }
232         } else if (!strncmp (str, "rgb(", 4)) {
233                 gboolean hasp, hasd;
234                 gchar *s, *e;
235                 gdouble r, g, b;
237                 s = (gchar *) str + 4;
238                 hasp = FALSE;
239                 hasd = FALSE;
241                 r = g_ascii_strtod (s, &e);
242                 if (s == e) return def;
243                 s = e;
244                 if (*s == '%') {
245                         hasp = TRUE;
246                         s += 1;
247                 } else {
248                         hasd = TRUE;
249                 }
250                 while (*s && g_ascii_isspace (*s)) s += 1;
251                 if (*s != ',') return def;
252                 s += 1;
253                 while (*s && g_ascii_isspace (*s)) s += 1;
254                 g = g_ascii_strtod (s, &e);
255                 if (s == e) return def;
256                 s = e;
257                 if (*s == '%') {
258                         hasp = TRUE;
259                         s += 1;
260                 } else {
261                         hasd = TRUE;
262                 }
263                 while (*s && g_ascii_isspace (*s)) s += 1;
264                 if (*s != ',') return def;
265                 s += 1;
266                 while (*s && g_ascii_isspace (*s)) s += 1;
267                 b = g_ascii_strtod (s, &e);
268                 if (s == e) return def;
269                 s = e;
270                 if (*s == '%') {
271                         hasp = TRUE;
272                 } else {
273                         hasd = TRUE;
274                 }
275                 if (hasp && hasd) return def;
276                 if (hasp) {
277                         val = (guint) floor (CLAMP (r, 0.0, 100.0) * 2.559999) << 24;
278                         val |= ((guint) floor (CLAMP (g, 0.0, 100.0) * 2.559999) << 16);
279                         val |= ((guint) floor (CLAMP (b, 0.0, 100.0) * 2.559999) << 8);
280                 } else {
281                         val = (guint) CLAMP (r, 0, 255) << 24;
282                         val |= ((guint) CLAMP (g, 0, 255) << 16);
283                         val |= ((guint) CLAMP (b, 0, 255) << 8);
284                 }
285                 return val;
286         } else {
287                 gint i;
288                 if (!colors) {
289                         colors = sp_svg_create_color_hash ();
290                 }
291                 for (i = 0; i < 31; i++) {
292                         if (str[i] == ';') {
293                                 c[i] = '\0';
294                                 break;
295                         }
296                         c[i] = g_ascii_tolower (str[i]);
297                         if (!str[i]) break;
298                 }
299                 c[31] = '\0';
301                 gpointer const rgb_ptr = g_hash_table_lookup(colors, c);
302                 if (rgb_ptr) {
303                         val = *(static_cast<unsigned long *>(rgb_ptr));
304                 } else {
305                         return def;
306                 }
307         }
309         return (val << 8);
312 gint
313 sp_svg_write_color (gchar * buf, gint buflen, guint32 color)
315         return g_snprintf (buf, buflen, "#%06x", color >> 8);
318 static GHashTable *
319 sp_svg_create_color_hash (void)
321         GHashTable * colors = g_hash_table_new (g_str_hash, g_str_equal);
323         for (unsigned i = 0 ; i < SP_SVG_NUMCOLORS ; i++) {
324                 void const *name = sp_svg_color_named[i].name;
325                 gpointer val = &(sp_svg_color_named[i].rgb);
326                 g_hash_table_insert(colors, const_cast<gpointer>(name), val);
327         }
329         return colors;