[gtk/wip/otte/css: 41/66] cssshadow: Use gtk_css_parser_consume_any()



commit 25344390ccd26001193ebf73e6633abe1a84b88e
Author: Benjamin Otte <otte redhat com>
Date:   Tue Apr 9 05:15:45 2019 +0200

    cssshadow: Use gtk_css_parser_consume_any()
    
    This way, the arguments can now really be speicified in any order.
    
    A new testcase testing all the ordering possibilities has been added.

 gtk/gtkcsscolorvalue.c                       |  17 +++
 gtk/gtkcsscolorvalueprivate.h                |   1 +
 gtk/gtkcssshadowvalue.c                      | 185 ++++++++++++++++-----------
 testsuite/css/parser/meson.build             |   2 +
 testsuite/css/parser/shadow-ordering.css     |  43 +++++++
 testsuite/css/parser/shadow-ordering.ref.css |  43 +++++++
 6 files changed, 213 insertions(+), 78 deletions(-)
---
diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c
index 40b3159666..617f92bdc1 100644
--- a/gtk/gtkcsscolorvalue.c
+++ b/gtk/gtkcsscolorvalue.c
@@ -574,6 +574,23 @@ parse_color_number (GtkCssParser *parser,
   }
 }
 
+gboolean
+gtk_css_color_value_can_parse (GtkCssParser *parser)
+{
+  /* This is way too generous, but meh... */
+  return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_IDENT)
+      || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_AT_KEYWORD)
+      || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_ID)
+      || gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_HASH_UNRESTRICTED)
+      || gtk_css_parser_has_function (parser, "lighter")
+      || gtk_css_parser_has_function (parser, "darker")
+      || gtk_css_parser_has_function (parser, "shade")
+      || gtk_css_parser_has_function (parser, "alpha")
+      || gtk_css_parser_has_function (parser, "mix")
+      || gtk_css_parser_has_function (parser, "rgb")
+      || gtk_css_parser_has_function (parser, "rgba");
+}
+
 GtkCssValue *
 _gtk_css_color_value_parse (GtkCssParser *parser)
 {
diff --git a/gtk/gtkcsscolorvalueprivate.h b/gtk/gtkcsscolorvalueprivate.h
index e5f9c42ee6..fa199ee6ab 100644
--- a/gtk/gtkcsscolorvalueprivate.h
+++ b/gtk/gtkcsscolorvalueprivate.h
@@ -39,6 +39,7 @@ GtkCssValue *   _gtk_css_color_value_new_mix            (GtkCssValue    *color1,
                                                          gdouble         factor);
 GtkCssValue *   _gtk_css_color_value_new_current_color  (void);
 
+gboolean        gtk_css_color_value_can_parse           (GtkCssParser   *parser);
 GtkCssValue *   _gtk_css_color_value_parse              (GtkCssParser   *parser);
 
 GtkCssValue *   _gtk_css_color_value_resolve            (GtkCssValue      *color,
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index 072396f6c9..f0b2fc243d 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -201,103 +201,132 @@ _gtk_css_shadow_value_new_for_transition (GtkCssValue *target)
                                    _gtk_css_rgba_value_new_from_rgba (&transparent));
 }
 
