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, see <http://www.gnu.org/licenses/>.
17 * Authors: Benjamin Otte <otte@gnome.org>
22 #include "gtkcssshorthandpropertyprivate.h"
24 #include <cairo-gobject.h>
27 #include "gtkcssimageprivate.h"
28 #include "gtkcssstylefuncsprivate.h"
29 #include "gtkcsstypesprivate.h"
30 #include "gtkprivatetypebuiltins.h"
31 #include "gtkstylepropertiesprivate.h"
32 #include "gtksymboliccolorprivate.h"
33 #include "gtktypebuiltins.h"
34 #include "gtkcssvalueprivate.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 = _gtk_css_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 = _gtk_css_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 = _gtk_css_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 = _gtk_css_value_get_int (v);
639 g_value_init (value, GTK_TYPE_BORDER);
640 g_value_set_boxed (value, &border);
644 unpack_border_radius (GtkCssShorthandProperty *shorthand,
645 GtkStyleProperties *props,
649 GtkCssBorderCornerRadius border;
650 GValue v = G_VALUE_INIT;
653 _gtk_css_number_init (&border.horizontal, g_value_get_int (value), GTK_CSS_PX);
654 border.vertical = border.horizontal;
655 g_value_init (&v, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
656 g_value_set_boxed (&v, &border);
658 for (i = 0; i < 4; i++)
659 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, i)), props, state, &v);
665 pack_border_radius (GtkCssShorthandProperty *shorthand,
667 GtkStyleQueryFunc query_func,
670 const GtkCssBorderCornerRadius *top_left;
671 GtkCssStyleProperty *prop;
675 prop = GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("border-top-left-radius"));
676 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
679 top_left = _gtk_css_value_get_border_corner_radius (v);
681 i = top_left->horizontal.value;
684 g_value_init (value, G_TYPE_INT);
685 g_value_set_int (value, i);
689 unpack_font_description (GtkCssShorthandProperty *shorthand,
690 GtkStyleProperties *props,
694 GtkStyleProperty *prop;
695 PangoFontDescription *description;
697 GValue v = G_VALUE_INIT;
699 /* For backwards compat, we only unpack values that are indeed set.
700 * For strict CSS conformance we need to unpack all of them.
701 * Note that we do set all of them in the parse function, so it
702 * will not have effects when parsing CSS files. It will though
703 * for custom style providers.
706 description = g_value_get_boxed (value);
709 mask = pango_font_description_get_set_fields (description);
713 if (mask & PANGO_FONT_MASK_FAMILY)
715 GPtrArray *strv = g_ptr_array_new ();
717 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description)));
718 g_ptr_array_add (strv, NULL);
719 g_value_init (&v, G_TYPE_STRV);
720 g_value_take_boxed (&v, g_ptr_array_free (strv, FALSE));
722 prop = _gtk_style_property_lookup ("font-family");
723 _gtk_style_property_assign (prop, props, state, &v);
727 if (mask & PANGO_FONT_MASK_STYLE)
729 g_value_init (&v, PANGO_TYPE_STYLE);
730 g_value_set_enum (&v, pango_font_description_get_style (description));
732 prop = _gtk_style_property_lookup ("font-style");
733 _gtk_style_property_assign (prop, props, state, &v);
737 if (mask & PANGO_FONT_MASK_VARIANT)
739 g_value_init (&v, PANGO_TYPE_VARIANT);
740 g_value_set_enum (&v, pango_font_description_get_variant (description));
742 prop = _gtk_style_property_lookup ("font-variant");
743 _gtk_style_property_assign (prop, props, state, &v);
747 if (mask & PANGO_FONT_MASK_WEIGHT)
749 g_value_init (&v, PANGO_TYPE_WEIGHT);
750 g_value_set_enum (&v, pango_font_description_get_weight (description));
752 prop = _gtk_style_property_lookup ("font-weight");
753 _gtk_style_property_assign (prop, props, state, &v);
757 if (mask & PANGO_FONT_MASK_SIZE)
759 g_value_init (&v, G_TYPE_DOUBLE);
760 g_value_set_double (&v, (double) pango_font_description_get_size (description) / PANGO_SCALE);
762 prop = _gtk_style_property_lookup ("font-size");
763 _gtk_style_property_assign (prop, props, state, &v);
769 pack_font_description (GtkCssShorthandProperty *shorthand,
771 GtkStyleQueryFunc query_func,
774 PangoFontDescription *description;
777 description = pango_font_description_new ();
779 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-family"))), query_data);
782 const char **families = _gtk_css_value_get_strv (v);
783 /* xxx: Can we set all the families here somehow? */
785 pango_font_description_set_family (description, families[0]);
788 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-size"))), query_data);
790 pango_font_description_set_size (description, round (_gtk_css_value_get_double (v) * PANGO_SCALE));
792 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-style"))), query_data);
794 pango_font_description_set_style (description, _gtk_css_value_get_pango_style (v));
796 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data);
798 pango_font_description_set_variant (description, _gtk_css_value_get_pango_variant (v));
800 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data);
802 pango_font_description_set_weight (description, _gtk_css_value_get_pango_weight (v));
804 g_value_init (value, PANGO_TYPE_FONT_DESCRIPTION);
805 g_value_take_boxed (value, description);
809 unpack_to_everything (GtkCssShorthandProperty *shorthand,
810 GtkStyleProperties *props,
814 GtkCssStyleProperty *prop;
817 n = _gtk_css_shorthand_property_get_n_subproperties (shorthand);
819 for (i = 0; i < n; i++)
821 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
822 _gtk_style_property_assign (GTK_STYLE_PROPERTY (prop), props, state, value);
827 pack_first_element (GtkCssShorthandProperty *shorthand,
829 GtkStyleQueryFunc query_func,
832 GtkCssStyleProperty *prop;
834 /* NB: This is a fallback for properties that originally were
835 * not used as shorthand. We just pick the first subproperty
836 * as a representative.
837 * Lesson learned: Don't query the shorthand, query the
838 * real properties instead. */
839 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
840 _gtk_style_property_query (GTK_STYLE_PROPERTY (prop),
847 _gtk_css_shorthand_property_register (const char *name,
849 const char **subproperties,
850 GtkCssShorthandPropertyParseFunc parse_func,
851 GtkCssShorthandPropertyAssignFunc assign_func,
852 GtkCssShorthandPropertyQueryFunc query_func)
854 GtkCssShorthandProperty *node;
856 node = g_object_new (GTK_TYPE_CSS_SHORTHAND_PROPERTY,
858 "value-type", value_type,
859 "subproperties", subproperties,
862 node->parse = parse_func;
863 node->assign = assign_func;
864 node->query = query_func;
868 _gtk_css_shorthand_property_init_properties (void)
870 /* The order is important here, be careful when changing it */
871 const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-size", NULL };
872 const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL };
873 const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL };
874 const char *border_width_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", NULL };
875 const char *border_radius_subproperties[] = { "border-top-left-radius", "border-top-right-radius",
876 "border-bottom-right-radius", "border-bottom-left-radius", NULL };
877 const char *border_color_subproperties[] = { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", NULL };
878 const char *border_style_subproperties[] = { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", NULL };
879 const char *border_image_subproperties[] = { "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
880 const char *border_top_subproperties[] = { "border-top-width", "border-top-style", "border-top-color", NULL };
881 const char *border_right_subproperties[] = { "border-right-width", "border-right-style", "border-right-color", NULL };
882 const char *border_bottom_subproperties[] = { "border-bottom-width", "border-bottom-style", "border-bottom-color", NULL };
883 const char *border_left_subproperties[] = { "border-left-width", "border-left-style", "border-left-color", NULL };
884 const char *border_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width",
885 "border-top-style", "border-right-style", "border-bottom-style", "border-left-style",
886 "border-top-color", "border-right-color", "border-bottom-color", "border-left-color",
887 "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
888 const char *outline_subproperties[] = { "outline-width", "outline-style", "outline-color", NULL };
889 const char *background_subproperties[] = { "background-image", "background-repeat", "background-clip", "background-origin",
890 "background-color", NULL };
892 _gtk_css_shorthand_property_register ("font",
893 PANGO_TYPE_FONT_DESCRIPTION,
896 unpack_font_description,
897 pack_font_description);
898 _gtk_css_shorthand_property_register ("margin",
900 margin_subproperties,
904 _gtk_css_shorthand_property_register ("padding",
906 padding_subproperties,
910 _gtk_css_shorthand_property_register ("border-width",
912 border_width_subproperties,
916 _gtk_css_shorthand_property_register ("border-radius",
918 border_radius_subproperties,
920 unpack_border_radius,
922 _gtk_css_shorthand_property_register ("border-color",
924 border_color_subproperties,
926 unpack_to_everything,
928 _gtk_css_shorthand_property_register ("border-style",
929 GTK_TYPE_BORDER_STYLE,
930 border_style_subproperties,
932 unpack_to_everything,
934 _gtk_css_shorthand_property_register ("border-image",
936 border_image_subproperties,
940 _gtk_css_shorthand_property_register ("border-top",
942 border_top_subproperties,
946 _gtk_css_shorthand_property_register ("border-right",
948 border_right_subproperties,
952 _gtk_css_shorthand_property_register ("border-bottom",
954 border_bottom_subproperties,
958 _gtk_css_shorthand_property_register ("border-left",
960 border_left_subproperties,
964 _gtk_css_shorthand_property_register ("border",
966 border_subproperties,
970 _gtk_css_shorthand_property_register ("outline",
972 outline_subproperties,
976 _gtk_css_shorthand_property_register ("background",
978 background_subproperties,