1 /* -*- Mode: C; indent-tabs-mode:nil; c-basic-offset: 8-*- */
2
3 /* libcroco - Library for parsing and applying CSS
4 * Copyright (C) 2006-2019 Free Software Foundation, Inc.
5 *
6 * This file is not part of the GNU gettext program, but is used with
7 * GNU gettext.
8 *
9 * The original copyright notice is as follows:
10 */
11
12 /*
13 * This file is part of The Croco Library
14 *
15 * Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of version 2.1 of the GNU Lesser General Public
19 * License as published by the Free Software Foundation.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 * USA
30 *
31 * Author: Dodji Seketeli
32 */
33
34 #include <config.h>
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <stdlib.h>
39 #include "cr-rgb.h"
40 #include "cr-term.h"
41 #include "cr-parser.h"
42
43 static const CRRgb gv_standard_colors[] = {
44 {(const guchar*)"aliceblue", 240, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
45 {(const guchar*)"antiquewhite", 250, 235, 215, FALSE, FALSE, FALSE, {0,0,0}},
46 {(const guchar*)"aqua", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
47 {(const guchar*)"aquamarine", 127, 255, 212, FALSE, FALSE, FALSE, {0,0,0}},
48 {(const guchar*)"azure", 240, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
49 {(const guchar*)"beige", 245, 245, 220, FALSE, FALSE, FALSE, {0,0,0}},
50 {(const guchar*)"bisque", 255, 228, 196, FALSE, FALSE, FALSE, {0,0,0}},
51 {(const guchar*)"black", 0, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
52 {(const guchar*)"blanchedalmond", 255, 235, 205, FALSE, FALSE, FALSE, {0,0,0}},
53 {(const guchar*)"blue", 0, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
54 {(const guchar*)"blueviolet", 138, 43, 226, FALSE, FALSE, FALSE, {0,0,0}},
55 {(const guchar*)"brown", 165, 42, 42, FALSE, FALSE, FALSE, {0,0,0}},
56 {(const guchar*)"burlywood", 222, 184, 135, FALSE, FALSE, FALSE, {0,0,0}},
57 {(const guchar*)"cadetblue", 95, 158, 160, FALSE, FALSE, FALSE, {0,0,0}},
58 {(const guchar*)"chartreuse", 127, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
59 {(const guchar*)"chocolate", 210, 105, 30, FALSE, FALSE, FALSE, {0,0,0}},
60 {(const guchar*)"coral", 255, 127, 80, FALSE, FALSE, FALSE, {0,0,0}},
61 {(const guchar*)"cornflowerblue", 100, 149, 237, FALSE, FALSE, FALSE, {0,0,0}},
62 {(const guchar*)"cornsilk", 255, 248, 220, FALSE, FALSE, FALSE, {0,0,0}},
63 {(const guchar*)"crimson", 220, 20, 60, FALSE, FALSE, FALSE, {0,0,0}},
64 {(const guchar*)"cyan", 0, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
65 {(const guchar*)"darkblue", 0, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
66 {(const guchar*)"darkcyan", 0, 139, 139, FALSE, FALSE, FALSE, {0,0,0}},
67 {(const guchar*)"darkgoldenrod", 184, 134, 11, FALSE, FALSE, FALSE, {0,0,0}},
68 {(const guchar*)"darkgray", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
69 {(const guchar*)"darkgreen", 0, 100, 0, FALSE, FALSE, FALSE, {0,0,0}},
70 {(const guchar*)"darkgrey", 169, 169, 169, FALSE, FALSE, FALSE, {0,0,0}},
71 {(const guchar*)"darkkhaki", 189, 183, 107, FALSE, FALSE, FALSE, {0,0,0}},
72 {(const guchar*)"darkmagenta", 139, 0, 139, FALSE, FALSE, FALSE, {0,0,0}},
73 {(const guchar*)"darkolivegreen", 85, 107, 47, FALSE, FALSE, FALSE, {0,0,0}},
74 {(const guchar*)"darkorange", 255, 140, 0, FALSE, FALSE, FALSE, {0,0,0}},
75 {(const guchar*)"darkorchid", 153, 50, 204, FALSE, FALSE, FALSE, {0,0,0}},
76 {(const guchar*)"darkred", 139, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
77 {(const guchar*)"darksalmon", 233, 150, 122, FALSE, FALSE, FALSE, {0,0,0}},
78 {(const guchar*)"darkseagreen", 143, 188, 143, FALSE, FALSE, FALSE, {0,0,0}},
79 {(const guchar*)"darkslateblue", 72, 61, 139, FALSE, FALSE, FALSE, {0,0,0}},
80 {(const guchar*)"darkslategray", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
81 {(const guchar*)"darkslategrey", 47, 79, 79, FALSE, FALSE, FALSE, {0,0,0}},
82 {(const guchar*)"darkturquoise", 0, 206, 209, FALSE, FALSE, FALSE, {0,0,0}},
83 {(const guchar*)"darkviolet", 148, 0, 211, FALSE, FALSE, FALSE, {0,0,0}},
84 {(const guchar*)"deeppink", 255, 20, 147, FALSE, FALSE, FALSE, {0,0,0}},
85 {(const guchar*)"deepskyblue", 0, 191, 255, FALSE, FALSE, FALSE, {0,0,0}},
86 {(const guchar*)"dimgray", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
87 {(const guchar*)"dimgrey", 105, 105, 105, FALSE, FALSE, FALSE, {0,0,0}},
88 {(const guchar*)"dodgerblue", 30, 144, 255, FALSE, FALSE, FALSE, {0,0,0}},
89 {(const guchar*)"firebrick", 178, 34, 34, FALSE, FALSE, FALSE, {0,0,0}},
90 {(const guchar*)"floralwhite", 255, 250, 240, FALSE, FALSE, FALSE, {0,0,0}},
91 {(const guchar*)"forestgreen", 34, 139, 34, FALSE, FALSE, FALSE, {0,0,0}},
92 {(const guchar*)"fuchsia", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
93 {(const guchar*)"gainsboro", 220, 220, 220, FALSE, FALSE, FALSE, {0,0,0}},
94 {(const guchar*)"ghostwhite", 248, 248, 255, FALSE, FALSE, FALSE, {0,0,0}},
95 {(const guchar*)"gold", 255, 215, 0, FALSE, FALSE, FALSE, {0,0,0}},
96 {(const guchar*)"goldenrod", 218, 165, 32, FALSE, FALSE, FALSE, {0,0,0}},
97 {(const guchar*)"gray", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
98 {(const guchar*)"green", 0, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
99 {(const guchar*)"greenyellow", 173, 255, 47, FALSE, FALSE, FALSE, {0,0,0}},
100 {(const guchar*)"grey", 128, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
101 {(const guchar*)"honeydew", 240, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
102 {(const guchar*)"hotpink", 255, 105, 180, FALSE, FALSE, FALSE, {0,0,0}},
103 {(const guchar*)"indianred", 205, 92, 92, FALSE, FALSE, FALSE, {0,0,0}},
104 {(const guchar*)"indigo", 75, 0, 130, FALSE, FALSE, FALSE, {0,0,0}},
105 {(const guchar*)"ivory", 255, 255, 240, FALSE, FALSE, FALSE, {0,0,0}},
106 {(const guchar*)"khaki", 240, 230, 140, FALSE, FALSE, FALSE, {0,0,0}},
107 {(const guchar*)"lavender", 230, 230, 250, FALSE, FALSE, FALSE, {0,0,0}},
108 {(const guchar*)"lavenderblush", 255, 240, 245, FALSE, FALSE, FALSE, {0,0,0}},
109 {(const guchar*)"lawngreen", 124, 252, 0, FALSE, FALSE, FALSE, {0,0,0}},
110 {(const guchar*)"lemonchiffon", 255, 250, 205, FALSE, FALSE, FALSE, {0,0,0}},
111 {(const guchar*)"lightblue", 173, 216, 230, FALSE, FALSE, FALSE, {0,0,0}},
112 {(const guchar*)"lightcoral", 240, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
113 {(const guchar*)"lightcyan", 224, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
114 {(const guchar*)"lightgoldenrodyellow", 250, 250, 210, FALSE, FALSE, FALSE, {0,0,0}},
115 {(const guchar*)"lightgray", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
116 {(const guchar*)"lightgreen", 144, 238, 144, FALSE, FALSE, FALSE, {0,0,0}},
117 {(const guchar*)"lightgrey", 211, 211, 211, FALSE, FALSE, FALSE, {0,0,0}},
118 {(const guchar*)"lightpink", 255, 182, 193, FALSE, FALSE, FALSE, {0,0,0}},
119 {(const guchar*)"lightsalmon", 255, 160, 122, FALSE, FALSE, FALSE, {0,0,0}},
120 {(const guchar*)"lightseagreen", 32, 178, 170, FALSE, FALSE, FALSE, {0,0,0}},
121 {(const guchar*)"lightskyblue", 135, 206, 250, FALSE, FALSE, FALSE, {0,0,0}},
122 {(const guchar*)"lightslategray", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
123 {(const guchar*)"lightslategrey", 119, 136, 153, FALSE, FALSE, FALSE, {0,0,0}},
124 {(const guchar*)"lightsteelblue", 176, 196, 222, FALSE, FALSE, FALSE, {0,0,0}},
125 {(const guchar*)"lightyellow", 255, 255, 224, FALSE, FALSE, FALSE, {0,0,0}},
126 {(const guchar*)"lime", 0, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
127 {(const guchar*)"limegreen", 50, 205, 50, FALSE, FALSE, FALSE, {0,0,0}},
128 {(const guchar*)"linen", 250, 240, 230, FALSE, FALSE, FALSE, {0,0,0}},
129 {(const guchar*)"magenta", 255, 0, 255, FALSE, FALSE, FALSE, {0,0,0}},
130 {(const guchar*)"maroon", 128, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
131 {(const guchar*)"mediumaquamarine", 102, 205, 170, FALSE, FALSE, FALSE, {0,0,0}},
132 {(const guchar*)"mediumblue", 0, 0, 205, FALSE, FALSE, FALSE, {0,0,0}},
133 {(const guchar*)"mediumorchid", 186, 85, 211, FALSE, FALSE, FALSE, {0,0,0}},
134 {(const guchar*)"mediumpurple", 147, 112, 219, FALSE, FALSE, FALSE, {0,0,0}},
135 {(const guchar*)"mediumseagreen", 60, 179, 113, FALSE, FALSE, FALSE, {0,0,0}},
136 {(const guchar*)"mediumslateblue", 123, 104, 238, FALSE, FALSE, FALSE, {0,0,0}},
137 {(const guchar*)"mediumspringgreen", 0, 250, 154, FALSE, FALSE, FALSE, {0,0,0}},
138 {(const guchar*)"mediumturquoise", 72, 209, 204, FALSE, FALSE, FALSE, {0,0,0}},
139 {(const guchar*)"mediumvioletred", 199, 21, 133, FALSE, FALSE, FALSE, {0,0,0}},
140 {(const guchar*)"midnightblue", 25, 25, 112, FALSE, FALSE, FALSE, {0,0,0}},
141 {(const guchar*)"mintcream", 245, 255, 250, FALSE, FALSE, FALSE, {0,0,0}},
142 {(const guchar*)"mistyrose", 255, 228, 225, FALSE, FALSE, FALSE, {0,0,0}},
143 {(const guchar*)"moccasin", 255, 228, 181, FALSE, FALSE, FALSE, {0,0,0}},
144 {(const guchar*)"navajowhite", 255, 222, 173, FALSE, FALSE, FALSE, {0,0,0}},
145 {(const guchar*)"navy", 0, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
146 {(const guchar*)"oldlace", 253, 245, 230, FALSE, FALSE, FALSE, {0,0,0}},
147 {(const guchar*)"olive", 128, 128, 0, FALSE, FALSE, FALSE, {0,0,0}},
148 {(const guchar*)"olivedrab", 107, 142, 35, FALSE, FALSE, FALSE, {0,0,0}},
149 {(const guchar*)"orange", 255, 165, 0, FALSE, FALSE, FALSE, {0,0,0}},
150 {(const guchar*)"orangered", 255, 69, 0, FALSE, FALSE, FALSE, {0,0,0}},
151 {(const guchar*)"orchid", 218, 112, 214, FALSE, FALSE, FALSE, {0,0,0}},
152 {(const guchar*)"palegoldenrod", 238, 232, 170, FALSE, FALSE, FALSE, {0,0,0}},
153 {(const guchar*)"palegreen", 152, 251, 152, FALSE, FALSE, FALSE, {0,0,0}},
154 {(const guchar*)"paleturquoise", 175, 238, 238, FALSE, FALSE, FALSE, {0,0,0}},
155 {(const guchar*)"palevioletred", 219, 112, 147, FALSE, FALSE, FALSE, {0,0,0}},
156 {(const guchar*)"papayawhip", 255, 239, 213, FALSE, FALSE, FALSE, {0,0,0}},
157 {(const guchar*)"peachpuff", 255, 218, 185, FALSE, FALSE, FALSE, {0,0,0}},
158 {(const guchar*)"peru", 205, 133, 63, FALSE, FALSE, FALSE, {0,0,0}},
159 {(const guchar*)"pink", 255, 192, 203, FALSE, FALSE, FALSE, {0,0,0}},
160 {(const guchar*)"plum", 221, 160, 221, FALSE, FALSE, FALSE, {0,0,0}},
161 {(const guchar*)"powderblue", 176, 224, 230, FALSE, FALSE, FALSE, {0,0,0}},
162 {(const guchar*)"purple", 128, 0, 128, FALSE, FALSE, FALSE, {0,0,0}},
163 {(const guchar*)"red", 255, 0, 0, FALSE, FALSE, FALSE, {0,0,0}},
164 {(const guchar*)"rosybrown", 188, 143, 143, FALSE, FALSE, FALSE, {0,0,0}},
165 {(const guchar*)"royalblue", 65, 105, 225, FALSE, FALSE, FALSE, {0,0,0}},
166 {(const guchar*)"saddlebrown", 139, 69, 19, FALSE, FALSE, FALSE, {0,0,0}},
167 {(const guchar*)"salmon", 250, 128, 114, FALSE, FALSE, FALSE, {0,0,0}},
168 {(const guchar*)"sandybrown", 244, 164, 96, FALSE, FALSE, FALSE, {0,0,0}},
169 {(const guchar*)"seagreen", 46, 139, 87, FALSE, FALSE, FALSE, {0,0,0}},
170 {(const guchar*)"seashell", 255, 245, 238, FALSE, FALSE, FALSE, {0,0,0}},
171 {(const guchar*)"sienna", 160, 82, 45, FALSE, FALSE, FALSE, {0,0,0}},
172 {(const guchar*)"silver", 192, 192, 192, FALSE, FALSE, FALSE, {0,0,0}},
173 {(const guchar*)"skyblue", 135, 206, 235, FALSE, FALSE, FALSE, {0,0,0}},
174 {(const guchar*)"slateblue", 106, 90, 205, FALSE, FALSE, FALSE, {0,0,0}},
175 {(const guchar*)"slategray", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
176 {(const guchar*)"slategrey", 112, 128, 144, FALSE, FALSE, FALSE, {0,0,0}},
177 {(const guchar*)"snow", 255, 250, 250, FALSE, FALSE, FALSE, {0,0,0}},
178 {(const guchar*)"springgreen", 0, 255, 127, FALSE, FALSE, FALSE, {0,0,0}},
179 {(const guchar*)"steelblue", 70, 130, 180, FALSE, FALSE, FALSE, {0,0,0}},
180 {(const guchar*)"tan", 210, 180, 140, FALSE, FALSE, FALSE, {0,0,0}},
181 {(const guchar*)"teal", 0, 128, 128, FALSE, FALSE, FALSE, {0,0,0}},
182 {(const guchar*)"thistle", 216, 191, 216, FALSE, FALSE, FALSE, {0,0,0}},
183 {(const guchar*)"tomato", 255, 99, 71, FALSE, FALSE, FALSE, {0,0,0}},
184 {(const guchar*)"transparent", 255, 255, 255, FALSE, FALSE, TRUE, {0,0,0}},
185 {(const guchar*)"turquoise", 64, 224, 208, FALSE, FALSE, FALSE, {0,0,0}},
186 {(const guchar*)"violet", 238, 130, 238, FALSE, FALSE, FALSE, {0,0,0}},
187 {(const guchar*)"wheat", 245, 222, 179, FALSE, FALSE, FALSE, {0,0,0}},
188 {(const guchar*)"white", 255, 255, 255, FALSE, FALSE, FALSE, {0,0,0}},
189 {(const guchar*)"whitesmoke", 245, 245, 245, FALSE, FALSE, FALSE, {0,0,0}},
190 {(const guchar*)"yellow", 255, 255, 0, FALSE, FALSE, FALSE, {0,0,0}},
191 {(const guchar*)"yellowgreen", 154, 205, 50, FALSE, FALSE, FALSE, {0,0,0}}
192 };
193
194 /**
195 * cr_rgb_new:
196 *
197 *The default constructor of #CRRgb.
198 *
199 *Returns the newly built instance of #CRRgb
200 */
201 CRRgb *
cr_rgb_new(void)202 cr_rgb_new (void)
203 {
204 CRRgb *result = NULL;
205
206 result = g_try_malloc (sizeof (CRRgb));
207
208 if (result == NULL) {
209 cr_utils_trace_info ("No more memory");
210 return NULL;
211 }
212
213 memset (result, 0, sizeof (CRRgb));
214
215 return result;
216 }
217
218 /**
219 * cr_rgb_new_with_vals:
220 *@a_red: the red component of the color.
221 *@a_green: the green component of the color.
222 *@a_blue: the blue component of the color.
223 *@a_unit: the unit of the rgb values.
224 *(either percentage or integer values)
225 *
226 *A constructor of #CRRgb.
227 *
228 *Returns the newly built instance of #CRRgb.
229 */
230 CRRgb *
cr_rgb_new_with_vals(gulong a_red,gulong a_green,gulong a_blue,gboolean a_is_percentage)231 cr_rgb_new_with_vals (gulong a_red, gulong a_green,
232 gulong a_blue, gboolean a_is_percentage)
233 {
234 CRRgb *result = NULL;
235
236 result = cr_rgb_new ();
237
238 g_return_val_if_fail (result, NULL);
239
240 result->red = a_red;
241 result->green = a_green;
242 result->blue = a_blue;
243 result->is_percentage = a_is_percentage;
244
245 return result;
246 }
247
248 /**
249 * cr_rgb_to_string:
250 *@a_this: the instance of #CRRgb to serialize.
251 *
252 *Serializes the rgb into a zero terminated string.
253 *
254 *Returns the zero terminated string containing the serialized
255 *rgb. MUST BE FREED by the caller using g_free().
256 */
257 guchar *
cr_rgb_to_string(CRRgb const * a_this)258 cr_rgb_to_string (CRRgb const * a_this)
259 {
260 guchar *result = NULL;
261 GString *str_buf = NULL;
262
263 str_buf = g_string_new (NULL);
264 g_return_val_if_fail (str_buf, NULL);
265
266 if (a_this->is_percentage == 1) {
267 g_string_append_printf (str_buf, "%ld", a_this->red);
268
269 g_string_append (str_buf, "%, ");
270
271 g_string_append_printf (str_buf, "%ld", a_this->green);
272 g_string_append (str_buf, "%, ");
273
274 g_string_append_printf (str_buf, "%ld", a_this->blue);
275 g_string_append_c (str_buf, '%');
276 } else {
277 g_string_append_printf (str_buf, "%ld", a_this->red);
278 g_string_append (str_buf, ", ");
279
280 g_string_append_printf (str_buf, "%ld", a_this->green);
281 g_string_append (str_buf, ", ");
282
283 g_string_append_printf (str_buf, "%ld", a_this->blue);
284 }
285
286 if (str_buf) {
287 result = (guchar *) str_buf->str;
288 g_string_free (str_buf, FALSE);
289 }
290
291 return result;
292 }
293
294 /**
295 * cr_rgb_dump:
296 *@a_this: the "this pointer" of
297 *the current instance of #CRRgb.
298 *@a_fp: the destination file pointer.
299 *
300 *Dumps the current instance of #CRRgb
301 *to a file.
302 */
303 void
cr_rgb_dump(CRRgb const * a_this,FILE * a_fp)304 cr_rgb_dump (CRRgb const * a_this, FILE * a_fp)
305 {
306 guchar *str = NULL;
307
308 g_return_if_fail (a_this);
309
310 str = cr_rgb_to_string (a_this);
311
312 if (str) {
313 fprintf (a_fp, "%s", str);
314 g_free (str);
315 str = NULL;
316 }
317 }
318
319 /**
320 * cr_rgb_compute_from_percentage:
321 *@a_this: the current instance of #CRRgb
322 *
323 *If the rgb values are expressed in percentage,
324 *compute their real value.
325 *
326 *Returns CR_OK upon successful completion, an error code otherwise.
327 */
328 enum CRStatus
cr_rgb_compute_from_percentage(CRRgb * a_this)329 cr_rgb_compute_from_percentage (CRRgb * a_this)
330 {
331 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
332
333 if (a_this->is_percentage == FALSE)
334 return CR_OK;
335 a_this->red = a_this->red * 255 / 100;
336 a_this->green = a_this->green * 255 / 100;
337 a_this->blue = a_this->blue * 255 / 100;
338 a_this->is_percentage = FALSE;
339 return CR_OK;
340 }
341
342 /**
343 * cr_rgb_set:
344 *@a_this: the current instance of #CRRgb.
345 *@a_red: the red value.
346 *@a_green: the green value.
347 *@a_blue: the blue value.
348 *
349 *Sets rgb values to the RGB.
350 *
351 *Returns CR_OK upon successful completion, an error code
352 *otherwise.
353 */
354 enum CRStatus
cr_rgb_set(CRRgb * a_this,gulong a_red,gulong a_green,gulong a_blue,gboolean a_is_percentage)355 cr_rgb_set (CRRgb * a_this, gulong a_red,
356 gulong a_green, gulong a_blue, gboolean a_is_percentage)
357 {
358 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR);
359 if (a_is_percentage != FALSE) {
360 g_return_val_if_fail (a_red <= 100
361 && a_green <= 100
362 && a_blue <= 100, CR_BAD_PARAM_ERROR);
363 }
364
365 a_this->is_percentage = a_is_percentage;
366
367 a_this->red = a_red;
368 a_this->green = a_green;
369 a_this->blue = a_blue;
370 a_this->inherit = FALSE ;
371 a_this->is_transparent = FALSE ;
372 return CR_OK;
373 }
374
375 /**
376 * cr_rgb_set_to_inherit:
377 *@a_this: the current instance of #CRRgb
378 *
379 *sets the value of the rgb to inherit.
380 *Look at the css spec from chapter 6.1 to 6.2 to understand
381 *the meaning of "inherit".
382 *
383 * Returns CR_OK upon succesful completion, an error code otherwise.
384 */
385 enum CRStatus
cr_rgb_set_to_inherit(CRRgb * a_this,gboolean a_inherit)386 cr_rgb_set_to_inherit (CRRgb *a_this, gboolean a_inherit)
387 {
388 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
389
390 a_this->inherit = a_inherit ;
391
392 return CR_OK ;
393 }
394
395 /**
396 * cr_rgb_is_set_to_inherit:
397 *
398 * @a_this: the current instance of #CRRgb.
399 *
400 * Returns TRUE if the rgb is set to the value "inherit", FALSE otherwise.
401 */
402 gboolean
cr_rgb_is_set_to_inherit(CRRgb const * a_this)403 cr_rgb_is_set_to_inherit (CRRgb const *a_this)
404 {
405 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
406
407 return a_this->inherit ;
408 }
409
410 /**
411 * cr_rgb_is_set_to_transparent:
412 *@a_this: the current instance of
413 *#CRRgb
414 *
415 *Tests if the the rgb is set to the
416 *value "transparent" or not.
417 *
418 *Returns TRUE if the rgb has been set to
419 *transparent, FALSE otherwise.
420 */
421 gboolean
cr_rgb_is_set_to_transparent(CRRgb const * a_this)422 cr_rgb_is_set_to_transparent (CRRgb const *a_this)
423 {
424 g_return_val_if_fail (a_this, FALSE) ;
425 return a_this->is_transparent ;
426 }
427
428
429 /**
430 * cr_rgb_set_to_transparent:
431 *@a_this: the current instance of #CRRgb
432 *@a_is_transparent: set to transparent or not.
433 *
434 *Sets the rgb to the "transparent" value (or not)
435 *Returns CR_OK upon successfull completion, an error code otherwise.
436 */
437 enum CRStatus
cr_rgb_set_to_transparent(CRRgb * a_this,gboolean a_is_transparent)438 cr_rgb_set_to_transparent (CRRgb *a_this,
439 gboolean a_is_transparent)
440 {
441 g_return_val_if_fail (a_this, CR_BAD_PARAM_ERROR) ;
442 a_this->is_transparent = a_is_transparent ;
443 return CR_OK ;
444 }
445
446 /**
447 * cr_rgb_set_from_rgb:
448 *@a_this: the current instance of #CRRgb.
449 *@a_rgb: the rgb to "copy"
450 *
451 *Sets the rgb from an other one.
452 *
453 *Returns CR_OK upon successful completion, an error code otherwise.
454 */
455 enum CRStatus
cr_rgb_set_from_rgb(CRRgb * a_this,CRRgb const * a_rgb)456 cr_rgb_set_from_rgb (CRRgb * a_this, CRRgb const * a_rgb)
457 {
458 g_return_val_if_fail (a_this && a_rgb, CR_BAD_PARAM_ERROR);
459
460 cr_rgb_copy (a_this, a_rgb) ;
461
462 return CR_OK;
463 }
464
465 static int
cr_rgb_color_name_compare(const void * a,const void * b)466 cr_rgb_color_name_compare (const void *a,
467 const void *b)
468 {
469 const char *a_color_name = a;
470 const CRRgb *rgb = b;
471
472 return g_ascii_strcasecmp (a_color_name, (const char *) rgb->name);
473 }
474
475 /**
476 * cr_rgb_set_from_name:
477 * @a_this: the current instance of #CRRgb
478 * @a_color_name: the color name
479 *
480 * Returns CR_OK upon successful completion, an error code otherwise.
481 */
482 enum CRStatus
cr_rgb_set_from_name(CRRgb * a_this,const guchar * a_color_name)483 cr_rgb_set_from_name (CRRgb * a_this, const guchar * a_color_name)
484 {
485 enum CRStatus status = CR_OK;
486 CRRgb *result;
487
488 g_return_val_if_fail (a_this && a_color_name, CR_BAD_PARAM_ERROR);
489
490 result = bsearch (a_color_name,
491 gv_standard_colors,
492 G_N_ELEMENTS (gv_standard_colors),
493 sizeof (gv_standard_colors[0]),
494 cr_rgb_color_name_compare);
495 if (result != NULL)
496 cr_rgb_set_from_rgb (a_this, result);
497 else
498 status = CR_UNKNOWN_TYPE_ERROR;
499
500 return status;
501 }
502
503 /**
504 * cr_rgb_set_from_hex_str:
505 * @a_this: the current instance of #CRRgb
506 * @a_hex: the hexadecimal value to set.
507 *
508 * Returns CR_OK upon successful completion.
509 */
510 enum CRStatus
cr_rgb_set_from_hex_str(CRRgb * a_this,const guchar * a_hex)511 cr_rgb_set_from_hex_str (CRRgb * a_this, const guchar * a_hex)
512 {
513 enum CRStatus status = CR_OK;
514 gulong i = 0;
515 guchar colors[3] = { 0 };
516
517 g_return_val_if_fail (a_this && a_hex, CR_BAD_PARAM_ERROR);
518
519 if (strlen ((const char *) a_hex) == 3) {
520 for (i = 0; i < 3; i++) {
521 if (a_hex[i] >= '0' && a_hex[i] <= '9') {
522 colors[i] = a_hex[i] - '0';
523 colors[i] = (colors[i] << 4) | colors[i];
524 } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
525 colors[i] = 10 + a_hex[i] - 'a';
526 colors[i] = (colors[i] << 4) | colors[i];
527 } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
528 colors[i] = 10 + a_hex[i] - 'A';
529 colors[i] = (colors[i] << 4) | colors[i];
530 } else {
531 status = CR_UNKNOWN_TYPE_ERROR;
532 }
533 }
534 } else if (strlen ((const char *) a_hex) == 6) {
535 for (i = 0; i < 6; i++) {
536 if (a_hex[i] >= '0' && a_hex[i] <= '9') {
537 colors[i / 2] <<= 4;
538 colors[i / 2] |= a_hex[i] - '0';
539 status = CR_OK;
540 } else if (a_hex[i] >= 'a' && a_hex[i] <= 'z') {
541 colors[i / 2] <<= 4;
542 colors[i / 2] |= 10 + a_hex[i] - 'a';
543 status = CR_OK;
544 } else if (a_hex[i] >= 'A' && a_hex[i] <= 'Z') {
545 colors[i / 2] <<= 4;
546 colors[i / 2] |= 10 + a_hex[i] - 'A';
547 status = CR_OK;
548 } else {
549 status = CR_UNKNOWN_TYPE_ERROR;
550 }
551 }
552 } else {
553 status = CR_UNKNOWN_TYPE_ERROR;
554 }
555
556 if (status == CR_OK) {
557 status = cr_rgb_set (a_this, colors[0],
558 colors[1], colors[2], FALSE);
559 cr_rgb_set_to_transparent (a_this, FALSE) ;
560 }
561 return status;
562 }
563
564 /**
565 * cr_rgb_set_from_term:
566 *@a_this: the instance of #CRRgb to set
567 *@a_value: the terminal from which to set
568 *
569 *Set the rgb from a terminal symbol
570 *
571 * Returns CR_OK upon successful completion, an error code otherwise.
572 */
573 enum CRStatus
cr_rgb_set_from_term(CRRgb * a_this,const struct _CRTerm * a_value)574 cr_rgb_set_from_term (CRRgb *a_this, const struct _CRTerm *a_value)
575 {
576 enum CRStatus status = CR_OK ;
577 g_return_val_if_fail (a_this && a_value,
578 CR_BAD_PARAM_ERROR) ;
579
580 switch(a_value->type) {
581 case TERM_RGB:
582 if (a_value->content.rgb) {
583 cr_rgb_set_from_rgb
584 (a_this, a_value->content.rgb) ;
585 }
586 break ;
587 case TERM_IDENT:
588 if (a_value->content.str
589 && a_value->content.str->stryng
590 && a_value->content.str->stryng->str) {
591 if (!strncmp ("inherit",
592 a_value->content.str->stryng->str,
593 sizeof ("inherit")-1)) {
594 a_this->inherit = TRUE;
595 a_this->is_transparent = FALSE ;
596 } else {
597 status = cr_rgb_set_from_name
598 (a_this,
599 (const guchar *) a_value->content.str->stryng->str) ;
600 }
601 } else {
602 cr_utils_trace_info
603 ("a_value has NULL string value") ;
604 }
605 break ;
606 case TERM_HASH:
607 if (a_value->content.str
608 && a_value->content.str->stryng
609 && a_value->content.str->stryng->str) {
610 status = cr_rgb_set_from_hex_str
611 (a_this,
612 (const guchar *) a_value->content.str->stryng->str) ;
613 } else {
614 cr_utils_trace_info
615 ("a_value has NULL string value") ;
616 }
617 break ;
618 default:
619 status = CR_UNKNOWN_TYPE_ERROR ;
620 }
621 return status ;
622 }
623
624 enum CRStatus
cr_rgb_copy(CRRgb * a_dest,CRRgb const * a_src)625 cr_rgb_copy (CRRgb *a_dest, CRRgb const *a_src)
626 {
627 g_return_val_if_fail (a_dest && a_src,
628 CR_BAD_PARAM_ERROR) ;
629
630 memcpy (a_dest, a_src, sizeof (CRRgb)) ;
631 return CR_OK ;
632 }
633
634 /**
635 * cr_rgb_destroy:
636 *@a_this: the "this pointer" of the
637 *current instance of #CRRgb.
638 *
639 *Destructor of #CRRgb.
640 */
641 void
cr_rgb_destroy(CRRgb * a_this)642 cr_rgb_destroy (CRRgb * a_this)
643 {
644 g_return_if_fail (a_this);
645 g_free (a_this);
646 }
647
648 /**
649 * cr_rgb_parse_from_buf:
650 *@a_str: a string that contains a color description
651 *@a_enc: the encoding of a_str
652 *
653 *Parses a text buffer that contains a rgb color
654 *
655 *Returns the parsed color, or NULL in case of error
656 */
657 CRRgb *
cr_rgb_parse_from_buf(const guchar * a_str,enum CREncoding a_enc)658 cr_rgb_parse_from_buf (const guchar *a_str,
659 enum CREncoding a_enc)
660 {
661 enum CRStatus status = CR_OK ;
662 CRTerm *value = NULL ;
663 CRParser * parser = NULL;
664 CRRgb *result = NULL;
665
666 g_return_val_if_fail (a_str, NULL);
667
668 parser = cr_parser_new_from_buf ((guchar *) a_str, strlen ((const char *) a_str), a_enc, FALSE);
669
670 g_return_val_if_fail (parser, NULL);
671
672 status = cr_parser_try_to_skip_spaces_and_comments (parser) ;
673 if (status != CR_OK)
674 goto cleanup;
675
676 status = cr_parser_parse_term (parser, &value);
677 if (status != CR_OK)
678 goto cleanup;
679
680 result = cr_rgb_new ();
681 if (!result)
682 goto cleanup;
683
684 status = cr_rgb_set_from_term (result, value);
685
686 cleanup:
687 if (parser) {
688 cr_parser_destroy (parser);
689 parser = NULL;
690 }
691 if (value) {
692 cr_term_destroy(value);
693 value = NULL;
694 }
695 return result ;
696 }
697
698