+enum {
+  HOFFSET,
+  VOFFSET,
+  RADIUS,
+  SPREAD,
+  N_VALUES
+};
+
+static gboolean
+has_inset (GtkCssParser *parser,
+           gpointer      option_data,
+           gpointer      box_shadow_mode)
+{
+  return box_shadow_mode && gtk_css_parser_has_ident (parser, "inset");
+}
+
+static gboolean
+parse_inset (GtkCssParser *parser,
+             gpointer      option_data,
+             gpointer      box_shadow_mode)
+{
+  gboolean *inset = option_data;
+
+  if (!gtk_css_parser_try_ident (parser, "inset"))
+    {
+      g_assert_not_reached ();
+      return FALSE;
+    }
+
+  *inset = TRUE;
+
+  return TRUE;
+}
+
+static gboolean
+parse_lengths (GtkCssParser *parser,
+               gpointer      option_data,
+               gpointer      box_shadow_mode)
+{
+  GtkCssValue **values = option_data;
+
+  values[HOFFSET] = _gtk_css_number_value_parse (parser,
+                                                 GTK_CSS_PARSE_LENGTH);
+  if (values[HOFFSET] == NULL)
+    return FALSE;
+
+  values[VOFFSET] = _gtk_css_number_value_parse (parser,
+                                                 GTK_CSS_PARSE_LENGTH);
+  if (values[VOFFSET] == NULL)
+    return FALSE;
+
+  if (gtk_css_number_value_can_parse (parser))
+    {
+      values[RADIUS] = _gtk_css_number_value_parse (parser,
+                                                    GTK_CSS_PARSE_LENGTH
+                                                    | GTK_CSS_POSITIVE_ONLY);
+      if (values[RADIUS] == NULL)
+        return FALSE;
+    }
+  else
+    values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+
+  if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
+    {
+      values[SPREAD] = _gtk_css_number_value_parse (parser,
+                                                    GTK_CSS_PARSE_LENGTH);
+      if (values[SPREAD] == NULL)
+        return FALSE;
+    }
+  else
+    values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+
+  return TRUE;
+}
+
 static gboolean
-value_is_done_parsing (GtkCssParser *parser)
+parse_color (GtkCssParser *parser,
+             gpointer      option_data,
+             gpointer      box_shadow_mode)
 {
-  return gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_EOF) ||
-         gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_COMMA) ||
-         gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_SEMICOLON) ||
-         gtk_css_parser_has_token (parser, GTK_CSS_TOKEN_CLOSE_CURLY);
+  GtkCssValue **color = option_data;
+  
+  *color = _gtk_css_color_value_parse (parser);
+  if (*color == NULL)
+    return FALSE;
+
+  return TRUE;
 }
 
 GtkCssValue *
 _gtk_css_shadow_value_parse (GtkCssParser *parser,
                              gboolean      box_shadow_mode)
 {
-  enum {
-    HOFFSET,
-    VOFFSET,
-    RADIUS,
-    SPREAD,
-    COLOR,
-    N_VALUES
-  };
   GtkCssValue *values[N_VALUES] = { NULL, };
-  gboolean inset;
+  GtkCssValue *color = NULL;
+  gboolean inset = FALSE;
+  GtkCssParseOption options[] =
+    {
+      { (void *) gtk_css_number_value_can_parse, parse_lengths, values },
+      { has_inset, parse_inset, &inset },
+      { (void *) gtk_css_color_value_can_parse, parse_color, &color },
+    };
   guint i;
 
-  inset = FALSE;
-
-  do
-  {
-    if (values[HOFFSET] == NULL &&
-        gtk_css_number_value_can_parse (parser))
-      {
-        values[HOFFSET] = _gtk_css_number_value_parse (parser,
-                                                       GTK_CSS_PARSE_LENGTH);
-        if (values[HOFFSET] == NULL)
-          goto fail;
-
-        values[VOFFSET] = _gtk_css_number_value_parse (parser,
-                                                       GTK_CSS_PARSE_LENGTH);
-        if (values[VOFFSET] == NULL)
-          goto fail;
-
-        if (gtk_css_number_value_can_parse (parser))
-          {
-            values[RADIUS] = _gtk_css_number_value_parse (parser,
-                                                          GTK_CSS_PARSE_LENGTH
-                                                          | GTK_CSS_POSITIVE_ONLY);
-            if (values[RADIUS] == NULL)
-              goto fail;
-          }
-        else
-          values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
-
-        if (box_shadow_mode && gtk_css_number_value_can_parse (parser))
-          {
-            values[SPREAD] = _gtk_css_number_value_parse (parser,
-                                                          GTK_CSS_PARSE_LENGTH);
-            if (values[SPREAD] == NULL)
-              goto fail;
-          }
-        else
-          values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
-      }
-    else if (!inset && box_shadow_mode && gtk_css_parser_try_ident (parser, "inset"))
-      {
-        inset = TRUE;
-      }
-    else if (values[COLOR] == NULL)
-      {
-        values[COLOR] = _gtk_css_color_value_parse (parser);
-
-        if (values[COLOR] == NULL)
-          goto fail;
-      }
-    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 */
-        goto fail;
-      }
-  }
-  while (values[HOFFSET] == NULL || !value_is_done_parsing (parser));
-
-  if (values[COLOR] == NULL)
-    values[COLOR] = _gtk_css_color_value_new_current_color ();
+  if (!gtk_css_parser_consume_any (parser, options, G_N_ELEMENTS (options), GUINT_TO_POINTER 
(box_shadow_mode)))
+    goto fail;
+
+  if (values[0] == NULL)
+    {
+      gtk_css_parser_error_syntax (parser, "Expected shadow value to contain a length");
+      goto fail;
+    }
+
+  if (color == NULL)
+    color = _gtk_css_color_value_new_current_color ();
 
   return gtk_css_shadow_value_new (values[HOFFSET], values[VOFFSET],
                                    values[RADIUS], values[SPREAD],
-                                   inset, values[COLOR]);
+                                   inset, color);
 
 fail:
   for (i = 0; i < N_VALUES; i++)
     {
-      if (values[i])
-        _gtk_css_value_unref (values[i]);
+      g_clear_pointer (&values[i], gtk_css_value_unref);
     }
