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