[gtk+/wip/otte/tokenizer: 62/78] cssimage: Add token parser for linear-gradient



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]