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