[gtk+/wip/otte/tokenizer: 28/78] css: Add token parsers for shadows



commit d7c8885852f5f2c4883db964c15ec0d2edb92b27
Author: Benjamin Otte <otte redhat com>
Date:   Fri Mar 18 03:27:44 2016 +0100

    css: Add token parsers for shadows
    
    This also introduces the new idea of check_token() functions. These
    functions check if a given function might be the initial token in
    parsing a certain value. Implementations for numbers and colors are
    included.

 gtk/gtkcsscolorvalue.c          |   22 ++++++++
 gtk/gtkcsscolorvalueprivate.h   |    3 +-
 gtk/gtkcssnumbervalue.c         |   18 +++++++
 gtk/gtkcssnumbervalueprivate.h  |    1 +
 gtk/gtkcssshadowsvalue.c        |   42 ++++++++++++++++
 gtk/gtkcssshadowsvalueprivate.h |    3 +
 gtk/gtkcssshadowvalue.c         |  104 +++++++++++++++++++++++++++++++++++++++
 gtk/gtkcssshadowvalueprivate.h  |    3 +
 gtk/gtkcssstylepropertyimpl.c   |   20 ++++++-
 9 files changed, 212 insertions(+), 4 deletions(-)
---
diff --git a/gtk/gtkcsscolorvalue.c b/gtk/gtkcsscolorvalue.c
index 246592f..37923e9 100644
--- a/gtk/gtkcsscolorvalue.c
+++ b/gtk/gtkcsscolorvalue.c
@@ -919,6 +919,27 @@ parse_percentage (GtkCssTokenSource *source,
     }
 }
 
+gboolean
+gtk_css_color_value_check_token (const GtkCssToken *token)
+{
+  GdkRGBA rgba;
+
+  return gtk_css_token_is_ident (token, "currentColor")
+      || gtk_css_token_is_ident (token, "transparent")
+      || gtk_css_token_is_function (token, "rgb")
+      || gtk_css_token_is_function (token, "rgba")
+      || gtk_css_token_is_function (token, "lighter")
+      || gtk_css_token_is_function (token, "darker")
+      || gtk_css_token_is_function (token, "shade")
+      || gtk_css_token_is_function (token, "alpha")
+      || gtk_css_token_is_function (token, "mix")
+      || gtk_css_token_is_function (token, GTK_WIN32_THEME_SYMBOLIC_COLOR_NAME)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_AT_KEYWORD)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_ID)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_HASH_UNRESTRICTED)
+      || (gtk_css_token_is (token, GTK_CSS_TOKEN_IDENT) && gdk_rgba_parse (&rgba, token->string.string));
+}
+
 GtkCssValue *
 gtk_css_color_value_token_parse (GtkCssTokenSource *source)
 {
@@ -967,6 +988,7 @@ gtk_css_color_value_token_parse (GtkCssTokenSource *source)
               if (!parse_number (source, &rgba.red) ||
                   !parse_comma (source) ||
                   !parse_number (source, &rgba.green) ||
+                  !parse_comma (source) ||
                   !parse_number (source, &rgba.blue))
                 return NULL;
               rgba.red = CLAMP (rgba.red, 0, 255.0) / 255.0;
diff --git a/gtk/gtkcsscolorvalueprivate.h b/gtk/gtkcsscolorvalueprivate.h
index dc3c645..9e599f1 100644
--- a/gtk/gtkcsscolorvalueprivate.h
+++ b/gtk/gtkcsscolorvalueprivate.h
@@ -42,8 +42,9 @@ GtkCssValue *   _gtk_css_color_value_new_win32          (const gchar    *theme_c
                                                          gint            id);
 GtkCssValue *   _gtk_css_color_value_new_current_color  (void);
 
-GtkCssValue *   _gtk_css_color_value_parse              (GtkCssParser   *parser);
+GtkCssValue *   _gtk_css_color_value_parse              (GtkCssParser            *parser);
 GtkCssValue *   gtk_css_color_value_token_parse         (GtkCssTokenSource       *source);
+gboolean        gtk_css_color_value_check_token         (const GtkCssToken       *token);
 
 GtkCssValue *   _gtk_css_color_value_resolve            (GtkCssValue             *color,
                                                          GtkStyleProviderPrivate *provider,
diff --git a/gtk/gtkcssnumbervalue.c b/gtk/gtkcssnumbervalue.c
index c31874c..8151dd8 100644
--- a/gtk/gtkcssnumbervalue.c
+++ b/gtk/gtkcssnumbervalue.c
@@ -158,6 +158,24 @@ _gtk_css_number_value_parse (GtkCssParser           *parser,
   return gtk_css_dimension_value_parse (parser, flags);
 }
 
+gboolean
+gtk_css_number_value_check_token (const GtkCssToken *token)
+{
+  return gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_NUMBER)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_DIMENSION)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_INTEGER_DIMENSION)
+      || gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE)
+      || gtk_css_token_is_function (token, "calc")
+      || gtk_css_token_is_function (token, "-gtk-win32-size")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-width")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-height")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-border-top")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-border-left")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-border-bottom")
+      || gtk_css_token_is_function (token, "-gtk-win32-part-border-right");
+}
+
 GtkCssValue *
 gtk_css_number_value_token_parse (GtkCssTokenSource      *source,
                                   GtkCssNumberParseFlags  flags)
