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