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 "gtktypebuiltins.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"
43 value_is_done_parsing (GtkCssParser *parser)
45 return _gtk_css_parser_is_eof (parser) ||
46 _gtk_css_parser_begins_with (parser, ';') ||
47 _gtk_css_parser_begins_with (parser, '}');
51 parse_border_width (GtkCssShorthandProperty *shorthand,
56 GValue temp = G_VALUE_INIT;
59 g_value_init (&temp, GTK_TYPE_BORDER);
60 if (!_gtk_css_style_parse_value (&temp, parser, base))
62 g_value_unset (&temp);
66 border = g_value_get_boxed (&temp);
68 g_value_init (&values[0], G_TYPE_INT);
69 g_value_init (&values[1], G_TYPE_INT);
70 g_value_init (&values[2], G_TYPE_INT);
71 g_value_init (&values[3], G_TYPE_INT);
72 g_value_set_int (&values[0], border->top);
73 g_value_set_int (&values[1], border->right);
74 g_value_set_int (&values[2], border->bottom);
75 g_value_set_int (&values[3], border->left);
77 g_value_unset (&temp);
83 parse_border_radius (GtkCssShorthandProperty *shorthand,
88 GtkCssBorderCornerRadius borders[4];
91 for (i = 0; i < G_N_ELEMENTS (borders); i++)
93 if (!_gtk_css_parser_try_double (parser, &borders[i].horizontal))
95 if (borders[i].horizontal < 0)
97 _gtk_css_parser_error (parser, "Border radius values cannot be negative");
104 _gtk_css_parser_error (parser, "Expected a number");
108 /* The magic (i - 1) >> 1 below makes it take the correct value
109 * according to spec. Feel free to check the 4 cases */
110 for (; i < G_N_ELEMENTS (borders); i++)
111 borders[i].horizontal = borders[(i - 1) >> 1].horizontal;
113 if (_gtk_css_parser_try (parser, "/", TRUE))
115 for (i = 0; i < G_N_ELEMENTS (borders); i++)
117 if (!_gtk_css_parser_try_double (parser, &borders[i].vertical))
119 if (borders[i].vertical < 0)
121 _gtk_css_parser_error (parser, "Border radius values cannot be negative");
128 _gtk_css_parser_error (parser, "Expected a number");
132 for (; i < G_N_ELEMENTS (borders); i++)
133 borders[i].vertical = borders[(i - 1) >> 1].vertical;
138 for (i = 0; i < G_N_ELEMENTS (borders); i++)
139 borders[i].vertical = borders[i].horizontal;
142 for (i = 0; i < G_N_ELEMENTS (borders); i++)
144 g_value_init (&values[i], GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
145 g_value_set_boxed (&values[i], &borders[i]);
152 parse_border_color (GtkCssShorthandProperty *shorthand,
154 GtkCssParser *parser,
157 GtkSymbolicColor *symbolic;
160 for (i = 0; i < 4; i++)
162 symbolic = _gtk_css_parser_read_symbolic_color (parser);
163 if (symbolic == NULL)
166 g_value_init (&values[i], GTK_TYPE_SYMBOLIC_COLOR);
167 g_value_set_boxed (&values[i], symbolic);
169 if (value_is_done_parsing (parser))
173 for (i++; i < 4; i++)
175 g_value_init (&values[i], GTK_TYPE_SYMBOLIC_COLOR);
176 g_value_copy (&values[(i - 1) >> 1], &values[i]);
183 parse_border_style (GtkCssShorthandProperty *shorthand,
185 GtkCssParser *parser,
188 GtkBorderStyle styles[4];
191 for (i = 0; i < 4; i++)
193 if (!_gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, (int *)&styles[i]))
199 _gtk_css_parser_error (parser, "Expected a border style");
203 for (; i < G_N_ELEMENTS (styles); i++)
204 styles[i] = styles[(i - 1) >> 1];
206 for (i = 0; i < G_N_ELEMENTS (styles); i++)
208 g_value_init (&values[i], GTK_TYPE_BORDER_STYLE);
209 g_value_set_enum (&values[i], styles[i]);
216 parse_border_image (GtkCssShorthandProperty *shorthand,
218 GtkCssParser *parser,
223 if (_gtk_css_parser_try (parser, "none", TRUE))
227 image = _gtk_css_image_new_parse (parser, base);
231 g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
232 g_value_set_object (&values[0], image);
234 if (value_is_done_parsing (parser))
237 g_value_init (&values[1], GTK_TYPE_BORDER);
238 if (!_gtk_css_style_parse_value (&values[1], parser, base))
241 if (_gtk_css_parser_try (parser, "/", TRUE))
243 g_value_init (&values[2], GTK_TYPE_BORDER);
244 if (!_gtk_css_style_parse_value (&values[2], parser, base))
248 if (value_is_done_parsing (parser))
251 g_value_init (&values[3], GTK_TYPE_CSS_BORDER_IMAGE_REPEAT);
252 if (!_gtk_css_style_parse_value (&values[3], parser, base))
259 parse_border_side (GtkCssShorthandProperty *shorthand,
261 GtkCssParser *parser,
269 if (!G_IS_VALUE (&values[0]) &&
270 _gtk_css_parser_try_length (parser, &width))
272 g_value_init (&values[0], G_TYPE_INT);
273 g_value_set_int (&values[0], width);
275 else if (!G_IS_VALUE (&values[1]) &&
276 _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
278 g_value_init (&values[1], GTK_TYPE_BORDER_STYLE);
279 g_value_set_enum (&values[1], style);
281 else if (!G_IS_VALUE (&values[2]))
283 GtkSymbolicColor *symbolic;
285 symbolic = _gtk_css_parser_read_symbolic_color (parser);
286 if (symbolic == NULL)
289 g_value_init (&values[2], GTK_TYPE_SYMBOLIC_COLOR);
290 g_value_take_boxed (&values[2], symbolic);
294 /* We parsed everything and there's still stuff left?
295 * Pretend we didn't notice and let the normal code produce
296 * a 'junk at end of value' error */
300 while (!value_is_done_parsing (parser));
306 parse_border (GtkCssShorthandProperty *shorthand,
308 GtkCssParser *parser,
316 if (!G_IS_VALUE (&values[0]) &&
317 _gtk_css_parser_try_length (parser, &width))
319 g_value_init (&values[0], G_TYPE_INT);
320 g_value_init (&values[1], G_TYPE_INT);
321 g_value_init (&values[2], G_TYPE_INT);
322 g_value_init (&values[3], G_TYPE_INT);
323 g_value_set_int (&values[0], width);
324 g_value_set_int (&values[1], width);
325 g_value_set_int (&values[2], width);
326 g_value_set_int (&values[3], width);
328 else if (!G_IS_VALUE (&values[4]) &&
329 _gtk_css_parser_try_enum (parser, GTK_TYPE_BORDER_STYLE, &style))
331 g_value_init (&values[4], GTK_TYPE_BORDER_STYLE);
332 g_value_init (&values[5], GTK_TYPE_BORDER_STYLE);
333 g_value_init (&values[6], GTK_TYPE_BORDER_STYLE);
334 g_value_init (&values[7], GTK_TYPE_BORDER_STYLE);
335 g_value_set_enum (&values[4], style);
336 g_value_set_enum (&values[5], style);
337 g_value_set_enum (&values[6], style);
338 g_value_set_enum (&values[7], style);
340 else if (!G_IS_VALUE (&values[8]))
342 GtkSymbolicColor *symbolic;
344 symbolic = _gtk_css_parser_read_symbolic_color (parser);
345 if (symbolic == NULL)
348 g_value_init (&values[8], GTK_TYPE_SYMBOLIC_COLOR);
349 g_value_init (&values[9], GTK_TYPE_SYMBOLIC_COLOR);
350 g_value_init (&values[10], GTK_TYPE_SYMBOLIC_COLOR);
351 g_value_init (&values[11], GTK_TYPE_SYMBOLIC_COLOR);
352 g_value_set_boxed (&values[8], symbolic);
353 g_value_set_boxed (&values[9], symbolic);
354 g_value_set_boxed (&values[10], symbolic);
355 g_value_take_boxed (&values[11], symbolic);
359 /* We parsed everything and there's still stuff left?
360 * Pretend we didn't notice and let the normal code produce
361 * a 'junk at end of value' error */
365 while (!value_is_done_parsing (parser));
367 /* Note that border-image values are not set: according to the spec
368 they just need to be reset when using the border shorthand */
374 parse_font (GtkCssShorthandProperty *shorthand,
376 GtkCssParser *parser,
379 PangoFontDescription *desc;
383 str = _gtk_css_parser_read_value (parser);
387 desc = pango_font_description_from_string (str);
390 mask = pango_font_description_get_set_fields (desc);
392 if (mask & PANGO_FONT_MASK_FAMILY)
394 GPtrArray *strv = g_ptr_array_new ();
396 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (desc)));
397 g_ptr_array_add (strv, NULL);
398 g_value_init (&values[0], G_TYPE_STRV);
399 g_value_take_boxed (&values[0], g_ptr_array_free (strv, FALSE));
401 if (mask & PANGO_FONT_MASK_STYLE)
403 g_value_init (&values[1], PANGO_TYPE_STYLE);
404 g_value_set_enum (&values[1], pango_font_description_get_style (desc));
406 if (mask & PANGO_FONT_MASK_VARIANT)
408 g_value_init (&values[2], PANGO_TYPE_VARIANT);
409 g_value_set_enum (&values[2], pango_font_description_get_variant (desc));
411 if (mask & PANGO_FONT_MASK_WEIGHT)
413 g_value_init (&values[3], PANGO_TYPE_WEIGHT);
414 g_value_set_enum (&values[3], pango_font_description_get_weight (desc));
416 if (mask & PANGO_FONT_MASK_SIZE)
418 g_value_init (&values[4], G_TYPE_DOUBLE);
419 g_value_set_double (&values[4],
420 (double) pango_font_description_get_size (desc) / PANGO_SCALE);
423 pango_font_description_free (desc);
429 parse_background (GtkCssShorthandProperty *shorthand,
431 GtkCssParser *parser,
439 if (!G_IS_VALUE (&values[0]) &&
440 (_gtk_css_parser_has_prefix (parser, "none") ||
441 _gtk_css_image_can_parse (parser)))
445 if (_gtk_css_parser_try (parser, "none", TRUE))
449 image = _gtk_css_image_new_parse (parser, base);
454 g_value_init (&values[0], GTK_TYPE_CSS_IMAGE);
455 g_value_take_object (&values[0], image);
457 else if (!G_IS_VALUE (&values[1]) &&
458 _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &enum_value))
460 if (enum_value <= GTK_CSS_BACKGROUND_REPEAT_MASK)
464 if (_gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_BACKGROUND_REPEAT, &vertical))
466 if (vertical >= GTK_CSS_BACKGROUND_REPEAT_MASK)
468 _gtk_css_parser_error (parser, "Not a valid 2nd value for border-repeat");
472 enum_value |= vertical << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
475 enum_value |= enum_value << GTK_CSS_BACKGROUND_REPEAT_SHIFT;
478 g_value_init (&values[1], GTK_TYPE_CSS_BACKGROUND_REPEAT);
479 g_value_set_enum (&values[1], enum_value);
481 else if ((!G_IS_VALUE (&values[2]) || !G_IS_VALUE (&values[3])) &&
482 _gtk_css_parser_try_enum (parser, GTK_TYPE_CSS_AREA, &enum_value))
484 guint idx = !G_IS_VALUE (&values[2]) ? 2 : 3;
485 g_value_init (&values[idx], GTK_TYPE_CSS_AREA);
486 g_value_set_enum (&values[idx], enum_value);
488 else if (!G_IS_VALUE (&values[4]))
490 GtkSymbolicColor *symbolic;
492 symbolic = _gtk_css_parser_read_symbolic_color (parser);
493 if (symbolic == NULL)
496 g_value_init (&values[4], GTK_TYPE_SYMBOLIC_COLOR);
497 g_value_take_boxed (&values[4], symbolic);
501 /* We parsed everything and there's still stuff left?
502 * Pretend we didn't notice and let the normal code produce
503 * a 'junk at end of value' error */
507 while (!value_is_done_parsing (parser));
515 unpack_border (const GValue *value,
522 GParameter *parameter = g_new0 (GParameter, 4);
523 GtkBorder *border = g_value_get_boxed (value);
525 parameter[0].name = top;
526 g_value_init (¶meter[0].value, G_TYPE_INT);
527 g_value_set_int (¶meter[0].value, border->top);
528 parameter[1].name = left;
529 g_value_init (¶meter[1].value, G_TYPE_INT);
530 g_value_set_int (¶meter[1].value, border->left);
531 parameter[2].name = bottom;
532 g_value_init (¶meter[2].value, G_TYPE_INT);
533 g_value_set_int (¶meter[2].value, border->bottom);
534 parameter[3].name = right;
535 g_value_init (¶meter[3].value, G_TYPE_INT);
536 g_value_set_int (¶meter[3].value, border->right);
543 pack_border (GtkCssShorthandProperty *shorthand,
545 GtkStyleProperties *props,
548 GtkCssStyleProperty *prop;
552 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0);
553 v = _gtk_style_properties_peek_property (props, prop, state);
555 border.top = g_value_get_int (v);
556 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 1);
557 v = _gtk_style_properties_peek_property (props, prop, state);
559 border.right = g_value_get_int (v);
560 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 2);
561 v = _gtk_style_properties_peek_property (props, prop, state);
563 border.bottom = g_value_get_int (v);
564 prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 3);
565 v = _gtk_style_properties_peek_property (props, prop, state);
567 border.left = g_value_get_int (v);
569 g_value_set_boxed (value, &border);
573 unpack_border_width (GtkCssShorthandProperty *shorthand,
577 return unpack_border (value, n_params,
578 "border-top-width", "border-left-width",
579 "border-bottom-width", "border-right-width");
583 unpack_padding (GtkCssShorthandProperty *shorthand,
587 return unpack_border (value, n_params,
588 "padding-top", "padding-left",
589 "padding-bottom", "padding-right");
593 unpack_margin (GtkCssShorthandProperty *shorthand,
597 return unpack_border (value, n_params,
598 "margin-top", "margin-left",
599 "margin-bottom", "margin-right");
603 unpack_border_radius (GtkCssShorthandProperty *shorthand,
607 GParameter *parameter = g_new0 (GParameter, 4);
608 GtkCssBorderCornerRadius border;
610 border.horizontal = border.vertical = g_value_get_int (value);
612 parameter[0].name = "border-top-left-radius";
613 g_value_init (¶meter[0].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
614 g_value_set_boxed (¶meter[0].value, &border);
615 parameter[1].name = "border-top-right-radius";
616 g_value_init (¶meter[1].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
617 g_value_set_boxed (¶meter[1].value, &border);
618 parameter[2].name = "border-bottom-right-radius";
619 g_value_init (¶meter[2].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
620 g_value_set_boxed (¶meter[2].value, &border);
621 parameter[3].name = "border-bottom-left-radius";
622 g_value_init (¶meter[3].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS);
623 g_value_set_boxed (¶meter[3].value, &border);
630 pack_border_radius (GtkCssShorthandProperty *shorthand,
632 GtkStyleProperties *props,
635 GtkCssBorderCornerRadius *top_left;
637 /* NB: We are an int property, so we have to resolve to an int here.
638 * So we just resolve to an int. We pick one and stick to it.
639 * Lesson learned: Don't query border-radius shorthand, query the
640 * real properties instead. */
641 gtk_style_properties_get (props,
643 "border-top-left-radius", &top_left,
647 g_value_set_int (value, top_left->horizontal);
653 unpack_font_description (GtkCssShorthandProperty *shorthand,
657 GParameter *parameter = g_new0 (GParameter, 5);
658 PangoFontDescription *description;
662 /* For backwards compat, we only unpack values that are indeed set.
663 * For strict CSS conformance we need to unpack all of them.
664 * Note that we do set all of them in the parse function, so it
665 * will not have effects when parsing CSS files. It will though
666 * for custom style providers.
669 description = g_value_get_boxed (value);
673 mask = pango_font_description_get_set_fields (description);
677 if (mask & PANGO_FONT_MASK_FAMILY)
679 GPtrArray *strv = g_ptr_array_new ();
681 g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description)));
682 g_ptr_array_add (strv, NULL);
683 parameter[n].name = "font-family";
684 g_value_init (¶meter[n].value, G_TYPE_STRV);
685 g_value_take_boxed (¶meter[n].value,
686 g_ptr_array_free (strv, FALSE));
690 if (mask & PANGO_FONT_MASK_STYLE)
692 parameter[n].name = "font-style";
693 g_value_init (¶meter[n].value, PANGO_TYPE_STYLE);
694 g_value_set_enum (¶meter[n].value,
695 pango_font_description_get_style (description));
699 if (mask & PANGO_FONT_MASK_VARIANT)
701 parameter[n].name = "font-variant";
702 g_value_init (¶meter[n].value, PANGO_TYPE_VARIANT);
703 g_value_set_enum (¶meter[n].value,
704 pango_font_description_get_variant (description));
708 if (mask & PANGO_FONT_MASK_WEIGHT)
710 parameter[n].name = "font-weight";
711 g_value_init (¶meter[n].value, PANGO_TYPE_WEIGHT);
712 g_value_set_enum (¶meter[n].value,
713 pango_font_description_get_weight (description));
717 if (mask & PANGO_FONT_MASK_SIZE)
719 parameter[n].name = "font-size";
720 g_value_init (¶meter[n].value, G_TYPE_DOUBLE);
721 g_value_set_double (¶meter[n].value,
722 (double) pango_font_description_get_size (description) / PANGO_SCALE);
732 pack_font_description (GtkCssShorthandProperty *shorthand,
734 GtkStyleProperties *props,
737 PangoFontDescription *description;
740 PangoVariant variant;
744 gtk_style_properties_get (props,
746 "font-family", &families,
747 "font-style", &style,
748 "font-variant", &variant,
749 "font-weight", &weight,
753 description = pango_font_description_new ();
754 /* xxx: Can we set all the families here somehow? */
756 pango_font_description_set_family (description, families[0]);
757 pango_font_description_set_size (description, round (size * PANGO_SCALE));
758 pango_font_description_set_style (description, style);
759 pango_font_description_set_variant (description, variant);
760 pango_font_description_set_weight (description, weight);
762 g_strfreev (families);
764 g_value_take_boxed (value, description);
768 unpack_border_color (GtkCssShorthandProperty *shorthand,
772 GParameter *parameter = g_new0 (GParameter, 4);
776 type = G_VALUE_TYPE (value);
778 parameter[0].name = "border-top-color";
779 g_value_init (¶meter[0].value, type);
780 parameter[1].name = "border-right-color";
781 g_value_init (¶meter[1].value, type);
782 parameter[2].name = "border-bottom-color";
783 g_value_init (¶meter[2].value, type);
784 parameter[3].name = "border-left-color";
785 g_value_init (¶meter[3].value, type);
787 /* can be RGBA or symbolic color */
788 p = g_value_get_boxed (value);
790 g_value_set_boxed (¶meter[0].value, p);
791 g_value_set_boxed (¶meter[1].value, p);
792 g_value_set_boxed (¶meter[2].value, p);
793 g_value_set_boxed (¶meter[3].value, p);
800 pack_border_color (GtkCssShorthandProperty *shorthand,
802 GtkStyleProperties *props,
805 /* NB: We are a color property, so we have to resolve to a color here.
806 * So we just resolve to a color. We pick one and stick to it.
807 * Lesson learned: Don't query border-color shorthand, query the
808 * real properties instead. */
809 g_value_unset (value);
810 gtk_style_properties_get_property (props, "border-top-color", state, value);
814 unpack_border_style (GtkCssShorthandProperty *shorthand,
818 GParameter *parameter = g_new0 (GParameter, 4);
819 GtkBorderStyle style;
821 style = g_value_get_enum (value);
823 parameter[0].name = "border-top-style";
824 g_value_init (¶meter[0].value, GTK_TYPE_BORDER_STYLE);
825 g_value_set_enum (¶meter[0].value, style);
826 parameter[1].name = "border-right-style";
827 g_value_init (¶meter[1].value, GTK_TYPE_BORDER_STYLE);
828 g_value_set_enum (¶meter[1].value, style);
829 parameter[2].name = "border-bottom-style";
830 g_value_init (¶meter[2].value, GTK_TYPE_BORDER_STYLE);
831 g_value_set_enum (¶meter[2].value, style);
832 parameter[3].name = "border-left-style";
833 g_value_init (¶meter[3].value, GTK_TYPE_BORDER_STYLE);
834 g_value_set_enum (¶meter[3].value, style);
841 pack_border_style (GtkCssShorthandProperty *shorthand,
843 GtkStyleProperties *props,
846 /* NB: We can just resolve to a style. We pick one and stick to it.
847 * Lesson learned: Don't query border-style shorthand, query the
848 * real properties instead. */
849 g_value_unset (value);
850 gtk_style_properties_get_property (props, "border-top-style", state, value);
854 _gtk_css_shorthand_property_register (const char *name,
856 const char **subproperties,
857 GtkCssShorthandPropertyParseFunc parse_func,
858 GtkCssShorthandPropertyAssignFunc assign_func,
859 GtkCssShorthandPropertyQueryFunc query_func)
861 GtkCssShorthandProperty *node;
863 node = g_object_new (GTK_TYPE_CSS_SHORTHAND_PROPERTY,
865 "value-type", value_type,
866 "subproperties", subproperties,
869 node->parse = parse_func;
870 node->assign = assign_func;
871 node->query = query_func;
875 _gtk_css_shorthand_property_init_properties (void)
877 /* The order is important here, be careful when changing it */
878 const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-size", NULL };
879 const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL };
880 const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL };
881 const char *border_width_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", NULL };
882 const char *border_radius_subproperties[] = { "border-top-left-radius", "border-top-right-radius",
883 "border-bottom-right-radius", "border-bottom-left-radius", NULL };
884 const char *border_color_subproperties[] = { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", NULL };
885 const char *border_style_subproperties[] = { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", NULL };
886 const char *border_image_subproperties[] = { "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
887 const char *border_top_subproperties[] = { "border-top-width", "border-top-style", "border-top-color", NULL };
888 const char *border_right_subproperties[] = { "border-right-width", "border-right-style", "border-right-color", NULL };
889 const char *border_bottom_subproperties[] = { "border-bottom-width", "border-bottom-style", "border-bottom-color", NULL };
890 const char *border_left_subproperties[] = { "border-left-width", "border-left-style", "border-left-color", NULL };
891 const char *border_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width",
892 "border-top-style", "border-right-style", "border-bottom-style", "border-left-style",
893 "border-top-color", "border-right-color", "border-bottom-color", "border-left-color",
894 "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL };
895 const char *outline_subproperties[] = { "outline-width", "outline-style", "outline-color", NULL };
896 const char *background_subproperties[] = { "background-image", "background-repeat", "background-clip", "background-origin",
897 "background-color", NULL };
899 _gtk_css_shorthand_property_register ("font",
900 PANGO_TYPE_FONT_DESCRIPTION,
903 unpack_font_description,
904 pack_font_description);
905 _gtk_css_shorthand_property_register ("margin",
907 margin_subproperties,
911 _gtk_css_shorthand_property_register ("padding",
913 padding_subproperties,
917 _gtk_css_shorthand_property_register ("border-width",
919 border_width_subproperties,
923 _gtk_css_shorthand_property_register ("border-radius",
925 border_radius_subproperties,
927 unpack_border_radius,
929 _gtk_css_shorthand_property_register ("border-color",
931 border_color_subproperties,
935 _gtk_css_shorthand_property_register ("border-style",
936 GTK_TYPE_BORDER_STYLE,
937 border_style_subproperties,
941 _gtk_css_shorthand_property_register ("border-image",
943 border_image_subproperties,
947 _gtk_css_shorthand_property_register ("border-top",
949 border_top_subproperties,
953 _gtk_css_shorthand_property_register ("border-right",
955 border_right_subproperties,
959 _gtk_css_shorthand_property_register ("border-bottom",
961 border_bottom_subproperties,
965 _gtk_css_shorthand_property_register ("border-left",
967 border_left_subproperties,
971 _gtk_css_shorthand_property_register ("border",
973 border_subproperties,
977 _gtk_css_shorthand_property_register ("outline",
979 outline_subproperties,
983 _gtk_css_shorthand_property_register ("background",
985 background_subproperties,