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 "gtkcssarrayvalueprivate.h"
28 #include "gtkcssenumvalueprivate.h"
29 #include "gtkcssimageprivate.h"
30 #include "gtkcssimagevalueprivate.h"
31 #include "gtkcssnumbervalueprivate.h"
32 #include "gtkcssstringvalueprivate.h"
33 #include "gtkcssstylefuncsprivate.h"
34 #include "gtkcsstypesprivate.h"
35 #include "gtkcssvalueprivate.h"
36 #include "gtkprivatetypebuiltins.h"
37 #include "gtkstylepropertiesprivate.h"
38 #include "gtksymboliccolorprivate.h"
39 #include "gtktypebuiltins.h"
41 /* this is in case round() is not provided by the compiler,
42 * such as in the case of C89 compilers, like MSVC
44 #include "fallback-c89.c"
49 value_is_done_parsing (GtkCssParser *parser)
51 return _gtk_css_parser_is_eof (parser) ||
52 _gtk_css_parser_begins_with (parser, ';') ||
53 _gtk_css_parser_begins_with (parser, '}');
57 parse_four_numbers (GtkCssShorthandProperty *shorthand,
60 GtkCssNumberParseFlags flags)
64 for (i = 0; i < 4; i++)
66 if (!_gtk_css_parser_has_number (parser))
69 values[i] = _gtk_css_number_value_parse (parser, flags);
70 if (values[i] == NULL)
76 _gtk_css_parser_error (parser, "Expected a length");
82 values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]);
89 parse_margin (GtkCssShorthandProperty *shorthand,
94 return parse_four_numbers (shorthand,
97 GTK_CSS_NUMBER_AS_PIXELS
98 | GTK_CSS_PARSE_LENGTH);
102 parse_padding (GtkCssShorthandProperty *shorthand,
103 GtkCssValue **values,
104 GtkCssParser *parser,
107 return parse_four_numbers (shorthand,
110 GTK_CSS_POSITIVE_ONLY
111 | GTK_CSS_NUMBER_AS_PIXELS
112 | GTK_CSS_PARSE_LENGTH);
116 parse_border_width (GtkCssShorthandProperty *shorthand,
117 GtkCssValue **values,
118 GtkCssParser *parser,
121 return parse_four_numbers (shorthand,
124 GTK_CSS_POSITIVE_ONLY
125 | GTK_CSS_NUMBER_AS_PIXELS
126 | GTK_CSS_PARSE_LENGTH);
130 parse_border_radius (GtkCssShorthandProperty *shorthand,
131 GtkCssValue **values,
132 GtkCssParser *parser,
135 GtkCssBorderCornerRadius borders[4];
138 for (i = 0; i < G_N_ELEMENTS (borders); i++)
140 if (!_gtk_css_parser_has_number (parser))
142 if (!_gtk_css_parser_read_number (parser,
143 &borders[i].horizontal,
144 GTK_CSS_POSITIVE_ONLY
145 | GTK_CSS_PARSE_PERCENT
146 | GTK_CSS_NUMBER_AS_PIXELS
147 | GTK_CSS_PARSE_LENGTH))
153 _gtk_css_parser_error (parser, "Expected a number");
157 /* The magic (i - 1) >> 1 below makes it take the correct value
158 * according to spec. Feel free to check the 4 cases */
159 for (; i < G_N_ELEMENTS (borders); i++)
160 borders[i].horizontal = borders[(i - 1) >> 1].horizontal;
162 if (_gtk_css_parser_try (parser, "/", TRUE))
164 for (i = 0; i < G_N_ELEMENTS (borders); i++)
166 if (!_gtk_css_parser_has_number (parser))
168 if (!_gtk_css_parser_read_number (parser,
169 &borders[i].vertical,
170 GTK_CSS_POSITIVE_ONLY
171 | GTK_CSS_PARSE_PERCENT
172 | GTK_CSS_NUMBER_AS_PIXELS
173 | GTK_CSS_PARSE_LENGTH))
179 _gtk_css_parser_error (parser, "Expected a number");
183 for (; i < G_N_ELEMENTS (borders); i++)
184 borders[i].vertical = borders[(i - 1) >> 1].vertical;
189 for (i = 0; i < G_N_ELEMENTS (borders); i++)
190 borders[i].vertical = borders[i].horizontal;
193 for (i = 0; i < G_N_ELEMENTS (borders); i++)
195 values[i] = _gtk_css_value_new_from_border_corner_radius (&borders[i]);
202 parse_border_color (GtkCssShorthandProperty *shorthand,
203 GtkCssValue **values,
204 GtkCssParser *parser,
207 GtkSymbolicColor *symbolic;
210 for (i = 0; i < 4; i++)
212 if (_gtk_css_parser_try (parser, "currentcolor", TRUE))
214 symbolic = gtk_symbolic_color_ref (_gtk_symbolic_color_get_current_color ());
218 symbolic = _gtk_css_parser_read_symbolic_color (parser);
219 if (symbolic == NULL)
223 values[i] = _gtk_css_value_new_take_symbolic_color (symbolic);
225 if (value_is_done_parsing (parser))
229 for (i++; i < 4; i++)
231 values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]);
238 parse_border_style (GtkCssShorthandProperty *shorthand,
239 GtkCssValue **values,
240 GtkCssParser *parser,
245 for (i = 0; i < 4; i++)
247 values[i] = _gtk_css_border_style_value_try_parse (parser);
248 if (values[i] == NULL)
254 _gtk_css_parser_error (parser, "Expected a border style");
259 values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]);
265 parse_border_image (GtkCssShorthandProperty *shorthand,
266 GtkCssValue **values,
267 GtkCssParser *parser,
270 GValue value = G_VALUE_INIT;
273 if (_gtk_css_parser_try (parser, "none", TRUE))
277 image = _gtk_css_image_new_parse (parser, base);
281 values[0] = _gtk_css_image_value_new (image);
283 if (value_is_done_parsing (parser))
286 g_value_init (&value, GTK_TYPE_BORDER);
287 if (!_gtk_css_style_parse_value (&value, parser, base))
289 values[1] = _gtk_css_value_new_from_gvalue (&value);
290 g_value_unset (&value);
292 if (_gtk_css_parser_try (parser, "/", TRUE))
294 g_value_init (&value, GTK_TYPE_BORDER);
295 if (!_gtk_css_style_parse_value (&value, parser, base))
297 values[2] = _gtk_css_value_new_from_gvalue (&value);
298 g_value_unset (&value);
301 if (value_is_done_parsing (parser))
304 g_value_init (&value, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
305 if (!_gtk_css_style_parse_value (&value, parser, base))
307 values[3] = _gtk_css_value_new_from_gvalue (&value);
308 g_value_unset (&value);
314 parse_border_side (GtkCssShorthandProperty *shorthand,
315 GtkCssValue **values,
316 GtkCssParser *parser,
321 if (values[0] == NULL &&
322 _gtk_css_parser_has_number (parser))
324 values[0] = _gtk_css_number_value_parse (parser,
325 GTK_CSS_POSITIVE_ONLY
326 | GTK_CSS_NUMBER_AS_PIXELS
327 | GTK_CSS_PARSE_LENGTH);
328 if (values[0] == NULL)
331 else if (values[1] == NULL &&
332 (values[1] = _gtk_css_border_style_value_try_parse (parser)))
336 else if (values[2] == NULL)
338 GtkSymbolicColor *symbolic;
340 symbolic = _gtk_css_parser_read_symbolic_color (parser);
341 if (symbolic == NULL)
344 values[2] = _gtk_css_value_new_take_symbolic_color (symbolic);
348 /* We parsed everything and there's still stuff left?
349 * Pretend we didn't notice and let the normal code produce
350 * a 'junk at end of value' error */
354 while (!value_is_done_parsing (parser));
360 parse_border (GtkCssShorthandProperty *shorthand,
361 GtkCssValue **values,
362 GtkCssParser *parser,
367 if (values[0] == NULL &&
368 _gtk_css_parser_has_number (parser))
370 values[0] = _gtk_css_number_value_parse (parser,
371 GTK_CSS_POSITIVE_ONLY
372 | GTK_CSS_NUMBER_AS_PIXELS
373 | GTK_CSS_PARSE_LENGTH);
374 if (values[0] == NULL)
376 values[1] = _gtk_css_value_ref (values[0]);
377 values[2] = _gtk_css_value_ref (values[0]);
378 values[3] = _gtk_css_value_ref (values[0]);
380 else if (values[4] == NULL &&
381 (values[4] = _gtk_css_border_style_value_try_parse (parser)))
383 values[5] = _gtk_css_value_ref (values[4]);
384 values[6] = _gtk_css_value_ref (values[4]);
385 values[7] = _gtk_css_value_ref (values[4]);
387 else if (!G_IS_VALUE (&values[8]))
389 GtkSymbolicColor *symbolic;
391 symbolic = _gtk_css_parser_read_symbolic_color (parser);
392 if (symbolic == NULL)
395 values[8] = _gtk_css_value_new_take_symbolic_color (symbolic);
396 values[9] = _gtk_css_value_ref (values[8]);
397 values[10] = _gtk_css_value_ref (values[8]);
398 values[11] = _gtk_css_value_ref (values[8]);
402 /* We parsed everything and there's still stuff left?
403 * Pretend we didn't notice and let the normal code produce
404 * a 'junk at end of value' error */
408 while (!value_is_done_parsing (parser));
410 /* Note that border-image values are not set: according to the spec
411 they just need to be reset when using the border shorthand */
417 parse_font (GtkCssShorthandProperty *shorthand,
418 GtkCssValue **values,
419 GtkCssParser *parser,
422 PangoFontDescription *desc;
426 str = _gtk_css_parser_read_value (parser);
430 desc = pango_font_description_from_string (str);
433 mask = pango_font_description_get_set_fields (desc);
435 if (mask & PANGO_FONT_MASK_FAMILY)
437 GtkCssValue *value = _gtk_css_string_value_new (pango_font_description_get_family (desc));
438 values[0] = _gtk_css_array_value_new (&value, 1);
440 if (mask & PANGO_FONT_MASK_STYLE)
442 values[1] = _gtk_css_font_style_value_new (pango_font_description_get_style (desc));
444 if (mask & PANGO_FONT_MASK_VARIANT)
446 values[2] = _gtk_css_font_variant_value_new (pango_font_description_get_variant (desc));
448 if (mask & PANGO_FONT_MASK_WEIGHT)
450 values[3] = _gtk_css_font_weight_value_new (pango_font_description_get_weight (desc));
452 if (mask & PANGO_FONT_MASK_SIZE)
454 values[4] = _gtk_css_number_value_new ((double) pango_font_description_get_size (desc) / PANGO_SCALE, GTK_CSS_PX);
457 pango_font_description_free (desc);
463 parse_background (GtkCssShorthandProperty *shorthand,
464 GtkCssValue **values,
465 GtkCssParser *parser,
473 if (values[0] == NULL &&
474 (_gtk_css_parser_has_prefix (parser, "none") ||
475 _gtk_css_image_can_parse (parser)))
479 if (_gtk_css_parser_try (parser, "none", TRUE))
483 image = _gtk_css_image_new_parse (parser, base);
488 values[0] = _gtk_css_image_value_new (image);
490 else if (values[1] == NULL &&
491 _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &enum_value))
493 if (enum_value <= GTK_CSS_BACKGROUND_REPEAT_MASK)
497 if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
499 if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
501 _gtk_css_parser_error (parser, "Not a valid 2nd value for border-repeat");
505 enum_value |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
508 enum_value |= enum_value << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
511 values[1] = _gtk_css_value_new_from_enum (GTK_TYPE_CSS_BACKGROUND_REPEAT, enum_value);
513 else if ((values[2] == NULL || values[3] == NULL) &&
514 (values[3] = _gtk_css_area_value_try_parse (parser)))
516 if (values[2] == NULL)
518 values[2] = values[3];
522 else if (values[4] == NULL)
524 GtkSymbolicColor *symbolic;
526 symbolic = _gtk_css_parser_read_symbolic_color (parser);
527 if (symbolic == NULL)
530 values[4] = _gtk_css_value_new_take_symbolic_color (symbolic);
534 /* We parsed everything and there's still stuff left?
535 * Pretend we didn't notice and let the normal code produce
536 * a 'junk at end of value' error */
540 while (!value_is_done_parsing (parser));
548 unpack_border (GtkCssShorthandProperty *shorthand,
549 GtkStyleProperties *props,
553 GValue v = G_VALUE_INIT;
554 GtkBorder *border = g_value_get_boxed (value);
556 g_value_init (&v, G_TYPE_INT);
558 g_value_set_int (&v, border->top);
559 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 0)), props, state, &v);
560 g_value_set_int (&v, border->right);
561 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 1)), props, state, &v);
562 g_value_set_int (&v, border->bottom);
563 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 2)), props, state, &v);
564 g_value_set_int (&v, border->left);
565 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 3)), props, state, &v);
571 pack_border (GtkCssShorthandProperty *shorthand,
573 GtkStyleQueryFunc query_func,
576 GtkCssStyleProperty *prop;
580 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
581 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
583 border.top = _gtk_css_value_get_int (v);
584 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 1);
585 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
587 border.right = _gtk_css_value_get_int (v);
588 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 2);
589 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
591 border.bottom = _gtk_css_value_get_int (v);
592 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 3);
593 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
595 border.left = _gtk_css_value_get_int (v);
597 g_value_init (value, GTK_TYPE_BORDER);
598 g_value_set_boxed (value, &border);
602 unpack_border_radius (GtkCssShorthandProperty *shorthand,
603 GtkStyleProperties *props,
607 GtkCssBorderCornerRadius border;
608 GValue v = G_VALUE_INIT;
611 _gtk_css_number_init (&border.horizontal, g_value_get_int (value), GTK_CSS_PX);
612 border.vertical = border.horizontal;
613 g_value_init (&v, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
614 g_value_set_boxed (&v, &border);
616 for (i = 0; i < 4; i++)
617 _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, i)), props, state, &v);
623 pack_border_radius (GtkCssShorthandProperty *shorthand,
625 GtkStyleQueryFunc query_func,
628 const GtkCssBorderCornerRadius *top_left;
629 GtkCssStyleProperty *prop;
633 prop = GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("border-top-left-radius"));
634 v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data);
637 top_left = _gtk_css_value_get_border_corner_radius (v);
639 i = top_left->horizontal.value;
642 g_value_init (value, G_TYPE_INT);
643 g_value_set_int (value, i);
647 unpack_font_description (GtkCssShorthandProperty *shorthand,
648 GtkStyleProperties *props,
652 GtkStyleProperty *prop;
653 PangoFontDescription *description;
655 GValue v = G_VALUE_INIT;
657 /* For backwards compat, we only unpack values that are indeed set.
658 * For strict CSS conformance we need to unpack all of them.
659 * Note that we do set all of them in the parse function, so it
660 * will not have effects when parsing CSS files. It will though
661 * for custom style providers.
664 description = g_value_get_boxed (value);
667 mask = pango_font_description_get_set_fields (description);
671 if (mask & PANGO_FONT_MASK_FAMILY)
673 GPtrArray *strv = g_ptr_array_new ();
675 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description)));
676 g_ptr_array_add (strv, NULL);
677 g_value_init (&v, G_TYPE_STRV);
678 g_value_take_boxed (&v, g_ptr_array_free (strv, FALSE));
680 prop = _gtk_style_property_lookup ("font-family");
681 _gtk_style_property_assign (prop, props, state, &v);
685 if (mask & PANGO_FONT_MASK_STYLE)
687 g_value_init (&v, PANGO_TYPE_STYLE);
688 g_value_set_enum (&v, pango_font_description_get_style (description));
690 prop = _gtk_style_property_lookup ("font-style");
691 _gtk_style_property_assign (prop, props, state, &v);
695 if (mask & PANGO_FONT_MASK_VARIANT)
697 g_value_init (&v, PANGO_TYPE_VARIANT);
698 g_value_set_enum (&v, pango_font_description_get_variant (description));
700 prop = _gtk_style_property_lookup ("font-variant");
701 _gtk_style_property_assign (prop, props, state, &v);
705 if (mask & PANGO_FONT_MASK_WEIGHT)
707 g_value_init (&v, PANGO_TYPE_WEIGHT);
708 g_value_set_enum (&v, pango_font_description_get_weight (description));
710 prop = _gtk_style_property_lookup ("font-weight");
711 _gtk_style_property_assign (prop, props, state, &v);
715 if (mask & PANGO_FONT_MASK_SIZE)
717 g_value_init (&v, G_TYPE_DOUBLE);
718 g_value_set_double (&v, (double) pango_font_description_get_size (description) / PANGO_SCALE);
720 prop = _gtk_style_property_lookup ("font-size");
721 _gtk_style_property_assign (prop, props, state, &v);
727 pack_font_description (GtkCssShorthandProperty *shorthand,
729 GtkStyleQueryFunc query_func,
732 PangoFontDescription *description;
735 description = pango_font_description_new ();
737 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-family"))), query_data);
740 /* xxx: Can we set all the families here somehow? */
741 pango_font_description_set_family (description, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0)));
744 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-size"))), query_data);
746 pango_font_description_set_size (description, round (_gtk_css_number_value_get (v, 100) * PANGO_SCALE));
748 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-style"))), query_data);
750 pango_font_description_set_style (description, _gtk_css_font_style_value_get (v));
752 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data);
754 pango_font_description_set_variant (description, _gtk_css_font_variant_value_get (v));
756 v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data);
758 pango_font_description_set_weight (description, _gtk_css_font_weight_value_get (v));
760 g_value_init (value, PANGO_TYPE_FONT_DESCRIPTION);
761 g_value_take_boxed (value, description);
765 unpack_to_everything (GtkCssShorthandProperty *shorthand,
766 GtkStyleProperties *props,
770 GtkCssStyleProperty *prop;
773 n = _gtk_css_shorthand_property_get_n_subproperties (shorthand);
775 for (i = 0; i < n; i++)
777 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i);
778 _gtk_style_property_assign (GTK_STYLE_PROPERTY (prop), props, state, value);
783 pack_first_element (GtkCssShorthandProperty *shorthand,
785 GtkStyleQueryFunc query_func,
788 GtkCssStyleProperty *prop;
790 /* NB: This is a fallback for properties that originally were
791 * not used as shorthand. We just pick the first subproperty
792 * as a representative.
793 * Lesson learned: Don't query the shorthand, query the
794 * real properties instead. */
795 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
796 _gtk_style_property_query (GTK_STYLE_PROPERTY (prop),
803 _gtk_css_shorthand_property_register (const char *name,
805 const char **subproperties,
806 GtkCssShorthandPropertyParseFunc parse_func,
807 GtkCssShorthandPropertyAssignFunc assign_func,
808 GtkCssShorthandPropertyQueryFunc query_func)
810 GtkCssShorthandProperty *node;
812 node = g_object_new (GTK_TYPE_CSS_SHORTHAND_PROPERTY,
814 "value-type", value_type,
815 "subproperties", subproperties,
818 node->parse = parse_func;
819 node->assign = assign_func;
820 node->query = query_func;
824 _gtk_css_shorthand_property_init_properties (void)
826 /* The order is important here, be careful when changing it */
827 const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-size", NULL };
828 const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL };
829 const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL };
830 const char *border_width_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", NULL };
831 const char *border_radius_subproperties[] = { "border-top-left-radius", "border-top-right-radius",
832 "border-bottom-right-radius", "border-bottom-left-radius", NULL };
833 const char *border_color_subproperties[] = { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", NULL };
834 const char *border_style_subproperties[] = { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", NULL };
835 const char *border_image_subproperties[] = { "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
836 const char *border_top_subproperties[] = { "border-top-width", "border-top-style", "border-top-color", NULL };
837 const char *border_right_subproperties[] = { "border-right-width", "border-right-style", "border-right-color", NULL };
838 const char *border_bottom_subproperties[] = { "border-bottom-width", "border-bottom-style", "border-bottom-color", NULL };
839 const char *border_left_subproperties[] = { "border-left-width", "border-left-style", "border-left-color", NULL };
840 const char *border_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width",
841 "border-top-style", "border-right-style", "border-bottom-style", "border-left-style",
842 "border-top-color", "border-right-color", "border-bottom-color", "border-left-color",
843 "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
844 const char *outline_subproperties[] = { "outline-width", "outline-style", "outline-color", NULL };
845 const char *background_subproperties[] = { "background-image", "background-repeat", "background-clip", "background-origin",
846 "background-color", NULL };
848 _gtk_css_shorthand_property_register ("font",
849 PANGO_TYPE_FONT_DESCRIPTION,
852 unpack_font_description,
853 pack_font_description);
854 _gtk_css_shorthand_property_register ("margin",
856 margin_subproperties,
860 _gtk_css_shorthand_property_register ("padding",
862 padding_subproperties,
866 _gtk_css_shorthand_property_register ("border-width",
868 border_width_subproperties,
872 _gtk_css_shorthand_property_register ("border-radius",
874 border_radius_subproperties,
876 unpack_border_radius,
878 _gtk_css_shorthand_property_register ("border-color",
880 border_color_subproperties,
882 unpack_to_everything,
884 _gtk_css_shorthand_property_register ("border-style",
885 GTK_TYPE_BORDER_STYLE,
886 border_style_subproperties,
888 unpack_to_everything,
890 _gtk_css_shorthand_property_register ("border-image",
892 border_image_subproperties,
896 _gtk_css_shorthand_property_register ("border-top",
898 border_top_subproperties,
902 _gtk_css_shorthand_property_register ("border-right",
904 border_right_subproperties,
908 _gtk_css_shorthand_property_register ("border-bottom",
910 border_bottom_subproperties,
914 _gtk_css_shorthand_property_register ("border-left",
916 border_left_subproperties,
920 _gtk_css_shorthand_property_register ("border",
922 border_subproperties,
926 _gtk_css_shorthand_property_register ("outline",
928 outline_subproperties,
932 _gtk_css_shorthand_property_register ("background",
934 background_subproperties,