]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssstylepropertyimpl.c
styleproperty: Fix 'currentColor'
[~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, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21
22 #include "gtkstylepropertyprivate.h"
23
24 #include <gobject/gvaluecollector.h>
25 #include <gdk-pixbuf/gdk-pixbuf.h>
26 #include <cairo-gobject.h>
27
28 #include "gtkcssparserprivate.h"
29 #include "gtkcssstylefuncsprivate.h"
30 #include "gtkcssstylepropertyprivate.h"
31 #include "gtkcsstypesprivate.h"
32 #include "gtkintl.h"
33 #include "gtkprivatetypebuiltins.h"
34 #include "gtkstylepropertiesprivate.h"
35
36 /* the actual parsers we have */
37 #include "gtkanimationdescription.h"
38 #include "gtkbindings.h"
39 #include "gtkcssimageprivate.h"
40 #include "gtkgradient.h"
41 #include "gtkshadowprivate.h"
42 #include "gtkthemingengine.h"
43 #include "gtktypebuiltins.h"
44 #include "gtkwin32themeprivate.h"
45
46 /*** REGISTRATION ***/
47
48 static void
49 color_compute (GtkCssStyleProperty    *property,
50                GValue                 *computed,
51                GtkStyleContext        *context,
52                const GValue           *specified)
53 {
54   g_value_init (computed, GDK_TYPE_RGBA);
55
56   /* for when resolvage fails */
57 restart:
58
59   if (G_VALUE_HOLDS (specified, GTK_TYPE_CSS_SPECIAL_VALUE))
60     {
61       g_assert (g_value_get_enum (specified) == GTK_CSS_CURRENT_COLOR);
62
63       /* The computed value of the ‘currentColor’ keyword is the computed
64        * value of the ‘color’ property. If the ‘currentColor’ keyword is
65        * set on the ‘color’ property itself, it is treated as ‘color: inherit’. 
66        */
67       if (g_str_equal (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (property)), "color"))
68         {
69           GtkStyleContext *parent = gtk_style_context_get_parent (context);
70
71           if (parent)
72             g_value_copy (_gtk_style_context_peek_property (parent, "color"), computed);
73           else
74             _gtk_css_style_compute_value (computed,
75                                           context,
76                                           _gtk_css_style_property_get_initial_value (property));
77         }
78       else
79         {
80           g_value_copy (_gtk_style_context_peek_property (context, "color"), computed);
81         }
82     }
83   else if (G_VALUE_HOLDS (specified, GTK_TYPE_SYMBOLIC_COLOR))
84     {
85       GdkRGBA rgba;
86
87       if (!_gtk_style_context_resolve_color (context,
88                                              g_value_get_boxed (specified),
89                                              &rgba))
90         {
91           specified = _gtk_css_style_property_get_initial_value (property);
92           goto restart;
93         }
94
95       g_value_set_boxed (computed, &rgba);
96     }
97   else
98     g_value_copy (specified, computed);
99 }
100
101 static void
102 _gtk_style_property_register (const char *                   name,
103                               GType                          value_type,
104                               GtkStylePropertyFlags          flags,
105                               GtkCssStylePropertyParseFunc   parse_value,
106                               GtkCssStylePropertyPrintFunc   print_value,
107                               GtkCssStylePropertyComputeFunc compute_value,
108                               const GValue *                 initial_value)
109 {
110   GtkCssStyleProperty *node;
111
112   node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
113                        "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
114                        "initial-value", initial_value,
115                        "name", name,
116                        "value-type", value_type,
117                        NULL);
118   
119   if (parse_value)
120     node->parse_value = parse_value;
121   if (print_value)
122     node->print_value = print_value;
123   if (compute_value)
124     node->compute_value = compute_value;
125 }
126
127 static void
128 gtk_style_property_register (const char *                   name,
129                              GType                          value_type,
130                              GtkStylePropertyFlags          flags,
131                              GtkCssStylePropertyParseFunc   parse_value,
132                              GtkCssStylePropertyPrintFunc   print_value,
133                              GtkCssStylePropertyComputeFunc compute_value,
134                              ...)
135 {
136   GValue initial_value = G_VALUE_INIT;
137   char *error = NULL;
138   va_list args;
139
140   va_start (args, compute_value);
141   G_VALUE_COLLECT_INIT (&initial_value, value_type,
142                         args, 0, &error);
143   if (error)
144     {
145       g_error ("property `%s' initial value is broken: %s", name, error);
146       g_value_unset (&initial_value);
147       return;
148     }
149
150   va_end (args);
151
152   _gtk_style_property_register (name,
153                                 value_type,
154                                 flags,
155                                 parse_value,
156                                 print_value,
157                                 compute_value,
158                                 &initial_value);
159
160   g_value_unset (&initial_value);
161 }
162
163 /*** HELPERS ***/
164
165 static void
166 string_append_double (GString *string,
167                       double   d)
168 {
169   char buf[G_ASCII_DTOSTR_BUF_SIZE];
170
171   g_ascii_dtostr (buf, sizeof (buf), d);
172   g_string_append (string, buf);
173 }
174
175 static void
176 string_append_string (GString    *str,
177                       const char *string)
178 {
179   gsize len;
180
181   g_string_append_c (str, '"');
182
183   do {
184     len = strcspn (string, "\"\n\r\f");
185     g_string_append (str, string);
186     string += len;
187     switch (*string)
188       {
189       case '\0':
190         break;
191       case '\n':
192         g_string_append (str, "\\A ");
193         break;
194       case '\r':
195         g_string_append (str, "\\D ");
196         break;
197       case '\f':
198         g_string_append (str, "\\C ");
199         break;
200       case '\"':
201         g_string_append (str, "\\\"");
202         break;
203       default:
204         g_assert_not_reached ();
205         break;
206       }
207   } while (*string);
208
209   g_string_append_c (str, '"');
210 }
211
212 /*** IMPLEMENTATIONS ***/
213
214 static gboolean
215 font_family_parse (GtkCssStyleProperty *property,
216                    GValue              *value,
217                    GtkCssParser        *parser,
218                    GFile               *base)
219 {
220   GPtrArray *names;
221   char *name;
222
223   /* We don't special case generic families. Pango should do
224    * that for us */
225
226   names = g_ptr_array_new ();
227
228   do {
229     name = _gtk_css_parser_try_ident (parser, TRUE);
230     if (name)
231       {
232         GString *string = g_string_new (name);
233         g_free (name);
234         while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
235           {
236             g_string_append_c (string, ' ');
237             g_string_append (string, name);
238             g_free (name);
239           }
240         name = g_string_free (string, FALSE);
241       }
242     else 
243       {
244         name = _gtk_css_parser_read_string (parser);
245         if (name == NULL)
246           {
247             g_ptr_array_free (names, TRUE);
248             return FALSE;
249           }
250       }
251
252     g_ptr_array_add (names, name);
253   } while (_gtk_css_parser_try (parser, ",", TRUE));
254
255   /* NULL-terminate array */
256   g_ptr_array_add (names, NULL);
257   g_value_set_boxed (value, g_ptr_array_free (names, FALSE));
258   return TRUE;
259 }
260
261 static void
262 font_family_value_print (GtkCssStyleProperty *property,
263                          const GValue        *value,
264                          GString             *string)
265 {
266   const char **names = g_value_get_boxed (value);
267
268   if (names == NULL || *names == NULL)
269     {
270       g_string_append (string, "none");
271       return;
272     }
273
274   string_append_string (string, *names);
275   names++;
276   while (*names)
277     {
278       g_string_append (string, ", ");
279       string_append_string (string, *names);
280       names++;
281     }
282 }
283
284 static gboolean 
285 bindings_value_parse (GtkCssStyleProperty *property,
286                       GValue              *value,
287                       GtkCssParser        *parser,
288                       GFile               *base)
289 {
290   GPtrArray *array;
291   GtkBindingSet *binding_set;
292   char *name;
293
294   array = g_ptr_array_new ();
295
296   do {
297       name = _gtk_css_parser_try_ident (parser, TRUE);
298       if (name == NULL)
299         {
300           _gtk_css_parser_error (parser, "Not a valid binding name");
301           g_ptr_array_free (array, TRUE);
302           return FALSE;
303         }
304
305       binding_set = gtk_binding_set_find (name);
306
307       if (!binding_set)
308         {
309           _gtk_css_parser_error (parser, "No binding set named '%s'", name);
310           g_free (name);
311           continue;
312         }
313
314       g_ptr_array_add (array, binding_set);
315       g_free (name);
316     }
317   while (_gtk_css_parser_try (parser, ",", TRUE));
318
319   g_value_take_boxed (value, array);
320
321   return TRUE;
322 }
323
324 static void
325 bindings_value_print (GtkCssStyleProperty *property,
326                       const GValue        *value,
327                       GString             *string)
328 {
329   GPtrArray *array;
330   guint i;
331
332   array = g_value_get_boxed (value);
333
334   for (i = 0; i < array->len; i++)
335     {
336       GtkBindingSet *binding_set = g_ptr_array_index (array, i);
337
338       if (i > 0)
339         g_string_append (string, ", ");
340       g_string_append (string, binding_set->set_name);
341     }
342 }
343
344 static gboolean 
345 border_corner_radius_value_parse (GtkCssStyleProperty *property,
346                                   GValue              *value,
347                                   GtkCssParser        *parser,
348                                   GFile               *base)
349 {
350   GtkCssBorderCornerRadius corner;
351
352   if (!_gtk_css_parser_try_double (parser, &corner.horizontal))
353     {
354       _gtk_css_parser_error (parser, "Expected a number");
355       return FALSE;
356     }
357   else if (corner.horizontal < 0)
358     goto negative;
359
360   if (!_gtk_css_parser_try_double (parser, &corner.vertical))
361     corner.vertical = corner.horizontal;
362   else if (corner.vertical < 0)
363     goto negative;
364
365   g_value_set_boxed (value, &corner);
366   return TRUE;
367
368 negative:
369   _gtk_css_parser_error (parser, "Border radius values cannot be negative");
370   return FALSE;
371 }
372
373 static void
374 border_corner_radius_value_print (GtkCssStyleProperty *property,
375                                   const GValue        *value,
376                                   GString             *string)
377 {
378   GtkCssBorderCornerRadius *corner;
379
380   corner = g_value_get_boxed (value);
381
382   if (corner == NULL)
383     {
384       g_string_append (string, "none");
385       return;
386     }
387
388   string_append_double (string, corner->horizontal);
389   if (corner->horizontal != corner->vertical)
390     {
391       g_string_append_c (string, ' ');
392       string_append_double (string, corner->vertical);
393     }
394 }
395
396 static gboolean 
397 css_image_value_parse (GtkCssStyleProperty *property,
398                        GValue              *value,
399                        GtkCssParser        *parser,
400                        GFile               *base)
401 {
402   GtkCssImage *image;
403
404   if (_gtk_css_parser_try (parser, "none", TRUE))
405     image = NULL;
406   else
407     {
408       image = _gtk_css_image_new_parse (parser, base);
409       if (image == NULL)
410         return FALSE;
411     }
412
413   g_value_unset (value);
414   g_value_init (value, GTK_TYPE_CSS_IMAGE);
415   g_value_take_object (value, image);
416   return TRUE;
417 }
418
419 static void
420 css_image_value_print (GtkCssStyleProperty *property,
421                        const GValue        *value,
422                        GString             *string)
423 {
424   GtkCssImage *image = g_value_get_object (value);
425
426   if (image)
427     _gtk_css_image_print (image, string);
428   else
429     g_string_append (string, "none");
430 }
431
432 static void
433 css_image_value_compute (GtkCssStyleProperty    *property,
434                          GValue                 *computed,
435                          GtkStyleContext        *context,
436                          const GValue           *specified)
437 {
438   GtkCssImage *image = g_value_get_object (specified);
439
440   if (image)
441     image = _gtk_css_image_compute (image, context);
442
443   g_value_init (computed, GTK_TYPE_CSS_IMAGE);
444   g_value_take_object (computed, image);
445 }
446
447 static void
448 compute_border_width (GtkCssStyleProperty    *property,
449                       GValue                 *computed,
450                       GtkStyleContext        *context,
451                       const GValue           *specified)
452 {
453   GtkCssStyleProperty *style;
454   GtkBorderStyle border_style;
455   
456   /* The -1 is magic that is only true because we register the style
457    * properties directly after the width properties.
458    */
459   style = _gtk_css_style_property_lookup_by_id (_gtk_css_style_property_get_id (property) - 1);
460   border_style = g_value_get_enum (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
461
462   g_value_init (computed, G_TYPE_INT);
463   if (border_style == GTK_BORDER_STYLE_NONE ||
464       border_style == GTK_BORDER_STYLE_HIDDEN)
465     g_value_set_int (computed, 0);
466   else
467     g_value_copy (specified, computed);
468 }
469
470 static gboolean
471 background_repeat_value_parse (GtkCssStyleProperty *property,
472                                GValue              *value,
473                                GtkCssParser        *parser,
474                                GFile               *base)
475 {
476   int repeat, vertical;
477
478   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &repeat))
479     {
480       _gtk_css_parser_error (parser, "Not a valid value");
481       return FALSE;
482     }
483
484   if (repeat <= GTK_CSS_BACKGROUND_REPEAT_MASK)
485     {
486       if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
487         {
488           if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
489             {
490               _gtk_css_parser_error (parser, "Not a valid 2nd value");
491               return FALSE;
492             }
493           else
494             repeat |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
495         }
496       else
497         repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
498     }
499
500   g_value_set_enum (value, repeat);
501   return TRUE;
502 }
503
504 static void
505 background_repeat_value_print (GtkCssStyleProperty *property,
506                                const GValue        *value,
507                                GString             *string)
508 {
509   GEnumClass *enum_class;
510   GEnumValue *enum_value;
511   GtkCssBackgroundRepeat repeat;
512
513   repeat = g_value_get_enum (value);
514   enum_class = g_type_class_ref (GTK_TYPE_CSS_BACKGROUND_REPEAT);
515   enum_value = g_enum_get_value (enum_class, repeat);
516
517   /* only triggers for 'repeat-x' and 'repeat-y' */
518   if (enum_value)
519     g_string_append (string, enum_value->value_nick);
520   else
521     {
522       enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_HORIZONTAL (repeat));
523       g_string_append (string, enum_value->value_nick);
524
525       if (GTK_CSS_BACKGROUND_HORIZONTAL (repeat) != GTK_CSS_BACKGROUND_VERTICAL (repeat))
526         {
527           enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_VERTICAL (repeat));
528           g_string_append (string, " ");
529           g_string_append (string, enum_value->value_nick);
530         }
531     }
532
533   g_type_class_unref (enum_class);
534 }
535
536 /*** REGISTRATION ***/
537
538 #define rgba_init(rgba, r, g, b, a) G_STMT_START{ \
539   (rgba)->red = (r); \
540   (rgba)->green = (g); \
541   (rgba)->blue = (b); \
542   (rgba)->alpha = (a); \
543 }G_STMT_END
544 void
545 _gtk_css_style_property_init_properties (void)
546 {
547   GValue value = { 0, };
548   char *default_font_family[] = { "Sans", NULL };
549   GdkRGBA rgba;
550   GtkCssBorderCornerRadius no_corner_radius = { 0, };
551   GtkBorder border_of_ones = { 1, 1, 1, 1 };
552   GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
553
554   /* Initialize "color" and "font-size" first,
555    * so that when computing values later they are
556    * done first. That way, 'currentColor' and font
557    * sizes in em can be looked up properly */
558   rgba_init (&rgba, 1, 1, 1, 1);
559   gtk_style_property_register            ("color",
560                                           GDK_TYPE_RGBA,
561                                           GTK_STYLE_PROPERTY_INHERIT,
562                                           NULL,
563                                           NULL,
564                                           color_compute,
565                                           &rgba);
566   gtk_style_property_register            ("font-size",
567                                           G_TYPE_DOUBLE,
568                                           GTK_STYLE_PROPERTY_INHERIT,
569                                           NULL,
570                                           NULL,
571                                           NULL,
572                                           10.0);
573
574   /* properties that aren't referenced when computing values
575    * start here */
576   rgba_init (&rgba, 0, 0, 0, 0);
577   gtk_style_property_register            ("background-color",
578                                           GDK_TYPE_RGBA,
579                                           0,
580                                           NULL,
581                                           NULL,
582                                           color_compute,
583                                           &rgba);
584
585   gtk_style_property_register            ("font-family",
586                                           G_TYPE_STRV,
587                                           GTK_STYLE_PROPERTY_INHERIT,
588                                           font_family_parse,
589                                           font_family_value_print,
590                                           NULL,
591                                           default_font_family);
592   gtk_style_property_register            ("font-style",
593                                           PANGO_TYPE_STYLE,
594                                           GTK_STYLE_PROPERTY_INHERIT,
595                                           NULL,
596                                           NULL,
597                                           NULL,
598                                           PANGO_STYLE_NORMAL);
599   gtk_style_property_register            ("font-variant",
600                                           PANGO_TYPE_VARIANT,
601                                           GTK_STYLE_PROPERTY_INHERIT,
602                                           NULL,
603                                           NULL,
604                                           NULL,
605                                           PANGO_VARIANT_NORMAL);
606   /* xxx: need to parse this properly, ie parse the numbers */
607   gtk_style_property_register            ("font-weight",
608                                           PANGO_TYPE_WEIGHT,
609                                           GTK_STYLE_PROPERTY_INHERIT,
610                                           NULL,
611                                           NULL,
612                                           NULL,
613                                           PANGO_WEIGHT_NORMAL);
614
615   gtk_style_property_register            ("text-shadow",
616                                           GTK_TYPE_SHADOW,
617                                           GTK_STYLE_PROPERTY_INHERIT,
618                                           NULL,
619                                           NULL,
620                                           NULL,
621                                           NULL);
622
623   gtk_style_property_register            ("icon-shadow",
624                                           GTK_TYPE_SHADOW,
625                                           GTK_STYLE_PROPERTY_INHERIT,
626                                           NULL,
627                                           NULL,
628                                           NULL,
629                                           NULL);
630
631   gtk_style_property_register            ("box-shadow",
632                                           GTK_TYPE_SHADOW,
633                                           0,
634                                           NULL,
635                                           NULL,
636                                           NULL,
637                                           NULL);
638
639   gtk_style_property_register            ("margin-top",
640                                           G_TYPE_INT,
641                                           0,
642                                           NULL,
643                                           NULL,
644                                           NULL,
645                                           0);
646   gtk_style_property_register            ("margin-left",
647                                           G_TYPE_INT,
648                                           0,
649                                           NULL,
650                                           NULL,
651                                           NULL,
652                                           0);
653   gtk_style_property_register            ("margin-bottom",
654                                           G_TYPE_INT,
655                                           0,
656                                           NULL,
657                                           NULL,
658                                           NULL,
659                                           0);
660   gtk_style_property_register            ("margin-right",
661                                           G_TYPE_INT,
662                                           0,
663                                           NULL,
664                                           NULL,
665                                           NULL,
666                                           0);
667   gtk_style_property_register            ("padding-top",
668                                           G_TYPE_INT,
669                                           0,
670                                           NULL,
671                                           NULL,
672                                           NULL,
673                                           0);
674   gtk_style_property_register            ("padding-left",
675                                           G_TYPE_INT,
676                                           0,
677                                           NULL,
678                                           NULL,
679                                           NULL,
680                                           0);
681   gtk_style_property_register            ("padding-bottom",
682                                           G_TYPE_INT,
683                                           0,
684                                           NULL,
685                                           NULL,
686                                           NULL,
687                                           0);
688   gtk_style_property_register            ("padding-right",
689                                           G_TYPE_INT,
690                                           0,
691                                           NULL,
692                                           NULL,
693                                           NULL,
694                                           0);
695   /* IMPORTANT: compute_border_width() requires that the border-width
696    * properties be immeditaly followed by the border-style properties
697    */
698   gtk_style_property_register            ("border-top-style",
699                                           GTK_TYPE_BORDER_STYLE,
700                                           0,
701                                           NULL,
702                                           NULL,
703                                           NULL,
704                                           GTK_BORDER_STYLE_NONE);
705   gtk_style_property_register            ("border-top-width",
706                                           G_TYPE_INT,
707                                           0,
708                                           NULL,
709                                           NULL,
710                                           compute_border_width,
711                                           0);
712   gtk_style_property_register            ("border-left-style",
713                                           GTK_TYPE_BORDER_STYLE,
714                                           0,
715                                           NULL,
716                                           NULL,
717                                           NULL,
718                                           GTK_BORDER_STYLE_NONE);
719   gtk_style_property_register            ("border-left-width",
720                                           G_TYPE_INT,
721                                           0,
722                                           NULL,
723                                           NULL,
724                                           compute_border_width,
725                                           0);
726   gtk_style_property_register            ("border-bottom-style",
727                                           GTK_TYPE_BORDER_STYLE,
728                                           0,
729                                           NULL,
730                                           NULL,
731                                           NULL,
732                                           GTK_BORDER_STYLE_NONE);
733   gtk_style_property_register            ("border-bottom-width",
734                                           G_TYPE_INT,
735                                           0,
736                                           NULL,
737                                           NULL,
738                                           compute_border_width,
739                                           0);
740   gtk_style_property_register            ("border-right-style",
741                                           GTK_TYPE_BORDER_STYLE,
742                                           0,
743                                           NULL,
744                                           NULL,
745                                           NULL,
746                                           GTK_BORDER_STYLE_NONE);
747   gtk_style_property_register            ("border-right-width",
748                                           G_TYPE_INT,
749                                           0,
750                                           NULL,
751                                           NULL,
752                                           compute_border_width,
753                                           0);
754
755   gtk_style_property_register            ("border-top-left-radius",
756                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
757                                           0,
758                                           border_corner_radius_value_parse,
759                                           border_corner_radius_value_print,
760                                           NULL,
761                                           &no_corner_radius);
762   gtk_style_property_register            ("border-top-right-radius",
763                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
764                                           0,
765                                           border_corner_radius_value_parse,
766                                           border_corner_radius_value_print,
767                                           NULL,
768                                           &no_corner_radius);
769   gtk_style_property_register            ("border-bottom-right-radius",
770                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
771                                           0,
772                                           border_corner_radius_value_parse,
773                                           border_corner_radius_value_print,
774                                           NULL,
775                                           &no_corner_radius);
776   gtk_style_property_register            ("border-bottom-left-radius",
777                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
778                                           0,
779                                           border_corner_radius_value_parse,
780                                           border_corner_radius_value_print,
781                                           NULL,
782                                           &no_corner_radius);
783
784   gtk_style_property_register            ("outline-style",
785                                           GTK_TYPE_BORDER_STYLE,
786                                           0,
787                                           NULL,
788                                           NULL,
789                                           NULL,
790                                           GTK_BORDER_STYLE_NONE);
791   gtk_style_property_register            ("outline-width",
792                                           G_TYPE_INT,
793                                           0,
794                                           NULL,
795                                           NULL,
796                                           compute_border_width,
797                                           0);
798   gtk_style_property_register            ("outline-offset",
799                                           G_TYPE_INT,
800                                           0,
801                                           NULL,
802                                           NULL,
803                                           NULL,
804                                           0);
805
806   gtk_style_property_register            ("background-clip",
807                                           GTK_TYPE_CSS_AREA,
808                                           0,
809                                           NULL,
810                                           NULL,
811                                           NULL,
812                                           GTK_CSS_AREA_BORDER_BOX);
813                                         
814   gtk_style_property_register            ("background-origin",
815                                           GTK_TYPE_CSS_AREA,
816                                           0,
817                                           NULL,
818                                           NULL,
819                                           NULL,
820                                           GTK_CSS_AREA_PADDING_BOX);
821
822   g_value_init (&value, GTK_TYPE_CSS_SPECIAL_VALUE);
823   g_value_set_enum (&value, GTK_CSS_CURRENT_COLOR);
824   _gtk_style_property_register           ("border-top-color",
825                                           GDK_TYPE_RGBA,
826                                           0,
827                                           NULL,
828                                           NULL,
829                                           color_compute,
830                                           &value);
831   _gtk_style_property_register           ("border-right-color",
832                                           GDK_TYPE_RGBA,
833                                           0,
834                                           NULL,
835                                           NULL,
836                                           color_compute,
837                                           &value);
838   _gtk_style_property_register           ("border-bottom-color",
839                                           GDK_TYPE_RGBA,
840                                           0,
841                                           NULL,
842                                           NULL,
843                                           color_compute,
844                                           &value);
845   _gtk_style_property_register           ("border-left-color",
846                                           GDK_TYPE_RGBA,
847                                           0,
848                                           NULL,
849                                           NULL,
850                                           color_compute,
851                                           &value);
852   _gtk_style_property_register           ("outline-color",
853                                           GDK_TYPE_RGBA,
854                                           0,
855                                           NULL,
856                                           NULL,
857                                           color_compute,
858                                           &value);
859   g_value_unset (&value);
860
861   gtk_style_property_register            ("background-repeat",
862                                           GTK_TYPE_CSS_BACKGROUND_REPEAT,
863                                           0,
864                                           background_repeat_value_parse,
865                                           background_repeat_value_print,
866                                           NULL,
867                                           GTK_CSS_BACKGROUND_REPEAT | (GTK_CSS_BACKGROUND_REPEAT << GTK_CSS_BACKGROUND_REPEAT_SHIFT));
868   g_value_init (&value, GTK_TYPE_CSS_IMAGE);
869   _gtk_style_property_register           ("background-image",
870                                           CAIRO_GOBJECT_TYPE_PATTERN,
871                                           0,
872                                           css_image_value_parse,
873                                           css_image_value_print,
874                                           css_image_value_compute,
875                                           &value);
876
877   _gtk_style_property_register           ("border-image-source",
878                                           CAIRO_GOBJECT_TYPE_PATTERN,
879                                           0,
880                                           css_image_value_parse,
881                                           css_image_value_print,
882                                           css_image_value_compute,
883                                           &value);
884   g_value_unset (&value);
885   gtk_style_property_register            ("border-image-repeat",
886                                           GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
887                                           0,
888                                           NULL,
889                                           NULL,
890                                           NULL,
891                                           &border_image_repeat);
892
893   /* XXX: The initial vaue is wrong, it should be 100% */
894   gtk_style_property_register            ("border-image-slice",
895                                           GTK_TYPE_BORDER,
896                                           0,
897                                           NULL,
898                                           NULL,
899                                           NULL,
900                                           &border_of_ones);
901   gtk_style_property_register            ("border-image-width",
902                                           GTK_TYPE_BORDER,
903                                           0,
904                                           NULL,
905                                           NULL,
906                                           NULL,
907                                           NULL);
908   gtk_style_property_register            ("engine",
909                                           GTK_TYPE_THEMING_ENGINE,
910                                           0,
911                                           NULL,
912                                           NULL,
913                                           NULL,
914                                           gtk_theming_engine_load (NULL));
915   gtk_style_property_register            ("transition",
916                                           GTK_TYPE_ANIMATION_DESCRIPTION,
917                                           0,
918                                           NULL,
919                                           NULL,
920                                           NULL,
921                                           NULL);
922
923   /* Private property holding the binding sets */
924   gtk_style_property_register            ("gtk-key-bindings",
925                                           G_TYPE_PTR_ARRAY,
926                                           0,
927                                           bindings_value_parse,
928                                           bindings_value_print,
929                                           NULL,
930                                           NULL);
931 }
932