[monet/monet-xml] mn-config: simplify the markup parser



commit 204f4a1f8bc35d7ac871fb15a564ebbf69169d4a
Author: Thomas Wood <thos gnome org>
Date:   Sat Sep 4 22:17:30 2010 +0100

    mn-config: simplify the markup parser
    
    Move the state tracking into the private structure and remove the use of
    a sub-parser for widgets elements.

 monet/mn-config.c |  376 +++++++++++++++++++++++++++--------------------------
 1 files changed, 194 insertions(+), 182 deletions(-)
---
diff --git a/monet/mn-config.c b/monet/mn-config.c
index 22a2660..549b3ed 100644
--- a/monet/mn-config.c
+++ b/monet/mn-config.c
@@ -33,6 +33,10 @@ G_DEFINE_TYPE (MnConfig, mn_config, G_TYPE_OBJECT)
 struct _MnConfigPrivate
 {
   GHashTable *colors;
+
+  MnDrawingOps *current_ops;
+  MnDrawingOp *current_op;
+  cairo_pattern_t *current_pattern;
 };
 
 static void
@@ -139,210 +143,185 @@ perror (GMarkupParseContext *context,
   g_warning ("An error occured during parsing: %s", error->message);
 }
 
-typedef struct state
-{
-  MnDrawingOp *op;
-  cairo_pattern_t *gradient;
-} MnConfigState;
-
-static MnConfigState state;
-
 static void
-widget_start_element (GMarkupParseContext  *context,
-                      const gchar          *element_name,
-                      const gchar         **attribute_names,
-                      const gchar         **attribute_values,
-                      gpointer              user_data,
-                      GError              **error)
+add_pattern (MnConfig     *config,
+             const gchar **names,
+             const gchar **values,
+             gboolean      stroke)
 {
-  GSList **ops = (GSList **) user_data;
-  const gchar **attr_n;
-  int i;
+  MnConfigPrivate *priv = config->priv;
+  cairo_pattern_t *gradient;
+  double x_1, y_1, x_2, y_2;
+  gint i;
 
-  /* check for gradient defition */
-  if (!strcmp (element_name, "gradient")
-      || !strcmp (element_name, "stroke-gradient"))
+  if (!priv->current_op)
     {
-      MnDrawingOp *op = state.op;
-      cairo_pattern_t *gradient;
-      double x_1, y_1, x_2, y_2;
-
-      if (!op)
-        {
-          g_warning ("Gradient found outside of drawing operation");
-          return;
-        }
-
-      /* inspect the attributes */
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
-        {
-          if (!strcmp (*attr_n, "x1"))
-            x_1 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "y1"))
-            y_1 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "x2"))
-            x_2 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "y2"))
-            y_2 = g_ascii_strtod (attribute_values[i], NULL);
-        }
-
-      gradient = cairo_pattern_create_linear (x_1, y_1, x_2, y_2);
+      g_warning ("Gradient found outside of drawing operation");
+      return;
+    }
 
-      if (!strcmp (element_name, "stroke-gradient"))
-        {
-          if (op->stroke)
-            cairo_pattern_destroy (op->stroke);
+  /* inspect the attributes */
+  for (i = 0; names[i]; i++)
+    {
+      if (!strcmp (names[i], "x1"))
+        x_1 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "y1"))
+        y_1 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "x2"))
+        x_2 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "y2"))
+        y_2 = g_ascii_strtod (values[i], NULL);
+    }
 
-          op->stroke = gradient;
-        }
-      else
-        {
-          if (op->fill)
-            cairo_pattern_destroy (op->fill);
+  gradient = cairo_pattern_create_linear (x_1, y_1, x_2, y_2);
 
-          op->fill = gradient;
-        }
+  if (stroke)
+    {
+      if (priv->current_op->stroke)
+        cairo_pattern_destroy (priv->current_op->stroke);
 
-      state.gradient = gradient;
+      priv->current_op->stroke = gradient;
     }
-  else if (!strcmp (element_name, "stop"))
+  else
     {
-      double position;
-      MnColor color;
+      if (priv->current_op->fill)
+        cairo_pattern_destroy (priv->current_op->fill);
 
-      /* add the stop to the current gradient */
-      if (!state.gradient)
-        {
-          g_warning ("stop found outside gradient");
-          return;
-        }
+      priv->current_op->fill = gradient;
+    }
 
