[gtk/wip/otte/css: 8/18] cross-fade: Use gtk_css_parser_consume_any()



commit 9dc49ded7bde019c20071a75fdc6cba2c80dcf3b
Author: Benjamin Otte <otte redhat com>
Date:   Sat Mar 30 12:04:51 2019 +0100

    cross-fade: Use gtk_css_parser_consume_any()
    
    .. and gtk_css_parser_consume_function().
    
    gtk_css_parser_consume_any() is a new function that implements the CSS
    spec's any combinator ||.

 gtk/gtkcssimagecrossfade.c | 95 ++++++++++++++++++++++++++++------------------
 gtk/gtkcssparser.c         | 39 +++++++++++++++++++
 gtk/gtkcssparserprivate.h  | 17 +++++++++
 3 files changed, 114 insertions(+), 37 deletions(-)
---
diff --git a/gtk/gtkcssimagecrossfade.c b/gtk/gtkcssimagecrossfade.c
index 4a5736370b..30e87f61ea 100644
--- a/gtk/gtkcssimagecrossfade.c
+++ b/gtk/gtkcssimagecrossfade.c
@@ -230,59 +230,80 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image,
 }
 
 static gboolean
-gtk_css_image_cross_fade_parse (GtkCssImage  *image,
-                                GtkCssParser *parser)
+parse_progress (GtkCssParser *parser,
+                gpointer      option_data,
+                gpointer      user_data)
 {
-  GtkCssImageCrossFade *self = GTK_CSS_IMAGE_CROSS_FADE (image);
-  double progress;
+  double *progress = option_data;
+  GtkCssValue *number;
+  
+  number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
+  if (number == NULL)
+    return FALSE;
+  *progress = _gtk_css_number_value_get (number, 1);
+  _gtk_css_value_unref (number);
 
-  if (!_gtk_css_parser_try (parser, "cross-fade(", TRUE))
+  if (*progress > 1.0)
     {
-      _gtk_css_parser_error (parser, "Expected 'cross-fade('");
+      _gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
       return FALSE;
     }
 
-  if (gtk_css_number_value_can_parse (parser))
-    {
-      GtkCssValue *number;
-      
-      number = _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_PERCENT | GTK_CSS_POSITIVE_ONLY);
-      if (number == NULL)
-        return FALSE;
-      progress = _gtk_css_number_value_get (number, 1);
-      _gtk_css_value_unref (number);
-
-      if (progress > 1.0)
-        {
-          _gtk_css_parser_error (parser, "Percentages over 100%% are not allowed");
-          return FALSE;
-        }
-    }
-  else
-    progress = 0.5;
+  return TRUE;
+}
 
-  image = _gtk_css_image_new_parse (parser);
-  if (image == NULL)
+static gboolean
+parse_image (GtkCssParser *parser,
+             gpointer      option_data,
+             gpointer      user_data)
+{
+  GtkCssImage **image = option_data;
+
+  *image = _gtk_css_image_new_parse (parser);
+  if (*image == NULL)
     return FALSE;
 
-  gtk_css_image_cross_fade_add (self, progress, image);
+  return TRUE;
+}
 
-  if (_gtk_css_parser_try (parser, ",", TRUE))
+static guint
+gtk_css_image_cross_fade_parse_arg (GtkCssParser *parser,
+                                    guint         arg,
+                                    gpointer      data)
+{
+  GtkCssImageCrossFade *self = data;
+  double progress = -1.0;
+  GtkCssImage *image = NULL;
+  GtkCssParseOption options[] =
     {
-      /* XXX: allow parsing colors here */
-      image = _gtk_css_image_new_parse (parser);
-      if (image == NULL)
-        return FALSE;
-      gtk_css_image_cross_fade_add (self, 1.0 - progress, image);
-    }
+      { (void *) gtk_css_number_value_can_parse, parse_progress, &progress },
+      { NULL, parse_image, &image },
+    };
+
+  if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), self))
+    return 0;
+
+  g_assert (image != NULL);
+
+  /* XXX */
+  if (progress < 0)
+    progress = 1.0 - self->total_progress;
+  gtk_css_image_cross_fade_add (self, progress, image);
 