diff --git a/gtk/gtkcssnumbervalueprivate.h b/gtk/gtkcssnumbervalueprivate.h
index b4cb0ca..4178654 100644
--- a/gtk/gtkcssnumbervalueprivate.h
+++ b/gtk/gtkcssnumbervalueprivate.h
@@ -62,6 +62,7 @@ GtkCssValue *   gtk_css_number_value_transition     (GtkCssValue            *sta
 gboolean        gtk_css_number_value_can_parse      (GtkCssParser           *parser);
 GtkCssValue *   _gtk_css_number_value_parse         (GtkCssParser           *parser,
                                                      GtkCssNumberParseFlags  flags);
+gboolean        gtk_css_number_value_check_token    (const GtkCssToken      *token);
 GtkCssValue *   gtk_css_number_value_token_parse    (GtkCssTokenSource      *source,
                                                      GtkCssNumberParseFlags  flags);
 
diff --git a/gtk/gtkcssshadowsvalue.c b/gtk/gtkcssshadowsvalue.c
index 083b536..87ce81e 100644
--- a/gtk/gtkcssshadowsvalue.c
+++ b/gtk/gtkcssshadowsvalue.c
@@ -240,6 +240,48 @@ _gtk_css_shadows_value_parse (GtkCssParser *parser,
   return result;
 }
 
+GtkCssValue *
+gtk_css_shadows_value_token_parse (GtkCssTokenSource *source,
+                                   gboolean           box_shadow_mode)
+{
+  GtkCssValue *value, *result;
+  const GtkCssToken *token;
+  GPtrArray *values;
+
+  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_shadows_value_new_none ();
+    }
+
+  values = g_ptr_array_new ();
+
+  while (TRUE)
+    {
+      value = gtk_css_shadow_value_token_parse (source, box_shadow_mode);
+
+      if (value == NULL)
+        {
+          g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
+          g_ptr_array_free (values, TRUE);
+          return NULL;
+        }
+
+      g_ptr_array_add (values, value);
+      gtk_css_token_source_consume_whitespace (source);
+      token = gtk_css_token_source_get_token (source);
+      if (!gtk_css_token_is (token, GTK_CSS_TOKEN_COMMA))
+        break;
+      gtk_css_token_source_consume_token (source);
+      gtk_css_token_source_consume_whitespace (source);
+    }
+
+  result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
+  g_ptr_array_free (values, TRUE);
+  return result;
+}
+
 gboolean
 _gtk_css_shadows_value_is_none (const GtkCssValue *shadows)
 {
diff --git a/gtk/gtkcssshadowsvalueprivate.h b/gtk/gtkcssshadowsvalueprivate.h
index 790e8ec..fad8408 100644
--- a/gtk/gtkcssshadowsvalueprivate.h
+++ b/gtk/gtkcssshadowsvalueprivate.h
@@ -25,6 +25,7 @@
 
 #include "gtktypes.h"
 #include "gtkcssparserprivate.h"
+#include "gtkcsstokensourceprivate.h"
 #include "gtkcssvalueprivate.h"
 #include "gtkroundedboxprivate.h"
 
@@ -33,6 +34,8 @@ G_BEGIN_DECLS
 GtkCssValue *   _gtk_css_shadows_value_new_none       (void);
 GtkCssValue *   _gtk_css_shadows_value_parse          (GtkCssParser             *parser,
                                                        gboolean                  box_shadow_mode);
+GtkCssValue *   gtk_css_shadows_value_token_parse     (GtkCssTokenSource        *source,
+                                                       gboolean                  box_shadow_mode);
 
 gboolean        _gtk_css_shadows_value_is_none        (const GtkCssValue        *shadows);
 
diff --git a/gtk/gtkcssshadowvalue.c b/gtk/gtkcssshadowvalue.c
index c06de2d..3202584 100644
--- a/gtk/gtkcssshadowvalue.c
+++ b/gtk/gtkcssshadowvalue.c
@@ -293,6 +293,110 @@ fail:
   return NULL;
 }
 
