[gtk+] GtkCssProvider: Add a parser for gradients.



commit 3fc5c87bcb4505a4d63e2163d1e2e1c6775cc0f1
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Sep 2 02:06:05 2010 +0200

    GtkCssProvider: Add a parser for gradients.

 gtk/gtkcssprovider.c |  246 +++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 244 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c
index c64ab88..a4a1af7 100644
--- a/gtk/gtkcssprovider.c
+++ b/gtk/gtkcssprovider.c
@@ -1312,8 +1312,6 @@ symbolic_color_parse_str (const gchar  *string,
   return symbolic_color;
 }
 
-#undef SKIP_SPACES
-
 static GtkSymbolicColor *
 symbolic_color_parse (const gchar *str)
 {
@@ -1337,6 +1335,235 @@ symbolic_color_parse (const gchar *str)
   return color;
 }
 
+static GtkGradient *
+gradient_parse_str (const gchar  *str,
+                    gchar       **end_ptr)
+{
+  GtkGradient *gradient = NULL;
+
+  if (g_str_has_prefix (str, "-gtk-gradient"))
+    {
+      cairo_pattern_type_t type;
+
+      str += strlen ("-gtk-gradient");
+      SKIP_SPACES (str);
+
+      if (*str != '(')
+        {
+          *end_ptr = (gchar *) str;
+          return NULL;
+        }
+
+      str++;
+      SKIP_SPACES (str);
+
+      /* Parse gradient type */
+      if (g_str_has_prefix (str, "linear"))
+        {
+          type = CAIRO_PATTERN_TYPE_LINEAR;
+          str += strlen ("linear");
+        }
+      else if (g_str_has_prefix (str, "radial"))
+        {
+          type = CAIRO_PATTERN_TYPE_RADIAL;
+          str += strlen ("radial");
+        }
+      else
+        {
+          *end_ptr = (gchar *) str;
+          return NULL;
+        }
+
+      SKIP_SPACES (str);
+
+      if (type == CAIRO_PATTERN_TYPE_LINEAR)
+        {
+          gdouble coords[4];
+          gchar *end;
+          guint i;
+
+          /* Parse start/stop position parameters */
+          for (i = 0; i < 2; i++)
+            {
+              if (*str != ',')
+                {
+                  *end_ptr = (gchar *) str;
+                  return NULL;
+                }
+
+              str++;
+              SKIP_SPACES (str);
+
+              if (g_str_has_prefix (str, "left"))
+                {
+                  coords[i * 2] = 0;
+                  str += strlen ("left");
+                }
+              else if (g_str_has_prefix (str, "right"))
+                {
+                  coords[i * 2] = 1;
+                  str += strlen ("right");
+                }
+              else
+                {
+                  coords[i * 2] = g_ascii_strtod (str, &end);
+                  str = end;
+                }
+
+              SKIP_SPACES (str);
+
+              if (g_str_has_prefix (str, "top"))
+                {
+                  coords[(i * 2) + 1] = 0;
+                  str += strlen ("top");
+                }
+              else if (g_str_has_prefix (str, "bottom"))
+                {
+                  coords[(i * 2) + 1] = 1;
+                  str += strlen ("bottom");
+                }
+              else
+                {
+                  coords[(i * 2) + 1] = g_ascii_strtod (str, &end);
+                  str = end;
+                }
+
+              SKIP_SPACES (str);
+            }
+
+          gradient = gtk_gradient_new_linear (coords[0], coords[1], coords[2], coords[3]);
+
+          while (*str == ',')
+            {
+              GtkSymbolicColor *color;
+              gdouble position;
+
+              if (*str != ',')
+                {
+                  *end_ptr = (gchar *) str;
+                  return gradient;
+                }
+
+              str++;
+              SKIP_SPACES (str);
+
+              if (g_str_has_prefix (str, "from"))
+                {
+                  position = 0;
+                  str += strlen ("from");
+                  SKIP_SPACES (str);
+
+                  if (*str != '(')
+                    {
+                      *end_ptr = (gchar *) str;
+                      return gradient;
+                    }
+                }
+              else if (g_str_has_prefix (str, "to"))
+                {
+                  position = 1;
+                  str += strlen ("to");
+                  SKIP_SPACES (str);
+
+                  if (*str != '(')
+                    {
+                      *end_ptr = (gchar *) str;
+                      return gradient;
+                    }
+                }
+              else if (g_str_has_prefix (str, "color-stop"))
+                {
+                  str += strlen ("color-stop");
+                  SKIP_SPACES (str);
+
+                  if (*str != '(')
+                    {
+                      *end_ptr = (gchar *) str;
+                      return gradient;
+                    }
+
+                  str++;
+                  SKIP_SPACES (str);
+
+                  position = g_strtod (str, &end);
+
+                  str = end;
+                  SKIP_SPACES (str);
+
+                  if (*str != ',')
+                    {
+                      *end_ptr = (gchar *) str;
+                      return gradient;
+                    }
+                }
+              else
+                {
+                  *end_ptr = (gchar *) str;
+                  return gradient;
+                }
+
+              str++;
+              SKIP_SPACES (str);
+
+              color = symbolic_color_parse_str (str, &end);
+
+              str = end;
+              SKIP_SPACES (str);
+
+              if (*str != ')')
+                {
+                  *end_ptr = (gchar *) str;
+                  return gradient;
+                }
+
+              str++;
+              SKIP_SPACES (str);
+
+              if (color)
+                {
+                  gtk_gradient_add_color_stop (gradient, position, color);
+                  gtk_symbolic_color_unref (color);
+                }
+            }
+
+          if (*str != ')')
+            {
+              *end_ptr = (gchar *) str;
+              return gradient;
+            }
+
+          str++;
+        }
+    }
+
+  *end_ptr = (gchar *) str;
+
+  return gradient;
+}
+
+static GtkGradient *
+gradient_parse (const gchar *str)
+{
+  GtkGradient *gradient;
+  gchar *end;
+
+  gradient = gradient_parse_str (str, &end);
+
+  if (*end != '\0')
+    {
+      g_warning ("Error parsing pattern \"%s\", stopped at char %ld : '%c'",
+                 str, end - str, *end);
+
+      if (gradient)
+        {
+          gtk_gradient_unref (gradient);
+          gradient = NULL;
+        }
+    }
+
+  return gradient;
+}
+
 static gboolean
 css_provider_parse_value (const gchar *value_str,
                           GValue      *value)
@@ -1440,6 +1667,21 @@ css_provider_parse_value (const gchar *value_str,
       if (parsed)
         g_value_set_boxed (value, &border);
     }
+  else if (type == GDK_TYPE_CAIRO_PATTERN)
+    {
+      GtkGradient *gradient;
+
+      gradient = gradient_parse (value_str);
+
+      if (gradient)
+        {
+          g_value_unset (value);
+          g_value_init (value, GTK_TYPE_GRADIENT);
+          g_value_take_boxed (value, gradient);
+        }
+      else
+        parsed = FALSE;
+    }
   else
     {
       g_warning ("Cannot parse string '%s' for type %s", value_str, g_type_name (type));



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