-  if (!_gtk_css_parser_try (parser, ")", TRUE))
+  return 1;
+}
+
+static gboolean
+gtk_css_image_cross_fade_parse (GtkCssImage  *image,
+                                GtkCssParser *parser)
+{
+  if (!gtk_css_parser_has_function (parser, "cross-fade"))
     {
-      _gtk_css_parser_error (parser, "Missing closing bracket");
+      _gtk_css_parser_error (parser, "Expected 'cross-fade('");
       return FALSE;
     }
 
-  return TRUE;
+  return gtk_css_parser_consume_function (parser, 1, G_MAXUINT, gtk_css_image_cross_fade_parse_arg, image);
 }
 
 static void
diff --git a/gtk/gtkcssparser.c b/gtk/gtkcssparser.c
index b43a975173..806cc2701c 100644
--- a/gtk/gtkcssparser.c
+++ b/gtk/gtkcssparser.c
@@ -1210,3 +1210,42 @@ gtk_css_parser_consume_function (GtkCssParser *self,
   return result;
 }
 
+gsize
+gtk_css_parser_consume_any (GtkCssParser            *parser,
+                            const GtkCssParseOption *options,
+                            gsize                    n_options,
+                            gpointer                 user_data)
+{
+  gsize result;
+  gsize i;
+
+  g_return_val_if_fail (parser != NULL, 0);
+  g_return_val_if_fail (options != NULL, 0);
+  g_return_val_if_fail (n_options < sizeof (gsize) * 8 - 1, 0);
+
+  result = 0;
+  while (result != (1 << n_options) - 1)
+    {
+      for (i = 0; i < n_options; i++)
+        {
+          if (result & (1 << i))
+            continue;
+          if (options[i].can_parse && !options[i].can_parse (parser, options[i].data, user_data))
+            continue;
+          if (!options[i].parse (parser, options[i].data, user_data))
+            return 0;
+          result |= 1 << i;
+          break;
+        }
+      if (i == n_options)
+        break;
+    }
+  if (result == 0)
+    {
+      _gtk_css_parser_error (parser, "No valid value given");
+      return result;
+    }
+
+  return result;
+}
+
diff --git a/gtk/gtkcssparserprivate.h b/gtk/gtkcssparserprivate.h
index 019d417f16..e4b763a826 100644
--- a/gtk/gtkcssparserprivate.h
+++ b/gtk/gtkcssparserprivate.h
@@ -31,6 +31,19 @@ typedef void (* GtkCssParserErrorFunc) (GtkCssParser *parser,
                                         const GError *error,
                                         gpointer      user_data);
 
+typedef struct _GtkCssParseOption GtkCssParseOption;
+
+struct _GtkCssParseOption
+{
+  gboolean (* can_parse)  (GtkCssParser *parser,
+                           gpointer      option_data,
+                           gpointer      user_data);
+  gboolean (* parse)      (GtkCssParser *parser,
+                           gpointer      option_data,
+                           gpointer      user_data);
+  gpointer data;
+};
+
 GtkCssParser *  _gtk_css_parser_new               (const char            *data,
                                                    GFile                 *file,
                                                    GtkCssParserErrorFunc  error_func,
@@ -90,6 +103,10 @@ gboolean        gtk_css_parser_consume_function   (GtkCssParser          *self,
                                                    guint                  max_args,
                                                    guint (* parse_func) (GtkCssParser *, guint, gpointer),
                                                    gpointer               data);
+gsize           gtk_css_parser_consume_any        (GtkCssParser          *parser,
+                                                   const GtkCssParseOption *options,
+                                                   gsize                  n_options,
+                                                   gpointer               user_data);
 
 gboolean        _gtk_css_parser_has_number        (GtkCssParser          *parser);
 char *          _gtk_css_parser_read_string       (GtkCssParser          *parser);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]