+GtkCssValue *
+gtk_css_shadow_value_token_parse (GtkCssTokenSource *source,
+                                  gboolean           box_shadow_mode)
+{
+  enum {
+    HOFFSET,
+    VOFFSET,
+    RADIUS,
+    SPREAD,
+    COLOR,
+    N_VALUES
+  };
+  GtkCssValue *values[N_VALUES] = { NULL, };
+  gboolean inset = FALSE;
+  const GtkCssToken *token;
+  guint i;
+
+  for (token = gtk_css_token_source_get_token (source);
+       !gtk_css_token_is (token, GTK_CSS_TOKEN_EOF);
+       token = gtk_css_token_source_get_token (source))
+    {
+      if (box_shadow_mode && !inset &&
+          gtk_css_token_is_ident (token, "inset"))
+        {
+          inset = TRUE;
+          gtk_css_token_source_consume_token (source);
+          gtk_css_token_source_consume_whitespace (source);
+        }
+      else if (values[COLOR] == NULL && gtk_css_color_value_check_token (token))
+        {
+          values[COLOR] = gtk_css_color_value_token_parse (source);
+          if (values[COLOR] == NULL)
+            goto fail;
+          gtk_css_token_source_consume_whitespace (source);
+        }
+      else if (values[HOFFSET] == NULL && gtk_css_number_value_check_token (token))
+        {
+          values[HOFFSET] = gtk_css_number_value_token_parse (source,
+                                                              GTK_CSS_PARSE_LENGTH
+                                                              | GTK_CSS_NUMBER_AS_PIXELS);
+          if (values[HOFFSET] == NULL)
+            goto fail;
+          gtk_css_token_source_consume_whitespace (source);
+
+          values[VOFFSET] = gtk_css_number_value_token_parse (source,
+                                                              GTK_CSS_PARSE_LENGTH
+                                                              | GTK_CSS_NUMBER_AS_PIXELS);
+          if (values[VOFFSET] == NULL)
+            goto fail;
+          gtk_css_token_source_consume_whitespace (source);
+
+          if (gtk_css_number_value_check_token (gtk_css_token_source_get_token (source)))
+            {
+              values[RADIUS] = gtk_css_number_value_token_parse (source,
+                                                                 GTK_CSS_PARSE_LENGTH
+                                                                 | GTK_CSS_POSITIVE_ONLY
+                                                                 | GTK_CSS_NUMBER_AS_PIXELS);
+              if (values[RADIUS] == NULL)
+                goto fail;
+              gtk_css_token_source_consume_whitespace (source);
+            }
+          else
+            values[RADIUS] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+
+        if (box_shadow_mode &&
+            gtk_css_number_value_check_token (gtk_css_token_source_get_token (source)))
+          {
+            values[SPREAD] = gtk_css_number_value_token_parse (source,
+                                                               GTK_CSS_PARSE_LENGTH
+                                                               | GTK_CSS_NUMBER_AS_PIXELS);
+            if (values[SPREAD] == NULL)
+              goto fail;
+            gtk_css_token_source_consume_whitespace (source);
+          }
+        else
+          values[SPREAD] = _gtk_css_number_value_new (0.0, GTK_CSS_PX);
+        }
+      else if (values[HOFFSET] == NULL)
+        {
+          gtk_css_token_source_error (source, "Expected a shadow definition");
+          gtk_css_token_source_consume_all (source);
+          goto fail;
+        }
+      else
+        break;
+    }
+
+  if (values[COLOR] == NULL)
+    values[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]);
+
+fail:
+  for (i = 0; i < N_VALUES; i++)
+    {
+      if (values[i])
+        _gtk_css_value_unref (values[i]);
+    }
+
+  return NULL;
+}
+
 static gboolean
 needs_blur (const GtkCssValue *shadow)
 {
diff --git a/gtk/gtkcssshadowvalueprivate.h b/gtk/gtkcssshadowvalueprivate.h
index 5fab1cc..2ca9c7e 100644
--- a/gtk/gtkcssshadowvalueprivate.h
+++ b/gtk/gtkcssshadowvalueprivate.h
@@ -25,6 +25,7 @@
 
 #include "gtktypes.h"
 #include "gtkcssparserprivate.h"
+#include "gtkcsstokensourceprivate.h"
 #include "gtkcssvalueprivate.h"
 #include "gtkroundedboxprivate.h"
 
@@ -34,6 +35,8 @@ GtkCssValue *   _gtk_css_shadow_value_new_for_transition (GtkCssValue
 
 GtkCssValue *   _gtk_css_shadow_value_parse           (GtkCssParser             *parser,
                                                        gboolean                  box_shadow_mode);
+GtkCssValue *   gtk_css_shadow_value_token_parse      (GtkCssTokenSource        *source,
+                                                       gboolean                  box_shadow_mode);
 
 gboolean        _gtk_css_shadow_value_get_inset       (const GtkCssValue        *shadow);
 
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index 927613f..9bbc81d 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -933,6 +933,13 @@ box_shadow_value_parse (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+box_shadow_value_token_parse (GtkCssTokenSource   *source,
+                              GtkCssStyleProperty *property)
+{
+  return gtk_css_shadows_value_token_parse (source, TRUE);
+}
+
+static GtkCssValue *
 shadow_value_parse (GtkCssStyleProperty *property,
                     GtkCssParser        *parser)
 {
@@ -940,6 +947,13 @@ shadow_value_parse (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+shadow_value_token_parse (GtkCssTokenSource   *source,
+                          GtkCssStyleProperty *property)
+{
+  return gtk_css_shadows_value_token_parse (source, FALSE);
+}
+
+static GtkCssValue *
 transform_value_parse (GtkCssStyleProperty *property,
                        GtkCssParser        *parser)
 {
@@ -1612,7 +1626,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_TEXT | GTK_CSS_AFFECTS_CLIP,
                                           shadow_value_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          shadow_value_token_parse,
                                           NULL,
                                           NULL,
                                           _gtk_css_shadows_value_new_none ());
@@ -1623,7 +1637,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_BACKGROUND | GTK_CSS_AFFECTS_CLIP,
                                           box_shadow_value_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          box_shadow_value_token_parse,
                                           NULL,
                                           NULL,
                                           _gtk_css_shadows_value_new_none ());
@@ -2097,7 +2111,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_INHERIT | GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | 
GTK_CSS_AFFECTS_CLIP,
                                           shadow_value_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          shadow_value_token_parse,
                                           NULL,
                                           NULL,
                                           _gtk_css_shadows_value_new_none ());


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