aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-10-15 07:25:40 +0800
committerMatthew Barnes <mbarnes@redhat.com>2010-10-30 01:50:00 +0800
commit24e39b9fb54cad437cc12b24e953be890519d86a (patch)
tree554da00fae5be782689f20ada6b3259c633663d5
parent9c183ab12ae27089ce972e29aab7000c2edfd466 (diff)
downloadgsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar.gz
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar.bz2
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar.lz
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar.xz
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.tar.zst
gsoc2013-evolution-24e39b9fb54cad437cc12b24e953be890519d86a.zip
gnome-canvas: Rewrite GnomeCanvasShape to use Cairo
Dashing properties were commented out in the process. They are not used inside Evolution.
-rw-r--r--libgnomecanvas/gnome-canvas-rect.c34
-rw-r--r--libgnomecanvas/gnome-canvas-rect.h2
-rw-r--r--libgnomecanvas/gnome-canvas-shape-private.h67
-rw-r--r--libgnomecanvas/gnome-canvas-shape.c1070
-rw-r--r--libgnomecanvas/gnome-canvas-shape.h12
-rw-r--r--libgnomecanvas/gnome-canvas.c90
-rw-r--r--libgnomecanvas/gnome-canvas.h4
7 files changed, 293 insertions, 986 deletions
diff --git a/libgnomecanvas/gnome-canvas-rect.c b/libgnomecanvas/gnome-canvas-rect.c
index 6e347e36e5..013ce086d5 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 1a161ee3e3..fd9946583f 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 fb4637c035..4be04f6ec5 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 e033add5fe..f99b10b976 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 2f8d687b78..dcd1c01305 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 958fc45e1c..203f36d909 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 70a8f5c736..5f35f33b02 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