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 "gtkcssimageprivate.h"
44 #include "gtkgradient.h"
45 #include "gtkshadowprivate.h"
46 #include "gtksymboliccolorprivate.h"
47 #include "gtkthemingengine.h"
48 #include "gtktypebuiltins.h"
49 #include "gtkwin32themeprivate.h"
51 /*** REGISTRATION ***/
54 gtk_css_style_property_register (const char * name,
58 GtkStylePropertyFlags flags,
59 GtkCssStylePropertyParseFunc parse_value,
60 GtkCssStylePropertyPrintFunc print_value,
61 GtkCssStylePropertyComputeFunc compute_value,
62 GtkCssStylePropertyEqualFunc equal_func,
65 GtkCssStyleProperty *node;
66 GValue initial_gvalue = G_VALUE_INIT;
67 GtkCssValue *initial_value;
71 va_start (args, equal_func);
72 G_VALUE_COLLECT_INIT (&initial_gvalue, specified_type,
76 g_error ("property `%s' initial value is broken: %s", name, error);
77 g_value_unset (&initial_gvalue);
83 initial_value = _gtk_css_value_new_take_gvalue (&initial_gvalue);
85 node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
86 "value-type", value_type,
87 "computed-type", computed_type,
88 "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
89 "initial-value", initial_value,
94 node->parse_value = parse_value;
96 node->print_value = print_value;
98 node->compute_value = compute_value;
100 node->equal_func = equal_func;
102 _gtk_css_value_unref (initial_value);
108 string_append_string (GString *str,
113 g_string_append_c (str, '"');
116 len = strcspn (string, "\"\n\r\f");
117 g_string_append (str, string);
124 g_string_append (str, "\\A ");
127 g_string_append (str, "\\D ");
130 g_string_append (str, "\\C ");
133 g_string_append (str, "\\\"");
136 g_assert_not_reached ();
141 g_string_append_c (str, '"');
144 /*** IMPLEMENTATIONS ***/
147 color_compute (GtkCssStyleProperty *property,
148 GtkStyleContext *context,
149 GtkCssValue *specified)
151 GtkSymbolicColor *symbolic = _gtk_css_value_get_symbolic_color (specified);
152 GtkCssValue *resolved;
154 if (symbolic == _gtk_symbolic_color_get_current_color ())
156 /* The computed value of the ‘currentColor’ keyword is the computed
157 * value of the ‘color’ property. If the ‘currentColor’ keyword is
158 * set on the ‘color’ property itself, it is treated as ‘color: inherit’.
160 if (g_str_equal (_gtk_style_property_get_name (GTK_STYLE_PROPERTY (property)), "color"))
162 GtkStyleContext *parent = gtk_style_context_get_parent (context);
165 return _gtk_css_value_ref (_gtk_style_context_peek_property (parent, "color"));
167 return _gtk_css_style_compute_value (context,
169 _gtk_css_style_property_get_initial_value (property));
173 return _gtk_css_value_ref (_gtk_style_context_peek_property (context, "color"));
176 else if ((resolved = _gtk_style_context_resolve_color_value (context,
183 return color_compute (property,
185 _gtk_css_style_property_get_initial_value (property));
190 font_family_parse (GtkCssStyleProperty *property,
192 GtkCssParser *parser,
198 /* We don't special case generic families. Pango should do
201 names = g_ptr_array_new ();
204 name = _gtk_css_parser_try_ident (parser, TRUE);
207 GString *string = g_string_new (name);
209 while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
211 g_string_append_c (string, ' ');
212 g_string_append (string, name);
215 name = g_string_free (string, FALSE);
219 name = _gtk_css_parser_read_string (parser);
222 g_ptr_array_free (names, TRUE);
227 g_ptr_array_add (names, name);
228 } while (_gtk_css_parser_try (parser, ",", TRUE));
230 /* NULL-terminate array */
231 g_ptr_array_add (names, NULL);
232 g_value_set_boxed (value, g_ptr_array_free (names, FALSE));
237 font_family_value_print (GtkCssStyleProperty *property,
238 const GtkCssValue *value,
241 const char **names = _gtk_css_value_get_strv (value);
243 if (names == NULL || *names == NULL)
245 g_string_append (string, "none");
249 string_append_string (string, *names);
253 g_string_append (string, ", ");
254 string_append_string (string, *names);
260 bindings_value_parse (GtkCssStyleProperty *property,
262 GtkCssParser *parser,
266 GtkBindingSet *binding_set;
269 array = g_ptr_array_new ();
272 name = _gtk_css_parser_try_ident (parser, TRUE);
275 _gtk_css_parser_error (parser, "Not a valid binding name");
276 g_ptr_array_free (array, TRUE);
280 binding_set = gtk_binding_set_find (name);
284 _gtk_css_parser_error (parser, "No binding set named '%s'", name);
289 g_ptr_array_add (array, binding_set);
292 while (_gtk_css_parser_try (parser, ",", TRUE));
294 g_value_take_boxed (value, array);
300 bindings_value_print (GtkCssStyleProperty *property,
301 const GtkCssValue *value,
307 array = _gtk_css_value_get_boxed (value);
309 for (i = 0; i < array->len; i++)
311 GtkBindingSet *binding_set = g_ptr_array_index (array, i);
314 g_string_append (string, ", ");
315 g_string_append (string, binding_set->set_name);
320 border_corner_radius_value_parse (GtkCssStyleProperty *property,
322 GtkCssParser *parser,
325 GtkCssBorderCornerRadius corner;
327 if (!_gtk_css_parser_read_number (parser,
329 GTK_CSS_POSITIVE_ONLY
330 | GTK_CSS_PARSE_PERCENT
331 | GTK_CSS_NUMBER_AS_PIXELS
332 | GTK_CSS_PARSE_LENGTH))
335 if (!_gtk_css_parser_has_number (parser))
336 corner.vertical = corner.horizontal;
337 else if (!_gtk_css_parser_read_number (parser,
339 GTK_CSS_POSITIVE_ONLY
340 | GTK_CSS_PARSE_PERCENT
341 | GTK_CSS_NUMBER_AS_PIXELS
342 | GTK_CSS_PARSE_LENGTH))
345 g_value_set_boxed (value, &corner);
350 border_corner_radius_value_print (GtkCssStyleProperty *property,
351 const GtkCssValue *value,
354 const GtkCssBorderCornerRadius *corner;
356 corner = _gtk_css_value_get_border_corner_radius (value);
358 _gtk_css_number_print (&corner->horizontal, string);
360 if (!_gtk_css_number_equal (&corner->horizontal, &corner->vertical))
362 g_string_append_c (string, ' ');
363 _gtk_css_number_print (&corner->vertical, string);
368 css_image_value_parse (GtkCssStyleProperty *property,
370 GtkCssParser *parser,
375 if (_gtk_css_parser_try (parser, "none", TRUE))
379 image = _gtk_css_image_new_parse (parser, base);
384 g_value_take_object (value, image);
389 css_image_value_print (GtkCssStyleProperty *property,
390 const GtkCssValue *value,
393 GtkCssImage *image = _gtk_css_value_get_image (value);
396 _gtk_css_image_print (image, string);
398 g_string_append (string, "none");
402 css_image_value_compute (GtkCssStyleProperty *property,
403 GtkStyleContext *context,
404 GtkCssValue *specified)
406 GtkCssImage *image, *computed;
408 image = _gtk_css_value_get_image (specified);
411 return _gtk_css_value_ref (specified);
413 computed = _gtk_css_image_compute (image, context);
415 if (computed == image)
417 g_object_unref (computed);
418 return _gtk_css_value_ref (specified);
421 return _gtk_css_value_new_take_image (computed);
425 parse_margin (GtkCssStyleProperty *property,
427 GtkCssParser *parser,
432 if (!_gtk_css_parser_read_number (parser,
434 GTK_CSS_NUMBER_AS_PIXELS
435 | GTK_CSS_PARSE_LENGTH))
438 g_value_set_boxed (value, &number);
443 compute_margin (GtkCssStyleProperty *property,
444 GtkStyleContext *context,
445 GtkCssValue *specified)
449 if (_gtk_css_number_compute (&number,
450 _gtk_css_value_get_number (specified),
453 return _gtk_css_value_new_from_number (&number);
455 return _gtk_css_value_ref (specified);
459 parse_padding (GtkCssStyleProperty *property,
461 GtkCssParser *parser,
466 if (!_gtk_css_parser_read_number (parser,
468 GTK_CSS_POSITIVE_ONLY
469 | GTK_CSS_NUMBER_AS_PIXELS
470 | GTK_CSS_PARSE_LENGTH))
473 g_value_set_boxed (value, &number);
478 compute_padding (GtkCssStyleProperty *property,
479 GtkStyleContext *context,
480 GtkCssValue *specified)
484 if (_gtk_css_number_compute (&number,
485 _gtk_css_value_get_number (specified),
487 return _gtk_css_value_new_from_number (&number);
488 return _gtk_css_value_ref (specified);
492 parse_border_width (GtkCssStyleProperty *property,
494 GtkCssParser *parser,
499 if (!_gtk_css_parser_read_number (parser,
501 GTK_CSS_POSITIVE_ONLY
502 | GTK_CSS_NUMBER_AS_PIXELS
503 | GTK_CSS_PARSE_LENGTH))
506 g_value_set_boxed (value, &number);
511 compute_border_width (GtkCssStyleProperty *property,
512 GtkStyleContext *context,
513 GtkCssValue *specified)
515 GtkCssStyleProperty *style;
516 GtkBorderStyle border_style;
520 /* The -1 is magic that is only true because we register the style
521 * properties directly after the width properties.
523 style = _gtk_css_style_property_lookup_by_id (_gtk_css_style_property_get_id (property) - 1);
525 border_style = _gtk_css_value_get_border_style (_gtk_style_context_peek_property (context, _gtk_style_property_get_name (GTK_STYLE_PROPERTY (style))));
527 if (border_style == GTK_BORDER_STYLE_NONE ||
528 border_style == GTK_BORDER_STYLE_HIDDEN)
534 _gtk_css_number_compute (&number,
535 _gtk_css_value_get_number (specified),
537 value = round (number.value);
539 return _gtk_css_value_new_from_int (value);
543 background_repeat_value_parse (GtkCssStyleProperty *property,
545 GtkCssParser *parser,
548 int repeat, vertical;
550 if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &repeat))
552 _gtk_css_parser_error (parser, "Not a valid value");
556 if (repeat <= GTK_CSS_BACKGROUND_REPEAT_MASK)
558 if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
560 if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
562 _gtk_css_parser_error (parser, "Not a valid 2nd value");
566 repeat |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
569 repeat |= repeat << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
572 g_value_set_enum (value, repeat);
577 background_repeat_value_print (GtkCssStyleProperty *property,
578 const GtkCssValue *value,
581 GEnumClass *enum_class;
582 GEnumValue *enum_value;
583 GtkCssBackgroundRepeat repeat;
585 repeat = _gtk_css_value_get_enum (value);
586 enum_class = g_type_class_ref (GTK_TYPE_CSS_BACKGROUND_REPEAT);
587 enum_value = g_enum_get_value (enum_class, repeat);
589 /* only triggers for 'repeat-x' and 'repeat-y' */
591 g_string_append (string, enum_value->value_nick);
594 enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_HORIZONTAL (repeat));
595 g_string_append (string, enum_value->value_nick);
597 if (GTK_CSS_BACKGROUND_HORIZONTAL (repeat) != GTK_CSS_BACKGROUND_VERTICAL (repeat))
599 enum_value = g_enum_get_value (enum_class, GTK_CSS_BACKGROUND_VERTICAL (repeat));
600 g_string_append (string, " ");
601 g_string_append (string, enum_value->value_nick);
605 g_type_class_unref (enum_class);
609 background_size_parse (GtkCssStyleProperty *property,
611 GtkCssParser *parser,
614 GtkCssBackgroundSize size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE};
616 if (_gtk_css_parser_try (parser, "cover", TRUE))
618 else if (_gtk_css_parser_try (parser, "contain", TRUE))
622 if (_gtk_css_parser_try (parser, "auto", TRUE))
623 _gtk_css_number_init (&size.width, 0, GTK_CSS_PX);
624 else if (!_gtk_css_parser_read_number (parser,
626 GTK_CSS_POSITIVE_ONLY
627 | GTK_CSS_PARSE_PERCENT
628 | GTK_CSS_PARSE_LENGTH))
631 if (_gtk_css_parser_try (parser, "auto", TRUE))
632 _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
633 else if (_gtk_css_parser_has_number (parser))
635 if (!_gtk_css_parser_read_number (parser,
637 GTK_CSS_POSITIVE_ONLY
638 | GTK_CSS_PARSE_PERCENT
639 | GTK_CSS_PARSE_LENGTH))
643 _gtk_css_number_init (&size.height, 0, GTK_CSS_PX);
646 g_value_set_boxed (value, &size);
651 background_size_print (GtkCssStyleProperty *property,
652 const GtkCssValue *value,
655 const GtkCssBackgroundSize *size = _gtk_css_value_get_background_size (value);
658 g_string_append (string, "cover");
659 else if (size->contain)
660 g_string_append (string, "contain");
663 if (size->width.value == 0)
664 g_string_append (string, "auto");
666 _gtk_css_number_print (&size->width, string);
668 if (size->height.value != 0)
670 g_string_append (string, " ");
671 _gtk_css_number_print (&size->height, string);
677 background_size_compute (GtkCssStyleProperty *property,
678 GtkStyleContext *context,
679 GtkCssValue *specified)
681 const GtkCssBackgroundSize *ssize = _gtk_css_value_get_background_size (specified);
682 GtkCssBackgroundSize csize;
685 csize.cover = ssize->cover;
686 csize.contain = ssize->contain;
687 changed = _gtk_css_number_compute (&csize.width,
690 changed |= _gtk_css_number_compute (&csize.height,
694 return _gtk_css_value_new_from_background_size (&csize);
695 return _gtk_css_value_ref (specified);
699 background_position_parse (GtkCssStyleProperty *property,
701 GtkCssParser *parser,
704 static const struct {
710 { "left", 0, TRUE, FALSE },
711 { "right", 100, TRUE, FALSE },
712 { "center", 50, TRUE, TRUE },
713 { "top", 0, FALSE, TRUE },
714 { "bottom", 100, FALSE, TRUE },
715 { NULL , 0, TRUE, FALSE }, /* used for numbers */
716 { NULL , 50, TRUE, TRUE } /* used for no value */
718 GtkCssBackgroundPosition pos;
719 GtkCssNumber *missing;
722 for (first = 0; names[first].name != NULL; first++)
724 if (_gtk_css_parser_try (parser, names[first].name, TRUE))
726 if (names[first].horizontal)
728 _gtk_css_number_init (&pos.x, names[first].percentage, GTK_CSS_PERCENT);
733 _gtk_css_number_init (&pos.y, names[first].percentage, GTK_CSS_PERCENT);
739 if (names[first].name == NULL)
742 if (!_gtk_css_parser_read_number (parser,
744 GTK_CSS_PARSE_PERCENT
745 | GTK_CSS_PARSE_LENGTH))
749 for (second = 0; names[second].name != NULL; second++)
751 if (_gtk_css_parser_try (parser, names[second].name, TRUE))
753 _gtk_css_number_init (missing, names[second].percentage, GTK_CSS_PERCENT);
758 if (names[second].name == NULL)
760 if (_gtk_css_parser_has_number (parser))
762 if (missing != &pos.y)
764 _gtk_css_parser_error (parser, "Invalid combination of values");
767 if (!_gtk_css_parser_read_number (parser,
769 GTK_CSS_PARSE_PERCENT
770 | GTK_CSS_PARSE_LENGTH))
776 _gtk_css_number_init (missing, 50, GTK_CSS_PERCENT);
781 if ((names[first].horizontal && !names[second].vertical) ||
782 (!names[first].horizontal && !names[second].horizontal))
784 _gtk_css_parser_error (parser, "Invalid combination of values");
789 g_value_set_boxed (value, &pos);
794 background_position_print (GtkCssStyleProperty *property,
795 const GtkCssValue *value,
798 const GtkCssBackgroundPosition *pos = _gtk_css_value_get_background_position (value);
799 static const GtkCssNumber center = GTK_CSS_NUMBER_INIT (50, GTK_CSS_PERCENT);
800 static const struct {
805 { "left", "top", GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT) },
806 { "right", "bottom", GTK_CSS_NUMBER_INIT (100, GTK_CSS_PERCENT) }
810 if (_gtk_css_number_equal (&pos->x, ¢er))
812 if (_gtk_css_number_equal (&pos->y, ¢er))
814 g_string_append (string, "center");
820 for (i = 0; i < G_N_ELEMENTS (values); i++)
822 if (_gtk_css_number_equal (&pos->x, &values[i].number))
824 g_string_append (string, values[i].x_name);
828 if (i == G_N_ELEMENTS (values))
829 _gtk_css_number_print (&pos->x, string);
831 if (_gtk_css_number_equal (&pos->y, ¢er))
834 g_string_append_c (string, ' ');
837 for (i = 0; i < G_N_ELEMENTS (values); i++)
839 if (_gtk_css_number_equal (&pos->y, &values[i].number))
841 g_string_append (string, values[i].y_name);
845 if (i == G_N_ELEMENTS (values))
847 if (_gtk_css_number_equal (&pos->x, ¢er))
848 g_string_append (string, "center ");
849 _gtk_css_number_print (&pos->y, string);
854 background_position_compute (GtkCssStyleProperty *property,
855 GtkStyleContext *context,
856 GtkCssValue *specified)
858 const GtkCssBackgroundPosition *spos = _gtk_css_value_get_background_position (specified);
859 GtkCssBackgroundPosition cpos;
862 changed = _gtk_css_number_compute (&cpos.x,
865 changed |= _gtk_css_number_compute (&cpos.y,
869 return _gtk_css_value_new_from_background_position (&cpos);
870 return _gtk_css_value_ref (specified);
873 /*** REGISTRATION ***/
875 static GtkSymbolicColor *
876 gtk_symbolic_color_new_rgba (double red,
881 GdkRGBA rgba = { red, green, blue, alpha };
883 return gtk_symbolic_color_new_literal (&rgba);
887 _gtk_css_style_property_init_properties (void)
889 char *default_font_family[] = { "Sans", NULL };
891 GtkSymbolicColor *symbolic;
892 GtkCssBackgroundSize default_background_size = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), FALSE, FALSE };
893 GtkCssBackgroundPosition default_background_position = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PERCENT)};
894 GtkCssBorderCornerRadius no_corner_radius = { GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX), GTK_CSS_NUMBER_INIT (0, GTK_CSS_PX) };
895 GtkBorder border_of_ones = { 1, 1, 1, 1 };
896 GtkCssBorderImageRepeat border_image_repeat = { GTK_CSS_REPEAT_STYLE_STRETCH, GTK_CSS_REPEAT_STYLE_STRETCH };
898 /* Initialize "color" and "font-size" first,
899 * so that when computing values later they are
900 * done first. That way, 'currentColor' and font
901 * sizes in em can be looked up properly */
902 symbolic = gtk_symbolic_color_new_rgba (1, 1, 1, 1);
903 gtk_css_style_property_register ("color",
904 GTK_TYPE_SYMBOLIC_COLOR,
907 GTK_STYLE_PROPERTY_INHERIT,
913 gtk_symbolic_color_unref (symbolic);
914 gtk_css_style_property_register ("font-size",
918 GTK_STYLE_PROPERTY_INHERIT,
925 /* properties that aren't referenced when computing values
927 symbolic = gtk_symbolic_color_new_rgba (0, 0, 0, 0);
928 gtk_css_style_property_register ("background-color",
929 GTK_TYPE_SYMBOLIC_COLOR,
938 gtk_symbolic_color_unref (symbolic);
940 gtk_css_style_property_register ("font-family",
944 GTK_STYLE_PROPERTY_INHERIT,
946 font_family_value_print,
949 default_font_family);
950 gtk_css_style_property_register ("font-style",
954 GTK_STYLE_PROPERTY_INHERIT,
960 gtk_css_style_property_register ("font-variant",
964 GTK_STYLE_PROPERTY_INHERIT,
969 PANGO_VARIANT_NORMAL);
970 /* xxx: need to parse this properly, ie parse the numbers */
971 gtk_css_style_property_register ("font-weight",
975 GTK_STYLE_PROPERTY_INHERIT,
980 PANGO_WEIGHT_NORMAL);
982 gtk_css_style_property_register ("text-shadow",
986 GTK_STYLE_PROPERTY_INHERIT,
993 gtk_css_style_property_register ("icon-shadow",
997 GTK_STYLE_PROPERTY_INHERIT,
1004 gtk_css_style_property_register ("box-shadow",
1015 _gtk_css_number_init (&number, 0, GTK_CSS_PX);
1016 gtk_css_style_property_register ("margin-top",
1017 GTK_TYPE_CSS_NUMBER,
1018 GTK_TYPE_CSS_NUMBER,
1026 gtk_css_style_property_register ("margin-left",
1027 GTK_TYPE_CSS_NUMBER,
1028 GTK_TYPE_CSS_NUMBER,
1036 gtk_css_style_property_register ("margin-bottom",
1037 GTK_TYPE_CSS_NUMBER,
1038 GTK_TYPE_CSS_NUMBER,
1046 gtk_css_style_property_register ("margin-right",
1047 GTK_TYPE_CSS_NUMBER,
1048 GTK_TYPE_CSS_NUMBER,
1056 gtk_css_style_property_register ("padding-top",
1057 GTK_TYPE_CSS_NUMBER,
1058 GTK_TYPE_CSS_NUMBER,
1066 gtk_css_style_property_register ("padding-left",
1067 GTK_TYPE_CSS_NUMBER,
1068 GTK_TYPE_CSS_NUMBER,
1076 gtk_css_style_property_register ("padding-bottom",
1077 GTK_TYPE_CSS_NUMBER,
1078 GTK_TYPE_CSS_NUMBER,
1086 gtk_css_style_property_register ("padding-right",
1087 GTK_TYPE_CSS_NUMBER,
1088 GTK_TYPE_CSS_NUMBER,
1096 /* IMPORTANT: compute_border_width() requires that the border-width
1097 * properties be immeditaly followed by the border-style properties
1099 gtk_css_style_property_register ("border-top-style",
1100 GTK_TYPE_BORDER_STYLE,
1101 GTK_TYPE_BORDER_STYLE,
1102 GTK_TYPE_BORDER_STYLE,
1108 GTK_BORDER_STYLE_NONE);
1109 gtk_css_style_property_register ("border-top-width",
1110 GTK_TYPE_CSS_NUMBER,
1116 compute_border_width,
1119 gtk_css_style_property_register ("border-left-style",
1120 GTK_TYPE_BORDER_STYLE,
1121 GTK_TYPE_BORDER_STYLE,
1122 GTK_TYPE_BORDER_STYLE,
1128 GTK_BORDER_STYLE_NONE);
1129 gtk_css_style_property_register ("border-left-width",
1130 GTK_TYPE_CSS_NUMBER,
1136 compute_border_width,
1139 gtk_css_style_property_register ("border-bottom-style",
1140 GTK_TYPE_BORDER_STYLE,
1141 GTK_TYPE_BORDER_STYLE,
1142 GTK_TYPE_BORDER_STYLE,
1148 GTK_BORDER_STYLE_NONE);
1149 gtk_css_style_property_register ("border-bottom-width",
1150 GTK_TYPE_CSS_NUMBER,
1156 compute_border_width,
1159 gtk_css_style_property_register ("border-right-style",
1160 GTK_TYPE_BORDER_STYLE,
1161 GTK_TYPE_BORDER_STYLE,
1162 GTK_TYPE_BORDER_STYLE,
1168 GTK_BORDER_STYLE_NONE);
1169 gtk_css_style_property_register ("border-right-width",
1170 GTK_TYPE_CSS_NUMBER,
1176 compute_border_width,
1180 gtk_css_style_property_register ("border-top-left-radius",
1181 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1182 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1183 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1185 border_corner_radius_value_parse,
1186 border_corner_radius_value_print,
1190 gtk_css_style_property_register ("border-top-right-radius",
1191 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1192 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1193 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1195 border_corner_radius_value_parse,
1196 border_corner_radius_value_print,
1200 gtk_css_style_property_register ("border-bottom-right-radius",
1201 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1202 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1203 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1205 border_corner_radius_value_parse,
1206 border_corner_radius_value_print,
1210 gtk_css_style_property_register ("border-bottom-left-radius",
1211 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1212 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1213 GTK_TYPE_CSS_BORDER_CORNER_RADIUS,
1215 border_corner_radius_value_parse,
1216 border_corner_radius_value_print,
1221 gtk_css_style_property_register ("outline-style",
1222 GTK_TYPE_BORDER_STYLE,
1223 GTK_TYPE_BORDER_STYLE,
1224 GTK_TYPE_BORDER_STYLE,
1230 GTK_BORDER_STYLE_NONE);
1231 gtk_css_style_property_register ("outline-width",
1232 GTK_TYPE_CSS_NUMBER,
1238 compute_border_width,
1241 gtk_css_style_property_register ("outline-offset",
1252 gtk_css_style_property_register ("background-clip",
1261 GTK_CSS_AREA_BORDER_BOX);
1262 gtk_css_style_property_register ("background-origin",
1271 GTK_CSS_AREA_PADDING_BOX);
1272 gtk_css_style_property_register ("background-size",
1273 GTK_TYPE_CSS_BACKGROUND_SIZE,
1274 GTK_TYPE_CSS_BACKGROUND_SIZE,
1277 background_size_parse,
1278 background_size_print,
1279 background_size_compute,
1281 &default_background_size);
1282 gtk_css_style_property_register ("background-position",
1283 GTK_TYPE_CSS_BACKGROUND_POSITION,
1284 GTK_TYPE_CSS_BACKGROUND_POSITION,
1287 background_position_parse,
1288 background_position_print,
1289 background_position_compute,
1291 &default_background_position);
1293 gtk_css_style_property_register ("border-top-color",
1294 GTK_TYPE_SYMBOLIC_COLOR,
1302 _gtk_symbolic_color_get_current_color ());
1303 gtk_css_style_property_register ("border-right-color",
1304 GTK_TYPE_SYMBOLIC_COLOR,
1312 _gtk_symbolic_color_get_current_color ());
1313 gtk_css_style_property_register ("border-bottom-color",
1314 GTK_TYPE_SYMBOLIC_COLOR,
1322 _gtk_symbolic_color_get_current_color ());
1323 gtk_css_style_property_register ("border-left-color",
1324 GTK_TYPE_SYMBOLIC_COLOR,
1332 _gtk_symbolic_color_get_current_color ());
1333 gtk_css_style_property_register ("outline-color",
1334 GTK_TYPE_SYMBOLIC_COLOR,
1342 _gtk_symbolic_color_get_current_color ());
1344 gtk_css_style_property_register ("background-repeat",
1345 GTK_TYPE_CSS_BACKGROUND_REPEAT,
1346 GTK_TYPE_CSS_BACKGROUND_REPEAT,
1347 GTK_TYPE_CSS_BACKGROUND_REPEAT,
1349 background_repeat_value_parse,
1350 background_repeat_value_print,
1353 GTK_CSS_BACKGROUND_REPEAT | (GTK_CSS_BACKGROUND_REPEAT << GTK_CSS_BACKGROUND_REPEAT_SHIFT));
1354 gtk_css_style_property_register ("background-image",
1357 CAIRO_GOBJECT_TYPE_PATTERN,
1359 css_image_value_parse,
1360 css_image_value_print,
1361 css_image_value_compute,
1365 gtk_css_style_property_register ("border-image-source",
1368 CAIRO_GOBJECT_TYPE_PATTERN,
1370 css_image_value_parse,
1371 css_image_value_print,
1372 css_image_value_compute,
1375 gtk_css_style_property_register ("border-image-repeat",
1376 GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1377 GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1378 GTK_TYPE_CSS_BORDER_IMAGE_REPEAT,
1384 &border_image_repeat);
1386 /* XXX: The initial value is wrong, it should be 100% */
1387 gtk_css_style_property_register ("border-image-slice",
1397 gtk_css_style_property_register ("border-image-width",
1407 gtk_css_style_property_register ("engine",
1408 GTK_TYPE_THEMING_ENGINE,
1409 GTK_TYPE_THEMING_ENGINE,
1410 GTK_TYPE_THEMING_ENGINE,
1416 gtk_theming_engine_load (NULL));
1417 gtk_css_style_property_register ("transition",
1418 GTK_TYPE_ANIMATION_DESCRIPTION,
1419 GTK_TYPE_ANIMATION_DESCRIPTION,
1420 GTK_TYPE_ANIMATION_DESCRIPTION,
1428 /* Private property holding the binding sets */
1429 gtk_css_style_property_register ("gtk-key-bindings",
1434 bindings_value_parse,
1435 bindings_value_print,