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