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