]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssstylepropertyimpl.c
cssvalue: Add a custom RGBA value
[~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 "gtkcssimagegradientprivate.h"
44 #include "gtkcssimageprivate.h"
45 #include "gtkcssimageprivate.h"
46 #include "gtkcssnumbervalueprivate.h"
47 #include "gtkcssrgbavalueprivate.h"
48 #include "gtkcssshadowvalueprivate.h"
49 #include "gtksymboliccolorprivate.h"
50 #include "gtkthemingengine.h"
51 #include "gtktypebuiltins.h"
52 #include "gtkwin32themeprivate.h"
53
54 /*** REGISTRATION ***/
55
56 static void
57 gtk_css_style_property_register (const char *                   name,
58                                  GType                          value_type,
59                                  GtkStylePropertyFlags          flags,
60                                  GtkCssStylePropertyParseFunc   parse_value,
61                                  GtkCssStylePropertyPrintFunc   print_value,
62                                  GtkCssStylePropertyComputeFunc compute_value,
63                                  GtkCssStylePropertyQueryFunc   query_value,
64                                  GtkCssStylePropertyAssignFunc  assign_value,
65                                  GtkCssStylePropertyEqualFunc   equal_func,
66                                  GtkCssValue *                  initial_value)
67 {
68   GtkCssStyleProperty *node;
69
70   g_assert (initial_value != NULL);
71   g_assert (parse_value != NULL);
72   g_assert (value_type == G_TYPE_NONE || query_value != NULL);
73   g_assert (value_type == G_TYPE_NONE || assign_value != NULL);
74
75   node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
76                        "value-type", value_type,
77                        "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
78                        "initial-value", initial_value,
79                        "name", name,
80                        NULL);
81   
82   node->parse_value = parse_value;
83   if (print_value)
84     node->print_value = print_value;
85   if (compute_value)
86     node->compute_value = compute_value;
87   node->query_value = query_value;
88   node->assign_value = assign_value;
89   if (equal_func)
90     node->equal_func = equal_func;
91
92   _gtk_css_value_unref (initial_value);
93 }
94
95 /*** HELPERS ***/
96
97 static void
98 string_append_string (GString    *str,
99                       const char *string)
100 {
101   gsize len;
102
103   g_string_append_c (str, '"');
104
105   do {
106     len = strcspn (string, "\"\n\r\f");
107     g_string_append (str, string);
108     string += len;
109     switch (*string)
110       {
111       case '\0':
112         break;
113       case '\n':
114         g_string_append (str, "\\A ");
115         break;
116       case '\r':
117         g_string_append (str, "\\D ");
118         break;
119       case '\f':
120         g_string_append (str, "\\C ");
121         break;
122       case '\"':
123         g_string_append (str, "\\\"");
124         break;
125       default:
126         g_assert_not_reached ();
127         break;
128       }
129   } while (*string);
130
131   g_string_append_c (str, '"');
132 }
133
134 /*** IMPLEMENTATIONS ***/
135
136 static void
137 query_simple (GtkCssStyleProperty *property,
138               const GtkCssValue   *css_value,
139               GValue              *value)
140 {
141   _gtk_css_value_init_gvalue (css_value, value);
142 }
143
144 static GtkCssValue *
145 assign_simple (GtkCssStyleProperty *property,
146               const GValue        *value)
147 {
148   return _gtk_css_value_new_from_gvalue (value);
149 }
150
151 static void
152 query_length_as_int (GtkCssStyleProperty *property,
153                      const GtkCssValue   *css_value,
154                      GValue              *value)
155 {
156   g_value_init (value, G_TYPE_INT);
157   g_value_set_int (value, round (_gtk_css_number_value_get (css_value, 100)));
158 }
159
160 static GtkCssValue *
161 assign_length_from_int (GtkCssStyleProperty *property,
162                         const GValue        *value)
163 {
164   return _gtk_css_number_value_new (g_value_get_int (value), GTK_CSS_PX);
165 }
166
167 static GtkCssValue *
168 color_parse (GtkCssStyleProperty *property,
169              GtkCssParser        *parser,
170              GFile               *base)
171 {
172   GtkSymbolicColor *symbolic;
173
174   if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
175     {
176       symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
177     }
178   else
179     {
180       symbolic = _gtk_css_parser_read_symbolic_color (parser);
181       if (symbolic == NULL)
182         return NULL;
183     }
184
185   return _gtk_css_value_new_take_symbolic_color (symbolic);
186 }
187
188 static GtkCssValue *
189 color_compute (GtkCssStyleProperty    *property,
190                GtkStyleContext        *context,
191                GtkCssValue            *specified)
192 {
193   return _gtk_css_rgba_value_compute_from_symbolic (specified,
194                                                     _gtk_css_style_property_get_initial_value (property),
195                                                     context,
196                                                     FALSE);
197 }
198
199 static GtkCssValue *
200 color_property_compute (GtkCssStyleProperty    *property,
201                         GtkStyleContext        *context,
202                         GtkCssValue            *specified)
203 {
204   GtkCssValue *value;
205
206   value = _gtk_css_rgba_value_compute_from_symbolic (specified,
207                                                     _gtk_css_style_property_get_initial_value (property),
208                                                     context,
209                                                     TRUE);
210   _gtk_css_rgba_value_get_rgba (value);
211   return value;
212 }
213
214 static void
215 color_query (GtkCssStyleProperty *property,
216              const GtkCssValue   *css_value,
217              GValue              *value)
218 {
219   g_value_init (value, GDK_TYPE_RGBA);
220   g_value_set_boxed (value, _gtk_css_rgba_value_get_rgba (css_value));
221 }
222
223 static GtkCssValue *
224 color_assign (GtkCssStyleProperty *property,
225               const GValue        *value)
226 {
227   return _gtk_css_rgba_value_new_from_rgba (g_value_get_boxed (value));
228 }
229
230 static GtkCssValue *
231 font_family_parse (GtkCssStyleProperty *property,
232                    GtkCssParser        *parser,
233                    GFile               *base)
234 {
235   GPtrArray *names;
236   char *name;
237
238   /* We don't special case generic families. Pango should do
239    * that for us */
240
241   names = g_ptr_array_new ();
242
243   do {
244     name = _gtk_css_parser_try_ident (parser, TRUE);
245     if (name)
246       {
247         GString *string = g_string_new (name);
248         g_free (name);
249         while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
250           {
251             g_string_append_c (string, ' ');
252             g_string_append (string, name);
253             g_free (name);
254           }
255         name = g_string_free (string, FALSE);
256       }
257     else 
258       {
259         name = _gtk_css_parser_read_string (parser);
260         if (name == NULL)
261           {
262             g_ptr_array_free (names, TRUE);
263             return FALSE;
264           }
265       }
266
267     g_ptr_array_add (names, name);
268   } while (_gtk_css_parser_try (parser, ",", TRUE));
269
270   /* NULL-terminate array */
271   g_ptr_array_add (names, NULL);
272   return _gtk_css_value_new_take_strv ((char **) g_ptr_array_free (names, FALSE));
273 }
274
275 static void
276 font_family_value_print (GtkCssStyleProperty *property,
277                          const GtkCssValue   *value,
278                          GString             *string)
279 {
280   const char **names = _gtk_css_value_get_strv (value);
281
282   if (names == NULL || *names == NULL)
283     {
284       g_string_append (string, "none");
285       return;
286     }
287
288   string_append_string (string, *names);
289   names++;
290   while (*names)
291     {
292       g_string_append (string, ", ");
293       string_append_string (string, *names);
294       names++;
295     }
296 }
297
298 static GtkCssValue *
299 parse_pango_style (GtkCssStyleProperty *property,
300                    GtkCssParser        *parser,
301                    GFile               *base)
302 {
303   int value;
304
305   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_STYLE, &value))
306     {
307       _gtk_css_parser_error (parser, "unknown value for property");
308       return NULL;
309     }
310
311   return _gtk_css_value_new_from_enum (PANGO_TYPE_STYLE, value);
312 }
313
314 static GtkCssValue *
315 parse_pango_weight (GtkCssStyleProperty *property,
316                     GtkCssParser        *parser,
317                     GFile               *base)
318 {
319   int value;
320
321   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_WEIGHT, &value))
322     {
323       _gtk_css_parser_error (parser, "unknown value for property");
324       return NULL;
325     }
326
327   return _gtk_css_value_new_from_enum (PANGO_TYPE_WEIGHT, value);
328 }
329
330 static GtkCssValue *
331 parse_pango_variant (GtkCssStyleProperty *property,
332                      GtkCssParser        *parser,
333                      GFile               *base)
334 {
335   int value;
336
337   if (!_gtk_css_parser_try_enum (parser, PANGO_TYPE_VARIANT, &value))
338     {
339       _gtk_css_parser_error (parser, "unknown value for property");
340       return NULL;
341     }
342
343   return _gtk_css_value_new_from_enum (PANGO_TYPE_VARIANT, value);
344 }
345
346 static GtkCssValue *
347 parse_border_style (GtkCssStyleProperty *property,
348                     GtkCssParser        *parser,
349                     GFile               *base)
350 {
351   int value;
352
353   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &value))
354     {
355       _gtk_css_parser_error (parser, "unknown value for property");
356       return NULL;
357     }
358
359   return _gtk_css_value_new_from_enum (GTK_TYPE_BORDER_STYLE, value);
360 }
361
362 static GtkCssValue *
363 parse_css_area (GtkCssStyleProperty *property,
364                 GtkCssParser        *parser,
365                 GFile               *base)
366 {
367   int value;
368
369   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_AREA, &value))
370     {
371       _gtk_css_parser_error (parser, "unknown value for property");
372       return NULL;
373     }
374
375   return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, value);
376 }
377
378 static GtkCssValue *
379 bindings_value_parse (GtkCssStyleProperty *property,
380                       GtkCssParser        *parser,
381                       GFile               *base)
382 {
383   GPtrArray *array;
384   GtkBindingSet *binding_set;
385   char *name;
386
387   array = g_ptr_array_new ();
388
389   do {
390       name = _gtk_css_parser_try_ident (parser, TRUE);
391       if (name == NULL)
392         {
393           _gtk_css_parser_error (parser, "Not a valid binding name");
394           g_ptr_array_free (array, TRUE);
395           return FALSE;
396         }
397
398       binding_set = gtk_binding_set_find (name);
399
400       if (!binding_set)
401         {
402           _gtk_css_parser_error (parser, "No binding set named '%s'", name);
403           g_free (name);
404           continue;
405         }
406
407       g_ptr_array_add (array, binding_set);
408       g_free (name);
409     }
410   while (_gtk_css_parser_try (parser, ",", TRUE));
411
412   return _gtk_css_value_new_take_binding_sets (array);
413 }
414
415 static void
416 bindings_value_print (GtkCssStyleProperty *property,
417                       const GtkCssValue   *value,
418                       GString             *string)
419 {
420   GPtrArray *array;
421   guint i;
422
423   array = _gtk_css_value_get_boxed (value);
424
425   for (i = 0; i < array->len; i++)
426     {
427       GtkBindingSet *binding_set = g_ptr_array_index (array, i);
428
429       if (i > 0)
430         g_string_append (string, ", ");
431       g_string_append (string, binding_set->set_name);
432     }
433 }
434
435 static GtkCssValue *
436 shadow_value_parse (GtkCssStyleProperty *property,
437                     GtkCssParser        *parser,
438                     GFile               *base)
439 {
440   return _gtk_css_shadow_value_parse (parser);
441 }
442
443 static GtkCssValue *
444 shadow_value_compute (GtkCssStyleProperty *property,
445                       GtkStyleContext     *context,
446                       GtkCssValue         *specified)
447 {
448   return _gtk_css_shadow_value_compute (specified, context);
449 }
450
451 static GtkCssValue *
452 border_corner_radius_value_parse (GtkCssStyleProperty *property,
453                                   GtkCssParser        *parser,
454                                   GFile               *base)
455 {
456   GtkCssBorderCornerRadius corner;
457
458   if (!_gtk_css_parser_read_number (parser,
459                                     &corner.horizontal,
460                                     GTK_CSS_POSITIVE_ONLY
461                                     | GTK_CSS_PARSE_PERCENT
462                                     | GTK_CSS_NUMBER_AS_PIXELS
463                                     | GTK_CSS_PARSE_LENGTH))
464     return FALSE;
465
466   if (!_gtk_css_parser_has_number (parser))
467     corner.vertical = corner.horizontal;
468   else if (!_gtk_css_parser_read_number (parser,
469                                          &corner.vertical,
470                                          GTK_CSS_POSITIVE_ONLY
471                                          | GTK_CSS_PARSE_PERCENT
472                                          | GTK_CSS_NUMBER_AS_PIXELS
473                                          | GTK_CSS_PARSE_LENGTH))
474     return FALSE;
475
476   return _gtk_css_value_new_from_border_corner_radius (&corner);
477 }
478
479 static void
480 border_corner_radius_value_print (GtkCssStyleProperty *property,
481                                   const GtkCssValue   *value,
482                                   GString             *string)
483 {
484   const GtkCssBorderCornerRadius *corner;
485
486   corner = _gtk_css_value_get_border_corner_radius (value);
487
488   _gtk_css_number_print (&corner->horizontal, string);
489
490   if (!_gtk_css_number_equal (&corner->horizontal, &corner->vertical))
491     {
492       g_string_append_c (string, ' ');
493       _gtk_css_number_print (&corner->vertical, string);
494     }
495 }
496
497 static GtkCssValue *
498 css_image_value_parse (GtkCssStyleProperty *property,
499                        GtkCssParser        *parser,
500                        GFile               *base)
501 {
502   GtkCssImage *image;
503
504   if (_gtk_css_parser_try (parser, "none", TRUE))
505     image = NULL;
506   else
507     {
508       image = _gtk_css_image_new_parse (parser, base);
509       if (image == NULL)
510         return FALSE;
511     }
512
513   return _gtk_css_value_new_take_image (image);
514 }
515
516 static void
517 css_image_value_print (GtkCssStyleProperty *property,
518                        const GtkCssValue   *value,
519                        GString             *string)
520 {
521   GtkCssImage *image = _gtk_css_value_get_image (value);
522
523   if (image)
524     _gtk_css_image_print (image, string);
525   else
526     g_string_append (string, "none");
527 }
528
529 static GtkCssValue *
530 css_image_value_compute (GtkCssStyleProperty    *property,
531                          GtkStyleContext        *context,
532                          GtkCssValue            *specified)
533 {
534   GtkCssImage *image, *computed;
535   
536   image = _gtk_css_value_get_image (specified);
537
538   if (image == NULL)
539     return _gtk_css_value_ref (specified);
540
541   computed = _gtk_css_image_compute (image, context);
542
543   if (computed == image)
544     {
545       g_object_unref (computed);
546       return _gtk_css_value_ref (specified);
547     }
548
549   return _gtk_css_value_new_take_image (computed);
550 }
551
552 static void
553 css_image_value_query (GtkCssStyleProperty *property,
554                        const GtkCssValue   *css_value,
555                        GValue              *value)
556 {
557   GtkCssImage *image = _gtk_css_value_get_image (css_value);
558   cairo_pattern_t *pattern;
559   cairo_surface_t *surface;
560   cairo_matrix_t matrix;
561   
562   g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
563
564   if (GTK_IS_CSS_IMAGE_GRADIENT (image))
565     g_value_set_boxed (value, GTK_CSS_IMAGE_GRADIENT (image)->pattern);
566   else if (image != NULL)
567     {
568       double width, height;
569
570       /* the 100, 100 is rather random */
571       _gtk_css_image_get_concrete_size (image, 0, 0, 100, 100, &width, &height);
572       surface = _gtk_css_image_get_surface (image, NULL, width, height);
573       pattern = cairo_pattern_create_for_surface (surface);
574       cairo_matrix_init_scale (&matrix, width, height);
575       cairo_pattern_set_matrix (pattern, &matrix);
576       cairo_surface_destroy (surface);
577       g_value_take_boxed (value, pattern);
578     }
579 }
580
581 static GtkCssValue *
582 css_image_value_assign (GtkCssStyleProperty *property,
583                         const GValue        *value)
584 {
585   g_warning ("FIXME: assigning images is not implemented");
586   return _gtk_css_value_new_take_image (NULL);
587 }
588
589 static GtkCssValue *
590 font_size_parse (GtkCssStyleProperty *property,
591                  GtkCssParser        *parser,
592                  GFile               *base)
593 {
594   gdouble d;
595
596   if (!_gtk_css_parser_try_double (parser, &d))
597     {
598       _gtk_css_parser_error (parser, "Expected a number");
599       return NULL;
600     }
601
602   return _gtk_css_value_new_from_double (d);
603 }
604
605 static GtkCssValue *
606 outline_parse (GtkCssStyleProperty *property,
607                GtkCssParser        *parser,
608                GFile               *base)
609 {
610   int i;
611
612   if (!_gtk_css_parser_try_int (parser, &i))
613     {
614       _gtk_css_parser_error (parser, "Expected an integer");
615       return NULL;
616     }
617
618   return _gtk_css_value_new_from_int (i);
619 }
620
621 static GtkCssValue *
622 border_image_repeat_parse (GtkCssStyleProperty *property,
623                            GtkCssParser        *parser,
624                            GFile               *base)
625 {
626   GValue value = G_VALUE_INIT;
627   GtkCssValue *result;
628
629   g_value_init (&value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
630   if (!_gtk_css_style_parse_value (&value, parser, base))
631     {
632       g_value_unset (&value);
633       return NULL;
634     }
635
636   result = _gtk_css_value_new_from_gvalue (&value);
637   g_value_unset (&value);
638
639   return result;
640 }
641
642 static GtkCssValue *
643 border_image_slice_parse (GtkCssStyleProperty *property,
644                           GtkCssParser        *parser,
645                           GFile               *base)
646 {
647   GValue value = G_VALUE_INIT;
648   GtkCssValue *result;
649
650   g_value_init (&value, GTK_TYPE_BORDER);
651   if (!_gtk_css_style_parse_value (&value, parser, base))
652     {
653       g_value_unset (&value);
654       return NULL;
655     }
656
657   result = _gtk_css_value_new_from_gvalue (&value);
658   g_value_unset (&value);
659
660   return result;
661 }
662
663 static GtkCssValue *
664 border_image_width_parse (GtkCssStyleProperty *property,
665                           GtkCssParser        *parser,
666                           GFile               *base)
667 {
668   GValue value = G_VALUE_INIT;
669   GtkCssValue *result;
670
671   g_value_init (&value, GTK_TYPE_BORDER);
672   if (!_gtk_css_style_parse_value (&value, parser, base))
673     {
674       g_value_unset (&value);
675       return NULL;
676     }
677
678   result = _gtk_css_value_new_from_gvalue (&value);
679   g_value_unset (&value);
680
681   return result;
682 }
683
684 static GtkCssValue *
685 engine_parse (GtkCssStyleProperty *property,
686               GtkCssParser        *parser,
687               GFile               *base)
688 {
689   GtkThemingEngine *engine;
690   char *str;
691
692   if (_gtk_css_parser_try (parser, "none", TRUE))
693     return _gtk_css_value_new_from_theming_engine (gtk_theming_engine_load (NULL));
694
695   str = _gtk_css_parser_try_ident (parser, TRUE);
696   if (str == NULL)
697     {
698       _gtk_css_parser_error (parser, "Expected a valid theme name");
699       return NULL;
700     }
701
702   engine = gtk_theming_engine_load (str);
703
704   if (engine == NULL)
705     {
706       _gtk_css_parser_error (parser, "Theming engine '%s' not found", str);
707       g_free (str);
708       return NULL;
709     }
710
711   g_free (str);
712
713   return _gtk_css_value_new_from_theming_engine (engine);
714 }
715
716 static GtkCssValue *
717 transition_parse (GtkCssStyleProperty *property,
718                   GtkCssParser        *parser,
719                   GFile               *base)
720 {
721   GValue value = G_VALUE_INIT;
722   GtkCssValue *result;
723
724   g_value_init (&value, GTK_TYPE_ANIMATION_DESCRIPTION);
725   if (!_gtk_css_style_parse_value (&value, parser, base))
726     {
727       g_value_unset (&value);
728       return NULL;
729     }
730
731   result = _gtk_css_value_new_from_gvalue (&value);
732   g_value_unset (&value);
733
734   return result;
735 }
736
737 static GtkCssValue *
738 parse_margin (GtkCssStyleProperty *property,
739               GtkCssParser        *parser,
740               GFile               *base)
741 {
742   return _gtk_css_number_value_parse (parser,
743                                       GTK_CSS_NUMBER_AS_PIXELS
744                                       | GTK_CSS_PARSE_LENGTH);
745 }
746
747 static GtkCssValue *
748 compute_margin (GtkCssStyleProperty *property,
749                 GtkStyleContext     *context,
750                 GtkCssValue         *specified)
751 {
752   return _gtk_css_number_value_compute (specified, context);
753 }
754
755 static GtkCssValue *
756 parse_padding (GtkCssStyleProperty *property,
757                GtkCssParser        *parser,
758                GFile               *base)
759 {
760   return _gtk_css_number_value_parse (parser,
761                                       GTK_CSS_POSITIVE_ONLY
762                                       | GTK_CSS_NUMBER_AS_PIXELS
763                                       | GTK_CSS_PARSE_LENGTH);
764 }
765
766 static GtkCssValue *
767 compute_padding (GtkCssStyleProperty *property,
768                  GtkStyleContext     *context,
769                  GtkCssValue         *specified)
770 {
771   return _gtk_css_number_value_compute (specified, context);
772 }
773
774 static GtkCssValue *
775 parse_border_width (GtkCssStyleProperty *property,
776                     GtkCssParser        *parser,
777                     GFile               *base)
778 {
779   return _gtk_css_number_value_parse (parser,
780                                       GTK_CSS_POSITIVE_ONLY
781                                       | GTK_CSS_NUMBER_AS_PIXELS
782                                       | GTK_CSS_PARSE_LENGTH);
783 }
784
785 static GtkCssValue *
786 compute_border_width (GtkCssStyleProperty    *property,
787                       GtkStyleContext        *context,
788                       GtkCssValue            *specified)
789 {
790   GtkCssStyleProperty *style;
791   GtkBorderStyle border_style;
792   
793   /* The -1 is magic that is only true because we register the style
794    * properties directly after the width properties.
795    */
796   style = _gtk_css_style_property_lookup_by_id (_gtk_css_style_property_get_id (property) - 1);
797   
798   border_style = _gtk_css_value_get_border_style (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
799
800   if (border_style == GTK_BORDER_STYLE_NONE ||
801       border_style == GTK_BORDER_STYLE_HIDDEN)
802     return _gtk_css_number_value_new (0, GTK_CSS_PX);
803   else
804     return _gtk_css_number_value_compute (specified, context);
805 }
806
807 static GtkCssValue *
808 background_repeat_value_parse (GtkCssStyleProperty *property,
809                                GtkCssParser        *parser,
810                                GFile               *base)
811 {
812   int repeat, vertical;
813
814   if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &repeat))
815     {
816       _gtk_css_parser_error (parser, "Not a valid value");
817       return FALSE;
818     }
819
820   if (repeat <= GTK_CSS_BACKGROUND_REPEAT_MASK)
821     {
822       if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
823         {
824           if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
825             {
826               _gtk_css_parser_error (parser, "Not a valid 2nd value");
827               return FALSE;
828             }
829           else
830             repeat |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
831         }
832       else
833         repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
834     }
835
836   return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, repeat);
837 }
838
839 static void
840 background_repeat_value_print (GtkCssStyleProperty *property,
841                                const GtkCssValue   *value,
842                                GString             *string)
843 {
844   GEnumClass *enum_class;
845   GEnumValue *enum_value;
846   GtkCssBackgroundRepeat repeat;
847
848   repeat = _gtk_css_value_get_enum (value);
849   enum_class = g_type_class_ref (GTK_TYPE_CSS_BACKGROUND_REPEAT);
850   enum_value = g_enum_get_value (enum_class, repeat);
851
852   /* only triggers for 'repeat-x' and 'repeat-y' */
853   if (enum_value)
854     g_string_append (string, enum_value->value_nick);
855   else
856     {
857       enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_HORIZONTAL (repeat));
858       g_string_append (string, enum_value->value_nick);
859
860       if (GTK_CSS_BACKGROUND_HORIZONTAL (repeat) != GTK_CSS_BACKGROUND_VERTICAL (repeat))
861         {
862           enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_VERTICAL (repeat));
863           g_string_append (string, " ");
864           g_string_append (string, enum_value->value_nick);
865         }
866     }
867
868   g_type_class_unref (enum_class);
869 }
870
871 static GtkCssValue *
872 background_size_parse (GtkCssStyleProperty *property,
873                        GtkCssParser        *parser,
874                        GFile               *base)
875 {
876   GtkCssBackgroundSize size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE};
877
878   if (_gtk_css_parser_try (parser, "cover", TRUE))
879     size.cover = TRUE;
880   else if (_gtk_css_parser_try (parser, "contain", TRUE))
881     size.contain = TRUE;
882   else
883     {
884       if (_gtk_css_parser_try (parser, "auto", TRUE))
885         _gtk_css_number_init (&size.width, 0, GTK_CSS_PX);
886       else if (!_gtk_css_parser_read_number (parser,
887                                              &size.width,
888                                              GTK_CSS_POSITIVE_ONLY
889                                              | GTK_CSS_PARSE_PERCENT
890                                              | GTK_CSS_PARSE_LENGTH))
891         return NULL;
892
893       if (_gtk_css_parser_try (parser, "auto", TRUE))
894         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
895       else if (_gtk_css_parser_has_number (parser))
896         {
897           if (!_gtk_css_parser_read_number (parser,
898                                             &size.height,
899                                             GTK_CSS_POSITIVE_ONLY
900                                             | GTK_CSS_PARSE_PERCENT
901                                             | GTK_CSS_PARSE_LENGTH))
902             return NULL;
903         }
904       else
905         _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
906     }
907
908   return _gtk_css_value_new_from_background_size (&size);
909 }
910
911 static void
912 background_size_print (GtkCssStyleProperty *property,
913                        const GtkCssValue   *value,
914                        GString             *string)
915 {
916   const GtkCssBackgroundSize *size = _gtk_css_value_get_background_size (value);
917
918   if (size->cover)
919     g_string_append (string, "cover");
920   else if (size->contain)
921     g_string_append (string, "contain");
922   else
923     {
924       if (size->width.value == 0)
925         g_string_append (string, "auto");
926       else
927         _gtk_css_number_print (&size->width, string);
928
929       if (size->height.value != 0)
930         {
931           g_string_append (string, " ");
932           _gtk_css_number_print (&size->height, string);
933         }
934     }
935 }
936
937 static GtkCssValue *
938 background_size_compute (GtkCssStyleProperty    *property,
939                          GtkStyleContext        *context,
940                          GtkCssValue            *specified)
941 {
942   const GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
943   GtkCssBackgroundSize csize;
944   gboolean changed;
945
946   csize.cover = ssize->cover;
947   csize.contain = ssize->contain;
948   changed = _gtk_css_number_compute (&csize.width,
949                                      &ssize->width,
950                                      context);
951   changed |= _gtk_css_number_compute (&csize.height,
952                                       &ssize->height,
953                                       context);
954   if (changed)
955     return _gtk_css_value_new_from_background_size (&csize);
956   return _gtk_css_value_ref (specified);
957 }
958
959 static GtkCssValue *
960 background_position_parse (GtkCssStyleProperty *property,
961                            GtkCssParser        *parser,
962                            GFile               *base)
963 {
964   static const struct {
965     const char *name;
966     guint       percentage;
967     gboolean    horizontal;
968     gboolean    vertical;
969   } names[] = {
970     { "left",     0, TRUE,  FALSE },
971     { "right",  100, TRUE,  FALSE },
972     { "center",  50, TRUE,  TRUE  },
973     { "top",      0, FALSE, TRUE  },
974     { "bottom", 100, FALSE, TRUE  },
975     { NULL    ,   0, TRUE,  FALSE }, /* used for numbers */
976     { NULL    ,  50, TRUE,  TRUE  }  /* used for no value */
977   };
978   GtkCssBackgroundPosition pos;
979   GtkCssNumber *missing;
980   guint first, second;
981
982   for (first = 0; names[first].name != NULL; first++)
983     {
984       if (_gtk_css_parser_try (parser, names[first].name, TRUE))
985         {
986           if (names[first].horizontal)
987             {
988               _gtk_css_number_init (&pos.x, names[first].percentage, GTK_CSS_PERCENT);
989               missing = &pos.y;
990             }
991           else
992             {
993               _gtk_css_number_init (&pos.y, names[first].percentage, GTK_CSS_PERCENT);
994               missing = &pos.x;
995             }
996           break;
997         }
998     }
999   if (names[first].name == NULL)
1000     {
1001       missing = &pos.y;
1002       if (!_gtk_css_parser_read_number (parser,
1003                                         &pos.x,
1004                                         GTK_CSS_PARSE_PERCENT
1005                                         | GTK_CSS_PARSE_LENGTH))
1006         return NULL;
1007     }
1008
1009   for (second = 0; names[second].name != NULL; second++)
1010     {
1011       if (_gtk_css_parser_try (parser, names[second].name, TRUE))
1012         {
1013           _gtk_css_number_init (missing, names[second].percentage, GTK_CSS_PERCENT);
1014           break;
1015         }
1016     }
1017
1018   if (names[second].name == NULL)
1019     {
1020       if (_gtk_css_parser_has_number (parser))
1021         {
1022           if (missing != &pos.y)
1023             {
1024               _gtk_css_parser_error (parser, "Invalid combination of values");
1025               return NULL;
1026             }
1027           if (!_gtk_css_parser_read_number (parser,
1028                                             missing,
1029                                             GTK_CSS_PARSE_PERCENT
1030                                             | GTK_CSS_PARSE_LENGTH))
1031             return NULL;
1032         }
1033       else
1034         {
1035           second++;
1036           _gtk_css_number_init (missing, 50, GTK_CSS_PERCENT);
1037         }
1038     }
1039   else
1040     {
1041       if ((names[first].horizontal && !names[second].vertical) ||
1042           (!names[first].horizontal && !names[second].horizontal))
1043         {
1044           _gtk_css_parser_error (parser, "Invalid combination of values");
1045           return NULL;
1046         }
1047     }
1048
1049   return _gtk_css_value_new_from_background_position (&pos);
1050 }
1051
1052 static void
1053 background_position_print (GtkCssStyleProperty *property,
1054                            const GtkCssValue   *value,
1055                            GString             *string)
1056 {
1057   const GtkCssBackgroundPosition *pos = _gtk_css_value_get_background_position (value);
1058   static const GtkCssNumber center = GTK_CSS_NUMBER_INIT (50, GTK_CSS_PERCENT);
1059   static const struct {
1060     const char *x_name;
1061     const char *y_name;
1062     GtkCssNumber number;
1063   } values[] = { 
1064     { "left",   "top",    GTK_CSS_NUMBER_INIT (0,   GTK_CSS_PERCENT) },
1065     { "right",  "bottom", GTK_CSS_NUMBER_INIT (100, GTK_CSS_PERCENT) }
1066   };
1067   guint i;
1068
1069   if (_gtk_css_number_equal (&pos->x, &center))
1070     {
1071       if (_gtk_css_number_equal (&pos->y, &center))
1072         {
1073           g_string_append (string, "center");
1074           return;
1075         }
1076     }
1077   else
1078     {
1079       for (i = 0; i < G_N_ELEMENTS (values); i++)
1080         {
1081           if (_gtk_css_number_equal (&pos->x, &values[i].number))
1082             {
1083               g_string_append (string, values[i].x_name);
1084               break;
1085             }
1086         }
1087       if (i == G_N_ELEMENTS (values))
1088         _gtk_css_number_print (&pos->x, string);
1089
1090       if (_gtk_css_number_equal (&pos->y, &center))
1091         return;
1092
1093       g_string_append_c (string, ' ');
1094     }
1095
1096   for (i = 0; i < G_N_ELEMENTS (values); i++)
1097     {
1098       if (_gtk_css_number_equal (&pos->y, &values[i].number))
1099         {
1100           g_string_append (string, values[i].y_name);
1101           break;
1102         }
1103     }
1104   if (i == G_N_ELEMENTS (values))
1105     {
1106       if (_gtk_css_number_equal (&pos->x, &center))
1107         g_string_append (string, "center ");
1108       _gtk_css_number_print (&pos->y, string);
1109     }
1110 }
1111
1112 static GtkCssValue *
1113 background_position_compute (GtkCssStyleProperty    *property,
1114                              GtkStyleContext        *context,
1115                              GtkCssValue            *specified)
1116 {
1117   const GtkCssBackgroundPosition *spos = _gtk_css_value_get_background_position (specified);
1118   GtkCssBackgroundPosition cpos;
1119   gboolean changed;
1120
1121   changed = _gtk_css_number_compute (&cpos.x,
1122                                      &spos->x,
1123                                      context);
1124   changed |= _gtk_css_number_compute (&cpos.y,
1125                                       &spos->y,
1126                                       context);
1127   if (changed)
1128     return _gtk_css_value_new_from_background_position (&cpos);
1129   return _gtk_css_value_ref (specified);
1130 }
1131
1132 /*** REGISTRATION ***/
1133
1134 static GtkSymbolicColor *
1135 gtk_symbolic_color_new_rgba (double red,
1136                              double green,
1137                              double blue,
1138                              double alpha)
1139 {
1140   GdkRGBA rgba = { red, green, blue, alpha };
1141
1142   return gtk_symbolic_color_new_literal (&rgba);
1143 }
1144
1145 void
1146 _gtk_css_style_property_init_properties (void)
1147 {
1148   char *default_font_family[] = { "Sans", NULL };
1149   GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE };
1150   GtkCssBackgroundPosition default_background_position = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT)};
1151   GtkCssBorderCornerRadius no_corner_radius = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX) };
1152   GtkBorder border_of_ones = { 1, 1, 1, 1 };
1153   GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
1154
1155   /* Initialize "color" and "font-size" first,
1156    * so that when computing values later they are
1157    * done first. That way, 'currentColor' and font
1158    * sizes in em can be looked up properly */
1159   gtk_css_style_property_register        ("color",
1160                                           GDK_TYPE_RGBA,
1161                                           GTK_STYLE_PROPERTY_INHERIT,
1162                                           color_parse,
1163                                           NULL,
1164                                           color_property_compute,
1165                                           color_query,
1166                                           color_assign,
1167                                           NULL,
1168                                           _gtk_css_value_new_take_symbolic_color (
1169                                             gtk_symbolic_color_new_rgba (1, 1, 1, 1)));
1170   gtk_css_style_property_register        ("font-size",
1171                                           G_TYPE_DOUBLE,
1172                                           GTK_STYLE_PROPERTY_INHERIT,
1173                                           font_size_parse,
1174                                           NULL,
1175                                           NULL,
1176                                           query_simple,
1177                                           assign_simple,
1178                                           NULL,
1179                                           _gtk_css_value_new_from_double (10.0));
1180
1181   /* properties that aren't referenced when computing values
1182    * start here */
1183   gtk_css_style_property_register        ("background-color",
1184                                           GDK_TYPE_RGBA,
1185                                           0,
1186                                           color_parse,
1187                                           NULL,
1188                                           color_compute,
1189                                           color_query,
1190                                           color_assign,
1191                                           NULL,
1192                                           _gtk_css_value_new_take_symbolic_color (
1193                                             gtk_symbolic_color_new_rgba (0, 0, 0, 0)));
1194
1195   gtk_css_style_property_register        ("font-family",
1196                                           G_TYPE_STRV,
1197                                           GTK_STYLE_PROPERTY_INHERIT,
1198                                           font_family_parse,
1199                                           font_family_value_print,
1200                                           NULL,
1201                                           query_simple,
1202                                           assign_simple,
1203                                           NULL,
1204                                           _gtk_css_value_new_take_strv (g_strdupv (default_font_family)));
1205   gtk_css_style_property_register        ("font-style",
1206                                           PANGO_TYPE_STYLE,
1207                                           GTK_STYLE_PROPERTY_INHERIT,
1208                                           parse_pango_style,
1209                                           NULL,
1210                                           NULL,
1211                                           query_simple,
1212                                           assign_simple,
1213                                           NULL,
1214                                           _gtk_css_value_new_from_enum (PANGO_TYPE_STYLE,
1215                                                                         PANGO_STYLE_NORMAL));
1216   gtk_css_style_property_register        ("font-variant",
1217                                           PANGO_TYPE_VARIANT,
1218                                           GTK_STYLE_PROPERTY_INHERIT,
1219                                           parse_pango_variant,
1220                                           NULL,
1221                                           NULL,
1222                                           query_simple,
1223                                           assign_simple,
1224                                           NULL,
1225                                           _gtk_css_value_new_from_enum (PANGO_TYPE_VARIANT,
1226                                                                         PANGO_VARIANT_NORMAL));
1227   /* xxx: need to parse this properly, ie parse the numbers */
1228   gtk_css_style_property_register        ("font-weight",
1229                                           PANGO_TYPE_WEIGHT,
1230                                           GTK_STYLE_PROPERTY_INHERIT,
1231                                           parse_pango_weight,
1232                                           NULL,
1233                                           NULL,
1234                                           query_simple,
1235                                           assign_simple,
1236                                           NULL,
1237                                           _gtk_css_value_new_from_enum (PANGO_TYPE_WEIGHT,
1238                                                                         PANGO_WEIGHT_NORMAL));
1239
1240   gtk_css_style_property_register        ("text-shadow",
1241                                           G_TYPE_NONE,
1242                                           GTK_STYLE_PROPERTY_INHERIT,
1243                                           shadow_value_parse,
1244                                           NULL,
1245                                           shadow_value_compute,
1246                                           NULL,
1247                                           NULL,
1248                                           NULL,
1249                                           _gtk_css_shadow_value_new_none ());
1250
1251   gtk_css_style_property_register        ("icon-shadow",
1252                                           G_TYPE_NONE,
1253                                           GTK_STYLE_PROPERTY_INHERIT,
1254                                           shadow_value_parse,
1255                                           NULL,
1256                                           shadow_value_compute,
1257                                           NULL,
1258                                           NULL,
1259                                           NULL,
1260                                           _gtk_css_shadow_value_new_none ());
1261
1262   gtk_css_style_property_register        ("box-shadow",
1263                                           G_TYPE_NONE,
1264                                           0,
1265                                           shadow_value_parse,
1266                                           NULL,
1267                                           shadow_value_compute,
1268                                           NULL,
1269                                           NULL,
1270                                           NULL,
1271                                           _gtk_css_shadow_value_new_none ());
1272
1273   gtk_css_style_property_register        ("margin-top",
1274                                           G_TYPE_INT,
1275                                           0,
1276                                           parse_margin,
1277                                           NULL,
1278                                           compute_margin,
1279                                           query_length_as_int,
1280                                           assign_length_from_int,
1281                                           NULL,
1282                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1283   gtk_css_style_property_register        ("margin-left",
1284                                           G_TYPE_INT,
1285                                           0,
1286                                           parse_margin,
1287                                           NULL,
1288                                           compute_margin,
1289                                           query_length_as_int,
1290                                           assign_length_from_int,
1291                                           NULL,
1292                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1293   gtk_css_style_property_register        ("margin-bottom",
1294                                           G_TYPE_INT,
1295                                           0,
1296                                           parse_margin,
1297                                           NULL,
1298                                           compute_margin,
1299                                           query_length_as_int,
1300                                           assign_length_from_int,
1301                                           NULL,
1302                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1303   gtk_css_style_property_register        ("margin-right",
1304                                           G_TYPE_INT,
1305                                           0,
1306                                           parse_margin,
1307                                           NULL,
1308                                           compute_margin,
1309                                           query_length_as_int,
1310                                           assign_length_from_int,
1311                                           NULL,
1312                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1313   gtk_css_style_property_register        ("padding-top",
1314                                           G_TYPE_INT,
1315                                           0,
1316                                           parse_padding,
1317                                           NULL,
1318                                           compute_padding,
1319                                           query_length_as_int,
1320                                           assign_length_from_int,
1321                                           NULL,
1322                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1323   gtk_css_style_property_register        ("padding-left",
1324                                           G_TYPE_INT,
1325                                           0,
1326                                           parse_padding,
1327                                           NULL,
1328                                           compute_padding,
1329                                           query_length_as_int,
1330                                           assign_length_from_int,
1331                                           NULL,
1332                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1333   gtk_css_style_property_register        ("padding-bottom",
1334                                           G_TYPE_INT,
1335                                           0,
1336                                           parse_padding,
1337                                           NULL,
1338                                           compute_padding,
1339                                           query_length_as_int,
1340                                           assign_length_from_int,
1341                                           NULL,
1342                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1343   gtk_css_style_property_register        ("padding-right",
1344                                           G_TYPE_INT,
1345                                           0,
1346                                           parse_padding,
1347                                           NULL,
1348                                           compute_padding,
1349                                           query_length_as_int,
1350                                           assign_length_from_int,
1351                                           NULL,
1352                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1353   /* IMPORTANT: compute_border_width() requires that the border-width
1354    * properties be immeditaly followed by the border-style properties
1355    */
1356   gtk_css_style_property_register        ("border-top-style",
1357                                           GTK_TYPE_BORDER_STYLE,
1358                                           0,
1359                                           parse_border_style,
1360                                           NULL,
1361                                           NULL,
1362                                           query_simple,
1363                                           assign_simple,
1364                                           NULL,
1365                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1366   gtk_css_style_property_register        ("border-top-width",
1367                                           G_TYPE_INT,
1368                                           0,
1369                                           parse_border_width,
1370                                           NULL,
1371                                           compute_border_width,
1372                                           query_length_as_int,
1373                                           assign_length_from_int,
1374                                           NULL,
1375                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1376   gtk_css_style_property_register        ("border-left-style",
1377                                           GTK_TYPE_BORDER_STYLE,
1378                                           0,
1379                                           parse_border_style,
1380                                           NULL,
1381                                           NULL,
1382                                           query_simple,
1383                                           assign_simple,
1384                                           NULL,
1385                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1386   gtk_css_style_property_register        ("border-left-width",
1387                                           G_TYPE_INT,
1388                                           0,
1389                                           parse_border_width,
1390                                           NULL,
1391                                           compute_border_width,
1392                                           query_length_as_int,
1393                                           assign_length_from_int,
1394                                           NULL,
1395                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1396   gtk_css_style_property_register        ("border-bottom-style",
1397                                           GTK_TYPE_BORDER_STYLE,
1398                                           0,
1399                                           parse_border_style,
1400                                           NULL,
1401                                           NULL,
1402                                           query_simple,
1403                                           assign_simple,
1404                                           NULL,
1405                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1406   gtk_css_style_property_register        ("border-bottom-width",
1407                                           G_TYPE_INT,
1408                                           0,
1409                                           parse_border_width,
1410                                           NULL,
1411                                           compute_border_width,
1412                                           query_length_as_int,
1413                                           assign_length_from_int,
1414                                           NULL,
1415                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1416   gtk_css_style_property_register        ("border-right-style",
1417                                           GTK_TYPE_BORDER_STYLE,
1418                                           0,
1419                                           parse_border_style,
1420                                           NULL,
1421                                           NULL,
1422                                           query_simple,
1423                                           assign_simple,
1424                                           NULL,
1425                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1426   gtk_css_style_property_register        ("border-right-width",
1427                                           G_TYPE_INT,
1428                                           0,
1429                                           parse_border_width,
1430                                           NULL,
1431                                           compute_border_width,
1432                                           query_length_as_int,
1433                                           assign_length_from_int,
1434                                           NULL,
1435                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1436
1437   gtk_css_style_property_register        ("border-top-left-radius",
1438                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1439                                           0,
1440                                           border_corner_radius_value_parse,
1441                                           border_corner_radius_value_print,
1442                                           NULL,
1443                                           query_simple,
1444                                           assign_simple,
1445                                           NULL,
1446                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1447   gtk_css_style_property_register        ("border-top-right-radius",
1448                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1449                                           0,
1450                                           border_corner_radius_value_parse,
1451                                           border_corner_radius_value_print,
1452                                           NULL,
1453                                           query_simple,
1454                                           assign_simple,
1455                                           NULL,
1456                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1457   gtk_css_style_property_register        ("border-bottom-right-radius",
1458                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1459                                           0,
1460                                           border_corner_radius_value_parse,
1461                                           border_corner_radius_value_print,
1462                                           NULL,
1463                                           query_simple,
1464                                           assign_simple,
1465                                           NULL,
1466                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1467   gtk_css_style_property_register        ("border-bottom-left-radius",
1468                                           GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1469                                           0,
1470                                           border_corner_radius_value_parse,
1471                                           border_corner_radius_value_print,
1472                                           NULL,
1473                                           query_simple,
1474                                           assign_simple,
1475                                           NULL,
1476                                           _gtk_css_value_new_from_border_corner_radius (&no_corner_radius));
1477
1478   gtk_css_style_property_register        ("outline-style",
1479                                           GTK_TYPE_BORDER_STYLE,
1480                                           0,
1481                                           parse_border_style,
1482                                           NULL,
1483                                           NULL,
1484                                           query_simple,
1485                                           assign_simple,
1486                                           NULL,
1487                                           _gtk_css_value_new_from_border_style (GTK_BORDER_STYLE_NONE));
1488   gtk_css_style_property_register        ("outline-width",
1489                                           G_TYPE_INT,
1490                                           0,
1491                                           parse_border_width,
1492                                           NULL,
1493                                           compute_border_width,
1494                                           query_length_as_int,
1495                                           assign_length_from_int,
1496                                           NULL,
1497                                           _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1498   gtk_css_style_property_register        ("outline-offset",
1499                                           G_TYPE_INT,
1500                                           0,
1501                                           outline_parse,
1502                                           NULL,
1503                                           NULL,
1504                                           query_simple,
1505                                           assign_simple,
1506                                           NULL,
1507                                           _gtk_css_value_new_from_int (0));
1508
1509   gtk_css_style_property_register        ("background-clip",
1510                                           GTK_TYPE_CSS_AREA,
1511                                           0,
1512                                           parse_css_area,
1513                                           NULL,
1514                                           NULL,
1515                                           query_simple,
1516                                           assign_simple,
1517                                           NULL,
1518                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, GTK_CSS_AREA_BORDER_BOX));
1519   gtk_css_style_property_register        ("background-origin",
1520                                           GTK_TYPE_CSS_AREA,
1521                                           0,
1522                                           parse_css_area,
1523                                           NULL,
1524                                           NULL,
1525                                           query_simple,
1526                                           assign_simple,
1527                                           NULL,
1528                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_AREA, GTK_CSS_AREA_PADDING_BOX));
1529   gtk_css_style_property_register        ("background-size",
1530                                           G_TYPE_NONE,
1531                                           0,
1532                                           background_size_parse,
1533                                           background_size_print,
1534                                           background_size_compute,
1535                                           NULL,
1536                                           NULL,
1537                                           NULL,
1538                                           _gtk_css_value_new_from_background_size (&default_background_size));
1539   gtk_css_style_property_register        ("background-position",
1540                                           G_TYPE_NONE,
1541                                           0,
1542                                           background_position_parse,
1543                                           background_position_print,
1544                                           background_position_compute,
1545                                           NULL,
1546                                           NULL,
1547                                           NULL,
1548                                           _gtk_css_value_new_from_background_position (&default_background_position));
1549
1550   gtk_css_style_property_register        ("border-top-color",
1551                                           GDK_TYPE_RGBA,
1552                                           0,
1553                                           color_parse,
1554                                           NULL,
1555                                           color_compute,
1556                                           color_query,
1557                                           color_assign,
1558                                           NULL,
1559                                           _gtk_css_value_new_take_symbolic_color (
1560                                             gtk_symbolic_color_ref (
1561                                               _gtk_symbolic_color_get_current_color ())));
1562   gtk_css_style_property_register        ("border-right-color",
1563                                           GDK_TYPE_RGBA,
1564                                           0,
1565                                           color_parse,
1566                                           NULL,
1567                                           color_compute,
1568                                           color_query,
1569                                           color_assign,
1570                                           NULL,
1571                                           _gtk_css_value_new_take_symbolic_color (
1572                                             gtk_symbolic_color_ref (
1573                                               _gtk_symbolic_color_get_current_color ())));
1574   gtk_css_style_property_register        ("border-bottom-color",
1575                                           GDK_TYPE_RGBA,
1576                                           0,
1577                                           color_parse,
1578                                           NULL,
1579                                           color_compute,
1580                                           color_query,
1581                                           color_assign,
1582                                           NULL,
1583                                           _gtk_css_value_new_take_symbolic_color (
1584                                             gtk_symbolic_color_ref (
1585                                               _gtk_symbolic_color_get_current_color ())));
1586   gtk_css_style_property_register        ("border-left-color",
1587                                           GDK_TYPE_RGBA,
1588                                           0,
1589                                           color_parse,
1590                                           NULL,
1591                                           color_compute,
1592                                           color_query,
1593                                           color_assign,
1594                                           NULL,
1595                                           _gtk_css_value_new_take_symbolic_color (
1596                                             gtk_symbolic_color_ref (
1597                                               _gtk_symbolic_color_get_current_color ())));
1598   gtk_css_style_property_register        ("outline-color",
1599                                           GDK_TYPE_RGBA,
1600                                           0,
1601                                           color_parse,
1602                                           NULL,
1603                                           color_compute,
1604                                           color_query,
1605                                           color_assign,
1606                                           NULL,
1607                                           _gtk_css_value_new_take_symbolic_color (
1608                                             gtk_symbolic_color_ref (
1609                                               _gtk_symbolic_color_get_current_color ())));
1610
1611   gtk_css_style_property_register        ("background-repeat",
1612                                           GTK_TYPE_CSS_BACKGROUND_REPEAT,
1613                                           0,
1614                                           background_repeat_value_parse,
1615                                           background_repeat_value_print,
1616                                           NULL,
1617                                           query_simple,
1618                                           assign_simple,
1619                                           NULL,
1620                                           _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT,
1621                                                                         GTK_CSS_BACKGROUND_REPEAT | 
1622                                                                         (GTK_CSS_BACKGROUND_REPEAT << GTK_CSS_BACKGROUND_REPEAT_SHIFT)));
1623   gtk_css_style_property_register        ("background-image",
1624                                           CAIRO_GOBJECT_TYPE_PATTERN,
1625                                           0,
1626                                           css_image_value_parse,
1627                                           css_image_value_print,
1628                                           css_image_value_compute,
1629                                           css_image_value_query,
1630                                           css_image_value_assign,
1631                                           NULL,
1632                                           _gtk_css_value_new_take_image (NULL));
1633
1634   gtk_css_style_property_register        ("border-image-source",
1635                                           CAIRO_GOBJECT_TYPE_PATTERN,
1636                                           0,
1637                                           css_image_value_parse,
1638                                           css_image_value_print,
1639                                           css_image_value_compute,
1640                                           css_image_value_query,
1641                                           css_image_value_assign,
1642                                           NULL,
1643                                           _gtk_css_value_new_take_image (NULL));
1644   gtk_css_style_property_register        ("border-image-repeat",
1645                                           GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1646                                           0,
1647                                           border_image_repeat_parse,
1648                                           NULL,
1649                                           NULL,
1650                                           query_simple,
1651                                           assign_simple,
1652                                           NULL,
1653                                           _gtk_css_value_new_from_border_image_repeat (&border_image_repeat));
1654
1655   /* XXX: The initial value is wrong, it should be 100% */
1656   gtk_css_style_property_register        ("border-image-slice",
1657                                           GTK_TYPE_BORDER,
1658                                           0,
1659                                           border_image_slice_parse,
1660                                           NULL,
1661                                           NULL,
1662                                           query_simple,
1663                                           assign_simple,
1664                                           NULL,
1665                                           _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, &border_of_ones));
1666   gtk_css_style_property_register        ("border-image-width",
1667                                           GTK_TYPE_BORDER,
1668                                           0,
1669                                           border_image_width_parse,
1670                                           NULL,
1671                                           NULL,
1672                                           query_simple,
1673                                           assign_simple,
1674                                           NULL,
1675                                           _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, NULL));
1676   gtk_css_style_property_register        ("engine",
1677                                           GTK_TYPE_THEMING_ENGINE,
1678                                           0,
1679                                           engine_parse,
1680                                           NULL,
1681                                           NULL,
1682                                           query_simple,
1683                                           assign_simple,
1684                                           NULL,
1685                                           _gtk_css_value_new_from_theming_engine (gtk_theming_engine_load (NULL)));
1686   gtk_css_style_property_register        ("transition",
1687                                           GTK_TYPE_ANIMATION_DESCRIPTION,
1688                                           0,
1689                                           transition_parse,
1690                                           NULL,
1691                                           NULL,
1692                                           query_simple,
1693                                           assign_simple,
1694                                           NULL,
1695                                           _gtk_css_value_new_from_boxed (GTK_TYPE_ANIMATION_DESCRIPTION, NULL));
1696
1697   /* Private property holding the binding sets */
1698   gtk_css_style_property_register        ("gtk-key-bindings",
1699                                           G_TYPE_PTR_ARRAY,
1700                                           0,
1701                                           bindings_value_parse,
1702                                           bindings_value_print,
1703                                           NULL,
1704                                           query_simple,
1705                                           assign_simple,
1706                                           NULL,
1707                                           _gtk_css_value_new_take_binding_sets (NULL));
1708 }
1709