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