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