-      /* inspect the attributes */
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
-        {
-          if (!strcmp (*attr_n, "color"))
-            mn_color_from_string (&color, attribute_values[i]);
-          else if (!strcmp (*attr_n, "position"))
-            position = g_ascii_strtod (attribute_values[i], NULL);
-        }
+  config->priv->current_pattern = gradient;
+}
+
+static void
+pattern_add_stop (cairo_pattern_t  *pattern,
+                  const gchar     **names,
+                  const gchar     **values)
+{
+  double position;
+  MnColor color;
+  gint i;
 
-      cairo_pattern_add_color_stop_rgba (state.gradient,
-                                         position,
-                                         color.red / 255.0,
-                                         color.green / 255.0,
-                                         color.blue / 255.0,
-                                         color.alpha / 255.0);
+  /* add the stop to the current gradient */
+  if (!pattern)
+    {
+      g_warning ("stop found outside gradient");
+      return;
     }
 
-  else if (!strcmp (element_name, "rect"))
+  /* inspect the attributes */
+  for (i = 0; names[i]; i++)
     {
-      MnRectangleOp *op = g_slice_new0 (MnRectangleOp);
-      ((MnDrawingOp*)op)->type = MN_RECT;
+      if (!strcmp (names[i], "color"))
+        mn_color_from_string (&color, values[i]);
+      else if (!strcmp (names[i], "position"))
+        position = g_ascii_strtod (values[i], NULL);
+    }
 
-      state.op = (MnDrawingOp*) op;
+  cairo_pattern_add_color_stop_rgba (pattern,
+                                     position,
+                                     color.red / 255.0,
+                                     color.green / 255.0,
+                                     color.blue / 255.0,
+                                     color.alpha / 255.0);
+}
 
-      /* inspect the attributes */
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
-        {
-          if (!strcmp (*attr_n, "x"))
-            op->x = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "y"))
-            op->y = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "width"))
-            op->width = g_strdup (attribute_values[i]);
-          else if (!strcmp (*attr_n, "height"))
-            op->height = g_strdup (attribute_values[i]);
-          else if (!strcmp (*attr_n, "stroke"))
-            ((MnDrawingOp*) op)->stroke = cairo_pattern_from_paint (attribute_values[i]);
-          else if (!strcmp (*attr_n, "stroke-width"))
-            ((MnDrawingOp*) op)->stroke_width = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "fill"))
-            ((MnDrawingOp*)op)->fill = cairo_pattern_from_paint (attribute_values[i]);
-          else if (!strcmp (*attr_n, "corner-radius"))
-            op->radius = g_ascii_strtod (attribute_values[i], NULL);
-        }
+static void
+add_rect (MnConfig     *config,
+          const gchar **names,
+          const gchar **values)
+{
+  MnRectangleOp *op = g_slice_new0 (MnRectangleOp);
+  gint i;
 
-      *ops = g_slist_append (*ops, op);
-    }
-  else if (!strcmp (element_name, "line"))
-    {
-      MnLineOp *op = g_slice_new0 (MnLineOp);
-      ((MnDrawingOp*)op)->type = MN_LINE;
+  ((MnDrawingOp*)op)->type = MN_RECT;
 
-      state.op = (MnDrawingOp*) op;
+  /* inspect the attributes */
+  for (i = 0; names[i]; i++)
+    {
+      if (!strcmp (names[i], "x"))
+        op->x = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "y"))
+        op->y = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "width"))
+        op->width = g_strdup (values[i]);
+      else if (!strcmp (names[i], "height"))
+        op->height = g_strdup (values[i]);
+      else if (!strcmp (names[i], "stroke"))
+        ((MnDrawingOp*) op)->stroke = cairo_pattern_from_paint (values[i]);
+      else if (!strcmp (names[i], "stroke-width"))
+        ((MnDrawingOp*) op)->stroke_width = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "fill"))
+        ((MnDrawingOp*)op)->fill = cairo_pattern_from_paint (values[i]);
+      else if (!strcmp (names[i], "corner-radius"))
+        op->radius = g_ascii_strtod (values[i], NULL);
+    }
 
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
-        {
-          if (!strcmp (*attr_n, "x1"))
-            op->x1 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "y1"))
-            op->y1 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "x2"))
-            op->x2 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "y2"))
-            op->y2 = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "stroke"))
-            ((MnDrawingOp *) op)->stroke = cairo_pattern_from_paint (attribute_values[i]);
-          else if (!strcmp (*attr_n, "stroke-width"))
-            ((MnDrawingOp *) op)->stroke_width = g_ascii_strtod (attribute_values[i], NULL);
-        }
+  config->priv->current_ops->ops = g_slist_append (config->priv->current_ops->ops,
+                                                   op);
+  config->priv->current_op = (MnDrawingOp*) op;
+}
 
