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