]> Pileus Git - ~andy/gtk/blob - gtk/gtkcsscolorvalue.c
cssvalue: Remove useless call
[~andy/gtk] / gtk / gtkcsscolorvalue.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gtkcsscolorvalueprivate.h"
21
22 #include "gtkcssrgbavalueprivate.h"
23 #include "gtkcssstylepropertyprivate.h"
24 #include "gtkhslaprivate.h"
25 #include "gtkstylepropertyprivate.h"
26 #include "gtkstyleproperties.h"
27 #include "gtkwin32themeprivate.h"
28
29 typedef enum {
30   COLOR_TYPE_LITERAL,
31   COLOR_TYPE_NAME,
32   COLOR_TYPE_SHADE,
33   COLOR_TYPE_ALPHA,
34   COLOR_TYPE_MIX,
35   COLOR_TYPE_WIN32,
36   COLOR_TYPE_CURRENT_COLOR
37 } ColorType;
38
39 struct _GtkCssValue
40 {
41   GTK_CSS_VALUE_BASE
42   ColorType type;
43   GtkCssValue *last_value;
44
45   union
46   {
47     gchar *name;
48
49     struct
50     {
51       GtkCssValue *color;
52       gdouble factor;
53     } shade, alpha;
54
55     struct
56     {
57       GtkCssValue *color1;
58       GtkCssValue *color2;
59       gdouble factor;
60     } mix;
61
62     struct
63     {
64       gchar *theme_class;
65       gint id;
66     } win32;
67   } sym_col;
68 };
69
70 static void
71 gtk_css_value_color_free (GtkCssValue *color)
72 {
73   if (color->last_value)
74     _gtk_css_value_unref (color->last_value);
75
76   switch (color->type)
77     {
78     case COLOR_TYPE_NAME:
79       g_free (color->sym_col.name);
80       break;
81     case COLOR_TYPE_SHADE:
82       _gtk_css_value_unref (color->sym_col.shade.color);
83       break;
84     case COLOR_TYPE_ALPHA:
85       _gtk_css_value_unref (color->sym_col.alpha.color);
86       break;
87     case COLOR_TYPE_MIX:
88       _gtk_css_value_unref (color->sym_col.mix.color1);
89       _gtk_css_value_unref (color->sym_col.mix.color2);
90       break;
91     case COLOR_TYPE_WIN32:
92       g_free (color->sym_col.win32.theme_class);
93       break;
94     default:
95       break;
96     }
97
98   g_slice_free (GtkCssValue, color);
99 }
100
101 static GtkCssValue *
102 gtk_css_value_color_get_fallback (guint                    property_id,
103                                   GtkStyleProviderPrivate *provider,
104                                   GtkCssComputedValues    *values,
105                                   GtkCssComputedValues    *parent_values)
106 {
107   static const GdkRGBA transparent = { 0, 0, 0, 0 };
108
109   switch (property_id)
110     {
111       case GTK_CSS_PROPERTY_BACKGROUND_IMAGE:
112       case GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE:
113       case GTK_CSS_PROPERTY_TEXT_SHADOW:
114       case GTK_CSS_PROPERTY_ICON_SHADOW:
115       case GTK_CSS_PROPERTY_BOX_SHADOW:
116         return _gtk_css_rgba_value_new_from_rgba (&transparent);
117       case GTK_CSS_PROPERTY_COLOR:
118       case GTK_CSS_PROPERTY_BACKGROUND_COLOR:
119       case GTK_CSS_PROPERTY_BORDER_TOP_COLOR:
120       case GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR:
121       case GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR:
122       case GTK_CSS_PROPERTY_BORDER_LEFT_COLOR:
123       case GTK_CSS_PROPERTY_OUTLINE_COLOR:
124         return _gtk_css_value_compute (_gtk_css_style_property_get_initial_value (_gtk_css_style_property_lookup_by_id (property_id)),
125                                        property_id,
126                                        provider,
127                                        values,
128                                        parent_values,
129                                        NULL);
130       default:
131         if (property_id < GTK_CSS_PROPERTY_N_PROPERTIES)
132           g_warning ("No fallback color defined for property '%s'", 
133                      _gtk_style_property_get_name (GTK_STYLE_PROPERTY (_gtk_css_style_property_lookup_by_id (property_id))));
134         return _gtk_css_rgba_value_new_from_rgba (&transparent);
135     }
136 }
137
138 GtkCssValue *
139 _gtk_css_color_value_resolve (GtkCssValue             *color,
140                               GtkStyleProviderPrivate *provider,
141                               GtkCssValue             *current,
142                               GtkCssDependencies       current_deps,
143                               GtkCssDependencies      *dependencies)
144 {
145   GtkCssDependencies unused;
146   GtkCssValue *value;
147
148   g_return_val_if_fail (color != NULL, FALSE);
149   g_return_val_if_fail (provider == NULL || GTK_IS_STYLE_PROVIDER_PRIVATE (provider), FALSE);
150   g_return_val_if_fail (current != NULL, FALSE);
151
152   if (dependencies == NULL)
153     dependencies = &unused;
154   *dependencies = 0;
155
156   value = NULL;
157   switch (color->type)
158     {
159     case COLOR_TYPE_LITERAL:
160       return _gtk_css_value_ref (color->last_value);
161     case COLOR_TYPE_NAME:
162       {
163         GtkCssValue *named;
164
165         named = _gtk_style_provider_private_get_color (provider, color->sym_col.name);
166         if (named == NULL)
167           return NULL;
168
169         value = _gtk_css_color_value_resolve (named, provider, current, current_deps, dependencies);
170       }
171
172       break;
173     case COLOR_TYPE_SHADE:
174       {
175         GtkCssValue *val;
176         GtkHSLA hsla;
177         GdkRGBA shade;
178
179         val = _gtk_css_color_value_resolve (color->sym_col.shade.color, provider, current, current_deps, dependencies);
180         if (val == NULL)
181           return NULL;
182
183         *dependencies = _gtk_css_dependencies_union (*dependencies, 0);
184         
185         _gtk_hsla_init_from_rgba (&hsla, _gtk_css_rgba_value_get_rgba (val));
186         _gtk_hsla_shade (&hsla, &hsla, color->sym_col.shade.factor);
187
188         _gdk_rgba_init_from_hsla (&shade, &hsla);
189
190         _gtk_css_value_unref (val);
191
192         value = _gtk_css_rgba_value_new_from_rgba (&shade);
193       }
194
195       break;
196     case COLOR_TYPE_ALPHA:
197       {
198         GtkCssValue *val;
199         GdkRGBA alpha;
200
201         val = _gtk_css_color_value_resolve (color->sym_col.alpha.color, provider, current, current_deps, dependencies);
202         if (val == NULL)
203           return NULL;
204
205         *dependencies = _gtk_css_dependencies_union (*dependencies, 0);
206         alpha = *_gtk_css_rgba_value_get_rgba (val);
207         alpha.alpha = CLAMP (alpha.alpha * color->sym_col.alpha.factor, 0, 1);
208
209         _gtk_css_value_unref (val);
210
211         value = _gtk_css_rgba_value_new_from_rgba (&alpha);
212       }
213       break;
214
215     case COLOR_TYPE_MIX:
216       {
217         GtkCssValue *val;
218         GdkRGBA color1, color2, res;
219         GtkCssDependencies dep1, dep2;
220
221         val = _gtk_css_color_value_resolve (color->sym_col.mix.color1, provider, current, current_deps, &dep1);
222         if (val == NULL)
223           return NULL;
224         color1 = *_gtk_css_rgba_value_get_rgba (val);
225         _gtk_css_value_unref (val);
226
227         val = _gtk_css_color_value_resolve (color->sym_col.mix.color2, provider, current, current_deps, &dep2);
228         if (val == NULL)
229           return NULL;
230         color2 = *_gtk_css_rgba_value_get_rgba (val);
231         _gtk_css_value_unref (val);
232
233         *dependencies = _gtk_css_dependencies_union (dep1, dep2);
234         res.red = CLAMP (color1.red + ((color2.red - color1.red) * color->sym_col.mix.factor), 0, 1);
235         res.green = CLAMP (color1.green + ((color2.green - color1.green) * color->sym_col.mix.factor), 0, 1);
236         res.blue = CLAMP (color1.blue + ((color2.blue - color1.blue) * color->sym_col.mix.factor), 0, 1);
237         res.alpha = CLAMP (color1.alpha + ((color2.alpha - color1.alpha) * color->sym_col.mix.factor), 0, 1);
238
239         value =_gtk_css_rgba_value_new_from_rgba (&res);
240       }
241
242       break;
243     case COLOR_TYPE_WIN32:
244       {
245         GdkRGBA res;
246
247         if (!_gtk_win32_theme_color_resolve (color->sym_col.win32.theme_class,
248                                              color->sym_col.win32.id,
249                                              &res))
250           return NULL;
251
252         value = _gtk_css_rgba_value_new_from_rgba (&res);
253       }
254
255       break;
256     case COLOR_TYPE_CURRENT_COLOR:
257       if (current)
258         {
259           *dependencies = current_deps;
260           return _gtk_css_value_ref (current);
261         }
262       else
263         {
264           return NULL;
265         }
266       break;
267     default:
268       g_assert_not_reached ();
269     }
270
271   if (value != NULL)
272     {
273       if (color->last_value != NULL &&
274           _gtk_css_value_equal (color->last_value, value))
275         {
276           _gtk_css_value_unref (value);
277           value = _gtk_css_value_ref (color->last_value);
278         }
279       else
280         {
281           if (color->last_value != NULL)
282             _gtk_css_value_unref (color->last_value);
283           color->last_value = _gtk_css_value_ref (value);
284         }
285     }
286
287   return value;
288 }
289
290 static GtkCssValue *
291 gtk_css_value_color_compute (GtkCssValue             *value,
292                              guint                    property_id,
293                              GtkStyleProviderPrivate *provider,
294                              GtkCssComputedValues    *values,
295                              GtkCssComputedValues    *parent_values,
296                              GtkCssDependencies      *dependencies)
297 {
298   GtkCssValue *resolved, *current;
299   GtkCssDependencies current_deps;
300
301   /* The computed value of the â€˜currentColor’ keyword is the computed
302    * value of the â€˜color’ property. If the â€˜currentColor’ keyword is
303    * set on the â€˜color’ property itself, it is treated as â€˜color: inherit’. 
304    */
305   if (property_id == GTK_CSS_PROPERTY_COLOR)
306     {
307       if (parent_values)
308         {
309           current = _gtk_css_computed_values_get_value (parent_values, GTK_CSS_PROPERTY_COLOR);
310           current_deps = GTK_CSS_EQUALS_PARENT;
311         }
312       else
313         {
314           current = _gtk_css_style_property_get_initial_value (_gtk_css_style_property_lookup_by_id (GTK_CSS_PROPERTY_COLOR));
315           current_deps = 0;
316         }
317     }
318   else
319     {
320       current = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_COLOR);
321       current_deps = GTK_CSS_DEPENDS_ON_COLOR;
322     }
323   
324   resolved = _gtk_css_color_value_resolve (value,
325                                            provider,
326                                            current,
327                                            current_deps,
328                                            dependencies);
329
330   if (resolved == NULL)
331     return gtk_css_value_color_get_fallback (property_id, provider, values, parent_values);
332
333   return resolved;
334 }
335
336 static gboolean
337 gtk_css_value_color_equal (const GtkCssValue *value1,
338                            const GtkCssValue *value2)
339 {
340   if (value1->type != value2->type)
341     return FALSE;
342
343   switch (value1->type)
344     {
345     case COLOR_TYPE_LITERAL:
346       return _gtk_css_value_equal (value1->last_value, value2->last_value);
347     case COLOR_TYPE_NAME:
348       return g_str_equal (value1->sym_col.name, value2->sym_col.name);
349     case COLOR_TYPE_SHADE:
350       return value1->sym_col.shade.factor == value2->sym_col.shade.factor &&
351              _gtk_css_value_equal (value1->sym_col.shade.color,
352                                    value2->sym_col.shade.color);
353     case COLOR_TYPE_ALPHA:
354       return value1->sym_col.alpha.factor == value2->sym_col.alpha.factor &&
355              _gtk_css_value_equal (value1->sym_col.alpha.color,
356                                    value2->sym_col.alpha.color);
357     case COLOR_TYPE_MIX:
358       return value1->sym_col.mix.factor == value2->sym_col.mix.factor &&
359              _gtk_css_value_equal (value1->sym_col.mix.color1,
360                                    value2->sym_col.mix.color1) &&
361              _gtk_css_value_equal (value1->sym_col.mix.color2,
362                                    value2->sym_col.mix.color2);
363     case COLOR_TYPE_WIN32:
364       return g_str_equal (value1->sym_col.win32.theme_class, value2->sym_col.win32.theme_class) &&
365              value1->sym_col.win32.id == value2->sym_col.win32.id;
366     case COLOR_TYPE_CURRENT_COLOR:
367       return TRUE;
368     default:
369       g_assert_not_reached ();
370       return FALSE;
371     }
372 }
373
374 static GtkCssValue *
375 gtk_css_value_color_transition (GtkCssValue *start,
376                                 GtkCssValue *end,
377                                 guint        property_id,
378                                 double       progress)
379 {
380   return _gtk_css_color_value_new_mix (start, end, progress);
381 }
382
383 static void
384 gtk_css_value_color_print (const GtkCssValue *value,
385                            GString           *string)
386 {
387   switch (value->type)
388     {
389     case COLOR_TYPE_LITERAL:
390       _gtk_css_value_print (value->last_value, string);
391       break;
392     case COLOR_TYPE_NAME:
393       g_string_append (string, "@");
394       g_string_append (string, value->sym_col.name);
395       break;
396     case COLOR_TYPE_SHADE:
397       {
398         char factor[G_ASCII_DTOSTR_BUF_SIZE];
399
400         g_string_append (string, "shade(");
401         _gtk_css_value_print (value->sym_col.shade.color, string);
402         g_string_append (string, ", ");
403         g_ascii_dtostr (factor, sizeof (factor), value->sym_col.shade.factor);
404         g_string_append (string, factor);
405         g_string_append (string, ")");
406       }
407       break;
408     case COLOR_TYPE_ALPHA:
409       {
410         char factor[G_ASCII_DTOSTR_BUF_SIZE];
411
412         g_string_append (string, "alpha(");
413         _gtk_css_value_print (value->sym_col.alpha.color, string);
414         g_string_append (string, ", ");
415         g_ascii_dtostr (factor, sizeof (factor), value->sym_col.alpha.factor);
416         g_string_append (string, factor);
417         g_string_append (string, ")");
418       }
419       break;
420     case COLOR_TYPE_MIX:
421       {
422         char factor[G_ASCII_DTOSTR_BUF_SIZE];
423
424         g_string_append (string, "mix(");
425         _gtk_css_value_print (value->sym_col.mix.color1, string);
426         g_string_append (string, ", ");
427         _gtk_css_value_print (value->sym_col.mix.color2, string);
428         g_string_append (string, ", ");
429         g_ascii_dtostr (factor, sizeof (factor), value->sym_col.mix.factor);
430         g_string_append (string, factor);
431         g_string_append (string, ")");
432       }
433       break;
434     case COLOR_TYPE_WIN32:
435       {
436         g_string_append_printf (string, GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME"(%s, %d)", 
437                                 value->sym_col.win32.theme_class, value->sym_col.win32.id);
438       }
439       break;
440     case COLOR_TYPE_CURRENT_COLOR:
441       g_string_append (string, "currentColor");
442       break;
443     default:
444       g_assert_not_reached ();
445     }
446 }
447
448 static const GtkCssValueClass GTK_CSS_VALUE_COLOR = {
449   gtk_css_value_color_free,
450   gtk_css_value_color_compute,
451   gtk_css_value_color_equal,
452   gtk_css_value_color_transition,
453   gtk_css_value_color_print
454 };
455
456 GtkCssValue *
457 _gtk_css_color_value_new_literal (const GdkRGBA *color)
458 {
459   GtkCssValue *value;
460
461   g_return_val_if_fail (color != NULL, NULL);
462
463   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
464   value->type = COLOR_TYPE_LITERAL;
465   value->last_value = _gtk_css_rgba_value_new_from_rgba (color);
466
467   return value;
468 }
469
470 GtkCssValue *
471 _gtk_css_color_value_new_rgba (double red,
472                                double green,
473                                double blue,
474                                double alpha)
475 {
476   GdkRGBA rgba = { red, green, blue, alpha };
477
478   return _gtk_css_color_value_new_literal (&rgba);
479 }
480
481 GtkCssValue *
482 _gtk_css_color_value_new_name (const gchar *name)
483 {
484   GtkCssValue *value;
485
486   g_return_val_if_fail (name != NULL, NULL);
487
488   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
489   value->type = COLOR_TYPE_NAME;
490   value->sym_col.name = g_strdup (name);
491
492   return value;
493 }
494
495 GtkCssValue *
496 _gtk_css_color_value_new_shade (GtkCssValue *color,
497                                 gdouble      factor)
498 {
499   GtkCssValue *value;
500
501   g_return_val_if_fail (color->class == &GTK_CSS_VALUE_COLOR, NULL);
502
503   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
504   value->type = COLOR_TYPE_SHADE;
505   value->sym_col.shade.color = _gtk_css_value_ref (color);
506   value->sym_col.shade.factor = factor;
507
508   return value;
509 }
510
511 GtkCssValue *
512 _gtk_css_color_value_new_alpha (GtkCssValue *color,
513                                 gdouble      factor)
514 {
515   GtkCssValue *value;
516
517   g_return_val_if_fail (color->class == &GTK_CSS_VALUE_COLOR, NULL);
518
519   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
520   value->type = COLOR_TYPE_ALPHA;
521   value->sym_col.alpha.color = _gtk_css_value_ref (color);
522   value->sym_col.alpha.factor = factor;
523
524   return value;
525 }
526
527 GtkCssValue *
528 _gtk_css_color_value_new_mix (GtkCssValue *color1,
529                               GtkCssValue *color2,
530                               gdouble      factor)
531 {
532   GtkCssValue *value;
533
534   g_return_val_if_fail (color1->class == &GTK_CSS_VALUE_COLOR, NULL);
535   g_return_val_if_fail (color2->class == &GTK_CSS_VALUE_COLOR, NULL);
536
537   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
538   value->type = COLOR_TYPE_MIX;
539   value->sym_col.mix.color1 = _gtk_css_value_ref (color1);
540   value->sym_col.mix.color2 = _gtk_css_value_ref (color2);
541   value->sym_col.mix.factor = factor;
542
543   return value;
544 }
545
546 GtkCssValue *
547 _gtk_css_color_value_new_win32 (const gchar *theme_class,
548                                 gint         id)
549 {
550   GtkCssValue *value;
551
552   g_return_val_if_fail (theme_class != NULL, NULL);
553
554   value = _gtk_css_value_new (GtkCssValue, &GTK_CSS_VALUE_COLOR);
555   value->type = COLOR_TYPE_WIN32;
556   value->sym_col.win32.theme_class = g_strdup (theme_class);
557   value->sym_col.win32.id = id;
558
559   return value;
560 }
561
562 GtkCssValue *
563 _gtk_css_color_value_new_current_color (void)
564 {
565   static GtkCssValue current_color = { &GTK_CSS_VALUE_COLOR, 1, COLOR_TYPE_CURRENT_COLOR, NULL, };
566
567   return _gtk_css_value_ref (&current_color);
568 }
569
570 typedef enum {
571   COLOR_RGBA,
572   COLOR_RGB,
573   COLOR_LIGHTER,
574   COLOR_DARKER,
575   COLOR_SHADE,
576   COLOR_ALPHA,
577   COLOR_MIX,
578   COLOR_WIN32
579 } ColorParseType;
580
581 static GtkCssValue *
582 gtk_css_color_parse_win32 (GtkCssParser *parser)
583 {
584   GtkCssValue *color;
585   char *class;
586   int id;
587
588   class = _gtk_css_parser_try_name (parser, TRUE);
589   if (class == NULL)
590     {
591       _gtk_css_parser_error (parser,
592                              "Expected name as first argument to  '-gtk-win32-color'");
593       return NULL;
594     }
595
596   if (! _gtk_css_parser_try (parser, ",", TRUE))
597     {
598       g_free (class);
599       _gtk_css_parser_error (parser,
600                              "Expected ','");
601       return NULL;
602     }
603
604   if (!_gtk_css_parser_try_int (parser, &id))
605     {
606       g_free (class);
607       _gtk_css_parser_error (parser, "Expected a valid integer value");
608       return NULL;
609     }
610
611   color = _gtk_css_color_value_new_win32 (class, id);
612   g_free (class);
613   return color;
614 }
615
616 static GtkCssValue *
617 _gtk_css_color_value_parse_function (GtkCssParser   *parser,
618                                      ColorParseType  color)
619 {
620   GtkCssValue *value;
621   GtkCssValue *child1, *child2;
622   double d;
623
624   if (!_gtk_css_parser_try (parser, "(", TRUE))
625     {
626       _gtk_css_parser_error (parser, "Missing opening bracket in color definition");
627       return NULL;
628     }
629
630   if (color == COLOR_RGB || color == COLOR_RGBA)
631     {
632       GdkRGBA rgba;
633       double tmp;
634       guint i;
635
636       for (i = 0; i < 3; i++)
637         {
638           if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
639             {
640               _gtk_css_parser_error (parser, "Expected ',' in color definition");
641               return NULL;
642             }
643
644           if (!_gtk_css_parser_try_double (parser, &tmp))
645             {
646               _gtk_css_parser_error (parser, "Invalid number for color value");
647               return NULL;
648             }
649           if (_gtk_css_parser_try (parser, "%", TRUE))
650             tmp /= 100.0;
651           else
652             tmp /= 255.0;
653           if (i == 0)
654             rgba.red = tmp;
655           else if (i == 1)
656             rgba.green = tmp;
657           else if (i == 2)
658             rgba.blue = tmp;
659           else
660             g_assert_not_reached ();
661         }
662
663       if (color == COLOR_RGBA)
664         {
665           if (i > 0 && !_gtk_css_parser_try (parser, ",", TRUE))
666             {
667               _gtk_css_parser_error (parser, "Expected ',' in color definition");
668               return NULL;
669             }
670
671           if (!_gtk_css_parser_try_double (parser, &rgba.alpha))
672             {
673               _gtk_css_parser_error (parser, "Invalid number for alpha value");
674               return NULL;
675             }
676         }
677       else
678         rgba.alpha = 1.0;
679       
680       value = _gtk_css_color_value_new_literal (&rgba);
681     }
682   else if (color == COLOR_WIN32)
683     {
684       value = gtk_css_color_parse_win32 (parser);
685       if (value == NULL)
686         return NULL;
687     }
688   else
689     {
690       child1 = _gtk_css_color_value_parse (parser);
691       if (child1 == NULL)
692         return NULL;
693
694       if (color == COLOR_MIX)
695         {
696           if (!_gtk_css_parser_try (parser, ",", TRUE))
697             {
698               _gtk_css_parser_error (parser, "Expected ',' in color definition");
699               _gtk_css_value_unref (child1);
700               return NULL;
701             }
702
703           child2 = _gtk_css_color_value_parse (parser);
704           if (child2 == NULL)
705             {
706               _gtk_css_value_unref (child1);
707               return NULL;
708             }
709         }
710       else
711         child2 = NULL;
712
713       if (color == COLOR_LIGHTER)
714         d = 1.3;
715       else if (color == COLOR_DARKER)
716         d = 0.7;
717       else
718         {
719           if (!_gtk_css_parser_try (parser, ",", TRUE))
720             {
721               _gtk_css_parser_error (parser, "Expected ',' in color definition");
722               _gtk_css_value_unref (child1);
723               if (child2)
724                 _gtk_css_value_unref (child2);
725               return NULL;
726             }
727
728           if (!_gtk_css_parser_try_double (parser, &d))
729             {
730               _gtk_css_parser_error (parser, "Expected number in color definition");
731               _gtk_css_value_unref (child1);
732               if (child2)
733                 _gtk_css_value_unref (child2);
734               return NULL;
735             }
736         }
737       
738       switch (color)
739         {
740         case COLOR_LIGHTER:
741         case COLOR_DARKER:
742         case COLOR_SHADE:
743           value = _gtk_css_color_value_new_shade (child1, d);
744           break;
745         case COLOR_ALPHA:
746           value = _gtk_css_color_value_new_alpha (child1, d);
747           break;
748         case COLOR_MIX:
749           value = _gtk_css_color_value_new_mix (child1, child2, d);
750           break;
751         default:
752           g_assert_not_reached ();
753           value = NULL;
754         }
755
756       _gtk_css_value_unref (child1);
757       if (child2)
758         _gtk_css_value_unref (child2);
759     }
760
761   if (!_gtk_css_parser_try (parser, ")", TRUE))
762     {
763       _gtk_css_parser_error (parser, "Expected ')' in color definition");
764       _gtk_css_value_unref (value);
765       return NULL;
766     }
767
768   return value;
769 }
770
771 GtkCssValue *
772 _gtk_css_color_value_parse (GtkCssParser *parser)
773 {
774   GtkCssValue *value;
775   GdkRGBA rgba;
776   guint color;
777   const char *names[] = {"rgba", "rgb",  "lighter", "darker", "shade", "alpha", "mix",
778                          GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME};
779   char *name;
780
781   if (_gtk_css_parser_try (parser, "currentColor", TRUE))
782     return _gtk_css_color_value_new_current_color ();
783
784   if (_gtk_css_parser_try (parser, "transparent", TRUE))
785     {
786       GdkRGBA transparent = { 0, 0, 0, 0 };
787       
788       return _gtk_css_color_value_new_literal (&transparent);
789     }
790
791   if (_gtk_css_parser_try (parser, "@", FALSE))
792     {
793       name = _gtk_css_parser_try_name (parser, TRUE);
794
795       if (name)
796         {
797           value = _gtk_css_color_value_new_name (name);
798         }
799       else
800         {
801           _gtk_css_parser_error (parser, "'%s' is not a valid color color name", name);
802           value = NULL;
803         }
804
805       g_free (name);
806       return value;
807     }
808
809   for (color = 0; color < G_N_ELEMENTS (names); color++)
810     {
811       if (_gtk_css_parser_try (parser, names[color], TRUE))
812         break;
813     }
814
815   if (color < G_N_ELEMENTS (names))
816     return _gtk_css_color_value_parse_function (parser, color);
817
818   if (_gtk_css_parser_try_hash_color (parser, &rgba))
819     return _gtk_css_color_value_new_literal (&rgba);
820
821   name = _gtk_css_parser_try_name (parser, TRUE);
822   if (name)
823     {
824       if (gdk_rgba_parse (&rgba, name))
825         {
826           value = _gtk_css_color_value_new_literal (&rgba);
827         }
828       else
829         {
830           _gtk_css_parser_error (parser, "'%s' is not a valid color name", name);
831           value = NULL;
832         }
833       g_free (name);
834       return value;
835     }
836
837   _gtk_css_parser_error (parser, "Not a color definition");
838   return NULL;
839 }
840