[gtk+/wip/otte/tokenizer: 35/42] css: Add a token parser for transform values



commit a9a1376811c4eb7d93bd7e2e3df9746e8f0566de
Author: Benjamin Otte <otte redhat com>
Date:   Fri Mar 18 23:19:43 2016 +0100

    css: Add a token parser for transform values

 gtk/gtkcssstylepropertyimpl.c     |    2 +-
 gtk/gtkcsstransformvalue.c        |  316 +++++++++++++++++++++++++++++++++++++
 gtk/gtkcsstransformvalueprivate.h |    2 +
 3 files changed, 319 insertions(+), 1 deletions(-)
---
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index 6688515..ecc2f80 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -2166,7 +2166,7 @@ _gtk_css_style_property_init_properties (void)
                                           GTK_STYLE_PROPERTY_ANIMATED,
                                           GTK_CSS_AFFECTS_ICON | GTK_CSS_AFFECTS_SYMBOLIC_ICON | 
GTK_CSS_AFFECTS_CLIP,
                                           transform_value_parse,
-                                          gtk_css_style_property_token_parse_default,
+                                          (GtkCssStylePropertyTokenParseFunc) 
gtk_css_transform_value_token_parse,
                                           NULL,
                                           NULL,
                                           _gtk_css_transform_value_new_none ());
diff --git a/gtk/gtkcsstransformvalue.c b/gtk/gtkcsstransformvalue.c
index 13e9f0f..b456af8 100644
--- a/gtk/gtkcsstransformvalue.c
+++ b/gtk/gtkcsstransformvalue.c
@@ -1015,6 +1015,322 @@ _gtk_css_transform_value_parse (GtkCssParser *parser)
   return value;
 }
 