-      *ops = g_slist_append (*ops, op);
-    }
-  else if (!strcmp (element_name, "circle"))
-    {
-      MnCircleOp *op = g_slice_new0 (MnCircleOp);
-      ((MnDrawingOp*)op)->type = MN_CIRCLE;
+static void
+add_line (MnConfig     *config,
+          const gchar **names,
+          const gchar **values)
+{
+  MnLineOp *op = g_slice_new0 (MnLineOp);
+  gint i;
 
-      state.op = (MnDrawingOp *) op;
+  ((MnDrawingOp*)op)->type = MN_LINE;
 
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
-        {
-          if (!strcmp (*attr_n, "cx"))
-            op->x = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "cy"))
-            op->y = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "r"))
-            op->radius = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "stroke"))
-            ((MnDrawingOp*) op)->stroke = cairo_pattern_from_paint (attribute_values[i]);
-          else if (!strcmp (*attr_n, "stroke-width"))
-            ((MnDrawingOp *) op)->stroke_width = g_ascii_strtod (attribute_values[i], NULL);
-          else if (!strcmp (*attr_n, "fill"))
-            ((MnDrawingOp *) op)->fill = cairo_pattern_from_paint (attribute_values[i]);
-        }
 
-      *ops = g_slist_append (*ops, op);
+  for (i = 0; names[i]; i++)
+    {
+      if (!strcmp (names[i], "x1"))
+        op->x1 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "y1"))
+        op->y1 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "x2"))
+        op->x2 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "y2"))
+        op->y2 = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "stroke"))
+        ((MnDrawingOp *) op)->stroke = cairo_pattern_from_paint (values[i]);
+      else if (!strcmp (names[i], "stroke-width"))
+        ((MnDrawingOp *) op)->stroke_width = g_ascii_strtod (values[i], NULL);
     }
+
+  config->priv->current_op = (MnDrawingOp*) op;
+  config->priv->current_ops->ops = g_slist_append (config->priv->current_ops->ops, op);
 }
 
 static void
-widget_end_element (GMarkupParseContext  *context,
-                    const gchar          *element_name,
-                    gpointer              user_data,
-                    GError              **error)
+add_circle (MnConfig *config,
+            const gchar **names,
+            const gchar **values)
 {
-  /* update state */
-  if (!strcmp (element_name, "gradient"))
-    {
-      state.gradient = NULL;
-    }
-  else if (!strcmp (element_name, "rect"))
-    {
-      state.op = NULL;
-    }
-  else if (!strcmp (element_name, "line"))
-    {
-      state.op = NULL;
-    }
-  else if (!strcmp (element_name, "circle"))
+  MnCircleOp *op = g_slice_new0 (MnCircleOp);
+  gint i;
+
+  ((MnDrawingOp*)op)->type = MN_CIRCLE;
+
+  for (i = 0; names[i]; i++)
     {
-      state.op = NULL;
+      if (!strcmp (names[i], "cx"))
+        op->x = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "cy"))
+        op->y = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "r"))
+        op->radius = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "stroke"))
+        ((MnDrawingOp*) op)->stroke = cairo_pattern_from_paint (values[i]);
+      else if (!strcmp (names[i], "stroke-width"))
+        ((MnDrawingOp *) op)->stroke_width = g_ascii_strtod (values[i], NULL);
+      else if (!strcmp (names[i], "fill"))
+        ((MnDrawingOp *) op)->fill = cairo_pattern_from_paint (values[i]);
     }
