diff options
author | Benjamin Otte <otte@redhat.com> | 2016-03-18 23:19:43 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2016-04-08 16:18:30 +0200 |
commit | fef9fe68d065f72570dd48f35045d14f181f0d4f (patch) | |
tree | 3fa7f90dcd50418f04dc619ebc9c909e9f0455e1 | |
parent | 945bddf120ff7a7db5ee7df5aeb1734dcae0ecf2 (diff) | |
download | gtk+-fef9fe68d065f72570dd48f35045d14f181f0d4f.tar.gz |
css: Add a token parser for transform values
-rw-r--r-- | gtk/gtkcssstylepropertyimpl.c | 2 | ||||
-rw-r--r-- | gtk/gtkcsstransformvalue.c | 316 | ||||
-rw-r--r-- | gtk/gtkcsstransformvalueprivate.h | 2 |
3 files changed, 319 insertions, 1 deletions
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c index 6688515482..ecc2f801e8 100644 --- a/gtk/gtkcssstylepropertyimpl.c +++ b/gtk/gtkcssstylepropertyimpl.c @@ -2166,7 +2166,7 @@ _gtk_css_style_property_init_properties (void) GTK_STYLE_PROPERTY_ANIMATED, GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | GTK_CSS_AFFECTS_CLIP, transform_value_parse, - gtk_css_style_property_token_parse_default, + (GtkCssStylePropertyTokenParseFunc) gtk_css_transform_value_token_parse, NULL, NULL, _gtk_css_transform_value_new_none ()); diff --git a/gtk/gtkcsstransformvalue.c b/gtk/gtkcsstransformvalue.c index 13e9f0fcb9..b456af8d3d 100644 --- a/gtk/gtkcsstransformvalue.c +++ b/gtk/gtkcsstransformvalue.c @@ -1015,6 +1015,322 @@ _gtk_css_transform_value_parse (GtkCssParser *parser) return value; } +static gboolean +token_parse_matrix (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssTransform *transform = data; + + switch (n) + { + case 0: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx); + case 1: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy); + case 2: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0); + case 3: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx); + case 4: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy); + case 5: + return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0); + default: + g_assert_not_reached (); + return FALSE; + } +} + +static gboolean +token_parse_translate (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssTransform *transform = data; + + if (n == 0) + { + transform->translate.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH); + if (transform->translate.x == NULL) + return FALSE; + transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX); + } + else if (n == 1) + { + _gtk_css_value_unref (transform->translate.y); + transform->translate.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH); + if (transform->translate.y == NULL) + return FALSE; + } + else + { + g_assert_not_reached (); + } + return TRUE; +} + +static gboolean +token_parse_length (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssValue **value = data; + + *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH); + return *value != NULL; +} + +static gboolean +token_parse_scale (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssTransform *transform = data; + + if (n == 0) + { + transform->scale.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER); + if (transform->scale.x == NULL) + return FALSE; + transform->scale.y = _gtk_css_value_ref (transform->scale.x); + } + else if (n == 1) + { + _gtk_css_value_unref (transform->scale.y); + transform->scale.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER); + if (transform->scale.y == NULL) + return FALSE; + } + else + { + g_assert_not_reached (); + } + return TRUE; +} + +static gboolean +token_parse_number (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssValue **value = data; + + *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER); + return *value != NULL; +} + +static gboolean +token_parse_angle (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssValue **value = data; + + *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE); + return *value != NULL; +} + +static gboolean +token_parse_skew (GtkCssTokenSource *source, + guint n, + gpointer data) +{ + GtkCssTransform *transform = data; + + if (n == 0) + { + transform->skew.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE); + if (transform->skew.x == NULL) + return FALSE; + transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_PX); + } + else if (n == 1) + { + _gtk_css_value_unref (transform->skew.y); + transform->skew.y = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE); + if (transform->skew.y == NULL) + return FALSE; + } + else + { + g_assert_not_reached (); + } + return TRUE; +} + +GtkCssValue * +gtk_css_transform_value_token_parse (GtkCssTokenSource *source) +{ + const GtkCssToken *token; + GtkCssValue *value; + GArray *array; + guint i; + + token = gtk_css_token_source_get_token (source); + if (gtk_css_token_is_ident (token, "none")) + { + gtk_css_token_source_consume_token (source); + return _gtk_css_transform_value_new_none (); + } + + array = g_array_new (FALSE, FALSE, sizeof (GtkCssTransform)); + + while (TRUE) + { + GtkCssTransform transform = { 0, }; + + if (gtk_css_token_is_function (token, "matrix")) + { + transform.type = GTK_CSS_TRANSFORM_MATRIX; + if (!gtk_css_token_source_consume_function (source, 6, 6, token_parse_matrix, &transform)) + goto fail; + } + else if (gtk_css_token_is_function (token, "translate")) + { + transform.type = GTK_CSS_TRANSFORM_TRANSLATE; + if (!gtk_css_token_source_consume_function (source, 2, 2, token_parse_translate, &transform)) + { + if (transform.translate.x) + _gtk_css_value_unref (transform.translate.x); + if (transform.translate.y) + _gtk_css_value_unref (transform.translate.y); + goto fail; + } + } + else if (gtk_css_token_is_function (token, "translateX")) + { + transform.type = GTK_CSS_TRANSFORM_TRANSLATE; + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, &transform.translate.x)) + { + if (transform.translate.x) + _gtk_css_value_unref (transform.translate.x); + goto fail; + } + transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX); + } + else if (gtk_css_token_is_function (token, "translateY")) + { + transform.type = GTK_CSS_TRANSFORM_TRANSLATE; + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, &transform.translate.y)) + { + if (transform.translate.y) + _gtk_css_value_unref (transform.translate.y); + goto fail; + } + transform.translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX); + } + else if (gtk_css_token_is_function (token, "scale")) + { + transform.type = GTK_CSS_TRANSFORM_SCALE; + if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_scale, &transform)) + { + if (transform.scale.x) + _gtk_css_value_unref (transform.scale.x); + if (transform.scale.y) + _gtk_css_value_unref (transform.scale.y); + goto fail; + } + } + else if (gtk_css_token_is_function (token, "scaleX")) + { + transform.type = GTK_CSS_TRANSFORM_SCALE; + + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.x)) + { + if (transform.scale.x) + _gtk_css_value_unref (transform.scale.x); + goto fail; + } + transform.scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER); + } + else if (gtk_css_token_is_function (token, "scaleY")) + { + transform.type = GTK_CSS_TRANSFORM_SCALE; + + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.y)) + { + if (transform.scale.y) + _gtk_css_value_unref (transform.scale.y); + goto fail; + } + transform.scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER); + } + else if (gtk_css_token_is_function (token, "rotate")) + { + transform.type = GTK_CSS_TRANSFORM_ROTATE; + + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.rotate.rotate)) + { + if (transform.rotate.rotate) + _gtk_css_value_unref (transform.rotate.rotate); + goto fail; + } + } + else if (gtk_css_token_is_function (token, "skew")) + { + transform.type = GTK_CSS_TRANSFORM_SKEW; + if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_skew, &transform)) + { + if (transform.skew.x) + _gtk_css_value_unref (transform.skew.x); + if (transform.skew.y) + _gtk_css_value_unref (transform.skew.y); + goto fail; + } + } + else if (gtk_css_token_is_function (token, "skewX")) + { + transform.type = GTK_CSS_TRANSFORM_SKEW_X; + + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.skew_x.skew)) + { + if (transform.skew_x.skew) + _gtk_css_value_unref (transform.skew_x.skew); + goto fail; + } + } + else if (gtk_css_token_is_function (token, "skewY")) + { + transform.type = GTK_CSS_TRANSFORM_SKEW_Y; + + if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, &transform.skew_y.skew)) + { + if (transform.skew_y.skew) + _gtk_css_value_unref (transform.skew_y.skew); + goto fail; + } + } + else + break; + + g_array_append_val (array, transform); + token = gtk_css_token_source_get_token (source); + } + + if (array->len == 0) + { + gtk_css_token_source_error (source, "Expected a transform"); + gtk_css_token_source_consume_all (source); + goto fail; + } + + value = gtk_css_transform_value_alloc (array->len); + memcpy (value->transforms, array->data, sizeof (GtkCssTransform) * array->len); + + g_array_free (array, TRUE); + + return value; + +fail: + for (i = 0; i < array->len; i++) + { + gtk_css_transform_clear (&g_array_index (array, GtkCssTransform, i)); + } + g_array_free (array, TRUE); + return NULL; +} + gboolean _gtk_css_transform_value_get_matrix (const GtkCssValue *transform, cairo_matrix_t *matrix) diff --git a/gtk/gtkcsstransformvalueprivate.h b/gtk/gtkcsstransformvalueprivate.h index 49411ff88d..e7382ffa05 100644 --- a/gtk/gtkcsstransformvalueprivate.h +++ b/gtk/gtkcsstransformvalueprivate.h @@ -21,12 +21,14 @@ #define __GTK_CSS_TRANSFORM_VALUE_PRIVATE_H__ #include "gtkcssparserprivate.h" +#include "gtkcsstokensourceprivate.h" #include "gtkcssvalueprivate.h" G_BEGIN_DECLS GtkCssValue * _gtk_css_transform_value_new_none (void); GtkCssValue * _gtk_css_transform_value_parse (GtkCssParser *parser); +GtkCssValue * gtk_css_transform_value_token_parse (GtkCssTokenSource *source); gboolean _gtk_css_transform_value_get_matrix (const GtkCssValue *transform, cairo_matrix_t *matrix); |