2 * Copyright © 2011 Red Hat Inc.
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.1 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, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Benjamin Otte <otte@gnome.org>
23 #include "gtkcssshorthandpropertyprivate.h"
25 #include <cairo-gobject.h>
28 #include "gtkcssimageprivate.h"
29 #include "gtkcssstylefuncsprivate.h"
30 #include "gtkcsstypesprivate.h"
31 #include "gtkprivatetypebuiltins.h"
32 #include "gtkstylepropertiesprivate.h"
33 #include "gtksymboliccolorprivate.h"
34 #include "gtktypebuiltins.h"
36 /* this is in case round() is not provided by the compiler,
37 * such as in the case of C89 compilers, like MSVC
39 #include "fallback-c89.c"
44 value_is_done_parsing (GtkCssParser *parser)
46 return _gtk_css_parser_is_eof (parser) ||
47 _gtk_css_parser_begins_with (parser, ';') ||
48 _gtk_css_parser_begins_with (parser, '}');
52 parse_four_numbers (GtkCssShorthandProperty *shorthand,
55 GtkCssNumberParseFlags flags)
57 GtkCssNumber numbers[4];
60 for (i = 0; i < 4; i++)
62 if (!_gtk_css_parser_has_number (parser))
65 if (!_gtk_css_parser_read_number (parser,
73 _gtk_css_parser_error (parser, "Expected a length");
79 numbers[i] = numbers[(i - 1) >> 1];
82 for (i = 0; i < 4; i++)
84 g_value_init (&values[i], GTK_TYPE_CSS_NUMBER);
85 g_value_set_boxed (&values[i], &numbers[i]);
92 parse_margin (GtkCssShorthandProperty *shorthand,
97 return parse_four_numbers (shorthand,
100 GTK_CSS_NUMBER_AS_PIXELS
101 | GTK_CSS_PARSE_LENGTH);
105 parse_padding (GtkCssShorthandProperty *shorthand,
107 GtkCssParser *parser,
110 return parse_four_numbers (shorthand,
113 GTK_CSS_POSITIVE_ONLY
114 | GTK_CSS_NUMBER_AS_PIXELS
115 | GTK_CSS_PARSE_LENGTH);
119 parse_border_width (GtkCssShorthandProperty *shorthand,
121 GtkCssParser *parser,
124 return parse_four_numbers (shorthand,
127 GTK_CSS_POSITIVE_ONLY
128 | GTK_CSS_NUMBER_AS_PIXELS
129 | GTK_CSS_PARSE_LENGTH);
133 parse_border_radius (GtkCssShorthandProperty *shorthand,
135 GtkCssParser *parser,
138 GtkCssBorderCornerRadius borders[4];
141 for (i = 0; i < G_N_ELEMENTS (borders); i++)
143 if (!_gtk_css_parser_has_number (parser))
145 if (!_gtk_css_parser_read_number (parser,
146 &borders[i].horizontal,
147 GTK_CSS_POSITIVE_ONLY
148 | GTK_CSS_PARSE_PERCENT
149 | GTK_CSS_NUMBER_AS_PIXELS
150 | GTK_CSS_PARSE_LENGTH))
156 _gtk_css_parser_error (parser, "Expected a number");
160 /* The magic (i - 1) >> 1 below makes it take the correct value
161 * according to spec. Feel free to check the 4 cases */
162 for (; i < G_N_ELEMENTS (borders); i++)
163 borders[i].horizontal = borders[(i - 1) >> 1].horizontal;
165 if (_gtk_css_parser_try (parser, "/", TRUE))
167 for (i = 0; i < G_N_ELEMENTS (borders); i++)
169 if (!_gtk_css_parser_has_number (parser))
171 if (!_gtk_css_parser_read_number (parser,
172 &borders[i].vertical,
173 GTK_CSS_POSITIVE_ONLY
174 | GTK_CSS_PARSE_PERCENT
175 | GTK_CSS_NUMBER_AS_PIXELS
176 | GTK_CSS_PARSE_LENGTH))
182 _gtk_css_parser_error (parser, "Expected a number");
186 for (; i < G_N_ELEMENTS (borders); i++)
187 borders[i].vertical = borders[(i - 1) >> 1].vertical;
192 for (i = 0; i < G_N_ELEMENTS (borders); i++)
193 borders[i].vertical = borders[i].horizontal;
196 for (i = 0; i < G_N_ELEMENTS (borders); i++)
198 g_value_init (&values[i], GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
199 g_value_set_boxed (&values[i], &borders[i]);
206 parse_border_color (GtkCssShorthandProperty *shorthand,
208 GtkCssParser *parser,
211 GtkSymbolicColor *symbolic;
214 for (i = 0; i < 4; i++)
216 if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
218 symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
222 symbolic = _gtk_css_parser_read_symbolic_color (parser);
223 if (symbolic == NULL)
227 g_value_init (&values[i], GTK_TYPE_SYMBOLIC_COLOR);
228 g_value_set_boxed (&values[i], symbolic);
230 if (value_is_done_parsing (parser))
234 for (i++; i < 4; i++)
236 g_value_init (&values[i], G_VALUE_TYPE (&values[(i - 1) >> 1]));
237 g_value_copy (&values[(i - 1) >> 1], &values[i]);
244 parse_border_style (GtkCssShorthandProperty *shorthand,
246 GtkCssParser *parser,
249 GtkBorderStyle styles[4];
252 for (i = 0; i < 4; i++)
254 if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, (int *)&styles[i]))
260 _gtk_css_parser_error (parser, "Expected a border style");
264 for (; i < G_N_ELEMENTS (styles); i++)
265 styles[i] = styles[(i - 1) >> 1];
267 for (i = 0; i < G_N_ELEMENTS (styles); i++)
269 g_value_init (&values[i], GTK_TYPE_BORDER_STYLE);
270 g_value_set_enum (&values[i], styles[i]);
277 parse_border_image (GtkCssShorthandProperty *shorthand,
279 GtkCssParser *parser,
284 if (_gtk_css_parser_try (parser, "none", TRUE))
288 image = _gtk_css_image_new_parse (parser, base);
292 g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
293 g_value_set_object (&values[0], image);
295 if (value_is_done_parsing (parser))
298 g_value_init (&values[1], GTK_TYPE_BORDER);
299 if (!_gtk_css_style_parse_value (&values[1], parser, base))
302 if (_gtk_css_parser_try (parser, "/", TRUE))
304 g_value_init (&values[2], GTK_TYPE_BORDER);
305 if (!_gtk_css_style_parse_value (&values[2], parser, base))
309 if (value_is_done_parsing (parser))
312 g_value_init (&values[3], GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
313 if (!_gtk_css_style_parse_value (&values[3], parser, base))
320 parse_border_side (GtkCssShorthandProperty *shorthand,
322 GtkCssParser *parser,
329 if (!G_IS_VALUE (&values[0]) &&
330 _gtk_css_parser_has_number (parser))
333 if (!_gtk_css_parser_read_number (parser,
335 GTK_CSS_POSITIVE_ONLY
336 | GTK_CSS_NUMBER_AS_PIXELS
337 | GTK_CSS_PARSE_LENGTH))
340 g_value_init (&values[0], GTK_TYPE_CSS_NUMBER);
341 g_value_set_boxed (&values[0], &number);
343 else if (!G_IS_VALUE (&values[1]) &&
344 _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
346 g_value_init (&values[1], GTK_TYPE_BORDER_STYLE);
347 g_value_set_enum (&values[1], style);
349 else if (!G_IS_VALUE (&values[2]))
351 GtkSymbolicColor *symbolic;
353 symbolic = _gtk_css_parser_read_symbolic_color (parser);
354 if (symbolic == NULL)
357 g_value_init (&values[2], GTK_TYPE_SYMBOLIC_COLOR);
358 g_value_take_boxed (&values[2], symbolic);
362 /* We parsed everything and there's still stuff left?
363 * Pretend we didn't notice and let the normal code produce
364 * a 'junk at end of value' error */
368 while (!value_is_done_parsing (parser));
374 parse_border (GtkCssShorthandProperty *shorthand,
376 GtkCssParser *parser,
383 if (!G_IS_VALUE (&values[0]) &&
384 _gtk_css_parser_has_number (parser))
387 if (!_gtk_css_parser_read_number (parser,
389 GTK_CSS_POSITIVE_ONLY
390 | GTK_CSS_NUMBER_AS_PIXELS
391 | GTK_CSS_PARSE_LENGTH))
394 g_value_init (&values[0], GTK_TYPE_CSS_NUMBER);
395 g_value_init (&values[1], GTK_TYPE_CSS_NUMBER);
396 g_value_init (&values[2], GTK_TYPE_CSS_NUMBER);
397 g_value_init (&values[3], GTK_TYPE_CSS_NUMBER);
398 g_value_set_boxed (&values[0], &number);
399 g_value_set_boxed (&values[1], &number);
400 g_value_set_boxed (&values[2], &number);
401 g_value_set_boxed (&values[3], &number);
403 else if (!G_IS_VALUE (&values[4]) &&
404 _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
406 g_value_init (&values[4], GTK_TYPE_BORDER_STYLE);
407 g_value_init (&values[5], GTK_TYPE_BORDER_STYLE);
408 g_value_init (&values[6], GTK_TYPE_BORDER_STYLE);
409 g_value_init (&values[7], GTK_TYPE_BORDER_STYLE);
410 g_value_set_enum (&values[4], style);
411 g_value_set_enum (&values[5], style);
412 g_value_set_enum (&values[6], style);
413 g_value_set_enum (&values[7], style);
415 else if (!G_IS_VALUE (&values[8]))
417 GtkSymbolicColor *symbolic;
419 symbolic = _gtk_css_parser_read_symbolic_color (parser);
420 if (symbolic == NULL)
423 g_value_init (&values[8], GTK_TYPE_SYMBOLIC_COLOR);
424 g_value_init (&values[9], GTK_TYPE_SYMBOLIC_COLOR);
425 g_value_init (&values[10], GTK_TYPE_SYMBOLIC_COLOR);
426 g_value_init (&values[11], GTK_TYPE_SYMBOLIC_COLOR);
427 g_value_set_boxed (&values[8], symbolic);
428 g_value_set_boxed (&values[9], symbolic);
429 g_value_set_boxed (&values[10], symbolic);
430 g_value_take_boxed (&values[11], symbolic);
434 /* We parsed everything and there's still stuff left?
435 * Pretend we didn't notice and let the normal code produce
436 * a 'junk at end of value' error */
440 while (!value_is_done_parsing (parser));
442 /* Note that border-image values are not set: according to the spec
443 they just need to be reset when using the border shorthand */
449 parse_font (GtkCssShorthandProperty *shorthand,
451 GtkCssParser *parser,
454 PangoFontDescription *desc;
458 str = _gtk_css_parser_read_value (parser);
462 desc = pango_font_description_from_string (str);
465 mask = pango_font_description_get_set_fields (desc);
467 if (mask & PANGO_FONT_MASK_FAMILY)
469 GPtrArray *strv = g_ptr_array_new ();
471 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (desc)));
472 g_ptr_array_add (strv, NULL);
473 g_value_init (&values[0], G_TYPE_STRV);
474 g_value_take_boxed (&values[0], g_ptr_array_free (strv, FALSE));
476 if (mask & PANGO_FONT_MASK_STYLE)
478 g_value_init (&values[1], PANGO_TYPE_STYLE);
479 g_value_set_enum (&values[1], pango_font_description_get_style (desc));
481 if (mask & PANGO_FONT_MASK_VARIANT)
483 g_value_init (&values[2], PANGO_TYPE_VARIANT);
484 g_value_set_enum (&values[2], pango_font_description_get_variant (desc));
486 if (mask & PANGO_FONT_MASK_WEIGHT)
488 g_value_init (&values[3], PANGO_TYPE_WEIGHT);
489 g_value_set_enum (&values[3], pango_font_description_get_weight (desc));
491 if (mask & PANGO_FONT_MASK_SIZE)
493 g_value_init (&values[4], G_TYPE_DOUBLE);
494 g_value_set_double (&values[4],
495 (double) pango_font_description_get_size (desc) / PANGO_SCALE);
498 pango_font_description_free (desc);
504 parse_background (GtkCssShorthandProperty *shorthand,
506 GtkCssParser *parser,
514 if (!G_IS_VALUE (&values[0]) &&
515 (_gtk_css_parser_has_prefix (parser, "none") ||
516 _gtk_css_image_can_parse (parser)))
520 if (_gtk_css_parser_try (parser, "none", TRUE))
524 image = _gtk_css_image_new_parse (parser, base);
529 g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
530 g_value_take_object (&values[0], image);
532 else if (!G_IS_VALUE (&values[1]) &&
533 _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &enum_value))
535 if (enum_value <= GTK_CSS_BACKGROUND_REPEAT_MASK)
539 if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
541 if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
543 _gtk_css_parser_error (parser, "Not a valid 2nd value for border-repeat");
547 enum_value |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
550 enum_value |= enum_value << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
553 g_value_init (&values[1], GTK_TYPE_CSS_BACKGROUND_REPEAT);
554 g_value_set_enum (&values[1], enum_value);
556 else if ((!G_IS_VALUE (&values[2]) || !G_IS_VALUE (&values[3])) &&
557 _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_AREA, &enum_value))
559 guint idx = !G_IS_VALUE (&values[2]) ? 2 : 3;
560 g_value_init (&values[idx], GTK_TYPE_CSS_AREA);
561 g_value_set_enum (&values[idx], enum_value);
563 else if (!G_IS_VALUE (&values[4]))
565 GtkSymbolicColor *symbolic;
567 symbolic = _gtk_css_parser_read_symbolic_color (parser);
568 if (symbolic == NULL)
571 g_value_init (&values[4], GTK_TYPE_SYMBOLIC_COLOR);
572 g_value_take_boxed (&values[4], symbolic);
576 /* We parsed everything and there's still stuff left?
577 * Pretend we didn't notice and let the normal code produce
578 * a 'junk at end of value' error */
582 while (!value_is_done_parsing (parser));
590 unpack_border (GtkCssShorthandProperty *shorthand,
591 GtkStyleProperties *props,
595 GValue v = G_VALUE_INIT;
596 GtkBorder *border = g_value_get_boxed (value);
598 g_value_init (&v, G_TYPE_INT);
600 g_value_set_int (&v, border->top);
601 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 0)), props, state, &v);
602 g_value_set_int (&v, border->right);
603 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 1)), props, state, &v);
604 g_value_set_int (&v, border->bottom);
605 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 2)), props, state, &v);
606 g_value_set_int (&v, border->left);
607 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 3)), props, state, &v);
613 pack_border (GtkCssShorthandProperty *shorthand,
615 GtkStyleQueryFunc query_func,
618 GtkCssStyleProperty *prop;
622 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
623 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
625 border.top = g_value_get_int (v);
626 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 1);
627 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
629 border.right = g_value_get_int (v);
630 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 2);
631 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
633 border.bottom = g_value_get_int (v);
634 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 3);
635 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
637 border.left = g_value_get_int (v);
639 g_value_set_boxed (value, &border);
643 unpack_border_radius (GtkCssShorthandProperty *shorthand,
644 GtkStyleProperties *props,
648 GtkCssBorderCornerRadius border;
649 GValue v = G_VALUE_INIT;
652 _gtk_css_number_init (&border.horizontal, g_value_get_int (value), GTK_CSS_PX);
653 border.vertical = border.horizontal;
654 g_value_init (&v, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
655 g_value_set_boxed (&v, &border);
657 for (i = 0; i < 4; i++)
658 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, i)), props, state, &v);
664 pack_border_radius (GtkCssShorthandProperty *shorthand,
666 GtkStyleQueryFunc query_func,
669 GtkCssBorderCornerRadius *top_left;
670 GtkCssStyleProperty *prop;
673 prop = GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("border-top-left-radius"));
674 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
677 top_left = g_value_get_boxed (v);
679 g_value_set_int (value, top_left->horizontal.value);
684 unpack_font_description (GtkCssShorthandProperty *shorthand,
685 GtkStyleProperties *props,
689 GtkStyleProperty *prop;
690 PangoFontDescription *description;
692 GValue v = G_VALUE_INIT;
694 /* For backwards compat, we only unpack values that are indeed set.
695 * For strict CSS conformance we need to unpack all of them.
696 * Note that we do set all of them in the parse function, so it
697 * will not have effects when parsing CSS files. It will though
698 * for custom style providers.
701 description = g_value_get_boxed (value);
704 mask = pango_font_description_get_set_fields (description);
708 if (mask & PANGO_FONT_MASK_FAMILY)
710 GPtrArray *strv = g_ptr_array_new ();
712 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description)));
713 g_ptr_array_add (strv, NULL);
714 g_value_init (&v, G_TYPE_STRV);
715 g_value_take_boxed (&v, g_ptr_array_free (strv, FALSE));
717 prop = _gtk_style_property_lookup ("font-family");
718 _gtk_style_property_assign (prop, props, state, &v);
722 if (mask & PANGO_FONT_MASK_STYLE)
724 g_value_init (&v, PANGO_TYPE_STYLE);
725 g_value_set_enum (&v, pango_font_description_get_style (description));
727 prop = _gtk_style_property_lookup ("font-style");
728 _gtk_style_property_assign (prop, props, state, &v);
732 if (mask & PANGO_FONT_MASK_VARIANT)
734 g_value_init (&v, PANGO_TYPE_VARIANT);
735 g_value_set_enum (&v, pango_font_description_get_variant (description));
737 prop = _gtk_style_property_lookup ("font-variant");
738 _gtk_style_property_assign (prop, props, state, &v);
742 if (mask & PANGO_FONT_MASK_WEIGHT)
744 g_value_init (&v, PANGO_TYPE_WEIGHT);
745 g_value_set_enum (&v, pango_font_description_get_weight (description));
747 prop = _gtk_style_property_lookup ("font-weight");
748 _gtk_style_property_assign (prop, props, state, &v);
752 if (mask & PANGO_FONT_MASK_SIZE)
754 g_value_init (&v, G_TYPE_DOUBLE);
755 g_value_set_double (&v, (double) pango_font_description_get_size (description) / PANGO_SCALE);
757 prop = _gtk_style_property_lookup ("font-size");
758 _gtk_style_property_assign (prop, props, state, &v);
764 pack_font_description (GtkCssShorthandProperty *shorthand,
766 GtkStyleQueryFunc query_func,
769 PangoFontDescription *description;
772 description = pango_font_description_new ();
774 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-family"))), query_data);
777 const char **families = g_value_get_boxed (v);
778 /* xxx: Can we set all the families here somehow? */
780 pango_font_description_set_family (description, families[0]);
783 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-size"))), query_data);
785 pango_font_description_set_size (description, round (g_value_get_double (v) * PANGO_SCALE));
787 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-style"))), query_data);
789 pango_font_description_set_style (description, g_value_get_enum (v));
791 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data);
793 pango_font_description_set_variant (description, g_value_get_enum (v));
795 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data);
797 pango_font_description_set_weight (description, g_value_get_enum (v));
799 g_value_take_boxed (value, description);
803 unpack_to_everything (GtkCssShorthandProperty *shorthand,
804 GtkStyleProperties *props,
808 GtkCssStyleProperty *prop;
811 n = _gtk_css_shorthand_property_get_n_subproperties (shorthand);
813 for (i = 0; i < n; i++)
815 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
816 _gtk_style_property_assign (GTK_STYLE_PROPERTY (prop), props, state, value);
821 pack_first_element (GtkCssShorthandProperty *shorthand,
823 GtkStyleQueryFunc query_func,
826 GtkCssStyleProperty *prop;
830 /* NB: This is a fallback for properties that originally were
831 * not used as shorthand. We just pick the first subproperty
832 * as a representative.
833 * Lesson learned: Don't query the shorthand, query the
834 * real properties instead. */
835 for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++)
837 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
838 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
841 g_value_copy (v, value);
848 _gtk_css_shorthand_property_register (const char *name,
850 const char **subproperties,
851 GtkCssShorthandPropertyParseFunc parse_func,
852 GtkCssShorthandPropertyAssignFunc assign_func,
853 GtkCssShorthandPropertyQueryFunc query_func)
855 GtkCssShorthandProperty *node;
857 node = g_object_new (GTK_TYPE_CSS_SHORTHAND_PROPERTY,
859 "value-type", value_type,
860 "subproperties", subproperties,
863 node->parse = parse_func;
864 node->assign = assign_func;
865 node->query = query_func;
869 _gtk_css_shorthand_property_init_properties (void)
871 /* The order is important here, be careful when changing it */
872 const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-size", NULL };
873 const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL };
874 const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL };
875 const char *border_width_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", NULL };
876 const char *border_radius_subproperties[] = { "border-top-left-radius", "border-top-right-radius",
877 "border-bottom-right-radius", "border-bottom-left-radius", NULL };
878 const char *border_color_subproperties[] = { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", NULL };
879 const char *border_style_subproperties[] = { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", NULL };
880 const char *border_image_subproperties[] = { "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
881 const char *border_top_subproperties[] = { "border-top-width", "border-top-style", "border-top-color", NULL };
882 const char *border_right_subproperties[] = { "border-right-width", "border-right-style", "border-right-color", NULL };
883 const char *border_bottom_subproperties[] = { "border-bottom-width", "border-bottom-style", "border-bottom-color", NULL };
884 const char *border_left_subproperties[] = { "border-left-width", "border-left-style", "border-left-color", NULL };
885 const char *border_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width",
886 "border-top-style", "border-right-style", "border-bottom-style", "border-left-style",
887 "border-top-color", "border-right-color", "border-bottom-color", "border-left-color",
888 "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
889 const char *outline_subproperties[] = { "outline-width", "outline-style", "outline-color", NULL };
890 const char *background_subproperties[] = { "background-image", "background-repeat", "background-clip", "background-origin",
891 "background-color", NULL };
893 _gtk_css_shorthand_property_register ("font",
894 PANGO_TYPE_FONT_DESCRIPTION,
897 unpack_font_description,
898 pack_font_description);
899 _gtk_css_shorthand_property_register ("margin",
901 margin_subproperties,
905 _gtk_css_shorthand_property_register ("padding",
907 padding_subproperties,
911 _gtk_css_shorthand_property_register ("border-width",
913 border_width_subproperties,
917 _gtk_css_shorthand_property_register ("border-radius",
919 border_radius_subproperties,
921 unpack_border_radius,
923 _gtk_css_shorthand_property_register ("border-color",
925 border_color_subproperties,
927 unpack_to_everything,
929 _gtk_css_shorthand_property_register ("border-style",
930 GTK_TYPE_BORDER_STYLE,
931 border_style_subproperties,
933 unpack_to_everything,
935 _gtk_css_shorthand_property_register ("border-image",
937 border_image_subproperties,
941 _gtk_css_shorthand_property_register ("border-top",
943 border_top_subproperties,
947 _gtk_css_shorthand_property_register ("border-right",
949 border_right_subproperties,
953 _gtk_css_shorthand_property_register ("border-bottom",
955 border_bottom_subproperties,
959 _gtk_css_shorthand_property_register ("border-left",
961 border_left_subproperties,
965 _gtk_css_shorthand_property_register ("border",
967 border_subproperties,
971 _gtk_css_shorthand_property_register ("outline",
973 outline_subproperties,
977 _gtk_css_shorthand_property_register ("background",
979 background_subproperties,