[evolution] gnome-canvas: Rewrite GnomeCanvasShape to use Cairo



commit 24e39b9fb54cad437cc12b24e953be890519d86a
Author: Benjamin Otte <otte redhat com>
Date:   Fri Oct 15 01:25:40 2010 +0200

    gnome-canvas: Rewrite GnomeCanvasShape to use Cairo
    
    Dashing properties were commented out in the process. They are not used
    inside Evolution.

 libgnomecanvas/gnome-canvas-rect.c          |   34 +-
 libgnomecanvas/gnome-canvas-rect.h          |    2 -
 libgnomecanvas/gnome-canvas-shape-private.h |   67 +--
 libgnomecanvas/gnome-canvas-shape.c         | 1070 +++++----------------------
 libgnomecanvas/gnome-canvas-shape.h         |   12 +-
 libgnomecanvas/gnome-canvas.c               |   90 +++-
 libgnomecanvas/gnome-canvas.h               |    4 +
 7 files changed, 293 insertions(+), 986 deletions(-)
---
diff --git a/libgnomecanvas/gnome-canvas-rect.c b/libgnomecanvas/gnome-canvas-rect.c
index 6e347e3..013ce08 100644
--- a/libgnomecanvas/gnome-canvas-rect.c
+++ b/libgnomecanvas/gnome-canvas-rect.c
@@ -38,11 +38,6 @@
 #include "gnome-canvas-util.h"
 #include "gnome-canvas-shape.h"
 
-#include <libart_lgpl/art_vpath.h>
-#include <libart_lgpl/art_svp.h>
-#include <libart_lgpl/art_svp_vpath.h>
-#include <libart_lgpl/art_rgb_svp.h>
-
 /* Base class for rectangle and ellipse item types */
 
 #define noVERBOSE
