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