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