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