X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkcssshorthandpropertyimpl.c;h=b01494b7da888fd165f144482b339b94423f49d6;hb=02e915273845b21af223e7e5e2425569afcf1b83;hp=d303643018da8de153e8517af566d1611f9ca832;hpb=148d8fbca87f435140b3bd6f6a94e590b3d7b782;p=~andy%2Fgtk diff --git a/gtk/gtkcssshorthandpropertyimpl.c b/gtk/gtkcssshorthandpropertyimpl.c index d30364301..b01494b7d 100644 --- a/gtk/gtkcssshorthandpropertyimpl.c +++ b/gtk/gtkcssshorthandpropertyimpl.c @@ -12,8 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * License along with this library. If not, see . * * Authors: Benjamin Otte */ @@ -25,9 +24,23 @@ #include #include -#include "gtkborderimageprivate.h" +#include "gtkcssarrayvalueprivate.h" +#include "gtkcssbgsizevalueprivate.h" +#include "gtkcssbordervalueprivate.h" +#include "gtkcsscolorvalueprivate.h" +#include "gtkcsscornervalueprivate.h" +#include "gtkcsseasevalueprivate.h" +#include "gtkcssenumvalueprivate.h" +#include "gtkcssimageprivate.h" +#include "gtkcssimagevalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcsspositionvalueprivate.h" +#include "gtkcssrepeatvalueprivate.h" +#include "gtkcssstringvalueprivate.h" #include "gtkcssstylefuncsprivate.h" -#include "gtkcsstypesprivate.h" +#include "gtkcssvalueprivate.h" +#include "gtkstylepropertiesprivate.h" +#include "gtktypebuiltins.h" /* this is in case round() is not provided by the compiler, * such as in the case of C89 compilers, like MSVC @@ -37,424 +50,878 @@ /*** PARSING ***/ static gboolean -border_image_value_parse (GtkCssParser *parser, - GFile *base, - GValue *value) +value_is_done_parsing (GtkCssParser *parser) { - GValue temp = G_VALUE_INIT; - cairo_pattern_t *pattern = NULL; - gconstpointer *boxed = NULL; - GType boxed_type; - GtkBorder slice, *width = NULL, *parsed_slice; - GtkCssBorderImageRepeat repeat, *parsed_repeat; - gboolean retval = FALSE; - GtkBorderImage *image = NULL; + return _gtk_css_parser_is_eof (parser) || + _gtk_css_parser_begins_with (parser, ',') || + _gtk_css_parser_begins_with (parser, ';') || + _gtk_css_parser_begins_with (parser, '}'); +} - if (_gtk_css_parser_try (parser, "none", TRUE)) - return TRUE; +static gboolean +parse_four_numbers (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser, + GtkCssNumberParseFlags flags) +{ + guint i; - g_value_init (&temp, CAIRO_GOBJECT_TYPE_PATTERN); + for (i = 0; i < 4; i++) + { + if (!_gtk_css_parser_has_number (parser)) + break; - if (!_gtk_css_style_parse_value (&temp, parser, base)) - return FALSE; + values[i] = _gtk_css_number_value_parse (parser, flags); + if (values[i] == NULL) + return FALSE; + } - boxed_type = G_VALUE_TYPE (&temp); - if (boxed_type != CAIRO_GOBJECT_TYPE_PATTERN) - boxed = g_value_dup_boxed (&temp); - else - pattern = g_value_dup_boxed (&temp); + if (i == 0) + { + _gtk_css_parser_error (parser, "Expected a length"); + return FALSE; + } - g_value_unset (&temp); - g_value_init (&temp, GTK_TYPE_BORDER); + for (; i < 4; i++) + { + values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]); + } - if (!_gtk_css_style_parse_value (&temp, parser, base)) - goto out; + return TRUE; +} - parsed_slice = g_value_get_boxed (&temp); - slice = *parsed_slice; +static gboolean +parse_margin (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + return parse_four_numbers (shorthand, + values, + parser, + GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); +} - if (_gtk_css_parser_try (parser, "/", TRUE)) - { - g_value_unset (&temp); - g_value_init (&temp, GTK_TYPE_BORDER); +static gboolean +parse_padding (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + return parse_four_numbers (shorthand, + values, + parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); +} - if (!_gtk_css_style_parse_value (&temp, parser, base)) - goto out; +static gboolean +parse_border_width (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + return parse_four_numbers (shorthand, + values, + parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); +} - width = g_value_dup_boxed (&temp); +static gboolean +parse_border_radius (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + GtkCssValue *x[4] = { NULL, }, *y[4] = { NULL, }; + guint i; + + for (i = 0; i < 4; i++) + { + if (!_gtk_css_parser_has_number (parser)) + break; + x[i] = _gtk_css_number_value_parse (parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_PARSE_PERCENT + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); + if (x[i] == NULL) + goto fail; } - g_value_unset (&temp); - g_value_init (&temp, GTK_TYPE_CSS_BORDER_IMAGE_REPEAT); + if (i == 0) + { + _gtk_css_parser_error (parser, "Expected a number"); + goto fail; + } + + /* The magic (i - 1) >> 1 below makes it take the correct value + * according to spec. Feel free to check the 4 cases */ + for (; i < 4; i++) + x[i] = _gtk_css_value_ref (x[(i - 1) >> 1]); + + if (_gtk_css_parser_try (parser, "/", TRUE)) + { + for (i = 0; i < 4; i++) + { + if (!_gtk_css_parser_has_number (parser)) + break; + y[i] = _gtk_css_number_value_parse (parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_PARSE_PERCENT + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); + if (y[i] == NULL) + goto fail; + } - if (!_gtk_css_style_parse_value (&temp, parser, base)) - goto out; + if (i == 0) + { + _gtk_css_parser_error (parser, "Expected a number"); + goto fail; + } - parsed_repeat = g_value_get_boxed (&temp); - repeat = *parsed_repeat; + for (; i < 4; i++) + y[i] = _gtk_css_value_ref (y[(i - 1) >> 1]); + } + else + { + for (i = 0; i < 4; i++) + y[i] = _gtk_css_value_ref (x[i]); + } - g_value_unset (&temp); + for (i = 0; i < 4; i++) + { + values[i] = _gtk_css_corner_value_new (x[i], y[i]); + } - if (boxed != NULL) - image = _gtk_border_image_new_for_boxed (boxed_type, boxed, &slice, width, &repeat); - else if (pattern != NULL) - image = _gtk_border_image_new (pattern, &slice, width, &repeat); + return TRUE; - if (image != NULL) +fail: + for (i = 0; i < 4; i++) { - retval = TRUE; - g_value_take_boxed (value, image); + if (x[i]) + _gtk_css_value_unref (x[i]); + if (y[i]) + _gtk_css_value_unref (y[i]); } + return FALSE; +} - out: - if (pattern != NULL) - cairo_pattern_destroy (pattern); +static gboolean +parse_border_color (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + guint i; - if (boxed != NULL) - g_boxed_free (boxed_type, boxed); + for (i = 0; i < 4; i++) + { + values[i] = _gtk_css_color_value_parse (parser); + if (values[i] == NULL) + return FALSE; - if (width != NULL) - gtk_border_free (width); + if (value_is_done_parsing (parser)) + break; + } - return retval; + for (i++; i < 4; i++) + { + values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]); + } + + return TRUE; } -static gboolean -border_radius_value_parse (GtkCssParser *parser, - GFile *base, - GValue *value) +static gboolean +parse_border_style (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) { - GtkCssBorderRadius border; + guint i; - if (!_gtk_css_parser_try_double (parser, &border.top_left.horizontal)) + for (i = 0; i < 4; i++) { - _gtk_css_parser_error (parser, "Expected a number"); + values[i] = _gtk_css_border_style_value_try_parse (parser); + if (values[i] == NULL) + break; + } + + if (i == 0) + { + _gtk_css_parser_error (parser, "Expected a border style"); return FALSE; } - else if (border.top_left.horizontal < 0) - goto negative; - if (_gtk_css_parser_try_double (parser, &border.top_right.horizontal)) + for (; i < 4; i++) + values[i] = _gtk_css_value_ref (values[(i - 1) >> 1]); + + return TRUE; +} + +static gboolean +parse_border_image (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + do { - if (border.top_right.horizontal < 0) - goto negative; - if (_gtk_css_parser_try_double (parser, &border.bottom_right.horizontal)) + if (values[0] == NULL && + (_gtk_css_parser_has_prefix (parser, "none") || + _gtk_css_image_can_parse (parser))) + { + GtkCssImage *image; + + if (_gtk_css_parser_try (parser, "none", TRUE)) + image = NULL; + else + { + image = _gtk_css_image_new_parse (parser); + if (image == NULL) + return FALSE; + } + + values[0] = _gtk_css_image_value_new (image); + } + else if (values[3] == NULL && + (values[3] = _gtk_css_border_repeat_value_try_parse (parser))) { - if (border.bottom_right.horizontal < 0) - goto negative; - if (!_gtk_css_parser_try_double (parser, &border.bottom_left.horizontal)) - border.bottom_left.horizontal = border.top_right.horizontal; - else if (border.bottom_left.horizontal < 0) - goto negative; + /* please move along */ + } + else if (values[1] == NULL) + { + values[1] = _gtk_css_border_value_parse (parser, + GTK_CSS_PARSE_PERCENT + | GTK_CSS_PARSE_NUMBER + | GTK_CSS_POSITIVE_ONLY, + FALSE, + TRUE); + if (values[1] == NULL) + return FALSE; + + if (_gtk_css_parser_try (parser, "/", TRUE)) + { + values[2] = _gtk_css_border_value_parse (parser, + GTK_CSS_PARSE_PERCENT + | GTK_CSS_PARSE_LENGTH + | GTK_CSS_PARSE_NUMBER + | GTK_CSS_POSITIVE_ONLY, + TRUE, + FALSE); + if (values[2] == NULL) + return FALSE; + } } else { - border.bottom_right.horizontal = border.top_left.horizontal; - border.bottom_left.horizontal = border.top_right.horizontal; + /* We parsed everything and there's still stuff left? + * Pretend we didn't notice and let the normal code produce + * a 'junk at end of value' error */ + break; } } - else + while (!value_is_done_parsing (parser)); + + return TRUE; +} + +static gboolean +parse_border_side (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + do + { + if (values[0] == NULL && + _gtk_css_parser_has_number (parser)) + { + values[0] = _gtk_css_number_value_parse (parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); + if (values[0] == NULL) + return FALSE; + } + else if (values[1] == NULL && + (values[1] = _gtk_css_border_style_value_try_parse (parser))) + { + /* Nothing to do */ + } + else if (values[2] == NULL) + { + values[2] = _gtk_css_color_value_parse (parser); + if (values[2] == NULL) + return FALSE; + } + } + while (!value_is_done_parsing (parser)); + + return TRUE; +} + +static gboolean +parse_border (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + do + { + if (values[0] == NULL && + _gtk_css_parser_has_number (parser)) + { + values[0] = _gtk_css_number_value_parse (parser, + GTK_CSS_POSITIVE_ONLY + | GTK_CSS_NUMBER_AS_PIXELS + | GTK_CSS_PARSE_LENGTH); + if (values[0] == NULL) + return FALSE; + values[1] = _gtk_css_value_ref (values[0]); + values[2] = _gtk_css_value_ref (values[0]); + values[3] = _gtk_css_value_ref (values[0]); + } + else if (values[4] == NULL && + (values[4] = _gtk_css_border_style_value_try_parse (parser))) + { + values[5] = _gtk_css_value_ref (values[4]); + values[6] = _gtk_css_value_ref (values[4]); + values[7] = _gtk_css_value_ref (values[4]); + } + else if (!G_IS_VALUE (&values[8])) + { + values[8] = _gtk_css_color_value_parse (parser); + if (values[8] == NULL) + return FALSE; + + values[9] = _gtk_css_value_ref (values[8]); + values[10] = _gtk_css_value_ref (values[8]); + values[11] = _gtk_css_value_ref (values[8]); + } + else + { + /* We parsed everything and there's still stuff left? + * Pretend we didn't notice and let the normal code produce + * a 'junk at end of value' error */ + break; + } + } + while (!value_is_done_parsing (parser)); + + /* Note that border-image values are not set: according to the spec + they just need to be reset when using the border shorthand */ + + return TRUE; +} + +static gboolean +parse_font (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + PangoFontDescription *desc; + guint mask; + char *str; + + str = _gtk_css_parser_read_value (parser); + if (str == NULL) + return FALSE; + + desc = pango_font_description_from_string (str); + g_free (str); + + mask = pango_font_description_get_set_fields (desc); + + if (mask & PANGO_FONT_MASK_FAMILY) { - border.top_right.horizontal = border.top_left.horizontal; - border.bottom_right.horizontal = border.top_left.horizontal; - border.bottom_left.horizontal = border.top_left.horizontal; + values[0] = _gtk_css_array_value_new (_gtk_css_string_value_new (pango_font_description_get_family (desc))); + } + if (mask & PANGO_FONT_MASK_STYLE) + { + values[1] = _gtk_css_font_style_value_new (pango_font_description_get_style (desc)); + } + if (mask & PANGO_FONT_MASK_VARIANT) + { + values[2] = _gtk_css_font_variant_value_new (pango_font_description_get_variant (desc)); + } + if (mask & PANGO_FONT_MASK_WEIGHT) + { + values[3] = _gtk_css_font_weight_value_new (pango_font_description_get_weight (desc)); + } + if (mask & PANGO_FONT_MASK_SIZE) + { + values[4] = _gtk_css_number_value_new ((double) pango_font_description_get_size (desc) / PANGO_SCALE, GTK_CSS_PX); } - if (_gtk_css_parser_try (parser, "/", TRUE)) + pango_font_description_free (desc); + + return TRUE; +} + +static gboolean +parse_one_background (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + GtkCssValue *value = NULL; + + do { - if (!_gtk_css_parser_try_double (parser, &border.top_left.vertical)) + /* the image part */ + if (values[0] == NULL && + (_gtk_css_parser_has_prefix (parser, "none") || + _gtk_css_image_can_parse (parser))) { - _gtk_css_parser_error (parser, "Expected a number"); - return FALSE; - } - else if (border.top_left.vertical < 0) - goto negative; + GtkCssImage *image; + + if (_gtk_css_parser_try (parser, "none", TRUE)) + image = NULL; + else + { + image = _gtk_css_image_new_parse (parser); + if (image == NULL) + return FALSE; + } - if (_gtk_css_parser_try_double (parser, &border.top_right.vertical)) + values[0] = _gtk_css_image_value_new (image); + } + else if (values[1] == NULL && + (value = _gtk_css_position_value_try_parse (parser))) { - if (border.top_right.vertical < 0) - goto negative; - if (_gtk_css_parser_try_double (parser, &border.bottom_right.vertical)) + values[1] = value; + value = NULL; + + if (_gtk_css_parser_try (parser, "/", TRUE) && + (value = _gtk_css_bg_size_value_parse (parser))) { - if (border.bottom_right.vertical < 0) - goto negative; - if (!_gtk_css_parser_try_double (parser, &border.bottom_left.vertical)) - border.bottom_left.vertical = border.top_right.vertical; - else if (border.bottom_left.vertical < 0) - goto negative; + values[2] = value; + value = NULL; } - else + } + else if (values[3] == NULL && + (value = _gtk_css_background_repeat_value_try_parse (parser))) + { + values[3] = value; + value = NULL; + } + else if ((values[4] == NULL || values[5] == NULL) && + (value = _gtk_css_area_value_try_parse (parser))) + { + values[4] = value; + + if (values[5] == NULL) { - border.bottom_right.vertical = border.top_left.vertical; - border.bottom_left.vertical = border.top_right.vertical; + values[5] = values[4]; + values[4] = NULL; } + value = NULL; + } + else if (values[6] == NULL) + { + value = _gtk_css_color_value_parse (parser); + if (value == NULL) + values[6] = _gtk_css_value_ref (_gtk_css_style_property_get_initial_value + (_gtk_css_shorthand_property_get_subproperty (shorthand, 6))); + else + values[6] = value; + + value = NULL; } else { - border.top_right.vertical = border.top_left.vertical; - border.bottom_right.vertical = border.top_left.vertical; - border.bottom_left.vertical = border.top_left.vertical; + /* We parsed everything and there's still stuff left? + * Pretend we didn't notice and let the normal code produce + * a 'junk at end of value' error */ + break; } } - else + while (!value_is_done_parsing (parser)); + + if (values[5] != NULL && values[4] == NULL) + values[4] = _gtk_css_value_ref (values[5]); + + return TRUE; +} + +static gboolean +parse_background (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + GtkCssValue *step_values[7]; + GPtrArray *arrays[6]; + guint i; + + for (i = 0; i < 6; i++) { - border.top_left.vertical = border.top_left.horizontal; - border.top_right.vertical = border.top_right.horizontal; - border.bottom_right.vertical = border.bottom_right.horizontal; - border.bottom_left.vertical = border.bottom_left.horizontal; + arrays[i] = g_ptr_array_new (); + step_values[i] = NULL; } + + step_values[6] = NULL; + + do { + if (!parse_one_background (shorthand, step_values, parser)) + { + for (i = 0; i < 6; i++) + { + g_ptr_array_set_free_func (arrays[i], (GDestroyNotify) _gtk_css_value_unref); + g_ptr_array_unref (arrays[i]); + } + return FALSE; + } + + for (i = 0; i < 6; i++) + { + if (step_values[i] == NULL) + { + GtkCssValue *initial = _gtk_css_style_property_get_initial_value ( + _gtk_css_shorthand_property_get_subproperty (shorthand, i)); + step_values[i] = _gtk_css_value_ref (_gtk_css_array_value_get_nth (initial, 0)); + } - /* border-radius is an int property for backwards-compat reasons */ - g_value_unset (value); - g_value_init (value, GTK_TYPE_CSS_BORDER_RADIUS); - g_value_set_boxed (value, &border); + g_ptr_array_add (arrays[i], step_values[i]); + step_values[i] = NULL; + } + } while (_gtk_css_parser_try (parser, ",", TRUE)); + + for (i = 0; i < 6; i++) + { + values[i] = _gtk_css_array_value_new_from_array ((GtkCssValue **) arrays[i]->pdata, arrays[i]->len); + g_ptr_array_unref (arrays[i]); + } + + values[6] = step_values[6]; return TRUE; +} -negative: - _gtk_css_parser_error (parser, "Border radius values cannot be negative"); - return FALSE; +static gboolean +parse_one_transition (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + do + { + /* the image part */ + if (values[2] == NULL && + _gtk_css_parser_has_number (parser) && !_gtk_css_parser_begins_with (parser, '-')) + { + GtkCssValue *number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_TIME); + + if (number == NULL) + return FALSE; + + if (values[1] == NULL) + values[1] = number; + else + values[2] = number; + } + else if (values[3] == NULL && + _gtk_css_ease_value_can_parse (parser)) + { + values[3] = _gtk_css_ease_value_parse (parser); + + if (values[3] == NULL) + return FALSE; + } + else if (values[0] == NULL) + { + values[0] = _gtk_css_ident_value_try_parse (parser); + if (values[0] == NULL) + { + _gtk_css_parser_error (parser, "Unknown value for property"); + return FALSE; + } + + } + else + { + /* We parsed everything and there's still stuff left? + * Pretend we didn't notice and let the normal code produce + * a 'junk at end of value' error */ + break; + } + } + while (!value_is_done_parsing (parser)); + + return TRUE; } -static gboolean -border_color_shorthand_value_parse (GtkCssParser *parser, - GFile *base, - GValue *value) +static gboolean +parse_transition (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) { - GtkSymbolicColor *symbolic; - GPtrArray *array; + GtkCssValue *step_values[4]; + GPtrArray *arrays[4]; + guint i; - array = g_ptr_array_new_with_free_func ((GDestroyNotify) gtk_symbolic_color_unref); + for (i = 0; i < 4; i++) + { + arrays[i] = g_ptr_array_new (); + step_values[i] = NULL; + } + do { + if (!parse_one_transition (shorthand, step_values, parser)) + { + for (i = 0; i < 4; i++) + { + g_ptr_array_set_free_func (arrays[i], (GDestroyNotify) _gtk_css_value_unref); + g_ptr_array_unref (arrays[i]); + } + return FALSE; + } + + for (i = 0; i < 4; i++) + { + if (step_values[i] == NULL) + { + GtkCssValue *initial = _gtk_css_style_property_get_initial_value ( + _gtk_css_shorthand_property_get_subproperty (shorthand, i)); + step_values[i] = _gtk_css_value_ref (_gtk_css_array_value_get_nth (initial, 0)); + } + + g_ptr_array_add (arrays[i], step_values[i]); + step_values[i] = NULL; + } + } while (_gtk_css_parser_try (parser, ",", TRUE)); + + for (i = 0; i < 4; i++) + { + values[i] = _gtk_css_array_value_new_from_array ((GtkCssValue **) arrays[i]->pdata, arrays[i]->len); + g_ptr_array_unref (arrays[i]); + } + + return TRUE; +} + +static gboolean +parse_one_animation (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ do { - if (_gtk_css_parser_try (parser, "transparent", TRUE)) + if (values[1] == NULL && _gtk_css_parser_try (parser, "infinite", TRUE)) { - GdkRGBA transparent = { 0, 0, 0, 0 }; + values[1] = _gtk_css_number_value_new (HUGE_VAL, GTK_CSS_NUMBER); + } + else if ((values[1] == NULL || values[3] == NULL) && + _gtk_css_parser_has_number (parser)) + { + GtkCssValue *value; - symbolic = gtk_symbolic_color_new_literal (&transparent); + value = _gtk_css_number_value_parse (parser, + GTK_CSS_POSITIVE_ONLY + | (values[1] == NULL ? GTK_CSS_PARSE_NUMBER : 0) + | (values[3] == NULL ? GTK_CSS_PARSE_TIME : 0)); + if (_gtk_css_number_value_get_unit (value) == GTK_CSS_NUMBER) + values[1] = value; + else if (values[2] == NULL) + values[2] = value; + else + values[3] = value; } - else + else if (values[4] == NULL && + _gtk_css_ease_value_can_parse (parser)) { - symbolic = _gtk_css_parser_read_symbolic_color (parser); - - if (symbolic == NULL) + values[4] = _gtk_css_ease_value_parse (parser); + + if (values[4] == NULL) return FALSE; } - - g_ptr_array_add (array, symbolic); + else if (values[5] == NULL && + (values[5] = _gtk_css_direction_value_try_parse (parser))) + { + /* nothing to do */ + } + else if (values[6] == NULL && + (values[6] = _gtk_css_fill_mode_value_try_parse (parser))) + { + /* nothing to do */ + } + else if (values[0] == NULL && + (values[0] = _gtk_css_ident_value_try_parse (parser))) + { + /* nothing to do */ + /* keep in mind though that this needs to come last as fill modes, directions + * etc are valid idents */ + } + else + { + /* We parsed everything and there's still stuff left? + * Pretend we didn't notice and let the normal code produce + * a 'junk at end of value' error */ + break; + } } - while (array->len < 4 && - !_gtk_css_parser_is_eof (parser) && - !_gtk_css_parser_begins_with (parser, ';') && - !_gtk_css_parser_begins_with (parser, '}')); + while (!value_is_done_parsing (parser)); - switch (array->len) + return TRUE; +} + +static gboolean +parse_animation (GtkCssShorthandProperty *shorthand, + GtkCssValue **values, + GtkCssParser *parser) +{ + GtkCssValue *step_values[7]; + GPtrArray *arrays[6]; + guint i; + + for (i = 0; i < 6; i++) { - default: - g_assert_not_reached (); - break; - case 1: - g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 0))); - /* fall through */ - case 2: - g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 0))); - /* fall through */ - case 3: - g_ptr_array_add (array, gtk_symbolic_color_ref (g_ptr_array_index (array, 1))); - /* fall through */ - case 4: - break; + arrays[i] = g_ptr_array_new (); + step_values[i] = NULL; + } + + step_values[6] = NULL; + + do { + if (!parse_one_animation (shorthand, step_values, parser)) + { + for (i = 0; i < 6; i++) + { + g_ptr_array_set_free_func (arrays[i], (GDestroyNotify) _gtk_css_value_unref); + g_ptr_array_unref (arrays[i]); + } + return FALSE; + } + + for (i = 0; i < 6; i++) + { + if (step_values[i] == NULL) + { + GtkCssValue *initial = _gtk_css_style_property_get_initial_value ( + _gtk_css_shorthand_property_get_subproperty (shorthand, i)); + step_values[i] = _gtk_css_value_ref (_gtk_css_array_value_get_nth (initial, 0)); + } + + g_ptr_array_add (arrays[i], step_values[i]); + step_values[i] = NULL; + } + } while (_gtk_css_parser_try (parser, ",", TRUE)); + + for (i = 0; i < 6; i++) + { + values[i] = _gtk_css_array_value_new_from_array ((GtkCssValue **) arrays[i]->pdata, arrays[i]->len); + g_ptr_array_unref (arrays[i]); } - g_value_unset (value); - g_value_init (value, G_TYPE_PTR_ARRAY); - g_value_take_boxed (value, array); + values[6] = step_values[6]; return TRUE; } /*** PACKING ***/ -static GParameter * -unpack_border (const GValue *value, - guint *n_params, - const char *top, - const char *left, - const char *bottom, - const char *right) +static void +unpack_border (GtkCssShorthandProperty *shorthand, + GtkStyleProperties *props, + GtkStateFlags state, + const GValue *value) { - GParameter *parameter = g_new0 (GParameter, 4); + GValue v = G_VALUE_INIT; GtkBorder *border = g_value_get_boxed (value); - parameter[0].name = top; - g_value_init (¶meter[0].value, G_TYPE_INT); - g_value_set_int (¶meter[0].value, border->top); - parameter[1].name = left; - g_value_init (¶meter[1].value, G_TYPE_INT); - g_value_set_int (¶meter[1].value, border->left); - parameter[2].name = bottom; - g_value_init (¶meter[2].value, G_TYPE_INT); - g_value_set_int (¶meter[2].value, border->bottom); - parameter[3].name = right; - g_value_init (¶meter[3].value, G_TYPE_INT); - g_value_set_int (¶meter[3].value, border->right); - - *n_params = 4; - return parameter; + g_value_init (&v, G_TYPE_INT); + + g_value_set_int (&v, border->top); + _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 0)), props, state, &v); + g_value_set_int (&v, border->right); + _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 1)), props, state, &v); + g_value_set_int (&v, border->bottom); + _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 2)), props, state, &v); + g_value_set_int (&v, border->left); + _gtk_style_property_assign (GTK_STYLE_PROPERTY (_gtk_css_shorthand_property_get_subproperty (shorthand, 3)), props, state, &v); + + g_value_unset (&v); } static void -pack_border (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - const char *top, - const char *left, - const char *bottom, - const char *right) +pack_border (GtkCssShorthandProperty *shorthand, + GValue *value, + GtkStyleQueryFunc query_func, + gpointer query_data) { + GtkCssStyleProperty *prop; GtkBorder border; - int t, l, b, r; - - gtk_style_properties_get (props, - state, - top, &t, - left, &l, - bottom, &b, - right, &r, - NULL); + GValue v; - border.top = t; - border.left = l; - border.bottom = b; - border.right = r; + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0); + _gtk_style_property_query (GTK_STYLE_PROPERTY (prop), &v, query_func, query_data); + border.top = g_value_get_int (&v); + g_value_unset (&v); - g_value_set_boxed (value, &border); -} + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 1); + _gtk_style_property_query (GTK_STYLE_PROPERTY (prop), &v, query_func, query_data); + border.right = g_value_get_int (&v); + g_value_unset (&v); -static GParameter * -unpack_border_width (const GValue *value, - guint *n_params) -{ - return unpack_border (value, n_params, - "border-top-width", "border-left-width", - "border-bottom-width", "border-right-width"); -} + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 2); + _gtk_style_property_query (GTK_STYLE_PROPERTY (prop), &v, query_func, query_data); + border.bottom = g_value_get_int (&v); + g_value_unset (&v); -static void -pack_border_width (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) -{ - pack_border (value, props, state, - "border-top-width", "border-left-width", - "border-bottom-width", "border-right-width"); -} + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 3); + _gtk_style_property_query (GTK_STYLE_PROPERTY (prop), &v, query_func, query_data); + border.left = g_value_get_int (&v); + g_value_unset (&v); -static GParameter * -unpack_padding (const GValue *value, - guint *n_params) -{ - return unpack_border (value, n_params, - "padding-top", "padding-left", - "padding-bottom", "padding-right"); + g_value_init (value, GTK_TYPE_BORDER); + g_value_set_boxed (value, &border); } static void -pack_padding (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) +unpack_border_radius (GtkCssShorthandProperty *shorthand, + GtkStyleProperties *props, + GtkStateFlags state, + const GValue *value) { - pack_border (value, props, state, - "padding-top", "padding-left", - "padding-bottom", "padding-right"); -} - -static GParameter * -unpack_margin (const GValue *value, - guint *n_params) -{ - return unpack_border (value, n_params, - "margin-top", "margin-left", - "margin-bottom", "margin-right"); -} + GtkCssValue *css_value; + guint i; + + css_value = _gtk_css_corner_value_new (_gtk_css_number_value_new (g_value_get_int (value), GTK_CSS_PX), + _gtk_css_number_value_new (g_value_get_int (value), GTK_CSS_PX)); -static void -pack_margin (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) -{ - pack_border (value, props, state, - "margin-top", "margin-left", - "margin-bottom", "margin-right"); -} + for (i = 0; i < 4; i++) + _gtk_style_properties_set_property_by_property (props, + _gtk_css_shorthand_property_get_subproperty (shorthand, i), + state, + css_value); -static GParameter * -unpack_border_radius (const GValue *value, - guint *n_params) -{ - GParameter *parameter = g_new0 (GParameter, 4); - GtkCssBorderRadius *border; - - if (G_VALUE_HOLDS_BOXED (value)) - border = g_value_get_boxed (value); - else - border = NULL; - - parameter[0].name = "border-top-left-radius"; - g_value_init (¶meter[0].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS); - parameter[1].name = "border-top-right-radius"; - g_value_init (¶meter[1].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS); - parameter[2].name = "border-bottom-right-radius"; - g_value_init (¶meter[2].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS); - parameter[3].name = "border-bottom-left-radius"; - g_value_init (¶meter[3].value, GTK_TYPE_CSS_BORDER_CORNER_RADIUS); - if (border) - { - g_value_set_boxed (¶meter[0].value, &border->top_left); - g_value_set_boxed (¶meter[1].value, &border->top_right); - g_value_set_boxed (¶meter[2].value, &border->bottom_right); - g_value_set_boxed (¶meter[3].value, &border->bottom_left); - } - - *n_params = 4; - return parameter; + _gtk_css_value_unref (css_value); } static void -pack_border_radius (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) +pack_border_radius (GtkCssShorthandProperty *shorthand, + GValue *value, + GtkStyleQueryFunc query_func, + gpointer query_data) { - GtkCssBorderCornerRadius *top_left; - - /* NB: We are an int property, so we have to resolve to an int here. - * So we just resolve to an int. We pick one and stick to it. - * Lesson learned: Don't query border-radius shorthand, query the - * real properties instead. */ - gtk_style_properties_get (props, - state, - "border-top-left-radius", &top_left, - NULL); + GtkCssStyleProperty *prop; + GtkCssValue *v; + int i = 0; - if (top_left) - g_value_set_int (value, top_left->horizontal); + prop = GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("border-top-left-radius")); + v = (* query_func) (_gtk_css_style_property_get_id (prop), query_data); + if (v) + i = _gtk_css_corner_value_get_x (v, 100); - g_free (top_left); + g_value_init (value, G_TYPE_INT); + g_value_set_int (value, i); } -static GParameter * -unpack_font_description (const GValue *value, - guint *n_params) +static void +unpack_font_description (GtkCssShorthandProperty *shorthand, + GtkStyleProperties *props, + GtkStateFlags state, + const GValue *value) { - GParameter *parameter = g_new0 (GParameter, 5); + GtkStyleProperty *prop; PangoFontDescription *description; PangoFontMask mask; - guint n; + GValue v = G_VALUE_INIT; /* For backwards compat, we only unpack values that are indeed set. * For strict CSS conformance we need to unpack all of them. @@ -464,7 +931,6 @@ unpack_font_description (const GValue *value, */ description = g_value_get_boxed (value); - n = 0; if (description) mask = pango_font_description_get_set_fields (description); @@ -477,145 +943,129 @@ unpack_font_description (const GValue *value, g_ptr_array_add (strv, g_strdup (pango_font_description_get_family (description))); g_ptr_array_add (strv, NULL); - parameter[n].name = "font-family"; - g_value_init (¶meter[n].value, G_TYPE_STRV); - g_value_take_boxed (¶meter[n].value, - g_ptr_array_free (strv, FALSE)); - n++; + g_value_init (&v, G_TYPE_STRV); + g_value_take_boxed (&v, g_ptr_array_free (strv, FALSE)); + + prop = _gtk_style_property_lookup ("font-family"); + _gtk_style_property_assign (prop, props, state, &v); + g_value_unset (&v); } if (mask & PANGO_FONT_MASK_STYLE) { - parameter[n].name = "font-style"; - g_value_init (¶meter[n].value, PANGO_TYPE_STYLE); - g_value_set_enum (¶meter[n].value, - pango_font_description_get_style (description)); - n++; + g_value_init (&v, PANGO_TYPE_STYLE); + g_value_set_enum (&v, pango_font_description_get_style (description)); + + prop = _gtk_style_property_lookup ("font-style"); + _gtk_style_property_assign (prop, props, state, &v); + g_value_unset (&v); } if (mask & PANGO_FONT_MASK_VARIANT) { - parameter[n].name = "font-variant"; - g_value_init (¶meter[n].value, PANGO_TYPE_VARIANT); - g_value_set_enum (¶meter[n].value, - pango_font_description_get_variant (description)); - n++; + g_value_init (&v, PANGO_TYPE_VARIANT); + g_value_set_enum (&v, pango_font_description_get_variant (description)); + + prop = _gtk_style_property_lookup ("font-variant"); + _gtk_style_property_assign (prop, props, state, &v); + g_value_unset (&v); } if (mask & PANGO_FONT_MASK_WEIGHT) { - parameter[n].name = "font-weight"; - g_value_init (¶meter[n].value, PANGO_TYPE_WEIGHT); - g_value_set_enum (¶meter[n].value, - pango_font_description_get_weight (description)); - n++; + g_value_init (&v, PANGO_TYPE_WEIGHT); + g_value_set_enum (&v, pango_font_description_get_weight (description)); + + prop = _gtk_style_property_lookup ("font-weight"); + _gtk_style_property_assign (prop, props, state, &v); + g_value_unset (&v); } if (mask & PANGO_FONT_MASK_SIZE) { - parameter[n].name = "font-size"; - g_value_init (¶meter[n].value, G_TYPE_DOUBLE); - g_value_set_double (¶meter[n].value, - (double) pango_font_description_get_size (description) / PANGO_SCALE); - n++; - } - - *n_params = n; + g_value_init (&v, G_TYPE_DOUBLE); + g_value_set_double (&v, (double) pango_font_description_get_size (description) / PANGO_SCALE); - return parameter; + prop = _gtk_style_property_lookup ("font-size"); + _gtk_style_property_assign (prop, props, state, &v); + g_value_unset (&v); + } } static void -pack_font_description (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) +pack_font_description (GtkCssShorthandProperty *shorthand, + GValue *value, + GtkStyleQueryFunc query_func, + gpointer query_data) { PangoFontDescription *description; - char **families; - PangoStyle style; - PangoVariant variant; - PangoWeight weight; - double size; - - gtk_style_properties_get (props, - state, - "font-family", &families, - "font-style", &style, - "font-variant", &variant, - "font-weight", &weight, - "font-size", &size, - NULL); + GtkCssValue *v; description = pango_font_description_new (); - /* xxx: Can we set all the families here somehow? */ - if (families) - pango_font_description_set_family (description, families[0]); - pango_font_description_set_size (description, round (size * PANGO_SCALE)); - pango_font_description_set_style (description, style); - pango_font_description_set_variant (description, variant); - pango_font_description_set_weight (description, weight); - g_strfreev (families); + v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-family"))), query_data); + if (v) + { + /* xxx: Can we set all the families here somehow? */ + pango_font_description_set_family (description, _gtk_css_string_value_get (_gtk_css_array_value_get_nth (v, 0))); + } + + v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-size"))), query_data); + if (v) + pango_font_description_set_size (description, round (_gtk_css_number_value_get (v, 100) * PANGO_SCALE)); + + v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-style"))), query_data); + if (v) + pango_font_description_set_style (description, _gtk_css_font_style_value_get (v)); + v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-variant"))), query_data); + if (v) + pango_font_description_set_variant (description, _gtk_css_font_variant_value_get (v)); + + v = (* query_func) (_gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (_gtk_style_property_lookup ("font-weight"))), query_data); + if (v) + pango_font_description_set_weight (description, _gtk_css_font_weight_value_get (v)); + + g_value_init (value, PANGO_TYPE_FONT_DESCRIPTION); g_value_take_boxed (value, description); } -static GParameter * -unpack_border_color (const GValue *value, - guint *n_params) +static void +unpack_to_everything (GtkCssShorthandProperty *shorthand, + GtkStyleProperties *props, + GtkStateFlags state, + const GValue *value) { - GParameter *parameter = g_new0 (GParameter, 4); - GType type; + GtkCssStyleProperty *prop; + guint i, n; - type = G_VALUE_TYPE (value); - if (type == G_TYPE_PTR_ARRAY) - type = GTK_TYPE_SYMBOLIC_COLOR; + n = _gtk_css_shorthand_property_get_n_subproperties (shorthand); - parameter[0].name = "border-top-color"; - g_value_init (¶meter[0].value, type); - parameter[1].name = "border-right-color"; - g_value_init (¶meter[1].value, type); - parameter[2].name = "border-bottom-color"; - g_value_init (¶meter[2].value, type); - parameter[3].name = "border-left-color"; - g_value_init (¶meter[3].value, type); - - if (G_VALUE_TYPE (value) == G_TYPE_PTR_ARRAY) + for (i = 0; i < n; i++) { - GPtrArray *array = g_value_get_boxed (value); - guint i; - - for (i = 0; i < 4; i++) - g_value_set_boxed (¶meter[i].value, g_ptr_array_index (array, i)); + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i); + _gtk_style_property_assign (GTK_STYLE_PROPERTY (prop), props, state, value); } - else - { - /* can be RGBA or symbolic color */ - gpointer p = g_value_get_boxed (value); - - g_value_set_boxed (¶meter[0].value, p); - g_value_set_boxed (¶meter[1].value, p); - g_value_set_boxed (¶meter[2].value, p); - g_value_set_boxed (¶meter[3].value, p); - } - - *n_params = 4; - return parameter; } static void -pack_border_color (GValue *value, - GtkStyleProperties *props, - GtkStateFlags state, - GtkStylePropertyContext *context) +pack_first_element (GtkCssShorthandProperty *shorthand, + GValue *value, + GtkStyleQueryFunc query_func, + gpointer query_data) { - /* NB: We are a color property, so we have to resolve to a color here. - * So we just resolve to a color. We pick one and stick to it. - * Lesson learned: Don't query border-color shorthand, query the + GtkCssStyleProperty *prop; + + /* NB: This is a fallback for properties that originally were + * not used as shorthand. We just pick the first subproperty + * as a representative. + * Lesson learned: Don't query the shorthand, query the * real properties instead. */ - g_value_unset (value); - gtk_style_properties_get_property (props, "border-top-color", state, value); + prop = _gtk_css_shorthand_property_get_subproperty (shorthand, 0); + _gtk_style_property_query (GTK_STYLE_PROPERTY (prop), + value, + query_func, + query_data); } static void @@ -623,14 +1073,10 @@ _gtk_css_shorthand_property_register (const char *name, GType value_type, const char **subproperties, GtkCssShorthandPropertyParseFunc parse_func, - GtkStyleUnpackFunc unpack_func, - GtkStylePackFunc pack_func, - GtkStyleParseFunc old_parse_func) + GtkCssShorthandPropertyAssignFunc assign_func, + GtkCssShorthandPropertyQueryFunc query_func) { - GtkStyleProperty *node; - - g_return_if_fail (pack_func != NULL); - g_return_if_fail (unpack_func != NULL); + GtkCssShorthandProperty *node; node = g_object_new (GTK_TYPE_CSS_SHORTHAND_PROPERTY, "name", name, @@ -638,16 +1084,15 @@ _gtk_css_shorthand_property_register (const char *name, "subproperties", subproperties, NULL); - if (parse_func) - GTK_CSS_SHORTHAND_PROPERTY (node)->parse = parse_func; - node->pack_func = pack_func; - node->unpack_func = unpack_func; - node->parse_func = old_parse_func; + node->parse = parse_func; + node->assign = assign_func; + node->query = query_func; } void _gtk_css_shorthand_property_init_properties (void) { + /* The order is important here, be careful when changing it */ const char *font_subproperties[] = { "font-family", "font-style", "font-variant", "font-weight", "font-size", NULL }; const char *margin_subproperties[] = { "margin-top", "margin-right", "margin-bottom", "margin-left", NULL }; const char *padding_subproperties[] = { "padding-top", "padding-right", "padding-bottom", "padding-left", NULL }; @@ -655,55 +1100,123 @@ _gtk_css_shorthand_property_init_properties (void) const char *border_radius_subproperties[] = { "border-top-left-radius", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius", NULL }; const char *border_color_subproperties[] = { "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", NULL }; + const char *border_style_subproperties[] = { "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", NULL }; const char *border_image_subproperties[] = { "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL }; + const char *border_top_subproperties[] = { "border-top-width", "border-top-style", "border-top-color", NULL }; + const char *border_right_subproperties[] = { "border-right-width", "border-right-style", "border-right-color", NULL }; + const char *border_bottom_subproperties[] = { "border-bottom-width", "border-bottom-style", "border-bottom-color", NULL }; + const char *border_left_subproperties[] = { "border-left-width", "border-left-style", "border-left-color", NULL }; + const char *border_subproperties[] = { "border-top-width", "border-right-width", "border-bottom-width", "border-left-width", + "border-top-style", "border-right-style", "border-bottom-style", "border-left-style", + "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", + "border-image-source", "border-image-slice", "border-image-width", "border-image-repeat", NULL }; + const char *outline_subproperties[] = { "outline-width", "outline-style", "outline-color", NULL }; + const char *background_subproperties[] = { "background-image", "background-position", "background-size", "background-repeat", "background-clip", "background-origin", + "background-color", NULL }; + const char *transition_subproperties[] = { "transition-property", "transition-duration", "transition-delay", "transition-timing-function", NULL }; + const char *animation_subproperties[] = { "animation-name", "animation-iteration-count", "animation-duration", "animation-delay", + "animation-timing-function", "animation-direction", "animation-fill-mode", NULL }; _gtk_css_shorthand_property_register ("font", PANGO_TYPE_FONT_DESCRIPTION, font_subproperties, - NULL, + parse_font, unpack_font_description, - pack_font_description, - NULL); + pack_font_description); _gtk_css_shorthand_property_register ("margin", GTK_TYPE_BORDER, margin_subproperties, - NULL, - unpack_margin, - pack_margin, - NULL); + parse_margin, + unpack_border, + pack_border); _gtk_css_shorthand_property_register ("padding", GTK_TYPE_BORDER, padding_subproperties, - NULL, - unpack_padding, - pack_padding, - NULL); + parse_padding, + unpack_border, + pack_border); _gtk_css_shorthand_property_register ("border-width", GTK_TYPE_BORDER, border_width_subproperties, - NULL, - unpack_border_width, - pack_border_width, - NULL); + parse_border_width, + unpack_border, + pack_border); _gtk_css_shorthand_property_register ("border-radius", G_TYPE_INT, border_radius_subproperties, - NULL, + parse_border_radius, unpack_border_radius, - pack_border_radius, - border_radius_value_parse); + pack_border_radius); _gtk_css_shorthand_property_register ("border-color", GDK_TYPE_RGBA, border_color_subproperties, - NULL, - unpack_border_color, - pack_border_color, - border_color_shorthand_value_parse); + parse_border_color, + unpack_to_everything, + pack_first_element); + _gtk_css_shorthand_property_register ("border-style", + GTK_TYPE_BORDER_STYLE, + border_style_subproperties, + parse_border_style, + unpack_to_everything, + pack_first_element); _gtk_css_shorthand_property_register ("border-image", - GTK_TYPE_BORDER_IMAGE, + G_TYPE_NONE, border_image_subproperties, + parse_border_image, + NULL, + NULL); + _gtk_css_shorthand_property_register ("border-top", + G_TYPE_NONE, + border_top_subproperties, + parse_border_side, + NULL, + NULL); + _gtk_css_shorthand_property_register ("border-right", + G_TYPE_NONE, + border_right_subproperties, + parse_border_side, NULL, - _gtk_border_image_unpack, - _gtk_border_image_pack, - border_image_value_parse); + NULL); + _gtk_css_shorthand_property_register ("border-bottom", + G_TYPE_NONE, + border_bottom_subproperties, + parse_border_side, + NULL, + NULL); + _gtk_css_shorthand_property_register ("border-left", + G_TYPE_NONE, + border_left_subproperties, + parse_border_side, + NULL, + NULL); + _gtk_css_shorthand_property_register ("border", + G_TYPE_NONE, + border_subproperties, + parse_border, + NULL, + NULL); + _gtk_css_shorthand_property_register ("outline", + G_TYPE_NONE, + outline_subproperties, + parse_border_side, + NULL, + NULL); + _gtk_css_shorthand_property_register ("background", + G_TYPE_NONE, + background_subproperties, + parse_background, + NULL, + NULL); + _gtk_css_shorthand_property_register ("transition", + G_TYPE_NONE, + transition_subproperties, + parse_transition, + NULL, + NULL); + _gtk_css_shorthand_property_register ("animation", + G_TYPE_NONE, + animation_subproperties, + parse_animation, + NULL, + NULL); }