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