@@ -204,22 +199,23 @@ gnome_canvas_rect_get_property (GObject              *object,
 static void
 gnome_canvas_rect_update (GnomeCanvasItem *item, gdouble affine[6], ArtSVP *clip_path, gint flags)
 {
-        GnomeCanvasRect *rect;
-	GnomeCanvasPathDef *path_def;
-
-	rect = GNOME_CANVAS_RECT (item);
+        GnomeCanvasRect *rect = GNOME_CANVAS_RECT (item);
 
 	if (rect->path_dirty) {
-		path_def = gnome_canvas_path_def_new ();
-
-		gnome_canvas_path_def_moveto (path_def, rect->x1, rect->y1);
-		gnome_canvas_path_def_lineto (path_def, rect->x2, rect->y1);
-		gnome_canvas_path_def_lineto (path_def, rect->x2, rect->y2);
-		gnome_canvas_path_def_lineto (path_def, rect->x1, rect->y2);
-		gnome_canvas_path_def_lineto (path_def, rect->x1, rect->y1);
-		gnome_canvas_path_def_closepath_current (path_def);
-		gnome_canvas_shape_set_path_def (GNOME_CANVAS_SHAPE (item), path_def);
-		gnome_canvas_path_def_unref (path_def);
+                cairo_t *cr;
+
+                cr = gnome_canvas_cairo_create_scratch ();
+
+                cairo_rectangle (cr,
+                                 rect->x1, rect->y1,
+                                 rect->x2 - rect->x1,
+                                 rect->y2 - rect->y1);
+
+		gnome_canvas_shape_set_path (GNOME_CANVAS_SHAPE (item),
+                                             cairo_copy_path (cr));
+                
+                cairo_destroy (cr);
+
 		rect->path_dirty = 0;
 	}
 
diff --git a/libgnomecanvas/gnome-canvas-rect.h b/libgnomecanvas/gnome-canvas-rect.h
index 1a161ee..fd99465 100644
--- a/libgnomecanvas/gnome-canvas-rect.h
+++ b/libgnomecanvas/gnome-canvas-rect.h
@@ -38,8 +38,6 @@
 
 #include <libgnomecanvas/gnome-canvas-shape.h>
 
-#include <libart_lgpl/art_svp.h>
-
 G_BEGIN_DECLS
 
 /* Rectangle item.  These are defined by their top-left and bottom-right corners.
diff --git a/libgnomecanvas/gnome-canvas-shape-private.h b/libgnomecanvas/gnome-canvas-shape-private.h
index fb4637c..4be04f6 100644
--- a/libgnomecanvas/gnome-canvas-shape-private.h
+++ b/libgnomecanvas/gnome-canvas-shape-private.h
@@ -14,62 +14,12 @@
  */
 
 #include <gdk/gdk.h>
-#include <libart_lgpl/art_vpath.h>
-#include <libart_lgpl/art_svp.h>
-#include <libart_lgpl/art_vpath_dash.h>
-#include <libart_lgpl/art_svp_wind.h>
 #include <libgnomecanvas/gnome-canvas.h>
 
-#include <libgnomecanvas/gnome-canvas-path-def.h>
-
 G_BEGIN_DECLS
 
-typedef struct _GnomeCanvasShapePrivGdk GnomeCanvasShapePrivGdk;
-typedef struct _GCBPDrawCtx GCBPDrawCtx;
-
-/* Per canvas private structure, holding necessary data for rendering
- * temporary masks, which are needed for drawing multipart bpaths.
- * As canvas cannot multithread, we can be sure, that masks are used
- * serially, also one set of masks per canvas is sufficent to guarantee,
- * that masks are created on needed X server. Masks grow as needed.
- * Full structure is refcounted in Bpath implementation
- */
-
-struct _GCBPDrawCtx {
-	gint refcount;
-
-	GnomeCanvas * canvas;
-
-	gint width;
-	gint height;
-
-	GdkBitmap * mask;
-	GdkBitmap * clip;
-
-	GdkGC * clear_gc;
-	GdkGC * xor_gc;
-};
-
-/* Per Bpath private structure, holding Gdk specific data */
-
-struct _GnomeCanvasShapePrivGdk {
-	gulong fill_pixel;		/* Color for fill */
-	gulong outline_pixel;		/* Color for outline */
-
-	GdkGC * fill_gc;		/* GC for filling */
-	GdkGC * outline_gc;		/* GC for outline */
-
-	gint len_points;		/* Size of allocated points array */
-	gint num_points;		/* Gdk points in canvas coords */
-	GdkPoint * points;		/* Ivariant: closed paths are before open ones */
-	GSList * closed_paths;		/* List of lengths */
-	GSList * open_paths;		/* List of lengths */
-
-	GCBPDrawCtx * ctx;		/* Pointer to per-canvas drawing context */
-};
-
 struct _GnomeCanvasShapePriv {
-	GnomeCanvasPathDef * path;      /* Our bezier path representation */
+	cairo_path_t *path;             /* Our bezier path representation */
 
 	gdouble scale;			/* CTM scaling (for pen) */
 
@@ -81,17 +31,14 @@ struct _GnomeCanvasShapePriv {
 	guint32 fill_rgba;		/* Fill color, RGBA */
 	guint32 outline_rgba;		/* Outline color, RGBA */
 
-	GdkCapStyle cap;		/* Cap style for line */
-	GdkJoinStyle join;		/* Join style for line */
-	ArtWindRule wind;		/* Winding rule */
+	cairo_line_cap_t cap;		/* Cap style for line */
+	cairo_line_join_t join;		/* Join style for line */
+	cairo_fill_rule_t wind;		/* Winding rule */
 	gdouble miterlimit;		/* Miter limit */
 
-	ArtVpathDash dash;		/* Dashing pattern */
-
-	ArtSVP * fill_svp;		/* The SVP for the filled shape */
-	ArtSVP * outline_svp;		/* The SVP for the outline shape */
-
-	GnomeCanvasShapePrivGdk * gdk;	/* Gdk specific things */
+        guint n_dash;                   /* Number of elements in dashing pattern */
+	double *dash;     		/* Dashing pattern */
+        double dash_offset;             /* Dashing offset */
 };
 
 G_END_DECLS
diff --git a/libgnomecanvas/gnome-canvas-shape.c b/libgnomecanvas/gnome-canvas-shape.c
index e033add..f99b10b 100644
--- a/libgnomecanvas/gnome-canvas-shape.c
+++ b/libgnomecanvas/gnome-canvas-shape.c
@@ -22,24 +22,12 @@
 #include <string.h>
 
 #include <gtk/gtk.h>
+#include <cairo-gobject.h>
 #include "gnome-canvas.h"
 #include "gnome-canvas-util.h"
 
 #include "gnome-canvas-shape.h"
 #include "gnome-canvas-shape-private.h"
-#include "gnome-canvas-path-def.h"
-
-#include <libart_lgpl/art_rect.h>
-#include <libart_lgpl/art_vpath.h>
-#include <libart_lgpl/art_bpath.h>
-#include <libart_lgpl/art_vpath_bpath.h>
-#include <libart_lgpl/art_svp.h>
-#include <libart_lgpl/art_svp_point.h>
-#include <libart_lgpl/art_svp_vpath.h>
-#include <libart_lgpl/art_vpath_dash.h>
-#include <libart_lgpl/art_svp_wind.h>
-#include <libart_lgpl/art_svp_intersect.h>
-#include <libart_lgpl/art_rect_svp.h>
 
 enum {
 	PROP_0,
@@ -68,8 +56,6 @@ static void gnome_canvas_shape_get_property (GObject               *object,
                                              GParamSpec            *pspec);
 
 static void   gnome_canvas_shape_update      (GnomeCanvasItem *item, gdouble *affine, ArtSVP *clip_path, gint flags);
-static void   gnome_canvas_shape_realize     (GnomeCanvasItem *item);
-static void   gnome_canvas_shape_unrealize   (GnomeCanvasItem *item);
 static void   gnome_canvas_shape_draw        (GnomeCanvasItem *item, GdkDrawable *drawable,
                                               gint x, gint y, gint width, gint height);
 static GnomeCanvasItem *gnome_canvas_shape_point (GnomeCanvasItem *item, gdouble x, gdouble y,
@@ -77,14 +63,6 @@ static GnomeCanvasItem *gnome_canvas_shape_point (GnomeCanvasItem *item, gdouble
 static void   gnome_canvas_shape_bounds      (GnomeCanvasItem *item,
 					      gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2);
 
-static gulong get_pixel_from_rgba (GnomeCanvasItem *item, guint32 rgba_color);
-static guint32 get_rgba_from_color (GdkColor * color);
-static void set_gc_foreground (GdkGC *gc, gulong pixel);
-static void gcbp_ensure_gdk (GnomeCanvasShape * bpath);
-static void gcbp_destroy_gdk (GnomeCanvasShape * bpath);
-static void gcbp_ensure_mask (GnomeCanvasShape * bpath, gint width, gint height);
-static void gcbp_draw_ctx_unref (GCBPDrawCtx * ctx);
-
 G_DEFINE_TYPE (GnomeCanvasShape, gnome_canvas_shape, GNOME_TYPE_CANVAS_ITEM)
 
 static void
@@ -96,10 +74,6 @@ gnome_canvas_shape_class_init (GnomeCanvasShapeClass *class)
 	gobject_class = (GObjectClass *) class;
 	item_class = (GnomeCanvasItemClass *) class;
 
-	/* when this gets checked into libgnomeui, change the
-           GTK_TYPE_POINTER to GTK_TYPE_GNOME_CANVAS_SHAPE, and add an
-           entry to gnome-boxed.defs */
-
 	gobject_class->set_property = gnome_canvas_shape_set_property;
 	gobject_class->get_property = gnome_canvas_shape_get_property;
 
@@ -112,10 +86,10 @@ gnome_canvas_shape_class_init (GnomeCanvasShapeClass *class)
                                          PROP_FILL_COLOR_GDK,
                                          g_param_spec_boxed ("fill_color_gdk", NULL, NULL,
                                                              GDK_TYPE_COLOR,
-                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+                                                             G_PARAM_WRITABLE));
         g_object_class_install_property (gobject_class,
                                          PROP_FILL_COLOR_RGBA,
-                                         g_param_spec_uint ("fill_color_rgba", NULL, NULL,
+                                         g_param_spec_uint ("fill_rgba", NULL, NULL,
                                                             0, G_MAXUINT, 0,
                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (gobject_class,
@@ -127,10 +101,10 @@ gnome_canvas_shape_class_init (GnomeCanvasShapeClass *class)
                                          PROP_OUTLINE_COLOR_GDK,
                                          g_param_spec_boxed ("outline_color_gdk", NULL, NULL,
                                                              GDK_TYPE_COLOR,
-                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+                                                             G_PARAM_WRITABLE));
         g_object_class_install_property (gobject_class,
                                          PROP_OUTLINE_COLOR_RGBA,
-                                         g_param_spec_uint ("outline_color_rgba", NULL, NULL,
+                                         g_param_spec_uint ("outline_rgba", NULL, NULL,
                                                             0, G_MAXUINT, 0,
                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (gobject_class,
@@ -141,34 +115,36 @@ gnome_canvas_shape_class_init (GnomeCanvasShapeClass *class)
         g_object_class_install_property (gobject_class,
                                          PROP_CAP_STYLE,
                                          g_param_spec_enum ("cap_style", NULL, NULL,
-                                                            GDK_TYPE_CAP_STYLE,
-                                                            GDK_CAP_BUTT,
+                                                            CAIRO_GOBJECT_TYPE_LINE_CAP,
+                                                            CAIRO_LINE_CAP_BUTT,
                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (gobject_class,
                                          PROP_JOIN_STYLE,
                                          g_param_spec_enum ("join_style", NULL, NULL,
-                                                            GDK_TYPE_JOIN_STYLE,
-                                                            GDK_JOIN_MITER,
+                                                            CAIRO_GOBJECT_TYPE_LINE_JOIN,
+                                                            CAIRO_LINE_JOIN_MITER,
                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (gobject_class,
                                          PROP_WIND,
-                                         g_param_spec_uint ("wind", NULL, NULL,
-                                                            0, G_MAXUINT, 0,
+                                         g_param_spec_enum ("wind", NULL, NULL,
+                                                            CAIRO_GOBJECT_TYPE_FILL_RULE,
+                                                            CAIRO_FILL_RULE_EVEN_ODD,
                                                             (G_PARAM_READABLE | G_PARAM_WRITABLE)));
         g_object_class_install_property (gobject_class,
                                          PROP_MITERLIMIT,
                                          g_param_spec_double ("miterlimit", NULL, NULL,
-                                                              0.0, G_MAXDOUBLE, 0.0,
+                                                              0.0, G_MAXDOUBLE, 10.43,
                                                               (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+#if 0
+        /* XXX: Find a good way to pass dash properties in a property */
         g_object_class_install_property (gobject_class,
                                          PROP_DASH,
                                          g_param_spec_pointer ("dash", NULL, NULL,
                                                                (G_PARAM_READABLE | G_PARAM_WRITABLE)));
+#endif
 
 	item_class->destroy = gnome_canvas_shape_destroy;
 	item_class->update = gnome_canvas_shape_update;
-	item_class->realize = gnome_canvas_shape_realize;
-	item_class->unrealize = gnome_canvas_shape_unrealize;
 	item_class->draw = gnome_canvas_shape_draw;
 	item_class->point = gnome_canvas_shape_point;
 	item_class->bounds = gnome_canvas_shape_bounds;
@@ -195,18 +171,13 @@ gnome_canvas_shape_init (GnomeCanvasShape *shape)
 	shape->priv->fill_rgba = 0x0000003f;
 	shape->priv->outline_rgba = 0x0000007f;
 
-	shape->priv->cap = GDK_CAP_BUTT;
-	shape->priv->join = GDK_JOIN_MITER;
-	shape->priv->wind = ART_WIND_RULE_ODDEVEN;
+	shape->priv->cap = CAIRO_LINE_CAP_BUTT;
+	shape->priv->join = CAIRO_LINE_JOIN_MITER;
+	shape->priv->wind = CAIRO_FILL_RULE_EVEN_ODD;
 	shape->priv->miterlimit = 10.43;	   /* X11 default */
 
-	shape->priv->dash.n_dash = 0;
-	shape->priv->dash.dash = NULL;
-
-	shape->priv->fill_svp = NULL;
-	shape->priv->outline_svp = NULL;
-
-	shape->priv->gdk = NULL;
+	shape->priv->n_dash = 0;
+	shape->priv->dash = NULL;
 }
 
 static void
@@ -221,31 +192,25 @@ gnome_canvas_shape_destroy (GnomeCanvasItem *object)
         shape = GNOME_CANVAS_SHAPE (object);
 
         priv = shape->priv;
-        if (priv->gdk) gcbp_destroy_gdk (shape);
+        if (priv->path) cairo_path_destroy (priv->path);
 
-        if (priv->path) gnome_canvas_path_def_unref (priv->path);
-
-        if (priv->dash.dash) g_free (priv->dash.dash);
-        if (priv->fill_svp) art_svp_free (priv->fill_svp);
-        if (priv->outline_svp) art_svp_free (priv->outline_svp);
+        g_free (priv->dash);
 
 	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->destroy)
 		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->destroy (object);
 }
 
 /**
- * gnome_canvas_shape_set_path_def:
+ * gnome_canvas_shape_set_path:
  * @shape: a GnomeCanvasShape
- * @def: a GnomeCanvasPathDef
+ * @path: a cairo path from a cairo_copy_path() call
  *
- * This function sets the the GnomeCanvasPathDef used by the
- * GnomeCanvasShape. Notice, that it does not request updates, as
- * it is meant to be used from item implementations, from inside
- * update queue.
+ * This function sets the the path used by the GnomeCanvasShape.
+ * Notice that it does not request updates, as it is meant to be used
+ * from item implementations, from inside update queue.
  */
-
 void
-gnome_canvas_shape_set_path_def (GnomeCanvasShape *shape, GnomeCanvasPathDef *def)
+gnome_canvas_shape_set_path (GnomeCanvasShape *shape, cairo_path_t *path)
 {
 	GnomeCanvasShapePriv *priv;
 
@@ -255,13 +220,15 @@ gnome_canvas_shape_set_path_def (GnomeCanvasShape *shape, GnomeCanvasPathDef *de
 	priv = shape->priv;
 
 	if (priv->path) {
-		gnome_canvas_path_def_unref (priv->path);
+		cairo_path_destroy (priv->path);
 		priv->path = NULL;
 	}
+}
 
-	if (def) {
-		priv->path = gnome_canvas_path_def_duplicate (def);
-	}
+static guint32
+get_rgba_from_color (GdkColor * color)
+{
+       return ((color->red & 0xff00) << 16) | ((color->green & 0xff00) << 8) | (color->blue & 0xff00) | 0xff;
 }
 
 static void
@@ -273,24 +240,18 @@ gnome_canvas_shape_set_property (GObject      *object,
 	GnomeCanvasItem         *item;
 	GnomeCanvasShape        *shape;
 	GnomeCanvasShapePriv    *priv;
-	GnomeCanvasShapePrivGdk *gdk;
 	GdkColor                 color;
 	GdkColor                *colorptr;
-	ArtVpathDash            *dash;
 
 	item = GNOME_CANVAS_ITEM (object);
 	shape = GNOME_CANVAS_SHAPE (object);
 	priv = shape->priv;
 
-        gcbp_ensure_gdk (shape);
-        gdk = priv->gdk;
-
 	switch (param_id) {
 	case PROP_FILL_COLOR:
 		if (gnome_canvas_get_color (item->canvas, g_value_get_string (value), &color)) {
 			priv->fill_set = TRUE;
 			priv->fill_rgba = get_rgba_from_color (&color);
-			if (gdk) gdk->fill_pixel = color.pixel;
 		} else if (priv->fill_set)
 			priv->fill_set = FALSE;
 		else
@@ -304,12 +265,6 @@ gnome_canvas_shape_set_property (GObject      *object,
 		if (colorptr != NULL) {
 			priv->fill_set = TRUE;
 			priv->fill_rgba = get_rgba_from_color (colorptr);
-			if (gdk) {
-				GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas));
-				GdkColor tmp = *colorptr;
-				gdk_rgb_find_color (colormap, &tmp);
-				gdk->fill_pixel = tmp.pixel;
-			}
 		} else if (priv->fill_set)
 			priv->fill_set = FALSE;
 		else
@@ -321,7 +276,6 @@ gnome_canvas_shape_set_property (GObject      *object,
 	case PROP_FILL_COLOR_RGBA:
 		priv->fill_set = TRUE;
 		priv->fill_rgba = g_value_get_uint (value);
-		if (gdk) gdk->fill_pixel = get_pixel_from_rgba (item, priv->fill_rgba);
 
 		gnome_canvas_item_request_update (item);
 		break;
@@ -330,7 +284,6 @@ gnome_canvas_shape_set_property (GObject      *object,
 		if (gnome_canvas_get_color (item->canvas, g_value_get_string (value), &color)) {
 			priv->outline_set = TRUE;
 			priv->outline_rgba = get_rgba_from_color (&color);
-			if (gdk) gdk->outline_pixel = color.pixel;
 		} else if (priv->outline_set)
 			priv->outline_set = FALSE;
 		else
@@ -344,12 +297,6 @@ gnome_canvas_shape_set_property (GObject      *object,
 		if (colorptr != NULL) {
 			priv->outline_set = TRUE;
 			priv->outline_rgba = get_rgba_from_color (colorptr);
-			if (gdk) {
-				GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (item->canvas));
-				GdkColor tmp = *colorptr;
-				gdk_rgb_find_color (colormap, &tmp);
-				gdk->outline_pixel = tmp.pixel;
-			}
 		} else if (priv->outline_set)
 			priv->outline_set = FALSE;
 		else
@@ -361,7 +308,6 @@ gnome_canvas_shape_set_property (GObject      *object,
 	case PROP_OUTLINE_COLOR_RGBA:
 		priv->outline_set = TRUE;
 		priv->outline_rgba = g_value_get_uint (value);
-		if (gdk) gdk->outline_pixel = get_pixel_from_rgba (item, priv->outline_rgba);
 
 		gnome_canvas_item_request_update (item);
 		break;
@@ -373,7 +319,7 @@ gnome_canvas_shape_set_property (GObject      *object,
 		break;
 
 	case PROP_WIND:
-		priv->wind = g_value_get_uint (value);
+		priv->wind = g_value_get_enum (value);
 		gnome_canvas_item_request_update (item);
 		break;
 
@@ -393,70 +339,33 @@ gnome_canvas_shape_set_property (GObject      *object,
 		break;
 
 	case PROP_DASH:
-		dash = g_value_get_pointer (value);
-		if (priv->dash.dash) g_free (priv->dash.dash);
-		priv->dash.dash = NULL;
-
-		if (dash) {
-			priv->dash.offset = dash->offset;
-			priv->dash.n_dash = dash->n_dash;
-			if (dash->dash != NULL) {
-				priv->dash.dash = g_new (double, dash->n_dash);
-				memcpy (priv->dash.dash, dash->dash, dash->n_dash * sizeof (gdouble));
-			}
-		}
-		gnome_canvas_item_request_update (item);
+                /* XXX */
+                g_assert_not_reached ();
 		break;
+
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
 		break;
 	}
 }
 
-/* Allocates a GdkColor structure filled with the specified pixel, and
- * puts it into the specified value for returning it in the get_property
- * method.
- */
-
-static void
-get_color_value (GnomeCanvasShape *shape, gulong pixel, GValue *value)
-{
-	GnomeCanvas *canvas = GNOME_CANVAS_ITEM (shape)->canvas;
-	GdkColormap *colormap = gtk_widget_get_colormap (GTK_WIDGET (canvas));
-	GdkColor color;
-
-	gdk_colormap_query_color (colormap, pixel, &color);
-	g_value_set_boxed (value, &color);
-}
-
 /**
- * gnome_canvas_shape_get_path_def:
+ * gnome_canvas_shape_get_path:
  * @shape: a GnomeCanvasShape
  *
- * This function returns the #GnomeCanvasPathDef that the shape
- * currently uses.  It adds a reference to the #GnomeCanvasPathDef and
- * returns it, if there is not a #GnomeCanvasPathDef set for the shape
+ * This function returns the #cairo_path_t that the shape currently
+ * uses. If there is not a #GnomeCanvasPathDef set for the shape
  * it returns NULL.
  *
- * Returns: a #GnomeCanvasPathDef or NULL if none is set for the shape.
+ * Returns: a #cairo_path_t or NULL if none is set for the shape.
  */
-
-GnomeCanvasPathDef *
-gnome_canvas_shape_get_path_def (GnomeCanvasShape *shape)
+const cairo_path_t *
+gnome_canvas_shape_get_path (GnomeCanvasShape *shape)
 {
-	GnomeCanvasShapePriv *priv;
-
 	g_return_val_if_fail (shape != NULL, NULL);
 	g_return_val_if_fail (GNOME_IS_CANVAS_SHAPE (shape), NULL);
 
-	priv = shape->priv;
-
-	if (priv->path) {
-		gnome_canvas_path_def_ref (priv->path);
-		return priv->path;
-	}
-
-	return NULL;
+	return shape->priv->path;
 }
 
 static void
@@ -467,27 +376,8 @@ gnome_canvas_shape_get_property (GObject     *object,
 {
 	GnomeCanvasShape        *shape = GNOME_CANVAS_SHAPE (object);
 	GnomeCanvasShapePriv    *priv = shape->priv;
-	GnomeCanvasShapePrivGdk *gdk;
-
-        gcbp_ensure_gdk (shape);
-        gdk = priv->gdk;
 
 	switch (param_id) {
-	case PROP_FILL_COLOR_GDK:
-		if (gdk) {
-			get_color_value (shape, gdk->fill_pixel, value);
-		} else {
-			get_color_value (shape, 0, value);
-		}
-		break;
-
-	case PROP_OUTLINE_COLOR_GDK:
-		if (gdk) {
-			get_color_value (shape, gdk->outline_pixel, value);
-		} else {
-			get_color_value (shape, 0, value);
-		}
-		break;
 
 	case PROP_FILL_COLOR_RGBA:
 		g_value_set_uint (value, priv->fill_rgba);
@@ -518,7 +408,8 @@ gnome_canvas_shape_get_property (GObject     *object,
 		break;
 
 	case PROP_DASH:
-		g_value_set_pointer (value, &priv->dash);
+                /* XXX */
+                g_assert_not_reached ();
 		break;
 
 	default:
@@ -527,392 +418,140 @@ gnome_canvas_shape_get_property (GObject     *object,
 	}
 }
 
-static void
-gnome_canvas_shape_realize (GnomeCanvasItem *item)
+static gboolean
+gnome_canvas_shape_setup_for_fill (GnomeCanvasShape *shape, cairo_t *cr)
 {
-	GnomeCanvasShape *shape;
-        GtkLayout *layout;
-        GdkWindow *bin_window;
-
-	shape = GNOME_CANVAS_SHAPE (item);
-
-	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->realize)
-		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->realize (item);
+        GnomeCanvasShapePriv *priv = shape->priv;
 
-        gcbp_ensure_gdk (shape);
+        if (!priv->fill_set)
+                return FALSE;
 
-        layout = GTK_LAYOUT (item->canvas);
-        bin_window = gtk_layout_get_bin_window (layout);
+        cairo_set_source_rgba (cr,
+                               ((priv->fill_rgba >> 24) & 0xff) / 255.0,
+                               ((priv->fill_rgba >> 16) & 0xff) / 255.0,
+                               ((priv->fill_rgba >>  8) & 0xff) / 255.0,
+                               ( priv->fill_rgba        & 0xff) / 255.0);
+        cairo_set_fill_rule (cr, priv->wind);
 
-        g_assert (bin_window != NULL);
-
-        shape->priv->gdk->fill_gc = gdk_gc_new (bin_window);
-        shape->priv->gdk->outline_gc = gdk_gc_new (bin_window);
+        return TRUE;
 }
 
-static void
-gnome_canvas_shape_unrealize (GnomeCanvasItem *item)
+static gboolean
+gnome_canvas_shape_setup_for_stroke (GnomeCanvasShape *shape, cairo_t *cr)
 {
-	GnomeCanvasShape *shape;
-
-	shape = GNOME_CANVAS_SHAPE (item);
-
-        g_assert (shape->priv->gdk != NULL);
-
-        g_object_unref (shape->priv->gdk->fill_gc);
-        shape->priv->gdk->fill_gc = NULL;
-
-        g_object_unref (shape->priv->gdk->outline_gc);
-        shape->priv->gdk->outline_gc = NULL;
-
-	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->unrealize)
-		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->unrealize (item);
+        GnomeCanvasShapePriv *priv = shape->priv;
+
+        if (!priv->outline_set)
+                return FALSE;
+
+        cairo_set_source_rgba (cr,
+                               ((priv->outline_rgba >> 24) & 0xff) / 255.0,
+                               ((priv->outline_rgba >> 16) & 0xff) / 255.0,
+                               ((priv->outline_rgba >>  8) & 0xff) / 255.0,
+                               ( priv->outline_rgba        & 0xff) / 255.0);
+        cairo_set_line_width (cr, priv->line_width);
+        cairo_set_line_cap (cr, priv->cap);
+        cairo_set_line_join (cr, priv->join);
+        cairo_set_miter_limit (cr, priv->miterlimit);
+        cairo_set_dash (cr, priv->dash, priv->n_dash, priv->dash_offset);
+
+        return TRUE;
 }
 
 static void
 gnome_canvas_shape_draw (GnomeCanvasItem *item,
-	GdkDrawable *drawable,
-	gint x,
-	gint y,
-	gint width,
-	gint height)
+                         GdkDrawable *drawable,
+                         gint x,
+                         gint y,
+                         gint width,
+                         gint height)
 {
-	static GdkPoint * dpoints = NULL;
-	static gint num_dpoints = 0;
-
 	GnomeCanvasShape * shape;
-	GnomeCanvasShapePriv * priv;
-	GnomeCanvasShapePrivGdk * gdk;
-	gint i, pos, len;
-	GSList * l;
+        cairo_matrix_t matrix;
+        cairo_t *cr;
 
 	shape = GNOME_CANVAS_SHAPE (item);
-	priv = shape->priv;
-
-	/* We have to be realized, so gdk struct should exist! */
-
-	gdk = shape->priv->gdk;
-	g_assert (gdk != NULL);
-
-	/* Build temporary point list, translated by -x, -y */
-
-	if (dpoints == NULL) {
-		dpoints = g_new (GdkPoint, gdk->num_points);
-		num_dpoints = gdk->num_points;
-	} else if (num_dpoints < gdk->num_points) {
-		dpoints = g_renew (GdkPoint, dpoints, gdk->num_points);
-		num_dpoints = gdk->num_points;
-	}
-
-	for (i = 0; i < gdk->num_points; i++) {
-		dpoints[i].x = gdk->points[i].x - x;
-		dpoints[i].y = gdk->points[i].y - y;
-	}
-
-	if (priv->fill_set) {
-
-		/* Ensure, that we have mask and it is big enough */
-
-		gcbp_ensure_mask (shape, width, height);
+        cr = gdk_cairo_create (drawable);
+        gnome_canvas_item_i2c_matrix (item, &matrix);
+        if (cairo_matrix_invert (&matrix))
+                return;
+        cairo_transform (cr, &matrix);
+        cairo_append_path (cr, shape->priv->path);
 
-		/* Clear mask */
+        if (gnome_canvas_shape_setup_for_fill (shape, cr))
+                cairo_fill_preserve (cr);
 
-		gdk_draw_rectangle (gdk->ctx->mask,
-			gdk->ctx->clear_gc,
-			TRUE,
-			0, 0,
-			width, height);
+        if (gnome_canvas_shape_setup_for_stroke (shape, cr))
+                cairo_stroke_preserve (cr);
 
-		/* Draw subpaths, using XOR gc */
-
-		pos = 0;
-
-		for (l = gdk->closed_paths; l != NULL; l = l->next) {
-			len = GPOINTER_TO_INT (l->data);
-
-			gdk_draw_polygon (gdk->ctx->mask,
-				gdk->ctx->xor_gc,
-				TRUE,
-				&dpoints[pos],
-				len);
-
-			pos += len;
-		}
-
-		/* Set bitmap to clipping mask */
-
-		gdk_gc_set_clip_mask (gdk->fill_gc, gdk->ctx->mask);
-
-		/* Draw clipped rect to drawable */
-
-		gdk_draw_rectangle (drawable,
-			gdk->fill_gc,
-			TRUE,
-			0, 0,
-			width, height);
-	}
-
-	if (priv->outline_set) {
-
-		/* Draw subpaths */
-
-		pos = 0;
-
-		for (l = gdk->closed_paths; l != NULL; l = l->next) {
-			len = GPOINTER_TO_INT (l->data);
-
-			gdk_draw_polygon (drawable,
-					  gdk->outline_gc,
-					  FALSE,
-					  &dpoints[pos],
-					  len);
-
-			pos += len;
-		}
-
-		for (l = gdk->open_paths; l != NULL; l = l->next) {
-			len = GPOINTER_TO_INT (l->data);
-
-			gdk_draw_lines (drawable,
-					gdk->outline_gc,
-					&dpoints[pos],
-					len);
-
-			pos += len;
-		}
-	}
+        cairo_destroy (cr);
 }
 
-#define GDK_POINTS_BLOCK 32
-
 static void
-gnome_canvas_shape_ensure_gdk_points (GnomeCanvasShapePrivGdk *gdk, gint num)
+my_cairo_matrix_transform_rectangle (const cairo_matrix_t *matrix,
+                                     double *x1, double *y1, double *x2, double *y2)
 {
-	if (gdk->len_points < gdk->num_points + num) {
-		gdk->len_points = MAX (gdk->len_points + GDK_POINTS_BLOCK, gdk->len_points + num);
-		gdk->points = g_renew (GdkPoint, gdk->points, gdk->len_points);
-	}
+        double maxx, maxy, minx, miny;
+        double tmpx, tmpy;
+
+        tmpx = *x1;
+        tmpy = *y1;
+        cairo_matrix_transform_point (matrix, &tmpx, &tmpy);
+        minx = maxx = tmpx;
+        miny = maxy = tmpy;
+
+        tmpx = *x2;
+        tmpy = *y1;
+        cairo_matrix_transform_point (matrix, &tmpx, &tmpy);
+        minx = MIN (minx, tmpx);
+        maxx = MAX (maxx, tmpx);
+        miny = MIN (miny, tmpy);
+        maxy = MAX (maxy, tmpy);
+
+        tmpx = *x2;
+        tmpy = *y2;
+        cairo_matrix_transform_point (matrix, &tmpx, &tmpy);
+        minx = MIN (minx, tmpx);
+        maxx = MAX (maxx, tmpx);
+        miny = MIN (miny, tmpy);
+        maxy = MAX (maxy, tmpy);
+
+        tmpx = *x1;
+        tmpy = *y2;
+        cairo_matrix_transform_point (matrix, &tmpx, &tmpy);
+        minx = MIN (minx, tmpx);
+        maxx = MAX (maxx, tmpx);
+        miny = MIN (miny, tmpy);
+        maxy = MAX (maxy, tmpy);
+
+        *x1 = minx;
+        *x2 = maxx;
+        *y1 = miny;
+        *y2 = maxy;
 }
 
 static void
-gnome_canvas_shape_update_gdk (GnomeCanvasShape * shape, gdouble * affine, ArtSVP * clip, gint flags)
+gnome_canvas_shape_bounds (GnomeCanvasItem *item, gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2)
 {
+	GnomeCanvasShape * shape;
 	GnomeCanvasShapePriv * priv;
-	GnomeCanvasShapePrivGdk * gdk;
-	gint x1 = 0, y1 = 0, x2 = 0, y2 = 0;
-	gboolean bbox_set = FALSE;
-	gint width = 0; /* silence gcc */
+        cairo_t *cr;
 
+	shape = GNOME_CANVAS_SHAPE (item);
 	priv = shape->priv;
-	gdk = priv->gdk;
-	g_assert (gdk != NULL);
-
-	if (priv->outline_set) {
-		GdkLineStyle style;
-
-                width = (gint) floor ((priv->line_width * priv->scale) + 0.5);
-                /* Never select 0 pixels unless the user asked for it,
-                 * since that is the X11 zero width lines are non-speciifed */
-                if (priv->line_width != 0 && width == 0) {
-                        width = 1;
-                }
-
-		/* If dashed, set it in GdkGC */
-
-		if ((shape->priv->dash.dash != NULL) && (shape->priv->dash.n_dash > 0)) {
-			gint8 * dash_list;
-			gint i;
-
-			dash_list = g_new (gint8, shape->priv->dash.n_dash);
-
-			for (i = 0; i < priv->dash.n_dash; i++) {
-				dash_list[i] = (gint8) shape->priv->dash.dash[i];
-			}
-
-			gdk_gc_set_dashes (gdk->outline_gc,
-				(gint) priv->dash.offset,
-				dash_list,
-				priv->dash.n_dash);
-
-			g_free (dash_list);
 
-			style = GDK_LINE_ON_OFF_DASH;
-		} else {
-			style = GDK_LINE_SOLID;
-		}
+        cr = gnome_canvas_cairo_create_scratch ();
+        cairo_append_path (cr, shape->priv->path);
 
-		/* Set line width, cap, join */
-		if (gdk->outline_gc) {
-
-			gdk_gc_set_line_attributes (gdk->outline_gc,
-						    width,
-						    style,
-						    priv->cap,
-						    priv->join);
-
-			set_gc_foreground (gdk->outline_gc, gdk->outline_pixel);
-		}
-	}
-
-	if (priv->fill_set) {
-
-		if (gdk->fill_gc) {
-			set_gc_foreground (gdk->fill_gc, gdk->fill_pixel);
-		}
-	}
-
-	/* Now the crazy part */
-
-	/* Free existing GdkPoint array */
-
-	if (gdk->points) {
-		g_free (gdk->points);
-		gdk->points = NULL;
-		gdk->len_points = 0;
-		gdk->num_points = 0;
-	}
-
-	/* Free subpath lists */
-
-	while (gdk->closed_paths) gdk->closed_paths = g_slist_remove (gdk->closed_paths, gdk->closed_paths->data);
-	while (gdk->open_paths) gdk->open_paths = g_slist_remove (gdk->open_paths, gdk->open_paths->data);
-
-	/* Calcualte new GdkPoints array and subpath lists */
-
-	if (priv->path) {
-		GnomeCanvasPathDef * apath, * cpath, * opath;
-		ArtBpath * abpath;
-		GSList * clist, * olist;
-		gint pos;
-
-#if 0
-		/* Allocate array */
-		gdk->num_points = gnome_canvas_path_def_length (priv->path) * 1000 - 1;
-		gdk->points = g_new (GdkPoint, gdk->num_points);
-		g_print ("Points %d\n", gdk->num_points);
-		/* Transform path */
-#endif
-
-		abpath = art_bpath_affine_transform (gnome_canvas_path_def_bpath (priv->path), affine);
-		apath = gnome_canvas_path_def_new_from_bpath (abpath);
-
-		/* Split path into open and closed parts */
-
-		cpath = gnome_canvas_path_def_closed_parts (apath);
-		opath = gnome_canvas_path_def_open_parts (apath);
-		gnome_canvas_path_def_unref (apath);
-
-		/* Split partial paths into subpaths */
-
-		clist = gnome_canvas_path_def_split (cpath);
-		gnome_canvas_path_def_unref (cpath);
-		olist = gnome_canvas_path_def_split (opath);
-		gnome_canvas_path_def_unref (opath);
-
-		pos = 0;
-
-		/* Fill GdkPoints and add subpaths to list: closed subpaths */
-
-		while (clist) {
-			GnomeCanvasPathDef * path;
-			ArtBpath * bpath;
-			ArtVpath * vpath;
-			gint len, i;
-
-			path = (GnomeCanvasPathDef *) clist->data;
-			bpath = gnome_canvas_path_def_bpath (path);
-			vpath = art_bez_path_to_vec (bpath, 0.1);
-			for (len = 0; vpath[len].code != ART_END; len++);
-
-			gnome_canvas_shape_ensure_gdk_points (gdk, len);
-			for (i = 0; i < len; i++) {
-				gdk->points[pos + i].x = (gint) floor (vpath[i].x + 0.5);
-				gdk->points[pos + i].y = (gint) floor (vpath[i].y + 0.5);
-
-				if (bbox_set) {
-					x1 = MIN (x1, gdk->points[pos + i].x);
-					x2 = MAX (x2, gdk->points[pos + i].x);
-					y1 = MIN (y1, gdk->points[pos + i].y);
-					y2 = MAX (y2, gdk->points[pos + i].y);
-				} else {
-					bbox_set = TRUE;
-					x1 = x2 = gdk->points[pos + i].x;
-					y1 = y2 = gdk->points[pos + i].y;
-				}
-			}
-			gdk->num_points += len;
-
-			art_free (vpath);
-
-			if (len > 0) {
-				pos += len;
-				gdk->closed_paths = g_slist_append (gdk->closed_paths, GINT_TO_POINTER (len));
-			}
-
-			gnome_canvas_path_def_unref (path);
-			clist = g_slist_remove (clist, clist->data);
-		}
-
-		/* Fill GdkPoints and add subpaths to list: open subpaths */
-
-		while (olist) {
-			GnomeCanvasPathDef * path;
-			ArtBpath * bpath;
-			ArtVpath * vpath;
-			gint len, i;
-
-			path = (GnomeCanvasPathDef *) olist->data;
-			bpath = gnome_canvas_path_def_bpath (path);
-			vpath = art_bez_path_to_vec (bpath, 0.1);
-			for (len = 0; vpath[len].code != ART_END; len++);
-
-			gnome_canvas_shape_ensure_gdk_points (gdk, len);
-			for (i = 0; i < len; i++) {
-				gdk->points[pos + i].x = (gint) floor (vpath[i].x + 0.5);
-				gdk->points[pos + i].y = (gint) floor (vpath[i].y + 0.5);
-
-				if (bbox_set) {
-					x1 = MIN (x1, gdk->points[pos + i].x);
-					x2 = MAX (x2, gdk->points[pos + i].x);
-					y1 = MIN (y1, gdk->points[pos + i].y);
-					y2 = MAX (y2, gdk->points[pos + i].y);
-				} else {
-					bbox_set = TRUE;
-					x1 = x2 = gdk->points[pos + i].x;
-					y1 = y2 = gdk->points[pos + i].y;
-				}
-			}
-			gdk->num_points += len;
-
-			art_free (vpath);
-
-			if (len > 0) {
-				pos += len;
-				gdk->open_paths = g_slist_append (gdk->open_paths, GINT_TO_POINTER (len));
-			}
-
-			gnome_canvas_path_def_unref (path);
-			olist = g_slist_remove (olist, olist->data);
-		}
-
-	}
-
-	if (bbox_set) {
-		if (priv->outline_set) {
-			gint stroke_border = (priv->join == GDK_JOIN_MITER)
-				? ceil (10.43*width/2) /* 10.43 is the miter limit for X11 */
-				: ceil (width/2);
-			x1 -= stroke_border;
-			x2 += stroke_border;
-			y1 -= stroke_border;
-			y2 += stroke_border;
-		}
-
-		gnome_canvas_update_bbox (GNOME_CANVAS_ITEM (shape),
-					  x1, y1,
-					  x2 + 1, y2 + 1);
-	}
+        if (gnome_canvas_shape_setup_for_stroke (shape, cr))
+                cairo_stroke_extents (cr, x1, x2, y1, y2);
+        else if (gnome_canvas_shape_setup_for_fill (shape, cr))
+                cairo_fill_extents (cr, x1, x2, y1, y2);
+        else {
+          *x1 = *x2 = *y1 = *y2 = 0;
+        }
 
+        cairo_destroy (cr);
 }
 
 static void
@@ -920,410 +559,51 @@ gnome_canvas_shape_update (GnomeCanvasItem *item, gdouble *affine, ArtSVP *clip_
 {
 	GnomeCanvasShape * shape;
 	GnomeCanvasShapePriv * priv;
-	ArtSVP * svp;
+        double x1, x2, y1, y2;
+        cairo_matrix_t matrix;
 
 	shape = GNOME_CANVAS_SHAPE (item);
 
 	priv = shape->priv;
 
 	/* Common part */
-	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->update) {
+	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->update)
 		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_shape_parent_class)->update (item, affine, clip_path, flags);
-	}
-
-	/* Outline width */
-	shape->priv->scale = art_affine_expansion (affine);
-
-	/* Clipped fill SVP */
-
-	if ((priv->fill_set) && (priv->path) && (gnome_canvas_path_def_any_closed (priv->path))) {
-		GnomeCanvasPathDef * cpath;
-		ArtSvpWriter *swr;
-		ArtVpath *vpath;
-		ArtBpath *abp;
-		ArtSVP *svp2;
-
-		/* Get closed part of path */
-
-		cpath = gnome_canvas_path_def_closed_parts (shape->priv->path);
-		abp = art_bpath_affine_transform (gnome_canvas_path_def_bpath (cpath), affine);
-		gnome_canvas_path_def_unref (cpath);
-
-		/* Render, until SVP */
-
-		vpath = art_bez_path_to_vec (abp, 0.1);
-		art_free (abp);
-
-		svp = art_svp_from_vpath (vpath);
-		art_free (vpath);
 
-		swr = art_svp_writer_rewind_new (shape->priv->wind);
-		art_svp_intersector (svp, swr);
+        gnome_canvas_shape_bounds (item, &x1, &x2, &y1, &y2);
+        gnome_canvas_item_i2w_matrix (item, &matrix);
 
-		svp2 = art_svp_writer_rewind_reap (swr);
-		art_svp_free (svp);
-
-                if (priv->fill_svp) {
-                        art_svp_free (priv->fill_svp);
-                        priv->fill_svp = NULL;
-                }
-                /* No clipping */
-                shape->priv->fill_svp = svp2;
-	}
-
-	if (priv->outline_set && priv->path && !gnome_canvas_path_def_is_empty (priv->path)) {
-		gdouble width;
-		ArtBpath * abp;
-		ArtVpath * vpath;
-
-		/* Set linewidth */
-
-		width = priv->line_width * priv->scale;
-
-		if (width < 0.5) width = 0.5;
-
-		/* Render full path until vpath */
-
-		abp = art_bpath_affine_transform (gnome_canvas_path_def_bpath (priv->path), affine);
-
-		vpath = art_bez_path_to_vec (abp, 0.1);
-		art_free (abp);
-
-		/* If dashed, apply dash */
-
-		if (priv->dash.dash != NULL)
-		{
-			ArtVpath *old = vpath;
-
-			vpath = art_vpath_dash (old, &priv->dash);
-			art_free (old);
-		}
-
-		/* Stroke vpath to SVP */
-
-		svp = art_svp_vpath_stroke (vpath,
-					    gnome_canvas_join_gdk_to_art (priv->join),
-					    gnome_canvas_cap_gdk_to_art (priv->cap),
-					    width,
-					    priv->miterlimit,
-					    0.25);
-		art_free (vpath);
-
-                if (priv->outline_svp) {
-                        art_svp_free (priv->outline_svp);
-                        priv->outline_svp = NULL;
-                }
-                /* No clipping (yet) */
-                shape->priv->outline_svp = svp;
-	}
-
-	/* Gdk requires additional handling */
-        gnome_canvas_shape_update_gdk (shape, affine, clip_path, flags);
+        my_cairo_matrix_transform_rectangle (&matrix, &x1, &y1, &x2, &y2);
+        gnome_canvas_update_bbox (GNOME_CANVAS_ITEM (shape),
+                                  floor (x1), floor (y1),
+                                  ceil (x2), ceil (y2));
 }
 
 static GnomeCanvasItem *
 gnome_canvas_shape_point (GnomeCanvasItem *item, gdouble x, gdouble y,
-			    gint cx, gint cy)
-{
-	GnomeCanvasShape *shape;
-	gint wind;
-
-#if 0
-	/* fixme: This is just for debugging, canvas should ensure that */
-	/* fixme: IF YOU ARE SURE THAT IT IS CORRECT BEHAVIOUR, you can remove warning */
-	/* fixme: and make it to return silently */
-	g_return_val_if_fail (!item->canvas->need_update, 1e18);
-#endif
-
-	shape = GNOME_CANVAS_SHAPE (item);
-
-	/* todo: update? */
-	if (shape->priv->fill_set && shape->priv->fill_svp) {
-		wind = art_svp_point_wind (shape->priv->fill_svp, cx, cy);
-		if ((shape->priv->wind == ART_WIND_RULE_NONZERO) && (wind != 0))
-			return item;
-		if ((shape->priv->wind == ART_WIND_RULE_ODDEVEN) && ((wind & 0x1) != 0))
-		        return item;
-	}
-
-	if (shape->priv->outline_set && shape->priv->outline_svp) {
-		wind = art_svp_point_wind (shape->priv->outline_svp, cx, cy);
-		if (wind)
-                        return item;
-	}
-
-	return NULL;
-}
-
-/* Helpers */
-
-/* Get 32bit rgba color from GdkColor */
-
-static guint32
-get_rgba_from_color (GdkColor * color)
-{
-	return ((color->red & 0xff00) << 16) | ((color->green & 0xff00) << 8) | (color->blue & 0xff00) | 0xff;
-}
-
-/* Get Gdk pixel value from 32bit rgba color */
-
-static gulong
-get_pixel_from_rgba (GnomeCanvasItem *item, guint32 rgba_color)
-{
-	return gnome_canvas_get_color_pixel (item->canvas, rgba_color);
-}
-
-/* Convenience function to set a GC's foreground color to the specified pixel value */
-
-static void
-set_gc_foreground (GdkGC *gc, gulong pixel)
-{
-	GdkColor c;
-
-	g_assert (gc != NULL);
-
-	c.pixel = pixel;
-
-	gdk_gc_set_foreground (gc, &c);
-}
-
-/* Creates private Gdk struct, if not present */
-/* We cannot do it during ::init, as we have to know canvas */
-
-static void
-gcbp_ensure_gdk (GnomeCanvasShape * shape)
-{
-	if (!shape->priv->gdk) {
-		GnomeCanvasShapePrivGdk * gdk;
-
-		gdk = g_new (GnomeCanvasShapePrivGdk, 1);
-
-		gdk->fill_pixel = get_pixel_from_rgba ((GnomeCanvasItem *) shape, shape->priv->fill_rgba);
-		gdk->outline_pixel = get_pixel_from_rgba ((GnomeCanvasItem *) shape, shape->priv->outline_rgba);
-
-		gdk->fill_gc = NULL;
-		gdk->outline_gc = NULL;
-
-		gdk->len_points = 0;
-		gdk->num_points = 0;
-		gdk->points = NULL;
-		gdk->closed_paths = NULL;
-		gdk->open_paths = NULL;
-
-		gdk->ctx = NULL;
-
-		shape->priv->gdk = gdk;
-	}
-}
-
-/* Destroy private Gdk struct */
-/* It is here, to make ::destroy implementation shorter :) */
-
-static void
-gcbp_destroy_gdk (GnomeCanvasShape * shape)
-{
-	GnomeCanvasShapePrivGdk * gdk;
-
-	gdk = shape->priv->gdk;
-
-	if (gdk) {
-		g_assert (!gdk->fill_gc);
-		g_assert (!gdk->outline_gc);
-
-		if (gdk->points)
-			g_free (gdk->points);
-
-		while (gdk->closed_paths)
-			gdk->closed_paths = g_slist_remove (gdk->closed_paths, gdk->closed_paths->data);
-		while (gdk->open_paths)
-			gdk->open_paths = g_slist_remove (gdk->open_paths, gdk->open_paths->data);
-
-		if (gdk->ctx)
-			gcbp_draw_ctx_unref (gdk->ctx);
-
-		g_free (gdk);
-
-		shape->priv->gdk = NULL;
-	}
-}
-
-/*
- * Ensure, that per-canvas Ctx struct is present and bitmaps are
- * big enough, to mask full redraw area. Ctx is refcounted and
- * defined as "BpathDrawCtx" data member on parent canvas
- */
-
-static void
-gcbp_ensure_mask (GnomeCanvasShape * shape, gint width, gint height)
-{
-	GnomeCanvasShapePrivGdk * gdk;
-	GCBPDrawCtx * ctx;
-
-	gdk = shape->priv->gdk;
-	g_assert (gdk != NULL);
-	ctx = gdk->ctx;
-
-	if (!ctx) {
-		/* Ctx is not yet defined for us */
-
-		GnomeCanvas * canvas;
-
-		canvas = GNOME_CANVAS_ITEM (shape)->canvas;
-
-		ctx = g_object_get_data (G_OBJECT (canvas), "BpathDrawCtx");
-
-		if (!ctx) {
-			/* Ctx is not defined for parent canvas yet */
-
-			ctx = g_new (GCBPDrawCtx, 1);
-
-			ctx->refcount = 1;
-			ctx->canvas = canvas;
-			ctx->width = 0;
-			ctx->height = 0;
-
-			ctx->mask = NULL;
-			ctx->clip = NULL;
-
-			ctx->clear_gc = NULL;
-			ctx->xor_gc = NULL;
-
-			g_object_set_data (G_OBJECT (canvas), "BpathDrawCtx", ctx);
-
-		} else {
-			ctx->refcount++;
-		}
-
-		gdk->ctx = ctx;
-
-	}
-
-	/* Now we are sure, that ctx is present and properly refcounted */
-
-	if ((width > ctx->width) || (height > ctx->height)) {
-		/* Ctx is too small */
-		GtkWidget *widget;
-		GdkWindow * window;
-
-		widget = GTK_WIDGET (GNOME_CANVAS_ITEM (shape)->canvas);
-		window = gtk_widget_get_window (widget);
-
-		if (ctx->clear_gc) g_object_unref (ctx->clear_gc);
-		if (ctx->xor_gc) g_object_unref (ctx->xor_gc);
-		if (ctx->mask) g_object_unref (ctx->mask);
-		if (ctx->clip) g_object_unref (ctx->clip);
-
-		ctx->mask = gdk_pixmap_new (window, width, height, 1);
-		ctx->clip = NULL;
-
-		ctx->clear_gc = gdk_gc_new (ctx->mask);
-		gdk_gc_set_function (ctx->clear_gc, GDK_CLEAR);
-
-		ctx->xor_gc = gdk_gc_new (ctx->mask);
-		gdk_gc_set_function (ctx->xor_gc, GDK_INVERT);
-	}
-}
-
-/* It is cleaner to have it here, not in parent function */
-
-static void
-gcbp_draw_ctx_unref (GCBPDrawCtx * ctx)
-{
-	if (--ctx->refcount < 1) {
-		if (ctx->clear_gc)
-			g_object_unref (ctx->clear_gc);
-		if (ctx->xor_gc)
-			g_object_unref (ctx->xor_gc);
-
-		if (ctx->mask)
-			g_object_unref (ctx->mask);
-		if (ctx->clip)
-			g_object_unref (ctx->clip);
-
-		g_object_set_data (G_OBJECT (ctx->canvas), "BpathDrawCtx", NULL);
-		g_free (ctx);
-	}
-}
-
-static void
-gnome_canvas_shape_bounds (GnomeCanvasItem *item, gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2)
+			  gint cx, gint cy)
 {
 	GnomeCanvasShape * shape;
-	GnomeCanvasShapePriv * priv;
-	ArtDRect bbox;
-	ArtSVP * svp;
+        cairo_t *cr;
 
 	shape = GNOME_CANVAS_SHAPE (item);
 
-	priv = shape->priv;
-
-	bbox.x0 = *x1;
-	bbox.y0 = *y1;
-	bbox.x1 = *x2;
-	bbox.y1 = *y2;
-
-	if (priv->outline_set && priv->path && !gnome_canvas_path_def_is_empty (priv->path)) {
-		gdouble width;
-		ArtVpath * vpath;
-
-		/* Set linewidth */
-
-		width = priv->line_width * priv->scale;
-
-		if (width < 0.5) width = 0.5;
-
-		/* Render full path until vpath */
-
-		vpath = art_bez_path_to_vec (gnome_canvas_path_def_bpath (priv->path), 0.1);
+        cr = gnome_canvas_cairo_create_scratch ();
+        cairo_append_path (cr, shape->priv->path);
 
-		/* If dashed, apply dash */
+        if (gnome_canvas_shape_setup_for_fill (shape, cr) &&
+            cairo_in_fill (cr, x, y)) {
+                cairo_destroy (cr);
+                return item;
+        }
 
-		if (priv->dash.dash != NULL)
-		{
-			ArtVpath *old = vpath;
+        if (gnome_canvas_shape_setup_for_stroke (shape, cr) &&
+            cairo_in_stroke (cr, x, y)) {
+                cairo_destroy (cr);
+                return item;
+        }
 
-			vpath = art_vpath_dash (old, &priv->dash);
-			art_free (old);
-		}
-
-		/* Stroke vpath to SVP */
-
-		svp = art_svp_vpath_stroke (vpath,
-					    gnome_canvas_join_gdk_to_art (priv->join),
-					    gnome_canvas_cap_gdk_to_art (priv->cap),
-					    width,
-					    priv->miterlimit,
-					    0.25);
-		art_free (vpath);
-		art_drect_svp (&bbox, svp);
-		art_svp_free (svp);
-	} else if ((priv->fill_set) && (priv->path) && (gnome_canvas_path_def_any_closed (priv->path))) {
-		GnomeCanvasPathDef *cpath;
-		ArtSvpWriter *swr;
-		ArtVpath *vpath;
-		ArtSVP *svp2;
-
-		/* Get closed part of path */
-		cpath = gnome_canvas_path_def_closed_parts (shape->priv->path);
-		/* Render, until SVP */
-		vpath = art_bez_path_to_vec (gnome_canvas_path_def_bpath (cpath), 0.1);
-		gnome_canvas_path_def_unref (cpath);
-
-		svp = art_svp_from_vpath (vpath);
-		art_free (vpath);
-
-		swr = art_svp_writer_rewind_new (shape->priv->wind);
-		art_svp_intersector (svp, swr);
-
-		svp2 = art_svp_writer_rewind_reap (swr);
-		art_svp_free (svp);
-
-		art_drect_svp (&bbox, svp2);
-		art_svp_free (svp2);
-	}
+        cairo_destroy (cr);
 
-	*x1 = bbox.x0;
-	*y1 = bbox.y0;
-	*x2 = bbox.x1;
-	*y2 = bbox.y1;
+        return NULL;
 }
diff --git a/libgnomecanvas/gnome-canvas-shape.h b/libgnomecanvas/gnome-canvas-shape.h
index 2f8d687..dcd1c01 100644
--- a/libgnomecanvas/gnome-canvas-shape.h
+++ b/libgnomecanvas/gnome-canvas-shape.h
@@ -35,10 +35,10 @@ G_BEGIN_DECLS
  *								not be scaled when the canvas zoom factor is changed.
  * width_units		gdouble			RW		Width of the outline in canvas units.  The outline
  *								will be scaled when the canvas zoom factor is changed.
- * cap_style		GdkCapStyle		RW		Cap ("endpoint") style for the bpath.
- * join_style		GdkJoinStyle		RW		Join ("vertex") style for the bpath.
- * wind                 ArtWindRule             RW              Winding rule for the bpath.
- * dash			ArtVpathDash		RW		Dashing pattern
+ * cap_style		cairo_line_cap_t        RW		Cap ("endpoint") style for the bpath.
+ * join_style		cairo_line_join_t	RW		Join ("vertex") style for the bpath.
+ * wind                 cairo_fill_rule_t       RW              Winding rule for the bpath.
+ * dash			XXX: disabled           RW		Dashing pattern
  * miterlimit		gdouble			RW		Minimum angle between segments, where miter join
  *								rule is applied.
  */
@@ -65,8 +65,8 @@ struct _GnomeCanvasShapeClass {
 
 /* WARNING! These are not usable from modifying shapes from user programs */
 /* These are meant, to set master shape from subclass ::update method */
-void gnome_canvas_shape_set_path_def (GnomeCanvasShape *shape, GnomeCanvasPathDef *def);
-GnomeCanvasPathDef *gnome_canvas_shape_get_path_def (GnomeCanvasShape *shape);
+void gnome_canvas_shape_set_path (GnomeCanvasShape *shape, cairo_path_t *path);
+const cairo_path_t *gnome_canvas_shape_get_path (GnomeCanvasShape *shape);
 
 /* Standard Gtk function */
 GType gnome_canvas_shape_get_type (void) G_GNUC_CONST;
diff --git a/libgnomecanvas/gnome-canvas.c b/libgnomecanvas/gnome-canvas.c
index 958fc45..203f36d 100644
--- a/libgnomecanvas/gnome-canvas.c
+++ b/libgnomecanvas/gnome-canvas.c
@@ -1044,6 +1044,44 @@ gnome_canvas_item_i2w_affine (GnomeCanvasItem *item, gdouble affine[6])
 	}
 }
 
+void
+gnome_canvas_item_i2w_matrix (GnomeCanvasItem *item, cairo_matrix_t *matrix)
+{
+	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
+	g_return_if_fail (matrix != NULL);
+
+	cairo_matrix_init_identity (matrix);
+
+	while (item) {
+		if (item->xform != NULL) {
+                        cairo_matrix_t tmp;
+                        gnome_canvas_matrix_from_affine (&tmp, item->xform);
+                        cairo_matrix_multiply (matrix, matrix, &tmp);
+		}
+
+		item = item->parent;
+	}
+}
+
+void
+gnome_canvas_item_w2i_matrix (GnomeCanvasItem *item, cairo_matrix_t *matrix)
+{
+	g_return_if_fail (GNOME_IS_CANVAS_ITEM (item));
+	g_return_if_fail (matrix != NULL);
+
+	cairo_matrix_init_identity (matrix);
+
+	while (item) {
+		if (item->xform != NULL) {
+                        cairo_matrix_t tmp;
+                        gnome_canvas_matrix_from_affine (&tmp, item->xform);
+                        cairo_matrix_multiply (matrix, &tmp, matrix);
+		}
+
+		item = item->parent;
+	}
+}
+
 /**
  * gnome_canvas_item_w2i:
  * @item: A canvas item.
@@ -1128,11 +1166,11 @@ gnome_canvas_item_i2c_affine (GnomeCanvasItem *item, gdouble affine[6])
 void
 gnome_canvas_item_i2c_matrix (GnomeCanvasItem *item, cairo_matrix_t *matrix)
 {
-  gdouble affine;
-
-  gnome_canvas_item_i2c_affine (item, &affine);
+	cairo_matrix_t i2w, w2c;
 
-  gnome_canvas_matrix_from_affine (matrix, &affine);
+	gnome_canvas_item_i2w_matrix (item, &i2w);
+	gnome_canvas_w2c_matrix (item->canvas, &w2c);
+	cairo_matrix_multiply (matrix, &i2w, &w2c);
 }
 
 /* Returns whether the item is an inferior of or is equal to the parent. */
@@ -3841,6 +3879,50 @@ gnome_canvas_w2c_affine (GnomeCanvas *canvas, gdouble affine[6])
 }
 
 /**
+ * gnome_canvas_w2c_matrix:
+ * @canvas: A canvas.
+ * @matrix: (out): matrix to initialize
+ *
+ * Gets the transformtion matrix that converts from world coordinates to canvas
+ * pixel coordinates.
+ **/
+void
+gnome_canvas_w2c_matrix (GnomeCanvas *canvas, cairo_matrix_t *matrix)
+{
+	g_return_if_fail (GNOME_IS_CANVAS (canvas));
+	g_return_if_fail (matrix != NULL);
+
+	cairo_matrix_init_scale (matrix,
+                                 canvas->pixels_per_unit,
+                                 canvas->pixels_per_unit);
+        cairo_matrix_translate (matrix,
+                                -canvas->scroll_x1,
+                                -canvas->scroll_y1);
+}
+
+/**
+ * gnome_canvas_c2w_matrix:
+ * @canvas: A canvas.
+ * @matrix: (out): matrix to initialize
+ *
+ * Gets the transformtion matrix that converts from canvas pixel coordinates to
+ * world coordinates.
+ **/
+void
+gnome_canvas_c2w_matrix (GnomeCanvas *canvas, cairo_matrix_t *matrix)
+{
+	g_return_if_fail (GNOME_IS_CANVAS (canvas));
+	g_return_if_fail (matrix != NULL);
+
+        cairo_matrix_init_translate (matrix,
+                                     canvas->scroll_x1,
+                                     canvas->scroll_y1);
+	cairo_matrix_scale (matrix,
+                            1 / canvas->pixels_per_unit,
+                            1 / canvas->pixels_per_unit);
+}
+
+/**
  * gnome_canvas_w2c:
  * @canvas: A canvas.
  * @wx: World X coordinate.
diff --git a/libgnomecanvas/gnome-canvas.h b/libgnomecanvas/gnome-canvas.h
index 70a8f5c..5f35f33 100644
--- a/libgnomecanvas/gnome-canvas.h
+++ b/libgnomecanvas/gnome-canvas.h
@@ -273,6 +273,8 @@ void gnome_canvas_item_i2w (GnomeCanvasItem *item, gdouble *x, gdouble *y);
  * world coordinates.
  */
 void gnome_canvas_item_i2w_affine (GnomeCanvasItem *item, gdouble affine[6]);
+void gnome_canvas_item_i2w_matrix (GnomeCanvasItem *item, cairo_matrix_t *matrix);
+void gnome_canvas_item_w2i_matrix (GnomeCanvasItem *item, cairo_matrix_t *matrix);
 
 /* Gets the affine transform that converts from item-relative coordinates to
  * canvas pixel coordinates.
@@ -516,6 +518,8 @@ void gnome_canvas_request_redraw (GnomeCanvas *canvas, gint x1, gint y1, gint x2
  * coordinates.
  */
 void gnome_canvas_w2c_affine (GnomeCanvas *canvas, gdouble affine[6]);
+void gnome_canvas_w2c_matrix (GnomeCanvas *canvas, cairo_matrix_t *matrix);
+void gnome_canvas_c2w_matrix (GnomeCanvas *canvas, cairo_matrix_t *matrix);
 
 /* These functions convert from a coordinate system to another.  "w" is world
  * coordinates, "c" is canvas pixel coordinates (pixel coordinates that are



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