]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssstylepropertyimpl.c
styleproperty: Remove default parse function
[~andy/gtk] / gtk / gtkcssstylepropertyimpl.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 "gtkstylepropertyprivate.h"
21
22 #include <gobject/gvaluecollector.h>
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <cairo-gobject.h>
25 #include <math.h>
26
27 #include "gtkcssparserprivate.h"
28 #include "gtkcssstylefuncsprivate.h"
29 #include "gtkcssstylepropertyprivate.h"
30 #include "gtkcsstypesprivate.h"
31 #include "gtkintl.h"
32 #include "gtkprivatetypebuiltins.h"
33 #include "gtkstylepropertiesprivate.h"
34
35 /* this is in case round() is not provided by the compiler, 
36  * such as in the case of C89 compilers, like MSVC
37  */
38 #include "fallback-c89.c"
39
40 /* the actual parsers we have */
41 #include "gtkanimationdescription.h"
42 #include "gtkbindings.h"
43 #include "gtkcssimageprivate.h"
44 #include "gtkgradient.h"
45 #include "gtkshadowprivate.h"
46 #include "gtksymboliccolorprivate.h"
47 #include "gtkthemingengine.h"
48 #include "gtktypebuiltins.h"
49 #include "gtkwin32themeprivate.h"
50
51 /*** REGISTRATION ***/
52
53 static void
54 gtk_css_style_property_register (const char *                   name,
55                                  GType                          specified_type,
56                                  GType                          computed_type,
57                                  GType                          value_type,
58                                  GtkStylePropertyFlags          flags,
59                                  GtkCssStylePropertyParseFunc   parse_value,
60                                  GtkCssStylePropertyPrintFunc   print_value,
61                                  GtkCssStylePropertyComputeFunc compute_value,
62                                  GtkCssStylePropertyEqualFunc   equal_func,
63                                  GtkCssValue *                  initial_value)
64 {
65   GtkCssStyleProperty *node;
66
67   g_assert (initial_value != NULL);
68   g_assert (parse_value != NULL);
69
70   node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
71                        "value-type", value_type,
72                        "computed-type", computed_type,
73                        "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
74                        "initial-value", initial_value,
75                        "name", name,
76                        NULL);
77   
78   node->parse_value = parse_value;
79   if (print_value)
80     node->print_value = print_value;
81   if (compute_value)
82     node->compute_value = compute_value;
83   if (equal_func)
84     node->equal_func = equal_func;
85
86   _gtk_css_value_unref (initial_value);
87 }
88
89 /*** HELPERS ***/
90
91 static void
92 string_append_string (GString    *str,
93                       const char *string)
94 {
95   gsize len;
96
97   g_string_append_c (str, '"');
98
99   do {
100     len = strcspn (string, "\"\n\r\f");
101     g_string_append (str, string);
102     string += len;
103     switch (*string)
104       {
105       case '\0':
106         break;
107       case '\n':
108         g_string_append (str, "\\A ");
109         break;
110       case '\r':
111         g_string_append (str, "\\D ");
112         break;
113       case '\f':
114         g_string_append (str, "\\C ");
115         break;
116       case '\"':
117         g_string_append (str, "\\\"");
118         break;
119       default:
120         g_assert_not_reached ();
121         break;
122       }
123   } while (*string);
124
125   g_string_append_c (str, '"');
126 }
127
128 /*** IMPLEMENTATIONS ***/
129
130 static GtkCssValue *
131 color_parse (GtkCssStyleProperty *property,
132              GtkCssParser        *parser,
133              GFile               *base)
134 {
135   GtkSymbolicColor *symbolic;
136
137   if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
138     {
139       symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
140     }
141   else
142     {
143       symbolic = _gtk_css_parser_read_symbolic_color (parser);
144       if (symbolic == NULL)
145         return NULL;
146     }
147
148   return _gtk_css_value_new_take_symbolic_color (symbolic);
149 }
150
151 static GtkCssValue *
152 color_compute (GtkCssStyleProperty    *property,
153                GtkStyleContext        *context,
154                GtkCssValue            *specified)
155 {
156   GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
157   GtkCssValue *resolved;
158
159   if (symbolic == _gtk_symbolic_color_get_current_color ())
160     {
161       /* The computed value of the ‘currentColor’ keyword is the computed
162        * value of the ‘color’ property. If the ‘currentColor’ keyword is
163        * set on the ‘color’ property itself, it is treated as ‘color: inherit’. 
164        */
165       if (g_str_equal (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (property)), "color"))
166         {
167           GtkStyleContext *parent = gtk_style_context_get_parent (context);
168
169           if (parent)
170             return _gtk_css_value_ref (_gtk_style_context_peek_property (parent, "color"));
171           else
172             return _gtk_css_style_compute_value (context,
173                                                  GDK_TYPE_RGBA,
174                                                  _gtk_css_style_property_get_initial_value (property));
175         }
176       else
177         {
178           return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color"));
179         }
180     }
181   else if ((resolved = _gtk_style_context_resolve_color_value (context,
182                                                                symbolic)) != NULL)
183     {
184       return resolved;
185     }
186   else
187     {
188       return color_compute (property,
189                             context,
190                             _gtk_css_style_property_get_initial_value (property));
191     }
192 }
193
194 static GtkCssValue *
195 font_family_parse (GtkCssStyleProperty *property,
196                    GtkCssParser        *parser,
197                    GFile               *base)
198 {
199   GPtrArray *names;
200   char *name;
201
202   /* We don't special case generic families. Pango should do
203    * that for us */
204
205   names = g_ptr_array_new ();
206
207   do {
208     name = _gtk_css_parser_try_ident (parser, TRUE);
209     if (name)
210       {
211         GString *string = g_string_new (name);
212         g_free (name);
213         while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
214           {
215             g_string_append_c (string, ' ');
216             g_string_append (string, name);
217             g_free (name);
218           }
219         name = g_string_free (string, FALSE);
220       }
221     else 
222       {
223         name = _gtk_css_parser_read_string (parser);
224         if (name == NULL)
225           {
226             g_ptr_array_free (names, TRUE);
227             return FALSE;
228           }
229       }
230
231     g_ptr_array_add (names, name);
232   } while (_gtk_css_parser_try (parser, ",", TRUE));
233
234   /* NULL-terminate array */
235   g_ptr_array_add (names, NULL);
236   return _gtk_css_value_new_take_strv ((char **) g_ptr_array_free (names, FALSE));
237 }
238
239 static void
240 font_family_value_print (GtkCssStyleProperty *property,
241                          const GtkCssValue   *value,
242                          GString             *string)
243 {
244   const char **names = _gtk_css_value_get_strv (value);
245
246   if (names == NULL || *names == NULL)
247     {
248       g_string_append (string, "none");
249       return;
250     }
251
252   string_append_string (string, *names);
253   names++;
254   while (*names)
255     {
256       g_string_append (string, ", ");
257       string_append_string (string, *names);
258       names++;
259     }
260 }
261
262 static GtkCssValue *
263 parse_pango_style (GtkCssStyleProperty *property,
264                    GtkCssParser        *parser,
265                    GFile               *base)
266 {
267   int value;
268
269   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_STYLE, &value))
270     {
271       _gtk_css_parser_error (parser, "unknown value for property");
272       return NULL;
273     }
274
275   return _gtk_css_value_new_from_enum (PANGO_TYPE_STYLE, value);
276 }
277
278 static GtkCssValue *
279 parse_pango_weight (GtkCssStyleProperty *property,
280                     GtkCssParser        *parser,
281                     GFile               *base)
282 {
283   int value;
284
285   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_WEIGHT, &value))
286     {
287       _gtk_css_parser_error (parser, "unknown value for property");
288       return NULL;
289     }
290
291   return _gtk_css_value_new_from_enum (PANGO_TYPE_WEIGHT, value);
292 }
293
294 static GtkCssValue *
295 parse_pango_variant (GtkCssStyleProperty *property,
296                      GtkCssParser        *parser,
297                      GFile               *base)
298 {
299   int value;
300
301   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_VARIANT, &value))
302     {
303       _gtk_css_parser_error (parser, "unknown value for property");
304       return NULL;
305     }
306
307   return _gtk_css_value_new_from_enum (PANGO_TYPE_VARIANT, value);
308 }
309
310 static GtkCssValue *
311 parse_border_style (GtkCssStyleProperty *property,
312                     GtkCssParser        *parser,
313                     GFile               *base)
314 {
315   int value;
316
317   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &value))
318     {
319       _gtk_css_parser_error (parser, "unknown value for property");
320       return NULL;
321     }
322
323   return _gtk_css_value_new_from_enum (GTK_TYPE_BORDER_STYLE, value);
324 }
325
326 static GtkCssValue *
327 parse_css_area (GtkCssStyleProperty *property,
328                 GtkCssParser        *parser,
329                 GFile               *base)
330 {
331   int value;
332
333   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_AREA, &value))
334     {
335       _gtk_css_parser_error (parser, "unknown value for property");
336       return NULL;
337     }
338
339   return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, value);
340 }
341
342 static GtkCssValue *
343 bindings_value_parse (GtkCssStyleProperty *property,
344                       GtkCssParser        *parser,
345                       GFile               *base)
346 {
347   GPtrArray *array;
348   GtkBindingSet *binding_set;
349   char *name;
350
351   array = g_ptr_array_new ();
352
353   do {
354       name = _gtk_css_parser_try_ident (parser, TRUE);
355       if (name == NULL)
356         {
357           _gtk_css_parser_error (parser, "Not a valid binding name");
358           g_ptr_array_free (array, TRUE);
359           return FALSE;
360         }
361
362       binding_set = gtk_binding_set_find (name);
363
364       if (!binding_set)
365         {
366           _gtk_css_parser_error (parser, "No binding set named '%s'", name);
367           g_free (name);
368           continue;
369         }
370
371       g_ptr_array_add (array, binding_set);
372       g_free (name);
373     }
374   while (_gtk_css_parser_try (parser, ",", TRUE));
375
376   return _gtk_css_value_new_take_binding_sets (array);
377 }
378
379 static void
380 bindings_value_print (GtkCssStyleProperty *property,
381                       const GtkCssValue   *value,
382                       GString             *string)
383 {
384   GPtrArray *array;
385   guint i;
386
387   array = _gtk_css_value_get_boxed (value);
388
389   for (i = 0; i < array->len; i++)
390     {
391       GtkBindingSet *binding_set = g_ptr_array_index (array, i);
392
393       if (i > 0)
394         g_string_append (string, ", ");
395       g_string_append (string, binding_set->set_name);
396     }
397 }
398
399 static GtkCssValue *
400 shadow_value_parse (GtkCssStyleProperty *property,
401                     GtkCssParser        *parser,
402                     GFile               *base)
403 {
404   gboolean have_inset, have_color, have_lengths;
405   gdouble hoffset, voffset, blur, spread;
406   GtkSymbolicColor *color;
407   GtkShadow *shadow;
408   guint i;
409
410   if (_gtk_css_parser_try (parser, "none", TRUE))
411     return _gtk_css_value_new_take_shadow (NULL);
412
413   shadow = _gtk_shadow_new ();
414
415   do
416     {
417       have_inset = have_lengths = have_color = FALSE;
418
419       for (i = 0; i < 3; i++)
420         {
421           if (!have_inset && 
422               _gtk_css_parser_try (parser, "inset", TRUE))
423             {
424               have_inset = TRUE;
425               continue;
426             }
427             
428           if (!have_lengths &&
429               _gtk_css_parser_try_double (parser, &hoffset))
430             {
431               have_lengths = TRUE;
432
433               if (!_gtk_css_parser_try_double (parser, &voffset))
434                 {
435                   _gtk_css_parser_error (parser, "Horizontal and vertical offsets are required");
436                   _gtk_shadow_unref (shadow);
437                   return NULL;
438                 }
439
440               if (!_gtk_css_parser_try_double (parser, &blur))
441                 blur = 0;
442
443               if (!_gtk_css_parser_try_double (parser, &spread))
444                 spread = 0;
445
446               continue;
447             }
448
449           if (!have_color)
450             {
451               have_color = TRUE;
452
453               /* XXX: the color is optional and UA-defined if it's missing,
454                * but it doesn't really make sense for us...
455                */
456               color = _gtk_css_parser_read_symbolic_color (parser);
457
458               if (color == NULL)
459                 {
460                   _gtk_shadow_unref (shadow);
461                   return NULL;
462                 }
463             }
464         }
465
466       if (!have_color || !have_lengths)
467         {
468           _gtk_css_parser_error (parser, "Must specify at least color and offsets");
469           _gtk_shadow_unref (shadow);
470           return NULL;
471         }
472
473       _gtk_shadow_append (shadow,
474                           hoffset, voffset,
475                           blur, spread,
476                           have_inset, color);
477
478       gtk_symbolic_color_unref (color);
479
480     }
481   while (_gtk_css_parser_try (parser, ",", TRUE));
482
483   return _gtk_css_value_new_take_shadow (shadow);
484 }
485
486 static void
487 shadow_value_print (GtkCssStyleProperty *property,
488                     const GtkCssValue   *value,
489                     GString             *string)
490 {
491   GtkShadow *shadow;
492
493   shadow = _gtk_css_value_get_shadow (value);
494
495   if (shadow == NULL)
496     g_string_append (string, "none");
497   else
498     _gtk_shadow_print (shadow, string);
499 }
500
501 static GtkCssValue *
502 shadow_value_compute (GtkCssStyleProperty *property,
503                       GtkStyleContext     *context,
504                       GtkCssValue         *specified)
505 {
506   GtkShadow *shadow;
507   
508   shadow = _gtk_css_value_get_shadow (specified);
509   if (shadow)
510     shadow = _gtk_shadow_resolve (shadow, context);
511
512   return _gtk_css_value_new_take_shadow (shadow);
513 }
514
515 static GtkCssValue *
516 border_corner_radius_value_parse (GtkCssStyleProperty *property,
517                                   GtkCssParser        *parser,
518                                   GFile               *base)
519 {
520   GtkCssBorderCornerRadius corner;
521
522   if (!_gtk_css_parser_read_number (parser,
523                                     &corner.horizontal,
524                                     GTK_CSS_POSITIVE_ONLY
525                                     | GTK_CSS_PARSE_PERCENT
526                                     | GTK_CSS_NUMBER_AS_PIXELS
527                                     | GTK_CSS_PARSE_LENGTH))
528     return FALSE;
529
530   if (!_gtk_css_parser_has_number (parser))
531     corner.vertical = corner.horizontal;
532   else if (!_gtk_css_parser_read_number (parser,
533                                          &corner.vertical,
534                                          GTK_CSS_POSITIVE_ONLY
535                                          | GTK_CSS_PARSE_PERCENT
536                                          | GTK_CSS_NUMBER_AS_PIXELS
537                                          | GTK_CSS_PARSE_LENGTH))
538     return FALSE;
539
540   return _gtk_css_value_new_from_border_corner_radius (&corner);
541 }
542
543 static void
544 border_corner_radius_value_print (GtkCssStyleProperty *property,
545                                   const GtkCssValue   *value,
546                                   GString             *string)
547 {
548   const GtkCssBorderCornerRadius *corner;
549
550   corner = _gtk_css_value_get_border_corner_radius (value);
551
552   _gtk_css_number_print (&corner->horizontal, string);
553
554   if (!_gtk_css_number_equal (&corner->horizontal, &corner->vertical))
555     {
556       g_string_append_c (string, ' ');
557       _gtk_css_number_print (&corner->vertical, string);
558     }
559 }
560
561 static GtkCssValue *
562 css_image_value_parse (GtkCssStyleProperty *property,
563                        GtkCssParser        *parser,
564                        GFile               *base)
565 {
566   GtkCssImage *image;
567
568   if (_gtk_css_parser_try (parser, "none", TRUE))
569     image = NULL;
570   else
571     {
572       image = _gtk_css_image_new_parse (parser, base);
573       if (image == NULL)
574         return FALSE;
575     }
576
577   return _gtk_css_value_new_take_image (image);
578 }
579
580 static void
581 css_image_value_print (GtkCssStyleProperty *property,
582                        const GtkCssValue   *value,
583                        GString             *string)
584 {
585   GtkCssImage *image = _gtk_css_value_get_image (value);
586
587   if (image)
588     _gtk_css_image_print (image, string);
589   else
590     g_string_append (string, "none");
591 }
592
593 static GtkCssValue *
594 css_image_value_compute (GtkCssStyleProperty    *property,
595                          GtkStyleContext        *context,
596                          GtkCssValue            *specified)
597 {
598   GtkCssImage *image, *computed;
599   
600   image = _gtk_css_value_get_image (specified);
601
602   if (image == NULL)
603     return _gtk_css_value_ref (specified);
604
605   computed = _gtk_css_image_compute (image, context);
606
607   if (computed == image)
608     {
609       g_object_unref (computed);
610       return _gtk_css_value_ref (specified);
611     }
612
613   return _gtk_css_value_new_take_image (computed);
614 }
615
616 static GtkCssValue *
617 font_size_parse (GtkCssStyleProperty *property,
618                  GtkCssParser        *parser,
619                  GFile               *base)
620 {
621   gdouble d;
622
623   if (!_gtk_css_parser_try_double (parser, &d))
624     {
625       _gtk_css_parser_error (parser, "Expected a number");
626       return NULL;
627     }
628
629   return _gtk_css_value_new_from_double (d);
630 }
631
632 static GtkCssValue *
633 outline_parse (GtkCssStyleProperty *property,
634                GtkCssParser        *parser,
635                GFile               *base)
636 {
637   int i;
638
639   if (!_gtk_css_parser_try_int (parser, &i))
640     {
641       _gtk_css_parser_error (parser, "Expected an integer");
642       return NULL;
643     }
644
645   return _gtk_css_value_new_from_int (i);
646 }
647
648 static GtkCssValue *
649 border_image_repeat_parse (GtkCssStyleProperty *property,
650                            GtkCssParser        *parser,
651                            GFile               *base)
652 {
653   GValue value = G_VALUE_INIT;
654   GtkCssValue *result;
655
656   g_value_init (&value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
657   if (!_gtk_css_style_parse_value (&value, parser, base))
658     {
659       g_value_unset (&value);
660       return NULL;
661     }
662
663   result = _gtk_css_value_new_from_gvalue (&value);
664   g_value_unset (&value);
665
666   return result;
667 }
668
669 static GtkCssValue *
670 border_image_slice_parse (GtkCssStyleProperty *property,
671                           GtkCssParser        *parser,
672                           GFile               *base)
673 {
674   GValue value = G_VALUE_INIT;
675   GtkCssValue *result;
676
677   g_value_init (&value, GTK_TYPE_BORDER);
678   if (!_gtk_css_style_parse_value (&value, parser, base))
679     {
680       g_value_unset (&value);
681       return NULL;
682     }
683
684   result = _gtk_css_value_new_from_gvalue (&value);
685   g_value_unset (&value);
686
687   return result;
688 }
689
690 static GtkCssValue *
691 border_image_width_parse (GtkCssStyleProperty *property,
692                           GtkCssParser        *parser,
693                           GFile               *base)
694 {
695   GValue value = G_VALUE_INIT;
696   GtkCssValue *result;
697
698   g_value_init (&value, GTK_TYPE_BORDER);
699   if (!_gtk_css_style_parse_value (&value, parser, base))
700     {
701       g_value_unset (&value);
702       return NULL;
703     }
704
705   result = _gtk_css_value_new_from_gvalue (&value);
706   g_value_unset (&value);
707
708   return result;
709 }
710
711 static GtkCssValue *
712 engine_parse (GtkCssStyleProperty *property,
713               GtkCssParser        *parser,
714               GFile               *base)
715 {
716   GtkThemingEngine *engine;
717   char *str;
718
719   if (_gtk_css_parser_try (parser, "none", TRUE))
720     return _gtk_css_value_new_from_theming_engine (gtk_theming_engine_load (NULL));
721
722   str = _gtk_css_parser_try_ident (parser, TRUE);
723   if (str == NULL)
724     {
725       _gtk_css_parser_error (parser, "Expected a valid theme name");
726       return NULL;
727     }
728
729   engine = gtk_theming_engine_load (str);
730
731   if (engine == NULL)
732     {
733       _gtk_css_parser_error (parser, "Theming engine '%s' not found", str);
734       g_free (str);
735       return NULL;
736     }
737
738   g_free (str);
739
740   return _gtk_css_value_new_from_theming_engine (engine);
741 }
742
743 static GtkCssValue *
744 transition_parse (GtkCssStyleProperty *property,
745                   GtkCssParser        *parser,
746                   GFile               *base)
747 {
748   GValue value = G_VALUE_INIT;
749   GtkCssValue *result;
750
751   g_value_init (&value, GTK_TYPE_ANIMATION_DESCRIPTION);
752   if (!_gtk_css_style_parse_value (&value, parser, base))
753     {
754       g_value_unset (&value);
755       return NULL;
756     }
757
758   result = _gtk_css_value_new_from_gvalue (&value);
759   g_value_unset (&value);
760
761   return result;
762 }
763
764 static GtkCssValue *
765 parse_margin (GtkCssStyleProperty *property,
766               GtkCssParser        *parser,
767               GFile               *base)
768 {
769   GtkCssNumber number;
770
771   if (!_gtk_css_parser_read_number (parser,
772                                     &number, 
773                                     GTK_CSS_NUMBER_AS_PIXELS
774                                     | GTK_CSS_PARSE_LENGTH))
775     return NULL;
776
777   return _gtk_css_value_new_from_number (&number);
778 }
779
780 static GtkCssValue *
781 compute_margin (GtkCssStyleProperty *property,
782                 GtkStyleContext     *context,
783                 GtkCssValue         *specified)
784 {
785   GtkCssNumber number;
786   
787   if (_gtk_css_number_compute (&number,
788                                _gtk_css_value_get_number (specified),
789                                context))
790     {
791       return _gtk_css_value_new_from_number (&number);
792     }
793   return  _gtk_css_value_ref (specified);
794 }
795
796 static GtkCssValue *
797 parse_padding (GtkCssStyleProperty *property,
798                GtkCssParser        *parser,
799                GFile               *base)
800 {
801   GtkCssNumber number;
802
803   if (!_gtk_css_parser_read_number (parser,
804                                     &number, 
805                                     GTK_CSS_POSITIVE_ONLY
806                                     | GTK_CSS_NUMBER_AS_PIXELS
807                                     | GTK_CSS_PARSE_LENGTH))
808     return NULL;
809
810   return _gtk_css_value_new_from_number (&number);
811 }
812
813 static GtkCssValue *
814 compute_padding (GtkCssStyleProperty *property,
815                  GtkStyleContext     *context,
816                  GtkCssValue         *specified)
817 {
818   GtkCssNumber number;
819
820   if (_gtk_css_number_compute (&number,
821                                _gtk_css_value_get_number (specified),
822                                context))
823     return _gtk_css_value_new_from_number (&number);
824   return _gtk_css_value_ref (specified);
825 }
826
827 static GtkCssValue *
828 parse_border_width (GtkCssStyleProperty *property,
829                     GtkCssParser        *parser,
830                     GFile               *base)
831 {
832   GtkCssNumber number;
833
834   if (!_gtk_css_parser_read_number (parser,
835                                     &number, 
836                                     GTK_CSS_POSITIVE_ONLY
837                                     | GTK_CSS_NUMBER_AS_PIXELS
838                                     | GTK_CSS_PARSE_LENGTH))
839     return FALSE;
840
841   return _gtk_css_value_new_from_number (&number);
842 }
843
844 static GtkCssValue *
845 compute_border_width (GtkCssStyleProperty    *property,
846                       GtkStyleContext        *context,
847                       GtkCssValue            *specified)
848 {
849   GtkCssStyleProperty *style;
850   GtkBorderStyle border_style;
851   GtkCssNumber number;
852   int value = 0;
853   
854   /* The -1 is magic that is only true because we register the style
855    * properties directly after the width properties.
856    */
857   style = _gtk_css_style_property_lookup_by_id (_gtk_css_style_property_get_id (property) - 1);
858   
859   border_style = _gtk_css_value_get_border_style (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
860
861   if (border_style == GTK_BORDER_STYLE_NONE ||
862       border_style == GTK_BORDER_STYLE_HIDDEN)
863     {
864       value = 0;
865     }
866   else
867     {
868       _gtk_css_number_compute (&number,
869                                _gtk_css_value_get_number (specified),
870                                context);
871       value = round (number.value);
872     }
873   return _gtk_css_value_new_from_int (value);
874 }
875
876 static GtkCssValue *
877 background_repeat_value_parse (GtkCssStyleProperty *property,
878                                GtkCssParser        *parser,
879                                GFile               *base)
880 {
881   int repeat, vertical;
882
883   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &repeat))
884     {
885       _gtk_css_parser_error (parser, "Not a valid value");
886       return FALSE;
887     }
888
889   if (repeat <= GTK_CSS_BACKGROUND_REPEAT_MASK)
890     {
891       if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
892         {
893           if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
894             {
895               _gtk_css_parser_error (parser, "Not a valid 2nd value");
896               return FALSE;
897             }
898           else
899             repeat |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
900         }
901       else
902         repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
903     }
904
905   return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, repeat);
906 }
907
908 static void
909 background_repeat_value_print (GtkCssStyleProperty *property,
910                                const GtkCssValue   *value,
911                                GString             *string)
912 {
913   GEnumClass *enum_class;
914   GEnumValue *enum_value;
915   GtkCssBackgroundRepeat repeat;
916
917   repeat = _gtk_css_value_get_enum (value);
918   enum_class = g_type_class_ref (GTK_TYPE_CSS_BACKGROUND_REPEAT);
919   enum_value = g_enum_get_value (enum_class, repeat);
920
921   /* only triggers for 'repeat-x' and 'repeat-y' */
922   if (enum_value)
923     g_string_append (string, enum_value->value_nick);
924   else
925     {
926       enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_HORIZONTAL (repeat));
927       g_string_append (string, enum_value->value_nick);
928
929       if (GTK_CSS_BACKGROUND_HORIZONTAL (repeat) != GTK_CSS_BACKGROUND_VERTICAL (repeat))
930         {
931           enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_VERTICAL (repeat));
932           g_string_append (string, " ");
933           g_string_append (string, enum_value->value_nick);
934         }
935     }
936
937   g_type_class_unref (enum_class);
938 }
939
940 static GtkCssValue *
941 background_size_parse (GtkCssStyleProperty *property,
942                        GtkCssParser        *parser,
943                        GFile               *base)
944 {
945   GtkCssBackgroundSize size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE};
946
947   if (_gtk_css_parser_try (parser, "cover", TRUE))
948     size.cover = TRUE;
949   else if (_gtk_css_parser_try (parser, "contain", TRUE))
950     size.contain = TRUE;
951   else
952     {
953       if (_gtk_css_parser_try (parser, "auto", TRUE))
954         _gtk_css_number_init (&size.width, 0, GTK_CSS_PX);
955       else if (!_gtk_css_parser_read_number (parser,
956                                              &size.width,
957                                              GTK_CSS_POSITIVE_ONLY
958                                              | GTK_CSS_PARSE_PERCENT
959                                              | GTK_CSS_PARSE_LENGTH))
960         return NULL;
961
962       if (_gtk_css_parser_try (parser, "auto", TRUE))
963         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
964       else if (_gtk_css_parser_has_number (parser))
965         {
966           if (!_gtk_css_parser_read_number (parser,
967                                             &size.height,
968                                             GTK_CSS_POSITIVE_ONLY
969                                             | GTK_CSS_PARSE_PERCENT
970                                             | GTK_CSS_PARSE_LENGTH))
971             return NULL;
972         }
973       else
974         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
975     }
976
977   return _gtk_css_value_new_from_background_size (&size);
978 }
979
980 static void
981 background_size_print (GtkCssStyleProperty *property,
982                        const GtkCssValue   *value,
983                        GString             *string)
984 {
985   const GtkCssBackgroundSize *size = _gtk_css_value_get_background_size (value);
986
987   if (size->cover)
988     g_string_append (string, "cover");
989   else if (size->contain)
990     g_string_append (string, "contain");
991   else
992     {
993       if (size->width.value == 0)
994         g_string_append (string, "auto");
995       else
996         _gtk_css_number_print (&size->width, string);
997
998       if (size->height.value != 0)
999         {
1000           g_string_append (string, " ");
1001           _gtk_css_number_print (&size->height, string);
1002         }
1003     }
1004 }
1005
1006 static GtkCssValue *
1007 background_size_compute (GtkCssStyleProperty    *property,
1008                          GtkStyleContext        *context,
1009                          GtkCssValue            *specified)
1010 {
1011   const GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
1012   GtkCssBackgroundSize csize;
1013   gboolean changed;
1014
1015   csize.cover = ssize->cover;
1016   csize.contain = ssize->contain;
1017   changed = _gtk_css_number_compute (&csize.width,
1018                                      &ssize->width,
1019                                      context);
1020   changed |= _gtk_css_number_compute (&csize.height,
1021                                       &ssize->height,
1022                                       context);
1023   if (changed)
1024     return _gtk_css_value_new_from_background_size (&csize);
1025   return _gtk_css_value_ref (specified);
1026 }
1027
1028 static GtkCssValue *
1029 background_position_parse (GtkCssStyleProperty *property,
1030                            GtkCssParser        *parser,
1031                            GFile               *base)
1032 {
1033   static const struct {
1034     const char *name;
1035     guint       percentage;
1036     gboolean    horizontal;
1037     gboolean    vertical;
1038   } names[] = {
1039     { "left",     0, TRUE,  FALSE },
1040     { "right",  100, TRUE,  FALSE },
1041     { "center",  50, TRUE,  TRUE  },
1042     { "top",      0, FALSE, TRUE  },
1043     { "bottom", 100, FALSE, TRUE  },
1044     { NULL    ,   0, TRUE,  FALSE }, /* used for numbers */
1045     { NULL    ,  50, TRUE,  TRUE  }  /* used for no value */
1046   };
1047   GtkCssBackgroundPosition pos;
1048   GtkCssNumber *missing;
1049   guint first, second;
1050
1051   for (first = 0; names[first].name != NULL; first++)
1052     {
1053       if (_gtk_css_parser_try (parser, names[first].name, TRUE))
1054         {
1055           if (names[first].horizontal)
1056             {
1057               _gtk_css_number_init (&pos.x, names[first].percentage, GTK_CSS_PERCENT);
1058               missing = &pos.y;
1059             }
1060           else
1061             {
1062               _gtk_css_number_init (&pos.y, names[first].percentage, GTK_CSS_PERCENT);
1063               missing = &pos.x;
1064             }
1065           break;
1066         }
1067     }
1068   if (names[first].name == NULL)
1069     {
1070       missing = &pos.y;
1071       if (!_gtk_css_parser_read_number (parser,
1072                                         &pos.x,
1073                                         GTK_CSS_PARSE_PERCENT
1074                                         | GTK_CSS_PARSE_LENGTH))
1075         return NULL;
1076     }
1077
1078   for (second = 0; names[second].name != NULL; second++)
1079     {
1080       if (_gtk_css_parser_try (parser, names[second].name, TRUE))
1081         {
1082           _gtk_css_number_init (missing, names[second].percentage, GTK_CSS_PERCENT);
1083           break;
1084         }
1085     }
1086
1087   if (names[second].name == NULL)
1088     {
1089       if (_gtk_css_parser_has_number (parser))
1090         {
1091           if (missing != &pos.y)
1092             {
1093               _gtk_css_parser_error (parser, "Invalid combination of values");
1094               return NULL;
1095             }
1096           if (!_gtk_css_parser_read_number (parser,
1097                                             missing,
1098                                             GTK_CSS_PARSE_PERCENT
1099                                             | GTK_CSS_PARSE_LENGTH))
1100             return NULL;
1101         }
1102       else
1103         {
1104           second++;
1105           _gtk_css_number_init (missing, 50, GTK_CSS_PERCENT);
1106         }
1107     }
1108   else
1109     {
1110       if ((names[first].horizontal && !names[second].vertical) ||
1111           (!names[first].horizontal && !names[second].horizontal))
1112         {
1113           _gtk_css_parser_error (parser, "Invalid combination of values");
1114           return NULL;
1115         }
1116     }
1117
1118   return _gtk_css_value_new_from_background_position (&pos);
1119 }
1120
1121 static void
1122 background_position_print (GtkCssStyleProperty *property,
1123                            const GtkCssValue   *value,
1124                            GString             *string)
1125 {
1126   const GtkCssBackgroundPosition *pos = _gtk_css_value_get_background_position (value);
1127   static const GtkCssNumber center = GTK_CSS_NUMBER_INIT (50, GTK_CSS_PERCENT);
1128   static const struct {
1129     const char *x_name;
1130     const char *y_name;
1131     GtkCssNumber number;
1132   } values[] = { 
1133     { "left",   "top",    GTK_CSS_NUMBER_INIT (0,   GTK_CSS_PERCENT) },
1134     { "right",  "bottom", GTK_CSS_NUMBER_INIT (100, GTK_CSS_PERCENT) }
1135   };
1136   guint i;
1137
1138   if (_gtk_css_number_equal (&pos->x, &center))
1139     {
1140       if (_gtk_css_number_equal (&pos->y, &center))
1141         {
1142           g_string_append (string, "center");
1143           return;
1144         }
1145     }
1146   else
1147     {
1148       for (i = 0; i < G_N_ELEMENTS (values); i++)
1149         {
1150           if (_gtk_css_number_equal (&pos->x, &values[i].number))
1151             {
1152               g_string_append (string, values[i].x_name);
1153               break;
1154             }
1155         }
1156       if (i == G_N_ELEMENTS (values))
1157         _gtk_css_number_print (&pos->x, string);
1158
1159       if (_gtk_css_number_equal (&pos->y, &center))
1160         return;
1161
1162       g_string_append_c (string, ' ');
1163     }
1164
1165   for (i = 0; i < G_N_ELEMENTS (values); i++)
1166     {
1167       if (_gtk_css_number_equal (&pos->y, &values[i].number))
1168         {
1169           g_string_append (string, values[i].y_name);
1170           break;
1171         }
1172     }
1173   if (i == G_N_ELEMENTS (values))
1174     {
1175       if (_gtk_css_number_equal (&pos->x, &center))
1176         g_string_append (string, "center ");
1177       _gtk_css_number_print (&pos->y, string);
1178     }
1179 }
1180
1181 static GtkCssValue *
1182 background_position_compute (GtkCssStyleProperty    *property,
1183                              GtkStyleContext        *context,
1184                              GtkCssValue            *specified)
1185 {
1186   const GtkCssBackgroundPosition *spos = _gtk_css_value_get_background_position (specified);
1187   GtkCssBackgroundPosition cpos;
1188   gboolean changed;
1189
1190   changed = _gtk_css_number_compute (&cpos.x,
1191                                      &spos->x,
1192                                      context);
1193   changed |= _gtk_css_number_compute (&cpos.y,
1194                                       &spos->y,
1195                                       context);
1196   if (changed)
1197     return _gtk_css_value_new_from_background_position (&cpos);
1198   return _gtk_css_value_ref (specified);
1199 }
1200
1201 /*** REGISTRATION ***/
1202
1203 static GtkSymbolicColor *
1204 gtk_symbolic_color_new_rgba (double red,
1205                              double green,
1206                              double blue,
1207                              double alpha)
1208 {
1209   GdkRGBA rgba = { red, green, blue, alpha };
1210
1211   return gtk_symbolic_color_new_literal (&rgba);
1212 }
1213
1214 void
1215 _gtk_css_style_property_init_properties (void)
1216 {
1217   char *default_font_family[] = { "Sans", NULL };
1218   GtkCssNumber number;
1219   GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE };
1220   GtkCssBackgroundPosition default_background_position = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT)};
1221   GtkCssBorderCornerRadius no_corner_radius = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX) };
1222   GtkBorder border_of_ones = { 1, 1, 1, 1 };
1223   GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
1224
1225   /* Initialize "color" and "font-size" first,
1226    * so that when computing values later they are
1227    * done first. That way, 'currentColor' and font
1228    * sizes in em can be looked up properly */
1229   gtk_css_style_property_register        ("color",
1230                                           GTK_TYPE_SYMBOLIC_COLOR,
1231                                           GDK_TYPE_RGBA,
1232                                           GDK_TYPE_RGBA,
1233                                           GTK_STYLE_PROPERTY_INHERIT,
1234                                           color_parse,
1235                                           NULL,
1236                                           color_compute,
1237                                           NULL,
1238                                           _gtk_css_value_new_take_symbolic_color (
1239                                             gtk_symbolic_color_new_rgba (1, 1, 1, 1)));
1240   gtk_css_style_property_register        ("font-size",
1241                                           G_TYPE_DOUBLE,
1242                                           G_TYPE_DOUBLE,
1243                                           G_TYPE_DOUBLE,
1244                                           GTK_STYLE_PROPERTY_INHERIT,
1245                                           font_size_parse,
1246                                           NULL,
1247                                           NULL,
1248                                           NULL,
1249                                           _gtk_css_value_new_from_double (10.0));
1250
1251   /* properties that aren't referenced when computing values
1252    * start here */
1253   gtk_css_style_property_register        ("background-color",
1254                                           GTK_TYPE_SYMBOLIC_COLOR,
1255                                           GDK_TYPE_RGBA,
1256                                           GDK_TYPE_RGBA,
1257                                           0,
1258                                           color_parse,
1259                                           NULL,
1260                                           color_compute,
1261                                           NULL,
1262                                           _gtk_css_value_new_take_symbolic_color (
1263                                             gtk_symbolic_color_new_rgba (0, 0, 0, 0)));
1264
1265   gtk_css_style_property_register        ("font-family",
1266                                           G_TYPE_STRV,
1267                                           G_TYPE_STRV,
1268                                           G_TYPE_STRV,
1269                                           GTK_STYLE_PROPERTY_INHERIT,
1270                                           font_family_parse,
1271                                           font_family_value_print,
1272                                           NULL,
1273                                           NULL,
1274                                           _gtk_css_value_new_take_strv (g_strdupv (default_font_family)));
1275   gtk_css_style_property_register        ("font-style",
1276                                           PANGO_TYPE_STYLE,
1277                                           PANGO_TYPE_STYLE,
1278                                           PANGO_TYPE_STYLE,
1279                                           GTK_STYLE_PROPERTY_INHERIT,
1280                                           parse_pango_style,
1281                                           NULL,
1282                                           NULL,
1283                                           NULL,
1284                                           _gtk_css_value_new_from_enum (PANGO_TYPE_STYLE,
1285                                                                         PANGO_STYLE_NORMAL));
1286   gtk_css_style_property_register        ("font-variant",
1287                                           PANGO_TYPE_VARIANT,
1288                                           PANGO_TYPE_VARIANT,
1289                                           PANGO_TYPE_VARIANT,
1290                                           GTK_STYLE_PROPERTY_INHERIT,
1291                                           parse_pango_variant,
1292                                           NULL,
1293                                           NULL,
1294                                           NULL,
1295                                           _gtk_css_value_new_from_enum (PANGO_TYPE_VARIANT,
1296                                                                         PANGO_VARIANT_NORMAL));
1297   /* xxx: need to parse this properly, ie parse the numbers */
1298   gtk_css_style_property_register        ("font-weight",
1299                                           PANGO_TYPE_WEIGHT,
1300                                           PANGO_TYPE_WEIGHT,
1301                                           PANGO_TYPE_WEIGHT,
1302                                           GTK_STYLE_PROPERTY_INHERIT,
1303                                           parse_pango_weight,
1304                                           NULL,
1305                                           NULL,
1306                                           NULL,
1307                                           _gtk_css_value_new_from_enum (PANGO_TYPE_WEIGHT,
1308                                                                         PANGO_WEIGHT_NORMAL));
1309
1310   gtk_css_style_property_register        ("text-shadow",
1311                                           GTK_TYPE_SHADOW,
1312                                           GTK_TYPE_SHADOW,
1313                                           GTK_TYPE_SHADOW,
1314                                           GTK_STYLE_PROPERTY_INHERIT,
1315                                           shadow_value_parse,
1316                                           shadow_value_print,
1317                                           shadow_value_compute,
1318                                           NULL,
1319                                           _gtk_css_value_new_take_shadow (NULL));
1320
1321   gtk_css_style_property_register        ("icon-shadow",
1322                                           GTK_TYPE_SHADOW,
1323                                           GTK_TYPE_SHADOW,
1324                                           GTK_TYPE_SHADOW,
1325                                           GTK_STYLE_PROPERTY_INHERIT,
1326                                           shadow_value_parse,
1327                                           shadow_value_print,
1328                                           shadow_value_compute,
1329                                           NULL,
1330                                           _gtk_css_value_new_take_shadow (NULL));
1331
1332   gtk_css_style_property_register        ("box-shadow",
1333                                           GTK_TYPE_SHADOW,
1334                                           GTK_TYPE_SHADOW,
1335                                           GTK_TYPE_SHADOW,
1336                                           0,
1337                                           shadow_value_parse,
1338                                           shadow_value_print,
1339                                           shadow_value_compute,
1340                                           NULL,
1341                                           _gtk_css_value_new_take_shadow (NULL));
1342
1343   _gtk_css_number_init (&number, 0, GTK_CSS_PX);
1344   gtk_css_style_property_register        ("margin-top",
1345                                           GTK_TYPE_CSS_NUMBER,
1346                                           GTK_TYPE_CSS_NUMBER,
1347                                           G_TYPE_INT,
1348                                           0,
1349                                           parse_margin,
1350                                           NULL,
1351                                           compute_margin,
1352                                           NULL,
1353                                           _gtk_css_value_new_from_number (&number));
1354   gtk_css_style_property_register        ("margin-left",
1355                                           GTK_TYPE_CSS_NUMBER,
1356                                           GTK_TYPE_CSS_NUMBER,
1357                                           G_TYPE_INT,
1358                                           0,
1359                                           parse_margin,
1360                                           NULL,
1361                                           compute_margin,
1362                                           NULL,
1363                                           _gtk_css_value_new_from_number (&number));
1364   gtk_css_style_property_register        ("margin-bottom",
1365                                           GTK_TYPE_CSS_NUMBER,
1366                                           GTK_TYPE_CSS_NUMBER,
1367                                           G_TYPE_INT,
1368                                           0,
1369                                           parse_margin,
1370                                           NULL,
1371                                           compute_margin,
1372                                           NULL,
1373                                           _gtk_css_value_new_from_number (&number));
1374   gtk_css_style_property_register        ("margin-right",
1375                                           GTK_TYPE_CSS_NUMBER,
1376                                           GTK_TYPE_CSS_NUMBER,
1377                                           G_TYPE_INT,
1378                                           0,
1379                                           parse_margin,
1380                                           NULL,
1381                                           compute_margin,
1382                                           NULL,
1383                                           _gtk_css_value_new_from_number (&number));
1384   gtk_css_style_property_register        ("padding-top",
1385                                           GTK_TYPE_CSS_NUMBER,
1386                                           GTK_TYPE_CSS_NUMBER,
1387                                           G_TYPE_INT,
1388                                           0,
1389                                           parse_padding,
1390                                           NULL,
1391                                           compute_padding,
1392                                           NULL,
1393                                           _gtk_css_value_new_from_number (&number));
1394   gtk_css_style_property_register        ("padding-left",
1395                                           GTK_TYPE_CSS_NUMBER,
1396                                           GTK_TYPE_CSS_NUMBER,
1397                                           G_TYPE_INT,
1398                                           0,
1399                                           parse_padding,
1400                                           NULL,
1401                                           compute_padding,
1402                                           NULL,
1403                                           _gtk_css_value_new_from_number (&number));
1404   gtk_css_style_property_register        ("padding-bottom",
1405                                           GTK_TYPE_CSS_NUMBER,
1406                                           GTK_TYPE_CSS_NUMBER,
1407                                           G_TYPE_INT,
1408                                           0,
1409                                           parse_padding,
1410                                           NULL,
1411                                           compute_padding,
1412                                           NULL,
1413                                           _gtk_css_value_new_from_number (&number));
1414   gtk_css_style_property_register        ("padding-right",
1415                                           GTK_TYPE_CSS_NUMBER,
1416                                           GTK_TYPE_CSS_NUMBER,
1417                                           G_TYPE_INT,
1418                                           0,
1419                                           parse_padding,
1420                                           NULL,
1421                                           compute_padding,
1422                                           NULL,
1423                                           _gtk_css_value_new_from_number (&number));
1424   /* IMPORTANT: compute_border_width() requires that the border-width
1425    * properties be immeditaly followed by the border-style properties
1426    */
1427   gtk_css_style_property_register        ("border-top-style",
1428                                           GTK_TYPE_BORDER_STYLE,
1429                                           GTK_TYPE_BORDER_STYLE,
1430                                           GTK_TYPE_BORDER_STYLE,
1431                                           0,
1432                                           parse_border_style,
1433                                           NULL,
1434                                           NULL,
1435                                           NULL,
1436                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1437   gtk_css_style_property_register        ("border-top-width",
1438                                           GTK_TYPE_CSS_NUMBER,
1439                                           G_TYPE_INT,
1440                                           G_TYPE_INT,
1441                                           0,
1442                                           parse_border_width,
1443                                           NULL,
1444                                           compute_border_width,
1445                                           NULL,
1446                                           _gtk_css_value_new_from_number (&number));
1447   gtk_css_style_property_register        ("border-left-style",
1448                                           GTK_TYPE_BORDER_STYLE,
1449                                           GTK_TYPE_BORDER_STYLE,
1450                                           GTK_TYPE_BORDER_STYLE,
1451                                           0,
1452                                           parse_border_style,
1453                                           NULL,
1454                                           NULL,
1455                                           NULL,
1456                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1457   gtk_css_style_property_register        ("border-left-width",
1458                                           GTK_TYPE_CSS_NUMBER,
1459                                           G_TYPE_INT,
1460                                           G_TYPE_INT,
1461                                           0,
1462                                           parse_border_width,
1463                                           NULL,
1464                                           compute_border_width,
1465                                           NULL,
1466                                           _gtk_css_value_new_from_number (&number));
1467   gtk_css_style_property_register        ("border-bottom-style",
1468                                           GTK_TYPE_BORDER_STYLE,
1469                                           GTK_TYPE_BORDER_STYLE,
1470                                           GTK_TYPE_BORDER_STYLE,
1471                                           0,
1472                                           parse_border_style,
1473                                           NULL,
1474                                           NULL,
1475                                           NULL,
1476                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1477   gtk_css_style_property_register        ("border-bottom-width",
1478                                           GTK_TYPE_CSS_NUMBER,
1479                                           G_TYPE_INT,
1480                                           G_TYPE_INT,
1481                                           0,
1482                                           parse_border_width,
1483                                           NULL,
1484                                           compute_border_width,
1485                                           NULL,
1486                                           _gtk_css_value_new_from_number (&number));
1487   gtk_css_style_property_register        ("border-right-style",
1488                                           GTK_TYPE_BORDER_STYLE,
1489                                           GTK_TYPE_BORDER_STYLE,
1490                                           GTK_TYPE_BORDER_STYLE,
1491                                           0,
1492                                           parse_border_style,
1493                                           NULL,
1494                                           NULL,
1495                                           NULL,
1496                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1497   gtk_css_style_property_register        ("border-right-width",
1498                                           GTK_TYPE_CSS_NUMBER,
1499                                           G_TYPE_INT,
1500                                           G_TYPE_INT,
1501                                           0,
1502                                           parse_border_width,
1503                                           NULL,
1504                                           compute_border_width,
1505                                           NULL,
1506                                           _gtk_css_value_new_from_number (&number));
1507
1508   gtk_css_style_property_register        ("border-top-left-radius",
1509                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1510                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1511                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1512                                           0,
1513                                           border_corner_radius_value_parse,
1514                                           border_corner_radius_value_print,
1515                                           NULL,
1516                                           NULL,
1517                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1518   gtk_css_style_property_register        ("border-top-right-radius",
1519                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1520                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1521                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1522                                           0,
1523                                           border_corner_radius_value_parse,
1524                                           border_corner_radius_value_print,
1525                                           NULL,
1526                                           NULL,
1527                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1528   gtk_css_style_property_register        ("border-bottom-right-radius",
1529                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1530                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1531                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1532                                           0,
1533                                           border_corner_radius_value_parse,
1534                                           border_corner_radius_value_print,
1535                                           NULL,
1536                                           NULL,
1537                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1538   gtk_css_style_property_register        ("border-bottom-left-radius",
1539                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1540                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1541                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1542                                           0,
1543                                           border_corner_radius_value_parse,
1544                                           border_corner_radius_value_print,
1545                                           NULL,
1546                                           NULL,
1547                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1548
1549   gtk_css_style_property_register        ("outline-style",
1550                                           GTK_TYPE_BORDER_STYLE,
1551                                           GTK_TYPE_BORDER_STYLE,
1552                                           GTK_TYPE_BORDER_STYLE,
1553                                           0,
1554                                           parse_border_style,
1555                                           NULL,
1556                                           NULL,
1557                                           NULL,
1558                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1559   gtk_css_style_property_register        ("outline-width",
1560                                           GTK_TYPE_CSS_NUMBER,
1561                                           G_TYPE_INT,
1562                                           G_TYPE_INT,
1563                                           0,
1564                                           parse_border_width,
1565                                           NULL,
1566                                           compute_border_width,
1567                                           NULL,
1568                                           _gtk_css_value_new_from_number (&number));
1569   gtk_css_style_property_register        ("outline-offset",
1570                                           G_TYPE_INT,
1571                                           G_TYPE_INT,
1572                                           G_TYPE_INT,
1573                                           0,
1574                                           outline_parse,
1575                                           NULL,
1576                                           NULL,
1577                                           NULL,
1578                                           _gtk_css_value_new_from_int (0));
1579
1580   gtk_css_style_property_register        ("background-clip",
1581                                           GTK_TYPE_CSS_AREA,
1582                                           GTK_TYPE_CSS_AREA,
1583                                           GTK_TYPE_CSS_AREA,
1584                                           0,
1585                                           parse_css_area,
1586                                           NULL,
1587                                           NULL,
1588                                           NULL,
1589                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, GTK_CSS_AREA_BORDER_BOX));
1590   gtk_css_style_property_register        ("background-origin",
1591                                           GTK_TYPE_CSS_AREA,
1592                                           GTK_TYPE_CSS_AREA,
1593                                           GTK_TYPE_CSS_AREA,
1594                                           0,
1595                                           parse_css_area,
1596                                           NULL,
1597                                           NULL,
1598                                           NULL,
1599                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, GTK_CSS_AREA_PADDING_BOX));
1600   gtk_css_style_property_register        ("background-size",
1601                                           GTK_TYPE_CSS_BACKGROUND_SIZE,
1602                                           GTK_TYPE_CSS_BACKGROUND_SIZE,
1603                                           G_TYPE_NONE,
1604                                           0,
1605                                           background_size_parse,
1606                                           background_size_print,
1607                                           background_size_compute,
1608                                           NULL,
1609                                           _gtk_css_value_new_from_background_size (&default_background_size));
1610   gtk_css_style_property_register        ("background-position",
1611                                           GTK_TYPE_CSS_BACKGROUND_POSITION,
1612                                           GTK_TYPE_CSS_BACKGROUND_POSITION,
1613                                           G_TYPE_NONE,
1614                                           0,
1615                                           background_position_parse,
1616                                           background_position_print,
1617                                           background_position_compute,
1618                                           NULL,
1619                                           _gtk_css_value_new_from_background_position (&default_background_position));
1620
1621   gtk_css_style_property_register        ("border-top-color",
1622                                           GTK_TYPE_SYMBOLIC_COLOR,
1623                                           GDK_TYPE_RGBA,
1624                                           GDK_TYPE_RGBA,
1625                                           0,
1626                                           color_parse,
1627                                           NULL,
1628                                           color_compute,
1629                                           NULL,
1630                                           _gtk_css_value_new_take_symbolic_color (
1631                                             gtk_symbolic_color_ref (
1632                                               _gtk_symbolic_color_get_current_color ())));
1633   gtk_css_style_property_register        ("border-right-color",
1634                                           GTK_TYPE_SYMBOLIC_COLOR,
1635                                           GDK_TYPE_RGBA,
1636                                           GDK_TYPE_RGBA,
1637                                           0,
1638                                           color_parse,
1639                                           NULL,
1640                                           color_compute,
1641                                           NULL,
1642                                           _gtk_css_value_new_take_symbolic_color (
1643                                             gtk_symbolic_color_ref (
1644                                               _gtk_symbolic_color_get_current_color ())));
1645   gtk_css_style_property_register        ("border-bottom-color",
1646                                           GTK_TYPE_SYMBOLIC_COLOR,
1647                                           GDK_TYPE_RGBA,
1648                                           GDK_TYPE_RGBA,
1649                                           0,
1650                                           color_parse,
1651                                           NULL,
1652                                           color_compute,
1653                                           NULL,
1654                                           _gtk_css_value_new_take_symbolic_color (
1655                                             gtk_symbolic_color_ref (
1656                                               _gtk_symbolic_color_get_current_color ())));
1657   gtk_css_style_property_register        ("border-left-color",
1658                                           GTK_TYPE_SYMBOLIC_COLOR,
1659                                           GDK_TYPE_RGBA,
1660                                           GDK_TYPE_RGBA,
1661                                           0,
1662                                           color_parse,
1663                                           NULL,
1664                                           color_compute,
1665                                           NULL,
1666                                           _gtk_css_value_new_take_symbolic_color (
1667                                             gtk_symbolic_color_ref (
1668                                               _gtk_symbolic_color_get_current_color ())));
1669   gtk_css_style_property_register        ("outline-color",
1670                                           GTK_TYPE_SYMBOLIC_COLOR,
1671                                           GDK_TYPE_RGBA,
1672                                           GDK_TYPE_RGBA,
1673                                           0,
1674                                           color_parse,
1675                                           NULL,
1676                                           color_compute,
1677                                           NULL,
1678                                           _gtk_css_value_new_take_symbolic_color (
1679                                             gtk_symbolic_color_ref (
1680                                               _gtk_symbolic_color_get_current_color ())));
1681
1682   gtk_css_style_property_register        ("background-repeat",
1683                                           GTK_TYPE_CSS_BACKGROUND_REPEAT,
1684                                           GTK_TYPE_CSS_BACKGROUND_REPEAT,
1685                                           GTK_TYPE_CSS_BACKGROUND_REPEAT,
1686                                           0,
1687                                           background_repeat_value_parse,
1688                                           background_repeat_value_print,
1689                                           NULL,
1690                                           NULL,
1691                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT,
1692                                                                         GTK_CSS_BACKGROUND_REPEAT | 
1693                                                                         (GTK_CSS_BACKGROUND_REPEAT << GTK_CSS_BACKGROUND_REPEAT_SHIFT)));
1694   gtk_css_style_property_register        ("background-image",
1695                                           GTK_TYPE_CSS_IMAGE,
1696                                           GTK_TYPE_CSS_IMAGE,
1697                                           CAIRO_GOBJECT_TYPE_PATTERN,
1698                                           0,
1699                                           css_image_value_parse,
1700                                           css_image_value_print,
1701                                           css_image_value_compute,
1702                                           NULL,
1703                                           _gtk_css_value_new_take_image (NULL));
1704
1705   gtk_css_style_property_register        ("border-image-source",
1706                                           GTK_TYPE_CSS_IMAGE,
1707                                           GTK_TYPE_CSS_IMAGE,
1708                                           CAIRO_GOBJECT_TYPE_PATTERN,
1709                                           0,
1710                                           css_image_value_parse,
1711                                           css_image_value_print,
1712                                           css_image_value_compute,
1713                                           NULL,
1714                                           _gtk_css_value_new_take_image (NULL));
1715   gtk_css_style_property_register        ("border-image-repeat",
1716                                           GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1717                                           GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1718                                           GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1719                                           0,
1720                                           border_image_repeat_parse,
1721                                           NULL,
1722                                           NULL,
1723                                           NULL,
1724                                           _gtk_css_value_new_from_border_image_repeat (&border_image_repeat));
1725
1726   /* XXX: The initial value is wrong, it should be 100% */
1727   gtk_css_style_property_register        ("border-image-slice",
1728                                           GTK_TYPE_BORDER,
1729                                           GTK_TYPE_BORDER,
1730                                           GTK_TYPE_BORDER,
1731                                           0,
1732                                           border_image_slice_parse,
1733                                           NULL,
1734                                           NULL,
1735                                           NULL,
1736                                           _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, &border_of_ones));
1737   gtk_css_style_property_register        ("border-image-width",
1738                                           GTK_TYPE_BORDER,
1739                                           GTK_TYPE_BORDER,
1740                                           GTK_TYPE_BORDER,
1741                                           0,
1742                                           border_image_width_parse,
1743                                           NULL,
1744                                           NULL,
1745                                           NULL,
1746                                           _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, NULL));
1747   gtk_css_style_property_register        ("engine",
1748                                           GTK_TYPE_THEMING_ENGINE,
1749                                           GTK_TYPE_THEMING_ENGINE,
1750                                           GTK_TYPE_THEMING_ENGINE,
1751                                           0,
1752                                           engine_parse,
1753                                           NULL,
1754                                           NULL,
1755                                           NULL,
1756                                           _gtk_css_value_new_from_theming_engine (gtk_theming_engine_load (NULL)));
1757   gtk_css_style_property_register        ("transition",
1758                                           GTK_TYPE_ANIMATION_DESCRIPTION,
1759                                           GTK_TYPE_ANIMATION_DESCRIPTION,
1760                                           GTK_TYPE_ANIMATION_DESCRIPTION,
1761                                           0,
1762                                           transition_parse,
1763                                           NULL,
1764                                           NULL,
1765                                           NULL,
1766                                           _gtk_css_value_new_from_boxed (GTK_TYPE_ANIMATION_DESCRIPTION, NULL));
1767
1768   /* Private property holding the binding sets */
1769   gtk_css_style_property_register        ("gtk-key-bindings",
1770                                           G_TYPE_PTR_ARRAY,
1771                                           G_TYPE_PTR_ARRAY,
1772                                           G_TYPE_PTR_ARRAY,
1773                                           0,
1774                                           bindings_value_parse,
1775                                           bindings_value_print,
1776                                           NULL,
1777                                           NULL,
1778                                           _gtk_css_value_new_take_binding_sets (NULL));
1779 }
1780