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