[monet/monet-xml] Add support for linear gradients
- From: Thomas Wood <thos src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [monet/monet-xml] Add support for linear gradients
- Date: Sun, 9 May 2010 17:34:46 +0000 (UTC)
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]