• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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