[monet/monet-xml] Add support for linear gradients



commit 59db9876fcc8dda377e1180d1886d8a338afc090
Author: Thomas Wood <thomas wood intel com>
Date:   Wed May 5 11:51:24 2010 +0100

    Add support for linear gradients

 monet-gtk/monet.xml |    8 +++-
 monet/mn-config.c   |  114 +++++++++++++++++++++++++++++++++++++++++++++++----
 monet/mn-config.h   |    3 +-
 monet/mn-style.c    |   22 +++++++---
 4 files changed, 129 insertions(+), 18 deletions(-)
---
diff --git a/monet-gtk/monet.xml b/monet-gtk/monet.xml
index f86e4e9..6982d1e 100644
--- a/monet-gtk/monet.xml
+++ b/monet-gtk/monet.xml
@@ -1,8 +1,14 @@
 <monet>
 <widget type="button">
-  <rect x="0.5" y="0.5" width="-1" height="-1" stroke-width="1" stroke="#aaa"></rect>
+  <rect x="0.5" y="0.5" width="-1" height="-1" stroke-width="1" stroke="#988c7c">
+    <gradient x1="0" y1="0" x2="0" y1="50">
+      <stop color="#fcfbfa" position="1"/>
+      <stop color="#e7e2da" position="0"/>
+    </gradient>
+  </rect>
   <rect x="1.5" y="1.5" width="-3" height="-3" stroke-width="1" stroke="#fff"></rect>
 </widget>
+
 <widget type="entry">
   <line x1="0.5" y1="0.5" y2="-0.5" x1="0.5" stroke="#999" stroke-width="1"/>
   <line x1="0.5" y1="0.5" y2="0.5" x1="-0.5" stroke="#999" stroke-width="1"/>