-}
 
-static GMarkupParser widget_parser = { widget_start_element, widget_end_element, NULL,
-    NULL, perror };
+  config->priv->current_op = (MnDrawingOp*) op;
+  config->priv->current_ops->ops = g_slist_append (config->priv->current_ops->ops, op);
+}
 
 static MnState
 monet_state_from_string (const gchar *string)
@@ -388,10 +367,10 @@ monet_start_element (GMarkupParseContext  *context,
                      gpointer              user_data,
                      GError              **error)
 {
+  MnConfig *config = (MnConfig *) user_data;
+  MnConfigPrivate *priv = config->priv;
   GError *err = NULL;
-  const gchar **attr_n;
   gint i, widget;
-  MnConfig *config = (MnConfig *) user_data;
 
   if (!strcmp (element_name, "monet"))
     {
@@ -402,7 +381,6 @@ monet_start_element (GMarkupParseContext  *context,
   if (!strcmp (element_name, "widget"))
     {
       const gchar *type = NULL;
-      gpointer ops_list;
       MnDrawingOps *ops;
       MnState wstate;
       MnFlags wflags;
@@ -411,15 +389,15 @@ monet_start_element (GMarkupParseContext  *context,
       wflags = 0;
 
       /* inspect the attributes */
-      for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
+      for (i = 0; attribute_names[i]; i++)
         {
-          if (!strcmp (*attr_n, "type"))
+          if (!strcmp (attribute_names[i], "type"))
             type = attribute_values[i];
 
-          else if (!strcmp (*attr_n, "state"))
+          else if (!strcmp (attribute_names[i], "state"))
             wstate = monet_state_from_string (attribute_values[i]);
 
-          else if (!strcmp (*attr_n, "flags"))
+          else if (!strcmp (attribute_names[i], "flags"))
             wflags = monet_flags_from_string (attribute_values[i]);
         }
 
@@ -452,12 +430,24 @@ monet_start_element (GMarkupParseContext  *context,
       ops = g_new0 (MnDrawingOps, 1);
       ops->flags = wflags;
 
-      config->widget_ops[widget][wstate] = g_slist_prepend (config->widget_ops[widget][wstate], ops);
+      priv->current_ops = ops;
 
-      ops_list = &ops->ops;
+      config->widget_ops[widget][wstate] =
+        g_slist_prepend (config->widget_ops[widget][wstate], ops);
 
-      g_markup_parse_context_push (context, &widget_parser, ops_list);
     }
+  else if (!strcmp (element_name, "gradient"))
+    add_pattern (config, attribute_names, attribute_values, FALSE);
+  else if (!strcmp (element_name, "stroke-gradient"))
+    add_pattern (config, attribute_names, attribute_values, TRUE);
+  else if (!strcmp (element_name, "stop"))
+    pattern_add_stop (priv->current_pattern, attribute_names, attribute_values);
+  else if (!strcmp (element_name, "rect"))
+    add_rect (config, attribute_names, attribute_values);
+  else if (!strcmp (element_name, "line"))
+    add_line (config, attribute_names, attribute_values);
+  else if (!strcmp (element_name, "circle"))
+    add_circle (config, attribute_names, attribute_names);
 }
 
 static void
@@ -466,9 +456,31 @@ monet_end_element (GMarkupParseContext  *context,
                    gpointer              user_data,
                    GError              **error)
 {
+  MnConfig *config = (MnConfig *) user_data;
+  MnConfigPrivate *priv = config->priv;
+
+  /* clear state */
   if (!strcmp ("widget", element_name))
     {
-      g_markup_parse_context_pop (context);
+      priv->current_ops = NULL;
+      priv->current_op = NULL;
+      priv->current_pattern = NULL;
+    }
+  else if (!strcmp (element_name, "gradient"))
+    {
+      priv->current_pattern = NULL;
+    }
+  else if (!strcmp (element_name, "rect"))
+    {
+      priv->current_op = NULL;
+    }
+  else if (!strcmp (element_name, "line"))
+    {
+      priv->current_op = NULL;
+    }
+  else if (!strcmp (element_name, "circle"))
+    {
+      priv->current_op = NULL;
     }
 }
 



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