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