diff --git a/monet/mn-config.c b/monet/mn-config.c
index b241c03..0167077 100644
--- a/monet/mn-config.c
+++ b/monet/mn-config.c
@@ -49,6 +49,13 @@ 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,
@@ -62,11 +69,73 @@ widget_start_element (GMarkupParseContext  *context,
   const gchar **attr_n;
   int i;
 
-  if (!strcmp (element_name, "rect"))
+  /* check for gradient defition */
+  if (!strcmp (element_name, "gradient"))
+    {
+      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);
+
+      state.gradient = gradient;
+      op->fill = gradient;
+    }
+  else if (!strcmp (element_name, "stop"))
+    {
+      double position;
+      MnColor color;
+
+      /* add the stop to the current gradient */
+      if (!state.gradient)
+        {
+          g_warning ("stop found outside gradient");
+          return;
+        }
+
+      /* 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);
+        }
+
+      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);
+    }
+
+  else if (!strcmp (element_name, "rect"))
     {
-      MnRectangleOp *op = g_slice_new (MnRectangleOp);
+      MnRectangleOp *op = g_slice_new0 (MnRectangleOp);
       ((MnDrawingOp*)op)->type = MN_RECT;
 
+      state.op = (MnDrawingOp*) op;
+
       /* inspect the attributes */
       for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
         {
@@ -83,16 +152,18 @@ widget_start_element (GMarkupParseContext  *context,
           else if (!strcmp (*attr_n, "stroke-width"))
             ((MnDrawingOp*) op)->stroke_width = g_ascii_strtod (attribute_values[i], NULL);
           else if (!strcmp (*attr_n, "fill"))
-            op->fill = cairo_pattern_from_paint (attribute_values[i]);
+            ((MnDrawingOp*)op)->fill = cairo_pattern_from_paint (attribute_values[i]);
         }
 
       *ops = g_slist_append (*ops, op);
     }
   else if (!strcmp (element_name, "line"))
     {
-      MnLineOp *op = g_slice_new (MnLineOp);
+      MnLineOp *op = g_slice_new0 (MnLineOp);
       ((MnDrawingOp*)op)->type = MN_LINE;
 
+      state.op = (MnDrawingOp*) op;
+
       for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
         {
           if (!strcmp (*attr_n, "x1"))
@@ -113,9 +184,11 @@ widget_start_element (GMarkupParseContext  *context,
     }
   else if (!strcmp (element_name, "circle"))
     {
-      MnCircleOp *op = g_slice_new (MnCircleOp);
+      MnCircleOp *op = g_slice_new0 (MnCircleOp);
       ((MnDrawingOp*)op)->type = MN_CIRCLE;
 
+      state.op = (MnDrawingOp *) op;
+
       for (attr_n = attribute_names, i = 0; *attr_n; attr_n++, i++)
         {
           if (!strcmp (*attr_n, "cx"))
@@ -127,16 +200,41 @@ widget_start_element (GMarkupParseContext  *context,
           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);
+            ((MnDrawingOp *) op)->stroke_width = g_ascii_strtod (attribute_values[i], NULL);
           else if (!strcmp (*attr_n, "fill"))
-            op->fill = cairo_pattern_from_paint (attribute_values[i]);
+            ((MnDrawingOp *) op)->fill = cairo_pattern_from_paint (attribute_values[i]);
         }
 
       *ops = g_slist_append (*ops, op);
     }
 }
 
-static GMarkupParser widget_parser = { widget_start_element, NULL, NULL,
+static void
+widget_end_element (GMarkupParseContext  *context,
+                    const gchar          *element_name,
+                    gpointer              user_data,
+                    GError              **error)
+{
+  /* 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"))
+    {
+      state.op = NULL;
+    }
+}
+
+static GMarkupParser widget_parser = { widget_start_element, widget_end_element, NULL,
     NULL, perror };
 
 static void
diff --git a/monet/mn-config.h b/monet/mn-config.h
index 42b447c..008a9b8 100644
--- a/monet/mn-config.h
+++ b/monet/mn-config.h
@@ -45,6 +45,7 @@ typedef struct
 {
   MnDrawingOpType type;
   cairo_pattern_t *stroke;
+  cairo_pattern_t *fill;
   double stroke_width;
 } MnDrawingOp;
 
@@ -52,7 +53,6 @@ typedef struct
 {
   MnDrawingOp op;
 
-  cairo_pattern_t *fill;
   double x;
   double y;
   double width;
@@ -63,7 +63,6 @@ typedef struct
 {
   MnDrawingOp op;
 
-  cairo_pattern_t *fill;
   double x;
   double y;
   double radius;
diff --git a/monet/mn-style.c b/monet/mn-style.c
index 877a368..ade90aa 100644
--- a/monet/mn-style.c
+++ b/monet/mn-style.c
@@ -136,6 +136,9 @@ mn_style_draw_ops (MnStyle   *style,
 {
   GSList *o;
 
+  /* translate to ensure pattern is in the correct position */
+  cairo_translate (cr, x, y);
+
   for (o = ops; o; o = g_slist_next (o))
     {
       MnDrawingOp *op = (MnDrawingOp *) o->data;
@@ -147,8 +150,6 @@ mn_style_draw_ops (MnStyle   *style,
 
       /* set generic options */
       cairo_set_line_width (cr, op->stroke_width);
-      if (op->stroke)
-        cairo_set_source (cr, op->stroke);
 
       switch (op->type)
         {
@@ -165,8 +166,7 @@ mn_style_draw_ops (MnStyle   *style,
           else
             h = rect->height;
 
-          cairo_rectangle (cr, x + rect->x, y + rect->y, w, h);
-          cairo_stroke (cr);
+          cairo_rectangle (cr, rect->x, rect->y, w, h);
           break;
 
         case MN_CIRCLE:
@@ -176,8 +176,6 @@ mn_style_draw_ops (MnStyle   *style,
           y_1 = (circle->y < 0) ? height + circle->y : circle->y;
 
           cairo_arc (cr, x_1, y_1, circle->radius, 0, M_PI * 360);
-
-          cairo_stroke (cr);
           break;
 
         case MN_LINE:
@@ -190,9 +188,19 @@ mn_style_draw_ops (MnStyle   *style,
 
           cairo_move_to (cr, x_1, y_1);
           cairo_line_to (cr, x_2, y_2);
-          cairo_stroke (cr);
           break;
         }
+
+      /* fill */
+      if (op->fill)
+        {
+          cairo_set_source (cr, op->fill);
+          cairo_fill_preserve (cr);
+        }
+
+      if (op->stroke)
+        cairo_set_source (cr, op->stroke);
+      cairo_stroke (cr);
     }
 }
 



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