+static gboolean
+token_parse_matrix (GtkCssTokenSource *source,
+                    guint              n,
+                    gpointer           data)
+{
+  GtkCssTransform *transform = data;
+
+  switch (n)
+    {
+    case 0:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xx);
+    case 1:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.xy);
+    case 2:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.x0);
+    case 3:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yx);
+    case 4:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.yy);
+    case 5:
+      return gtk_css_token_source_consume_number (source, &transform->matrix.matrix.y0);
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+    }
+}
+
+static gboolean
+token_parse_translate (GtkCssTokenSource *source,
+                       guint              n,
+                       gpointer           data)
+{
+  GtkCssTransform *transform = data;
+
+  if (n == 0)
+    {
+      transform->translate.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
+      if (transform->translate.x == NULL)
+        return FALSE;
+      transform->translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
+    }
+  else if (n == 1)
+    {
+      _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;
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+  return TRUE;
+}
+
+static gboolean
+token_parse_length (GtkCssTokenSource *source,
+                    guint              n,
+                    gpointer           data)
+{
+  GtkCssValue **value = data;
+
+  *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_LENGTH);
+  return *value != NULL;
+}
+
+static gboolean
+token_parse_scale (GtkCssTokenSource *source,
+                   guint              n,
+                   gpointer           data)
+{
+  GtkCssTransform *transform = data;
+
+  if (n == 0)
+    {
+      transform->scale.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
+      if (transform->scale.x == NULL)
+        return FALSE;
+      transform->scale.y = _gtk_css_value_ref (transform->scale.x);
+    }
+  else if (n == 1)
+    {
+      _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;
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+  return TRUE;
+}
+
+static gboolean
+token_parse_number (GtkCssTokenSource *source,
+                    guint              n,
+                    gpointer           data)
+{
+  GtkCssValue **value = data;
+
+  *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_NUMBER);
+  return *value != NULL;
+}
+
+static gboolean
+token_parse_angle (GtkCssTokenSource *source,
+                   guint              n,
+                   gpointer           data)
+{
+  GtkCssValue **value = data;
+
+  *value = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
+  return *value != NULL;
+}
+
+static gboolean
+token_parse_skew (GtkCssTokenSource *source,
+                  guint              n,
+                  gpointer           data)
+{
+  GtkCssTransform *transform = data;
+
+  if (n == 0)
+    {
+      transform->skew.x = gtk_css_number_value_token_parse (source, GTK_CSS_PARSE_ANGLE);
+      if (transform->skew.x == NULL)
+        return FALSE;
+      transform->skew.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
+    }
+  else if (n == 1)
+    {
+      _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;
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+  return TRUE;
+}
+
+GtkCssValue *
+gtk_css_transform_value_token_parse (GtkCssTokenSource *source)
+{
+  const GtkCssToken *token;
+  GtkCssValue *value;
+  GArray *array;
+  guint i;
+
+  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_transform_value_new_none ();
+    }
+
+  array = g_array_new (FALSE, FALSE, sizeof (GtkCssTransform));
+
+  while (TRUE)
+    {
+      GtkCssTransform transform = { 0, };
+
+      if (gtk_css_token_is_function (token, "matrix"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_MATRIX;
+          if (!gtk_css_token_source_consume_function (source, 6, 6, token_parse_matrix, &transform))
+            goto fail;
+        }
+      else if (gtk_css_token_is_function (token, "translate"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
+          if (!gtk_css_token_source_consume_function (source, 2, 2, token_parse_translate, &transform))
+            {
+              if (transform.translate.x)
+                _gtk_css_value_unref (transform.translate.x);
+              if (transform.translate.y)
+                _gtk_css_value_unref (transform.translate.y);
+              goto fail;
+            }
+        }
+      else if (gtk_css_token_is_function (token, "translateX"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, 
&transform.translate.x))
+            {
+              if (transform.translate.x)
+                _gtk_css_value_unref (transform.translate.x);
+              goto fail;
+            }
+          transform.translate.y = _gtk_css_number_value_new (0, GTK_CSS_PX);
+        }
+      else if (gtk_css_token_is_function (token, "translateY"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_TRANSLATE;
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_length, 
&transform.translate.y))
+            {
+              if (transform.translate.y)
+                _gtk_css_value_unref (transform.translate.y);
+              goto fail;
+            }
+          transform.translate.x = _gtk_css_number_value_new (0, GTK_CSS_PX);
+        }
+      else if (gtk_css_token_is_function (token, "scale"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SCALE;
+          if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_scale, &transform))
+            {
+              if (transform.scale.x)
+                _gtk_css_value_unref (transform.scale.x);
+              if (transform.scale.y)
+                _gtk_css_value_unref (transform.scale.y);
+              goto fail;
+            }
+        }
+      else if (gtk_css_token_is_function (token, "scaleX"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SCALE;
+
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.x))
+            {
+              if (transform.scale.x)
+                _gtk_css_value_unref (transform.scale.x);
+              goto fail;
+            }
+          transform.scale.y = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
+        }
+      else if (gtk_css_token_is_function (token, "scaleY"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SCALE;
+
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_number, &transform.scale.y))
+            {
+              if (transform.scale.y)
+                _gtk_css_value_unref (transform.scale.y);
+              goto fail;
+            }
+          transform.scale.x = _gtk_css_number_value_new (1, GTK_CSS_NUMBER);
+        }
+      else if (gtk_css_token_is_function (token, "rotate"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_ROTATE;
+
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, 
&transform.rotate.rotate))
+            {
+              if (transform.rotate.rotate)
+                _gtk_css_value_unref (transform.rotate.rotate);
+              goto fail;
+            }
+        }
+      else if (gtk_css_token_is_function (token, "skew"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SKEW;
+          if (!gtk_css_token_source_consume_function (source, 1, 2, token_parse_skew, &transform))
+            {
+              if (transform.skew.x)
+                _gtk_css_value_unref (transform.skew.x);
+              if (transform.skew.y)
+                _gtk_css_value_unref (transform.skew.y);
+              goto fail;
+            }
+        }
+      else if (gtk_css_token_is_function (token, "skewX"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SKEW_X;
+
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, 
&transform.skew_x.skew))
+            {
+              if (transform.skew_x.skew)
+                _gtk_css_value_unref (transform.skew_x.skew);
+              goto fail;
+            }
+        }
+      else if (gtk_css_token_is_function (token, "skewY"))
+        {
+          transform.type = GTK_CSS_TRANSFORM_SKEW_Y;
+
+          if (!gtk_css_token_source_consume_function (source, 1, 1, token_parse_angle, 
&transform.skew_y.skew))
+            {
+              if (transform.skew_y.skew)
+                _gtk_css_value_unref (transform.skew_y.skew);
+              goto fail;
+            }
+        }
+      else
+        break;
+
+      g_array_append_val (array, transform);
+      token = gtk_css_token_source_get_token (source);
+    }
+
+  if (array->len == 0)
+    {
+      gtk_css_token_source_error (source, "Expected a transform");
+      gtk_css_token_source_consume_all (source);
+      goto fail;
+    }
+
+  value = gtk_css_transform_value_alloc (array->len);
+  memcpy (value->transforms, array->data, sizeof (GtkCssTransform) * array->len);
+
+  g_array_free (array, TRUE);
+
+  return value;
+
+fail:
+  for (i = 0; i < array->len; i++)
+    {
+      gtk_css_transform_clear (&g_array_index (array, GtkCssTransform, i));
+    }
+  g_array_free (array, TRUE);
+  return NULL;
+}
+
 gboolean
 _gtk_css_transform_value_get_matrix (const GtkCssValue *transform,
                                      cairo_matrix_t    *matrix)
diff --git a/gtk/gtkcsstransformvalueprivate.h b/gtk/gtkcsstransformvalueprivate.h
index 49411ff..e7382ff 100644
--- a/gtk/gtkcsstransformvalueprivate.h
+++ b/gtk/gtkcsstransformvalueprivate.h
@@ -21,12 +21,14 @@
 #define __GTK_CSS_TRANSFORM_VALUE_PRIVATE_H__
 
 #include "gtkcssparserprivate.h"
+#include "gtkcsstokensourceprivate.h"
 #include "gtkcssvalueprivate.h"
 
 G_BEGIN_DECLS
 
 GtkCssValue *   _gtk_css_transform_value_new_none       (void);
 GtkCssValue *   _gtk_css_transform_value_parse          (GtkCssParser           *parser);
+GtkCssValue *   gtk_css_transform_value_token_parse     (GtkCssTokenSource      *source);
 
 gboolean        _gtk_css_transform_value_get_matrix     (const GtkCssValue      *transform,
                                                          cairo_matrix_t         *matrix);


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