+  g_clear_pointer (&color, gtk_css_value_unref);
 
   return NULL;
 }
diff --git a/testsuite/css/parser/meson.build b/testsuite/css/parser/meson.build
index db4672365a..9451633efd 100644
--- a/testsuite/css/parser/meson.build
+++ b/testsuite/css/parser/meson.build
@@ -383,6 +383,8 @@ test_data = [
   'selector.ref.css',
   'shadow.css',
   'shadow.ref.css',
+  'shadow-ordering.css',
+  'shadow-ordering.ref.css',
   'shorthand.css',
   'shorthand.ref.css',
   'simple.css',
diff --git a/testsuite/css/parser/shadow-ordering.css b/testsuite/css/parser/shadow-ordering.css
new file mode 100644
index 0000000000..5450fa38df
--- /dev/null
+++ b/testsuite/css/parser/shadow-ordering.css
@@ -0,0 +1,43 @@
+a {
+  box-shadow: 0 0;
+}
+
+b {
+  box-shadow: 0 0 inset;
+}
+
+c {
+  box-shadow: 0 0 inset red;
+}
+
+d {
+  box-shadow: 0 0 red;
+}
+
+e {
+  box-shadow: 0 0 red inset;
+}
+
+f {
+  box-shadow: inset 0 0;
+}
+
+g {
+  box-shadow: inset red 0 0;
+}
+
+h {
+  box-shadow: inset 0 0 red;
+}
+
+i {
+  box-shadow: red 0 0;
+}
+
+j {
+  box-shadow: red inset 0 0;
+}
+
+k {
+  box-shadow: red 0 0 inset;
+}
diff --git a/testsuite/css/parser/shadow-ordering.ref.css b/testsuite/css/parser/shadow-ordering.ref.css
new file mode 100644
index 0000000000..ee7a10a2b1
--- /dev/null
+++ b/testsuite/css/parser/shadow-ordering.ref.css
@@ -0,0 +1,43 @@
+a {
+  box-shadow: 0 0 currentColor;
+}
+
+b {
+  box-shadow: 0 0 currentColor inset;
+}
+
+c {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+d {
+  box-shadow: 0 0 rgb(255,0,0);
+}
+
+e {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+f {
+  box-shadow: 0 0 currentColor inset;
+}
+
+g {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+h {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+i {
+  box-shadow: 0 0 rgb(255,0,0);
+}
+
+j {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}
+
+k {
+  box-shadow: 0 0 rgb(255,0,0) inset;
+}


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