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