1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
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.
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.
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/>.
20 #include "gtkstylepropertyprivate.h"
22 #include <gobject/gvaluecollector.h>
23 #include <gdk-pixbuf/gdk-pixbuf.h>
24 #include <cairo-gobject.h>
27 #include "gtkcssparserprivate.h"
28 #include "gtkcssstylefuncsprivate.h"
29 #include "gtkcssstylepropertyprivate.h"
30 #include "gtkcsstypesprivate.h"
32 #include "gtkprivatetypebuiltins.h"
33 #include "gtkstylepropertiesprivate.h"
35 /* this is in case round() is not provided by the compiler,
36 * such as in the case of C89 compilers, like MSVC
38 #include "fallback-c89.c"
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 "gtkcssenginevalueprivate.h"
47 #include "gtkcssimagegradientprivate.h"
48 #include "gtkcssimageprivate.h"
49 #include "gtkcssimagevalueprivate.h"
50 #include "gtkcssenumvalueprivate.h"
51 #include "gtkcssnumbervalueprivate.h"
52 #include "gtkcsspositionvalueprivate.h"
53 #include "gtkcssrgbavalueprivate.h"
54 #include "gtkcssshadowsvalueprivate.h"
55 #include "gtkcssstringvalueprivate.h"
56 #include "gtksymboliccolorprivate.h"
57 #include "gtkthemingengine.h"
58 #include "gtktypebuiltins.h"
59 #include "gtkwin32themeprivate.h"
61 /*** REGISTRATION ***/
64 GTK_STYLE_PROPERTY_INHERIT = (1 << 0),
65 GTK_STYLE_PROPERTY_ANIMATED = (1 << 1)
66 } GtkStylePropertyFlags;
69 gtk_css_style_property_register (const char * name,
72 GtkStylePropertyFlags flags,
73 GtkCssStylePropertyParseFunc parse_value,
74 GtkCssStylePropertyPrintFunc print_value,
75 GtkCssStylePropertyComputeFunc compute_value,
76 GtkCssStylePropertyQueryFunc query_value,
77 GtkCssStylePropertyAssignFunc assign_value,
78 GtkCssStylePropertyEqualFunc equal_func,
79 GtkCssValue * initial_value)
81 GtkCssStyleProperty *node;
83 g_assert (initial_value != NULL);
84 g_assert (parse_value != NULL);
85 g_assert (value_type == G_TYPE_NONE || query_value != NULL);
86 g_assert (value_type == G_TYPE_NONE || assign_value != NULL);
88 node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
89 "value-type", value_type,
90 "animated", (flags & GTK_STYLE_PROPERTY_ANIMATED) ? TRUE : FALSE,
91 "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
92 "initial-value", initial_value,
96 node->parse_value = parse_value;
98 node->print_value = print_value;
100 node->compute_value = compute_value;
101 node->query_value = query_value;
102 node->assign_value = assign_value;
104 node->equal_func = equal_func;
106 _gtk_css_value_unref (initial_value);
108 g_assert (_gtk_css_style_property_get_id (node) == expected_id);
111 /*** IMPLEMENTATIONS ***/
114 query_simple (GtkCssStyleProperty *property,
115 const GtkCssValue *css_value,
118 _gtk_css_value_init_gvalue (css_value, value);
122 assign_simple (GtkCssStyleProperty *property,
125 return _gtk_css_value_new_from_gvalue (value);
129 query_length_as_int (GtkCssStyleProperty *property,
130 const GtkCssValue *css_value,
133 g_value_init (value, G_TYPE_INT);
134 g_value_set_int (value, round (_gtk_css_number_value_get (css_value, 100)));
138 assign_length_from_int (GtkCssStyleProperty *property,
141 return _gtk_css_number_value_new (g_value_get_int (value), GTK_CSS_PX);
145 query_length_as_double (GtkCssStyleProperty *property,
146 const GtkCssValue *css_value,
149 g_value_init (value, G_TYPE_DOUBLE);
150 g_value_set_double (value, _gtk_css_number_value_get (css_value, 100));
154 assign_length_from_double (GtkCssStyleProperty *property,
157 return _gtk_css_number_value_new (g_value_get_double (value), GTK_CSS_PX);
161 color_parse (GtkCssStyleProperty *property,
162 GtkCssParser *parser,
165 GtkSymbolicColor *symbolic;
167 if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
169 symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
173 symbolic = _gtk_css_parser_read_symbolic_color (parser);
174 if (symbolic == NULL)
178 return _gtk_css_value_new_take_symbolic_color (symbolic);
182 color_compute (GtkCssStyleProperty *property,
183 GtkStyleContext *context,
184 GtkCssValue *specified)
186 return _gtk_css_rgba_value_compute_from_symbolic (specified,
187 _gtk_css_style_property_get_initial_value (property),
193 color_property_compute (GtkCssStyleProperty *property,
194 GtkStyleContext *context,
195 GtkCssValue *specified)
199 value = _gtk_css_rgba_value_compute_from_symbolic (specified,
200 _gtk_css_style_property_get_initial_value (property),
203 _gtk_css_rgba_value_get_rgba (value);
208 color_query (GtkCssStyleProperty *property,
209 const GtkCssValue *css_value,
212 g_value_init (value, GDK_TYPE_RGBA);
213 g_value_set_boxed (value, _gtk_css_rgba_value_get_rgba (css_value));
217 color_assign (GtkCssStyleProperty *property,
220 return _gtk_css_rgba_value_new_from_rgba (g_value_get_boxed (value));
224 font_family_parse_one (GtkCssParser *parser)
228 name = _gtk_css_parser_try_ident (parser, TRUE);
231 GString *string = g_string_new (name);
233 while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
235 g_string_append_c (string, ' ');
236 g_string_append (string, name);
239 name = g_string_free (string, FALSE);
243 name = _gtk_css_parser_read_string (parser);
248 return _gtk_css_string_value_new_take (name);
252 font_family_parse (GtkCssStyleProperty *property,
253 GtkCssParser *parser,
256 return _gtk_css_array_value_parse (parser, font_family_parse_one, FALSE);
260 font_family_query (GtkCssStyleProperty *property,
261 const GtkCssValue *css_value,
267 array = g_ptr_array_new ();
269 for (i = 0; i < _gtk_css_array_value_get_n_values (css_value); i++)
271 g_ptr_array_add (array, g_strdup (_gtk_css_string_value_get (_gtk_css_array_value_get_nth (css_value, i))));
275 g_ptr_array_add (array, NULL);
277 g_value_init (value, G_TYPE_STRV);
278 g_value_set_boxed (value, g_ptr_array_free (array, FALSE));
282 font_family_assign (GtkCssStyleProperty *property,
285 const char **names = g_value_get_boxed (value);
289 array = g_ptr_array_new ();
291 for (names = g_value_get_boxed (value); *names; names++)
293 g_ptr_array_add (array, _gtk_css_string_value_new (*names));
296 result = _gtk_css_array_value_new_from_array ((GtkCssValue **) array->pdata, array->len);
297 g_ptr_array_free (array, TRUE);
302 parse_pango_style (GtkCssStyleProperty *property,
303 GtkCssParser *parser,
306 GtkCssValue *value = _gtk_css_font_style_value_try_parse (parser);
309 _gtk_css_parser_error (parser, "unknown value for property");
315 query_pango_style (GtkCssStyleProperty *property,
316 const GtkCssValue *css_value,
319 g_value_init (value, PANGO_TYPE_STYLE);
320 g_value_set_enum (value, _gtk_css_font_style_value_get (css_value));
324 assign_pango_style (GtkCssStyleProperty *property,
327 return _gtk_css_font_style_value_new (g_value_get_enum (value));
331 parse_pango_weight (GtkCssStyleProperty *property,
332 GtkCssParser *parser,
335 GtkCssValue *value = _gtk_css_font_weight_value_try_parse (parser);
338 _gtk_css_parser_error (parser, "unknown value for property");
344 query_pango_weight (GtkCssStyleProperty *property,
345 const GtkCssValue *css_value,
348 g_value_init (value, PANGO_TYPE_WEIGHT);
349 g_value_set_enum (value, _gtk_css_font_weight_value_get (css_value));
353 assign_pango_weight (GtkCssStyleProperty *property,
356 return _gtk_css_font_weight_value_new (g_value_get_enum (value));
360 parse_pango_variant (GtkCssStyleProperty *property,
361 GtkCssParser *parser,
364 GtkCssValue *value = _gtk_css_font_variant_value_try_parse (parser);
367 _gtk_css_parser_error (parser, "unknown value for property");
373 query_pango_variant (GtkCssStyleProperty *property,
374 const GtkCssValue *css_value,
377 g_value_init (value, PANGO_TYPE_VARIANT);
378 g_value_set_enum (value, _gtk_css_font_variant_value_get (css_value));
382 assign_pango_variant (GtkCssStyleProperty *property,
385 return _gtk_css_font_variant_value_new (g_value_get_enum (value));
389 parse_border_style (GtkCssStyleProperty *property,
390 GtkCssParser *parser,
393 GtkCssValue *value = _gtk_css_border_style_value_try_parse (parser);
396 _gtk_css_parser_error (parser, "unknown value for property");
402 query_border_style (GtkCssStyleProperty *property,
403 const GtkCssValue *css_value,
406 g_value_init (value, GTK_TYPE_BORDER_STYLE);
407 g_value_set_enum (value, _gtk_css_border_style_value_get (css_value));
411 assign_border_style (GtkCssStyleProperty *property,
414 return _gtk_css_border_style_value_new (g_value_get_enum (value));
418 parse_css_area (GtkCssStyleProperty *property,
419 GtkCssParser *parser,
422 GtkCssValue *value = _gtk_css_area_value_try_parse (parser);
425 _gtk_css_parser_error (parser, "unknown value for property");
431 bindings_value_parse_one (GtkCssParser *parser)
435 name = _gtk_css_parser_try_ident (parser, TRUE);
438 _gtk_css_parser_error (parser, "Not a valid binding name");
443 if (!gtk_binding_set_find (name))
445 _gtk_css_parser_error (parser, "No binding set named '%s'", name);
450 return _gtk_css_string_value_new_take (name);
454 bindings_value_parse (GtkCssStyleProperty *property,
455 GtkCssParser *parser,
458 return _gtk_css_array_value_parse (parser, bindings_value_parse_one, TRUE);
462 bindings_value_query (GtkCssStyleProperty *property,
463 const GtkCssValue *css_value,
469 g_value_init (value, G_TYPE_PTR_ARRAY);
471 if (_gtk_css_array_value_get_n_values (css_value) == 0)
474 array = g_ptr_array_new ();
476 for (i = 0; i < _gtk_css_array_value_get_n_values (css_value); i++)
478 GtkBindingSet *binding_set = gtk_binding_set_find (_gtk_css_string_value_get (_gtk_css_array_value_get_nth (css_value, i)));
480 g_ptr_array_add (array, binding_set);
483 g_value_take_boxed (value, array);
487 bindings_value_assign (GtkCssStyleProperty *property,
490 GPtrArray *binding_sets = g_value_get_boxed (value);
491 GtkCssValue **values, *result;
494 if (binding_sets == NULL || binding_sets->len == 0)
495 return _gtk_css_array_value_new (NULL);
497 values = g_new (GtkCssValue *, binding_sets->len);
499 for (i = 0; i < binding_sets->len; i++)
501 GtkBindingSet *binding_set = g_ptr_array_index (binding_sets, i);
502 values[i] = _gtk_css_string_value_new (binding_set->set_name);
505 result = _gtk_css_array_value_new_from_array (values, binding_sets->len);
511 shadow_value_parse (GtkCssStyleProperty *property,
512 GtkCssParser *parser,
515 return _gtk_css_shadows_value_parse (parser);
519 shadow_value_compute (GtkCssStyleProperty *property,
520 GtkStyleContext *context,
521 GtkCssValue *specified)
523 return _gtk_css_shadows_value_compute (specified, context);
527 border_corner_radius_value_parse (GtkCssStyleProperty *property,
528 GtkCssParser *parser,
531 return _gtk_css_corner_value_parse (parser);
535 border_corner_radius_value_compute (GtkCssStyleProperty *property,
536 GtkStyleContext *context,
537 GtkCssValue *specified)
539 return _gtk_css_corner_value_compute (specified, context);
543 css_image_value_parse (GtkCssStyleProperty *property,
544 GtkCssParser *parser,
549 if (_gtk_css_parser_try (parser, "none", TRUE))
553 image = _gtk_css_image_new_parse (parser, base);
558 return _gtk_css_image_value_new (image);
562 css_image_value_compute (GtkCssStyleProperty *property,
563 GtkStyleContext *context,
564 GtkCssValue *specified)
566 GtkCssImage *image, *computed;
568 image = _gtk_css_image_value_get_image (specified);
571 return _gtk_css_value_ref (specified);
573 computed = _gtk_css_image_compute (image, context);
575 if (computed == image)
577 g_object_unref (computed);
578 return _gtk_css_value_ref (specified);
581 return _gtk_css_image_value_new (computed);
585 css_image_value_query (GtkCssStyleProperty *property,
586 const GtkCssValue *css_value,
589 GtkCssImage *image = _gtk_css_image_value_get_image (css_value);
590 cairo_pattern_t *pattern;
591 cairo_surface_t *surface;
592 cairo_matrix_t matrix;
594 g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
596 if (GTK_IS_CSS_IMAGE_GRADIENT (image))
597 g_value_set_boxed (value, GTK_CSS_IMAGE_GRADIENT (image)->pattern);
598 else if (image != NULL)
600 double width, height;
602 /* the 100, 100 is rather random */
603 _gtk_css_image_get_concrete_size (image, 0, 0, 100, 100, &width, &height);
604 surface = _gtk_css_image_get_surface (image, NULL, width, height);
605 pattern = cairo_pattern_create_for_surface (surface);
606 cairo_matrix_init_scale (&matrix, width, height);
607 cairo_pattern_set_matrix (pattern, &matrix);
608 cairo_surface_destroy (surface);
609 g_value_take_boxed (value, pattern);
614 css_image_value_assign (GtkCssStyleProperty *property,
617 g_warning ("FIXME: assigning images is not implemented");
618 return _gtk_css_image_value_new (NULL);
622 font_size_parse (GtkCssStyleProperty *property,
623 GtkCssParser *parser,
628 if (!_gtk_css_parser_try_double (parser, &d))
630 _gtk_css_parser_error (parser, "Expected a number");
634 return _gtk_css_number_value_new (d, GTK_CSS_PX);
638 font_size_compute (GtkCssStyleProperty *property,
639 GtkStyleContext *context,
640 GtkCssValue *specified)
642 return _gtk_css_number_value_compute (specified, context);
646 outline_parse (GtkCssStyleProperty *property,
647 GtkCssParser *parser,
650 return _gtk_css_number_value_parse (parser,
651 GTK_CSS_NUMBER_AS_PIXELS
652 | GTK_CSS_PARSE_LENGTH);
656 outline_compute (GtkCssStyleProperty *property,
657 GtkStyleContext *context,
658 GtkCssValue *specified)
660 return _gtk_css_number_value_compute (specified, context);
664 border_image_repeat_parse (GtkCssStyleProperty *property,
665 GtkCssParser *parser,
668 GValue value = G_VALUE_INIT;
671 g_value_init (&value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
672 if (!_gtk_css_style_parse_value (&value, parser, base))
674 g_value_unset (&value);
678 result = _gtk_css_value_new_from_gvalue (&value);
679 g_value_unset (&value);
685 border_image_slice_parse (GtkCssStyleProperty *property,
686 GtkCssParser *parser,
689 GValue value = G_VALUE_INIT;
692 g_value_init (&value, GTK_TYPE_BORDER);
693 if (!_gtk_css_style_parse_value (&value, parser, base))
695 g_value_unset (&value);
699 result = _gtk_css_value_new_from_gvalue (&value);
700 g_value_unset (&value);
706 border_image_width_parse (GtkCssStyleProperty *property,
707 GtkCssParser *parser,
710 GValue value = G_VALUE_INIT;
713 g_value_init (&value, GTK_TYPE_BORDER);
714 if (!_gtk_css_style_parse_value (&value, parser, base))
716 g_value_unset (&value);
720 result = _gtk_css_value_new_from_gvalue (&value);
721 g_value_unset (&value);
727 transition_property_parse_one (GtkCssParser *parser)
731 value = _gtk_css_ident_value_try_parse (parser);
735 _gtk_css_parser_error (parser, "Expected an identifier");
743 transition_property_parse (GtkCssStyleProperty *property,
744 GtkCssParser *parser,
747 return _gtk_css_array_value_parse (parser, transition_property_parse_one, FALSE);
751 transition_time_parse_one (GtkCssParser *parser)
753 return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME);
757 transition_time_parse (GtkCssStyleProperty *property,
758 GtkCssParser *parser,
761 return _gtk_css_array_value_parse (parser, transition_time_parse_one, FALSE);
765 transition_timing_function_parse (GtkCssStyleProperty *property,
766 GtkCssParser *parser,
769 return _gtk_css_array_value_parse (parser, _gtk_css_ease_value_parse, FALSE);
773 engine_parse (GtkCssStyleProperty *property,
774 GtkCssParser *parser,
777 return _gtk_css_engine_value_parse (parser);
781 engine_query (GtkCssStyleProperty *property,
782 const GtkCssValue *css_value,
785 g_value_init (value, GTK_TYPE_THEMING_ENGINE);
786 g_value_set_object (value, _gtk_css_engine_value_get_engine (css_value));
790 engine_assign (GtkCssStyleProperty *property,
793 return _gtk_css_engine_value_new (g_value_get_object (value));
797 transition_parse (GtkCssStyleProperty *property,
798 GtkCssParser *parser,
801 GValue value = G_VALUE_INIT;
804 g_value_init (&value, GTK_TYPE_ANIMATION_DESCRIPTION);
805 if (!_gtk_css_style_parse_value (&value, parser, base))
807 g_value_unset (&value);
811 result = _gtk_css_value_new_from_gvalue (&value);
812 g_value_unset (&value);
818 parse_margin (GtkCssStyleProperty *property,
819 GtkCssParser *parser,
822 return _gtk_css_number_value_parse (parser,
823 GTK_CSS_NUMBER_AS_PIXELS
824 | GTK_CSS_PARSE_LENGTH);
828 compute_margin (GtkCssStyleProperty *property,
829 GtkStyleContext *context,
830 GtkCssValue *specified)
832 return _gtk_css_number_value_compute (specified, context);
836 parse_padding (GtkCssStyleProperty *property,
837 GtkCssParser *parser,
840 return _gtk_css_number_value_parse (parser,
841 GTK_CSS_POSITIVE_ONLY
842 | GTK_CSS_NUMBER_AS_PIXELS
843 | GTK_CSS_PARSE_LENGTH);
847 compute_padding (GtkCssStyleProperty *property,
848 GtkStyleContext *context,
849 GtkCssValue *specified)
851 return _gtk_css_number_value_compute (specified, context);
855 parse_border_width (GtkCssStyleProperty *property,
856 GtkCssParser *parser,
859 return _gtk_css_number_value_parse (parser,
860 GTK_CSS_POSITIVE_ONLY
861 | GTK_CSS_NUMBER_AS_PIXELS
862 | GTK_CSS_PARSE_LENGTH);
866 compute_border_width (GtkCssStyleProperty *property,
867 GtkStyleContext *context,
868 GtkCssValue *specified)
870 GtkBorderStyle border_style;
872 /* The -1 is magic that is only true because we register the style
873 * properties directly after the width properties.
875 border_style = _gtk_css_border_style_value_get (_gtk_style_context_peek_property (context, _gtk_css_style_property_get_id (property) - 1));
877 if (border_style == GTK_BORDER_STYLE_NONE ||
878 border_style == GTK_BORDER_STYLE_HIDDEN)
879 return _gtk_css_number_value_new (0, GTK_CSS_PX);
881 return _gtk_css_number_value_compute (specified, context);
885 background_repeat_value_parse (GtkCssStyleProperty *property,
886 GtkCssParser *parser,
889 int repeat, vertical;
891 if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &repeat))
893 _gtk_css_parser_error (parser, "Not a valid value");
897 if (repeat <= GTK_CSS_BACKGROUND_REPEAT_MASK)
899 if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
901 if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
903 _gtk_css_parser_error (parser, "Not a valid 2nd value");
907 repeat |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
910 repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
913 return _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, repeat);
917 background_repeat_value_print (GtkCssStyleProperty *property,
918 const GtkCssValue *value,
921 GEnumClass *enum_class;
922 GEnumValue *enum_value;
923 GtkCssBackgroundRepeat repeat;
925 repeat = _gtk_css_value_get_enum (value);
926 enum_class = g_type_class_ref (GTK_TYPE_CSS_BACKGROUND_REPEAT);
927 enum_value = g_enum_get_value (enum_class, repeat);
929 /* only triggers for 'repeat-x' and 'repeat-y' */
931 g_string_append (string, enum_value->value_nick);
934 enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_HORIZONTAL (repeat));
935 g_string_append (string, enum_value->value_nick);
937 if (GTK_CSS_BACKGROUND_HORIZONTAL (repeat) != GTK_CSS_BACKGROUND_VERTICAL (repeat))
939 enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_VERTICAL (repeat));
940 g_string_append (string, " ");
941 g_string_append (string, enum_value->value_nick);
945 g_type_class_unref (enum_class);
949 background_size_parse (GtkCssStyleProperty *property,
950 GtkCssParser *parser,
953 GtkCssBackgroundSize size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE};
955 if (_gtk_css_parser_try (parser, "cover", TRUE))
957 else if (_gtk_css_parser_try (parser, "contain", TRUE))
961 if (_gtk_css_parser_try (parser, "auto", TRUE))
962 _gtk_css_number_init (&size.width, 0, GTK_CSS_PX);
963 else if (!_gtk_css_parser_read_number (parser,
965 GTK_CSS_POSITIVE_ONLY
966 | GTK_CSS_PARSE_PERCENT
967 | GTK_CSS_PARSE_LENGTH))
970 if (_gtk_css_parser_try (parser, "auto", TRUE))
971 _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
972 else if (_gtk_css_parser_has_number (parser))
974 if (!_gtk_css_parser_read_number (parser,
976 GTK_CSS_POSITIVE_ONLY
977 | GTK_CSS_PARSE_PERCENT
978 | GTK_CSS_PARSE_LENGTH))
982 _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
985 return _gtk_css_value_new_from_background_size (&size);
989 background_size_print (GtkCssStyleProperty *property,
990 const GtkCssValue *value,
993 const GtkCssBackgroundSize *size = _gtk_css_value_get_background_size (value);
996 g_string_append (string, "cover");
997 else if (size->contain)
998 g_string_append (string, "contain");
1001 if (size->width.value == 0)
1002 g_string_append (string, "auto");
1004 _gtk_css_number_print (&size->width, string);
1006 if (size->height.value != 0)
1008 g_string_append (string, " ");
1009 _gtk_css_number_print (&size->height, string);
1014 static GtkCssValue *
1015 background_size_compute (GtkCssStyleProperty *property,
1016 GtkStyleContext *context,
1017 GtkCssValue *specified)
1019 const GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
1020 GtkCssBackgroundSize csize;
1023 csize.cover = ssize->cover;
1024 csize.contain = ssize->contain;
1025 changed = _gtk_css_number_compute (&csize.width,
1028 changed |= _gtk_css_number_compute (&csize.height,
1032 return _gtk_css_value_new_from_background_size (&csize);
1033 return _gtk_css_value_ref (specified);
1036 static GtkCssValue *
1037 background_position_parse (GtkCssStyleProperty *property,
1038 GtkCssParser *parser,
1041 return _gtk_css_position_value_parse (parser);
1044 static GtkCssValue *
1045 background_position_compute (GtkCssStyleProperty *property,
1046 GtkStyleContext *context,
1047 GtkCssValue *specified)
1049 return _gtk_css_position_value_compute (specified, context);
1052 /*** REGISTRATION ***/
1054 static GtkSymbolicColor *
1055 gtk_symbolic_color_new_rgba (double red,
1060 GdkRGBA rgba = { red, green, blue, alpha };
1062 return gtk_symbolic_color_new_literal (&rgba);
1066 _gtk_css_style_property_init_properties (void)
1068 GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE };
1069 GtkBorder border_of_ones = { 1, 1, 1, 1 };
1070 GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
1072 /* Initialize "color" and "font-size" first,
1073 * so that when computing values later they are
1074 * done first. That way, 'currentColor' and font
1075 * sizes in em can be looked up properly */
1076 gtk_css_style_property_register ("color",
1077 GTK_CSS_PROPERTY_COLOR,
1079 GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
1082 color_property_compute,
1086 _gtk_css_value_new_take_symbolic_color (
1087 gtk_symbolic_color_new_rgba (1, 1, 1, 1)));
1088 gtk_css_style_property_register ("font-size",
1089 GTK_CSS_PROPERTY_FONT_SIZE,
1091 GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
1095 query_length_as_double,
1096 assign_length_from_double,
1098 /* XXX: This should be 'normal' */
1099 _gtk_css_number_value_new (10.0, GTK_CSS_PX));
1101 /* properties that aren't referenced when computing values
1103 gtk_css_style_property_register ("background-color",
1104 GTK_CSS_PROPERTY_BACKGROUND_COLOR,
1106 GTK_STYLE_PROPERTY_ANIMATED,
1113 _gtk_css_value_new_take_symbolic_color (
1114 gtk_symbolic_color_new_rgba (0, 0, 0, 0)));
1116 gtk_css_style_property_register ("font-family",
1117 GTK_CSS_PROPERTY_FONT_FAMILY,
1119 GTK_STYLE_PROPERTY_INHERIT,
1126 _gtk_css_array_value_new (_gtk_css_string_value_new ("Sans")));
1127 gtk_css_style_property_register ("font-style",
1128 GTK_CSS_PROPERTY_FONT_STYLE,
1130 GTK_STYLE_PROPERTY_INHERIT,
1137 _gtk_css_font_style_value_new (PANGO_STYLE_NORMAL));
1138 gtk_css_style_property_register ("font-variant",
1139 GTK_CSS_PROPERTY_FONT_VARIANT,
1141 GTK_STYLE_PROPERTY_INHERIT,
1142 parse_pango_variant,
1145 query_pango_variant,
1146 assign_pango_variant,
1148 _gtk_css_font_variant_value_new (PANGO_VARIANT_NORMAL));
1149 gtk_css_style_property_register ("font-weight",
1150 GTK_CSS_PROPERTY_FONT_WEIGHT,
1152 GTK_STYLE_PROPERTY_INHERIT,
1157 assign_pango_weight,
1159 _gtk_css_font_weight_value_new (PANGO_WEIGHT_NORMAL));
1161 gtk_css_style_property_register ("text-shadow",
1162 GTK_CSS_PROPERTY_TEXT_SHADOW,
1164 GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
1167 shadow_value_compute,
1171 _gtk_css_shadows_value_new_none ());
1173 gtk_css_style_property_register ("icon-shadow",
1174 GTK_CSS_PROPERTY_ICON_SHADOW,
1176 GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
1179 shadow_value_compute,
1183 _gtk_css_shadows_value_new_none ());
1185 gtk_css_style_property_register ("box-shadow",
1186 GTK_CSS_PROPERTY_BOX_SHADOW,
1188 GTK_STYLE_PROPERTY_ANIMATED,
1191 shadow_value_compute,
1195 _gtk_css_shadows_value_new_none ());
1197 gtk_css_style_property_register ("margin-top",
1198 GTK_CSS_PROPERTY_MARGIN_TOP,
1200 GTK_STYLE_PROPERTY_ANIMATED,
1204 query_length_as_int,
1205 assign_length_from_int,
1207 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1208 gtk_css_style_property_register ("margin-left",
1209 GTK_CSS_PROPERTY_MARGIN_LEFT,
1211 GTK_STYLE_PROPERTY_ANIMATED,
1215 query_length_as_int,
1216 assign_length_from_int,
1218 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1219 gtk_css_style_property_register ("margin-bottom",
1220 GTK_CSS_PROPERTY_MARGIN_BOTTOM,
1222 GTK_STYLE_PROPERTY_ANIMATED,
1226 query_length_as_int,
1227 assign_length_from_int,
1229 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1230 gtk_css_style_property_register ("margin-right",
1231 GTK_CSS_PROPERTY_MARGIN_RIGHT,
1233 GTK_STYLE_PROPERTY_ANIMATED,
1237 query_length_as_int,
1238 assign_length_from_int,
1240 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1241 gtk_css_style_property_register ("padding-top",
1242 GTK_CSS_PROPERTY_PADDING_TOP,
1244 GTK_STYLE_PROPERTY_ANIMATED,
1248 query_length_as_int,
1249 assign_length_from_int,
1251 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1252 gtk_css_style_property_register ("padding-left",
1253 GTK_CSS_PROPERTY_PADDING_LEFT,
1255 GTK_STYLE_PROPERTY_ANIMATED,
1259 query_length_as_int,
1260 assign_length_from_int,
1262 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1263 gtk_css_style_property_register ("padding-bottom",
1264 GTK_CSS_PROPERTY_PADDING_BOTTOM,
1266 GTK_STYLE_PROPERTY_ANIMATED,
1270 query_length_as_int,
1271 assign_length_from_int,
1273 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1274 gtk_css_style_property_register ("padding-right",
1275 GTK_CSS_PROPERTY_PADDING_RIGHT,
1277 GTK_STYLE_PROPERTY_ANIMATED,
1281 query_length_as_int,
1282 assign_length_from_int,
1284 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1285 /* IMPORTANT: compute_border_width() requires that the border-width
1286 * properties be immeditaly followed by the border-style properties
1288 gtk_css_style_property_register ("border-top-style",
1289 GTK_CSS_PROPERTY_BORDER_TOP_STYLE,
1290 GTK_TYPE_BORDER_STYLE,
1296 assign_border_style,
1298 _gtk_css_border_style_value_new (GTK_BORDER_STYLE_NONE));
1299 gtk_css_style_property_register ("border-top-width",
1300 GTK_CSS_PROPERTY_BORDER_TOP_WIDTH,
1302 GTK_STYLE_PROPERTY_ANIMATED,
1305 compute_border_width,
1306 query_length_as_int,
1307 assign_length_from_int,
1309 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1310 gtk_css_style_property_register ("border-left-style",
1311 GTK_CSS_PROPERTY_BORDER_LEFT_STYLE,
1312 GTK_TYPE_BORDER_STYLE,
1318 assign_border_style,
1320 _gtk_css_border_style_value_new (GTK_BORDER_STYLE_NONE));
1321 gtk_css_style_property_register ("border-left-width",
1322 GTK_CSS_PROPERTY_BORDER_LEFT_WIDTH,
1324 GTK_STYLE_PROPERTY_ANIMATED,
1327 compute_border_width,
1328 query_length_as_int,
1329 assign_length_from_int,
1331 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1332 gtk_css_style_property_register ("border-bottom-style",
1333 GTK_CSS_PROPERTY_BORDER_BOTTOM_STYLE,
1334 GTK_TYPE_BORDER_STYLE,
1340 assign_border_style,
1342 _gtk_css_border_style_value_new (GTK_BORDER_STYLE_NONE));
1343 gtk_css_style_property_register ("border-bottom-width",
1344 GTK_CSS_PROPERTY_BORDER_BOTTOM_WIDTH,
1346 GTK_STYLE_PROPERTY_ANIMATED,
1349 compute_border_width,
1350 query_length_as_int,
1351 assign_length_from_int,
1353 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1354 gtk_css_style_property_register ("border-right-style",
1355 GTK_CSS_PROPERTY_BORDER_RIGHT_STYLE,
1356 GTK_TYPE_BORDER_STYLE,
1362 assign_border_style,
1364 _gtk_css_border_style_value_new (GTK_BORDER_STYLE_NONE));
1365 gtk_css_style_property_register ("border-right-width",
1366 GTK_CSS_PROPERTY_BORDER_RIGHT_WIDTH,
1368 GTK_STYLE_PROPERTY_ANIMATED,
1371 compute_border_width,
1372 query_length_as_int,
1373 assign_length_from_int,
1375 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1377 gtk_css_style_property_register ("border-top-left-radius",
1378 GTK_CSS_PROPERTY_BORDER_TOP_LEFT_RADIUS,
1380 GTK_STYLE_PROPERTY_ANIMATED,
1381 border_corner_radius_value_parse,
1383 border_corner_radius_value_compute,
1387 _gtk_css_corner_value_new (_gtk_css_number_value_new (0, GTK_CSS_PX),
1388 _gtk_css_number_value_new (0, GTK_CSS_PX)));
1389 gtk_css_style_property_register ("border-top-right-radius",
1390 GTK_CSS_PROPERTY_BORDER_TOP_RIGHT_RADIUS,
1392 GTK_STYLE_PROPERTY_ANIMATED,
1393 border_corner_radius_value_parse,
1395 border_corner_radius_value_compute,
1399 _gtk_css_corner_value_new (_gtk_css_number_value_new (0, GTK_CSS_PX),
1400 _gtk_css_number_value_new (0, GTK_CSS_PX)));
1401 gtk_css_style_property_register ("border-bottom-right-radius",
1402 GTK_CSS_PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS,
1404 GTK_STYLE_PROPERTY_ANIMATED,
1405 border_corner_radius_value_parse,
1407 border_corner_radius_value_compute,
1411 _gtk_css_corner_value_new (_gtk_css_number_value_new (0, GTK_CSS_PX),
1412 _gtk_css_number_value_new (0, GTK_CSS_PX)));
1413 gtk_css_style_property_register ("border-bottom-left-radius",
1414 GTK_CSS_PROPERTY_BORDER_BOTTOM_LEFT_RADIUS,
1416 GTK_STYLE_PROPERTY_ANIMATED,
1417 border_corner_radius_value_parse,
1419 border_corner_radius_value_compute,
1423 _gtk_css_corner_value_new (_gtk_css_number_value_new (0, GTK_CSS_PX),
1424 _gtk_css_number_value_new (0, GTK_CSS_PX)));
1426 gtk_css_style_property_register ("outline-style",
1427 GTK_CSS_PROPERTY_OUTLINE_STYLE,
1428 GTK_TYPE_BORDER_STYLE,
1434 assign_border_style,
1436 _gtk_css_border_style_value_new (GTK_BORDER_STYLE_NONE));
1437 gtk_css_style_property_register ("outline-width",
1438 GTK_CSS_PROPERTY_OUTLINE_WIDTH,
1440 GTK_STYLE_PROPERTY_ANIMATED,
1443 compute_border_width,
1444 query_length_as_int,
1445 assign_length_from_int,
1447 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1448 gtk_css_style_property_register ("outline-offset",
1449 GTK_CSS_PROPERTY_OUTLINE_OFFSET,
1455 query_length_as_int,
1456 assign_length_from_int,
1458 _gtk_css_number_value_new (0.0, GTK_CSS_PX));
1460 gtk_css_style_property_register ("background-clip",
1461 GTK_CSS_PROPERTY_BACKGROUND_CLIP,
1470 _gtk_css_area_value_new (GTK_CSS_AREA_BORDER_BOX));
1471 gtk_css_style_property_register ("background-origin",
1472 GTK_CSS_PROPERTY_BACKGROUND_ORIGIN,
1481 _gtk_css_area_value_new (GTK_CSS_AREA_PADDING_BOX));
1482 gtk_css_style_property_register ("background-size",
1483 GTK_CSS_PROPERTY_BACKGROUND_SIZE,
1486 background_size_parse,
1487 background_size_print,
1488 background_size_compute,
1492 _gtk_css_value_new_from_background_size (&default_background_size));
1493 gtk_css_style_property_register ("background-position",
1494 GTK_CSS_PROPERTY_BACKGROUND_POSITION,
1496 GTK_STYLE_PROPERTY_ANIMATED,
1497 background_position_parse,
1499 background_position_compute,
1503 _gtk_css_position_value_new (_gtk_css_number_value_new (0, GTK_CSS_PERCENT),
1504 _gtk_css_number_value_new (0, GTK_CSS_PERCENT)));
1506 gtk_css_style_property_register ("border-top-color",
1507 GTK_CSS_PROPERTY_BORDER_TOP_COLOR,
1509 GTK_STYLE_PROPERTY_ANIMATED,
1516 _gtk_css_value_new_take_symbolic_color (
1517 gtk_symbolic_color_ref (
1518 _gtk_symbolic_color_get_current_color ())));
1519 gtk_css_style_property_register ("border-right-color",
1520 GTK_CSS_PROPERTY_BORDER_RIGHT_COLOR,
1522 GTK_STYLE_PROPERTY_ANIMATED,
1529 _gtk_css_value_new_take_symbolic_color (
1530 gtk_symbolic_color_ref (
1531 _gtk_symbolic_color_get_current_color ())));
1532 gtk_css_style_property_register ("border-bottom-color",
1533 GTK_CSS_PROPERTY_BORDER_BOTTOM_COLOR,
1535 GTK_STYLE_PROPERTY_ANIMATED,
1542 _gtk_css_value_new_take_symbolic_color (
1543 gtk_symbolic_color_ref (
1544 _gtk_symbolic_color_get_current_color ())));
1545 gtk_css_style_property_register ("border-left-color",
1546 GTK_CSS_PROPERTY_BORDER_LEFT_COLOR,
1548 GTK_STYLE_PROPERTY_ANIMATED,
1555 _gtk_css_value_new_take_symbolic_color (
1556 gtk_symbolic_color_ref (
1557 _gtk_symbolic_color_get_current_color ())));
1558 gtk_css_style_property_register ("outline-color",
1559 GTK_CSS_PROPERTY_OUTLINE_COLOR,
1561 GTK_STYLE_PROPERTY_ANIMATED,
1568 _gtk_css_value_new_take_symbolic_color (
1569 gtk_symbolic_color_ref (
1570 _gtk_symbolic_color_get_current_color ())));
1572 gtk_css_style_property_register ("background-repeat",
1573 GTK_CSS_PROPERTY_BACKGROUND_REPEAT,
1574 GTK_TYPE_CSS_BACKGROUND_REPEAT,
1576 background_repeat_value_parse,
1577 background_repeat_value_print,
1582 _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT,
1583 GTK_CSS_BACKGROUND_REPEAT |
1584 (GTK_CSS_BACKGROUND_REPEAT << GTK_CSS_BACKGROUND_REPEAT_SHIFT)));
1585 gtk_css_style_property_register ("background-image",
1586 GTK_CSS_PROPERTY_BACKGROUND_IMAGE,
1587 CAIRO_GOBJECT_TYPE_PATTERN,
1588 GTK_STYLE_PROPERTY_ANIMATED,
1589 css_image_value_parse,
1591 css_image_value_compute,
1592 css_image_value_query,
1593 css_image_value_assign,
1595 _gtk_css_image_value_new (NULL));
1597 gtk_css_style_property_register ("border-image-source",
1598 GTK_CSS_PROPERTY_BORDER_IMAGE_SOURCE,
1599 CAIRO_GOBJECT_TYPE_PATTERN,
1600 GTK_STYLE_PROPERTY_ANIMATED,
1601 css_image_value_parse,
1603 css_image_value_compute,
1604 css_image_value_query,
1605 css_image_value_assign,
1607 _gtk_css_image_value_new (NULL));
1608 gtk_css_style_property_register ("border-image-repeat",
1609 GTK_CSS_PROPERTY_BORDER_IMAGE_REPEAT,
1610 GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1612 border_image_repeat_parse,
1618 _gtk_css_value_new_from_border_image_repeat (&border_image_repeat));
1620 /* XXX: The initial value is wrong, it should be 100% */
1621 gtk_css_style_property_register ("border-image-slice",
1622 GTK_CSS_PROPERTY_BORDER_IMAGE_SLICE,
1625 border_image_slice_parse,
1631 _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, &border_of_ones));
1632 gtk_css_style_property_register ("border-image-width",
1633 GTK_CSS_PROPERTY_BORDER_IMAGE_WIDTH,
1636 border_image_width_parse,
1642 _gtk_css_value_new_from_boxed (GTK_TYPE_BORDER, NULL));
1644 gtk_css_style_property_register ("transition-property",
1645 GTK_CSS_PROPERTY_TRANSITION_PROPERTY,
1648 transition_property_parse,
1654 _gtk_css_array_value_new (_gtk_css_ident_value_new ("all")));
1655 gtk_css_style_property_register ("transition-duration",
1656 GTK_CSS_PROPERTY_TRANSITION_DURATION,
1659 transition_time_parse,
1665 _gtk_css_array_value_new (_gtk_css_number_value_new (0, GTK_CSS_S)));
1666 gtk_css_style_property_register ("transition-timing-function",
1667 GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION,
1670 transition_timing_function_parse,
1676 _gtk_css_array_value_new (
1677 _gtk_css_ease_value_new_cubic_bezier (0.25, 0.1, 0.25, 1.0)));
1678 gtk_css_style_property_register ("transition-delay",
1679 GTK_CSS_PROPERTY_TRANSITION_DELAY,
1682 transition_time_parse,
1688 _gtk_css_array_value_new (_gtk_css_number_value_new (0, GTK_CSS_S)));
1690 gtk_css_style_property_register ("engine",
1691 GTK_CSS_PROPERTY_ENGINE,
1692 GTK_TYPE_THEMING_ENGINE,
1700 _gtk_css_engine_value_new (gtk_theming_engine_load (NULL)));
1701 gtk_css_style_property_register ("transition",
1702 GTK_CSS_PROPERTY_TRANSITION,
1703 GTK_TYPE_ANIMATION_DESCRIPTION,
1711 _gtk_css_value_new_from_boxed (GTK_TYPE_ANIMATION_DESCRIPTION, NULL));
1713 /* Private property holding the binding sets */
1714 gtk_css_style_property_register ("gtk-key-bindings",
1715 GTK_CSS_PROPERTY_GTK_KEY_BINDINGS,
1718 bindings_value_parse,
1721 bindings_value_query,
1722 bindings_value_assign,
1724 _gtk_css_array_value_new (NULL));