[gtk+/wip/otte/tokenizer: 62/78] cssimage: Add token parser for linear-gradient
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/otte/tokenizer: 62/78] cssimage: Add token parser for linear-gradient
- Date: Fri, 25 Nov 2016 22:36:55 +0000 (UTC)
commit 87eeb1bdfbf3407ca36db03740b91423c99e1032
Author: Benjamin Otte <otte redhat com>
Date: Sun Mar 27 07:41:24 2016 +0200
cssimage: Add token parser for linear-gradient
This requires refactoring of gtk_css_token_source_consume_function() to
allow a single call to the parse_args function to consume multiple
arguments.
Because the first argument to linear-gradient() is the optional
direction, we need to indicate that we skipped it. So the parse
function returns 2 in that case. This way we can set the minimum required
arguments to 3, while still allowing
linear-gradient(red, blue);
which is equivalent to
linear-gradient(to bottom, red, blue);
gtk/gtkcsseasevalue.c | 18 +++---
gtk/gtkcssimageicontheme.c | 6 +-
gtk/gtkcssimagelinear.c | 125 ++++++++++++++++++++++++++++++++++++++++
gtk/gtkcssimagescaled.c | 6 +-
gtk/gtkcsstokensource.c | 11 ++-
gtk/gtkcsstokensourceprivate.h | 2 +-
gtk/gtkcsstransformvalue.c | 61 +++++++++++--------
7 files changed, 183 insertions(+), 46 deletions(-)
---
diff --git a/gtk/gtkcsseasevalue.c b/gtk/gtkcsseasevalue.c
index b342b4b..72f7a37 100644
--- a/gtk/gtkcsseasevalue.c
+++ b/gtk/gtkcsseasevalue.c
@@ -327,7 +327,7 @@ _gtk_css_ease_value_parse (GtkCssParser *parser)
return NULL;
}
-static gboolean
+static guint
token_parse_cubic_bezier (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -342,13 +342,13 @@ token_parse_cubic_bezier (GtkCssTokenSource *source,
(numbers[n] < 0 || numbers[n] > 1.0))
{
gtk_css_token_source_error (source, "Value %g out of range. Must be from 0.0 to 1.0", numbers[n]);
- return FALSE;
+ return 0;
}
- return TRUE;
+ return 1;
}
-static gboolean
+static guint
token_parse_steps (GtkCssTokenSource *source,
guint nth_argument,
gpointer data)
@@ -363,17 +363,17 @@ token_parse_steps (GtkCssTokenSource *source,
{
gtk_css_token_source_error (source, "Expected a positive integer for number of steps");
gtk_css_token_source_consume_all (source);
- return FALSE;
+ return 0;
}
else if (token->number.number <= 0)
{
gtk_css_token_source_error (source, "Number of steps must be greater than 0");
gtk_css_token_source_consume_all (source);
- return FALSE;
+ return 0;
}
value->u.steps.steps = token->number.number;
gtk_css_token_source_consume_token (source);
- return TRUE;
+ return 1;
}
else
{
@@ -385,10 +385,10 @@ token_parse_steps (GtkCssTokenSource *source,
{
gtk_css_token_source_error (source, "Only allowed values are 'start' and 'end'");
gtk_css_token_source_consume_all (source);
- return FALSE;
+ return 0;
}
gtk_css_token_source_consume_token (source);
- return TRUE;
+ return 1;
}
}
diff --git a/gtk/gtkcssimageicontheme.c b/gtk/gtkcssimageicontheme.c
index 520ec58..4613218 100644
--- a/gtk/gtkcssimageicontheme.c
+++ b/gtk/gtkcssimageicontheme.c
@@ -117,7 +117,7 @@ gtk_css_image_icon_theme_parse (GtkCssImage *image,
return TRUE;
}
-static gboolean
+static guint
token_parse_arg (GtkCssTokenSource *source,
guint arg,
gpointer data)
@@ -130,13 +130,13 @@ token_parse_arg (GtkCssTokenSource *source,
{
gtk_css_token_source_error (source, "Expected a string for the icon name");
gtk_css_token_source_consume_all (source);
- return FALSE;
+ return 0;
}
icon_theme->name = g_strdup (token->string.string);
gtk_css_token_source_consume_token (source);
- return TRUE;
+ return 1;
}
static gboolean
diff --git a/gtk/gtkcssimagelinear.c b/gtk/gtkcssimagelinear.c
index b4a53f5..a3144ae 100644
--- a/gtk/gtkcssimagelinear.c
+++ b/gtk/gtkcssimagelinear.c
@@ -361,6 +361,130 @@ gtk_css_image_linear_parse (GtkCssImage *image,
return TRUE;
}
+static guint
+gtk_css_image_linear_token_parse_argument (GtkCssTokenSource *source,
+ guint arg,
+ gpointer data)
+{
+ GtkCssImageLinear *linear = data;
+ GtkCssImageLinearColorStop stop;
+ const GtkCssToken *token;
+
+ if (arg == 0)
+ {
+ token = gtk_css_token_source_get_token (source);
+
+ if (gtk_css_token_is_ident (token, "to"))
+ {
+ static const struct {
+ const char *name;
+ guint value;
+ guint optional_index[2];
+ } sides[] = {
+ { "top", 1 << GTK_CSS_TOP, { 2, 3 } },
+ { "bottom", 1 << GTK_CSS_BOTTOM, { 2, 3 } },
+ { "left", 1 << GTK_CSS_LEFT, { 0, 1 } },
+ { "right", 1 << GTK_CSS_RIGHT, { 0, 1 } }
+ };
+ guint i, j;
+ gtk_css_token_source_consume_token (source);
+
+ token = gtk_css_token_source_get_token (source);
+ for (i = 0; i < G_N_ELEMENTS (sides); i++)
+ {
+ if (!gtk_css_token_is_ident (token, sides[i].name))
+ continue;
+
+ linear->side = sides[i].value;
+ gtk_css_token_source_consume_token (source);
+
+ token = gtk_css_token_source_get_token (source);
+ for (j = 0; j < G_N_ELEMENTS (sides[i].optional_index); j++)
+ {
+ guint idx = sides[i].optional_index[j];
+ if (!gtk_css_token_is_ident (token, sides[idx].name))
+ continue;
+
+ linear->side = sides[idx].value;
+ gtk_css_token_source_consume_token (source);
+ break;
+ }
+
+ return 1;
+ }
+
+ gtk_css_token_source_error (source, "Expected a direction");
+ gtk_css_token_source_consume_all (source);
+ return 0;
+ }
+ else if (!gtk_css_color_value_check_token (token))
+ {
+ /* We check for !color here so the error message is "expected angle"
+ * for nonsense values */
+ linear->angle = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
+ if (linear->angle == NULL)
+ return 0;
+ return 1;
+ }
+
+ linear->side = 1 << GTK_CSS_BOTTOM;
+ }
+
+ stop.color = gtk_css_color_value_token_parse (source);
+ if (stop.color == NULL)
+ return 0;
+
+ token = gtk_css_token_source_get_token (source);
+ if (gtk_css_number_value_check_token (token))
+ {
+ stop.offset = gtk_css_number_value_token_parse (source,
+ GTK_CSS_PARSE_PERCENT
+ | GTK_CSS_PARSE_LENGTH);
+ if (stop.offset == NULL)
+ {
+ _gtk_css_value_unref (stop.color);
+ return FALSE;
+ }
+ }
+ else
+ {
+ stop.offset = NULL;
+ }
+
+ g_array_append_val (linear->stops, stop);
+ /* We consume the optional side argument here, too. */
+ return arg == 0 ? 2 : 1;
+}
+
+static gboolean
+gtk_css_image_linear_token_parse (GtkCssImage *image,
+ GtkCssTokenSource *source)
+{
+ GtkCssImageLinear *linear = GTK_CSS_IMAGE_LINEAR (image);
+ const GtkCssToken *token;
+
+ token = gtk_css_token_source_get_token (source);
+ if (gtk_css_token_is_function (token, "linear-gradient"))
+ {
+ /* nothing to do here */
+ }
+ else if (gtk_css_token_is_function (token, "repeating-linear-gradient"))
+ {
+ linear->repeating = TRUE;
+ }
+ else
+ {
+ gtk_css_token_source_error (source, "Expected 'linear-gradient('");
+ gtk_css_token_source_consume_all (source);
+ return FALSE;
+ }
+
+ return gtk_css_token_source_consume_function (source,
+ 3, G_MAXUINT,
+ gtk_css_image_linear_token_parse_argument,
+ image);
+}
+
static void
gtk_css_image_linear_print (GtkCssImage *image,
GString *string)
@@ -598,6 +722,7 @@ _gtk_css_image_linear_class_init (GtkCssImageLinearClass *klass)
image_class->draw = gtk_css_image_linear_draw;
image_class->parse = gtk_css_image_linear_parse;
+ image_class->token_parse = gtk_css_image_linear_token_parse;
image_class->print = gtk_css_image_linear_print;
image_class->compute = gtk_css_image_linear_compute;
image_class->equal = gtk_css_image_linear_equal;
diff --git a/gtk/gtkcssimagescaled.c b/gtk/gtkcssimagescaled.c
index 1c7add5..afa78c8 100644
--- a/gtk/gtkcssimagescaled.c
+++ b/gtk/gtkcssimagescaled.c
@@ -180,7 +180,7 @@ gtk_css_image_scaled_parse (GtkCssImage *image,
return TRUE;
}
-static gboolean
+static guint
token_parse_arg (GtkCssTokenSource *source,
guint arg,
gpointer data)
@@ -190,11 +190,11 @@ token_parse_arg (GtkCssTokenSource *source,
image = gtk_css_image_new_token_parse (source);
if (image == NULL)
- return FALSE;
+ return 0;
g_ptr_array_add (images, image);
- return TRUE;
+ return 1;
}
static gboolean
diff --git a/gtk/gtkcsstokensource.c b/gtk/gtkcsstokensource.c
index ef2435d..994086f 100644
--- a/gtk/gtkcsstokensource.c
+++ b/gtk/gtkcsstokensource.c
@@ -343,7 +343,7 @@ gboolean
gtk_css_token_source_consume_function (GtkCssTokenSource *source,
guint min_args,
guint max_args,
- gboolean (* parse_func) (GtkCssTokenSource *, guint, gpointer),
+ guint (* parse_func) (GtkCssTokenSource *, guint, gpointer),
gpointer data)
{
const GtkCssToken *token;
@@ -358,17 +358,20 @@ gtk_css_token_source_consume_function (GtkCssTokenSource *source,
gtk_css_token_source_consume_token (source);
func_source = gtk_css_token_source_new_for_part (source, GTK_CSS_TOKEN_CLOSE_PARENS);
- for (arg = 0; arg < max_args; arg++)
+ arg = 0;
+ while (arg < max_args)
{
- if (!parse_func (func_source, arg, data))
+ guint parse_args = parse_func (func_source, arg, data);
+ if (parse_args == 0)
{
gtk_css_token_source_consume_all (func_source);
break;
}
+ arg += parse_args;
token = gtk_css_token_source_get_token (func_source);
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
{
- if (arg + 1 < min_args)
+ if (arg < min_args)
{
gtk_css_token_source_error (source, "%s() requires at least %u arguments", function_name,
min_args);
gtk_css_token_source_consume_all (source);
diff --git a/gtk/gtkcsstokensourceprivate.h b/gtk/gtkcsstokensourceprivate.h
index def15bc..6748cb5 100644
--- a/gtk/gtkcsstokensourceprivate.h
+++ b/gtk/gtkcsstokensourceprivate.h
@@ -70,7 +70,7 @@ char * gtk_css_token_source_consume_to_string (GtkCssTokenSour
gboolean gtk_css_token_source_consume_function (GtkCssTokenSource *source,
guint min_args,
guint max_args,
- gboolean (* parse_func) (GtkCssTokenSource
*, guint, gpointer),
+ guint (* parse_func) (GtkCssTokenSource *,
guint, gpointer),
gpointer data);
gboolean gtk_css_token_source_consume_number (GtkCssTokenSource *source,
double *number);
diff --git a/gtk/gtkcsstransformvalue.c b/gtk/gtkcsstransformvalue.c
index b456af8..b9dc3f1 100644
--- a/gtk/gtkcsstransformvalue.c
+++ b/gtk/gtkcsstransformvalue.c
@@ -1015,7 +1015,7 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
return value;
}
-static gboolean
+static guint
token_parse_matrix (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1025,24 +1025,24 @@ token_parse_matrix (GtkCssTokenSource *source,
switch (n)
{
case 0:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx) ? 1 : 0;
case 1:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy) ? 1 : 0;
case 2:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0) ? 1 : 0;
case 3:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx) ? 1 : 0;
case 4:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy) ? 1 : 0;
case 5:
- return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0);
+ return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0) ? 1 : 0;
default:
g_assert_not_reached ();
- return FALSE;
+ return 0;
}
}
-static gboolean
+static guint
token_parse_translate (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1053,7 +1053,7 @@ token_parse_translate (GtkCssTokenSource *source,
{
transform->translate.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
if (transform->translate.x == NULL)
- return FALSE;
+ return 0;
transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (n == 1)
@@ -1061,16 +1061,16 @@ token_parse_translate (GtkCssTokenSource *source,
_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;
+ return 0;
}
else
{
g_assert_not_reached ();
}
- return TRUE;
+ return 1;
}
-static gboolean
+static guint
token_parse_length (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1078,10 +1078,13 @@ token_parse_length (GtkCssTokenSource *source,
GtkCssValue **value = data;
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
- return *value != NULL;
+ if (*value == NULL)
+ return 0;
+
+ return 1;
}
-static gboolean
+static guint
token_parse_scale (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1092,7 +1095,7 @@ token_parse_scale (GtkCssTokenSource *source,
{
transform->scale.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
if (transform->scale.x == NULL)
- return FALSE;
+ return 0;
transform->scale.y = _gtk_css_value_ref (transform->scale.x);
}
else if (n == 1)
@@ -1100,16 +1103,16 @@ token_parse_scale (GtkCssTokenSource *source,
_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;
+ return 0;
}
else
{
g_assert_not_reached ();
}
- return TRUE;
+ return 1;
}
-static gboolean
+static guint
token_parse_number (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1117,10 +1120,13 @@ token_parse_number (GtkCssTokenSource *source,
GtkCssValue **value = data;
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
- return *value != NULL;
+ if (*value == NULL)
+ return 0;
+
+ return 1;
}
-static gboolean
+static guint
token_parse_angle (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1128,10 +1134,13 @@ token_parse_angle (GtkCssTokenSource *source,
GtkCssValue **value = data;
*value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
- return *value != NULL;
+ if (*value == NULL)
+ return 0;
+
+ return 1;
}
-static gboolean
+static guint
token_parse_skew (GtkCssTokenSource *source,
guint n,
gpointer data)
@@ -1142,7 +1151,7 @@ token_parse_skew (GtkCssTokenSource *source,
{
transform->skew.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
if (transform->skew.x == NULL)
- return FALSE;
+ return 0;
transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
}
else if (n == 1)
@@ -1150,13 +1159,13 @@ token_parse_skew (GtkCssTokenSource *source,
_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;
+ return 0;
}
else
{
g_assert_not_reached ();
}
- return TRUE;
+ return 1;
}
GtkCssValue *
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]