From e35d4c6d6514622190f216c6bf9aa11a3f4596aa Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Mon, 25 Oct 1999 23:43:04 +0000 Subject: [PATCH] Sync to laptop - Federico --- gdk-pixbuf/gnome-canvas-pixbuf.c | 331 ++++++++++++++++++++++++++++++- 1 file changed, 328 insertions(+), 3 deletions(-) diff --git a/gdk-pixbuf/gnome-canvas-pixbuf.c b/gdk-pixbuf/gnome-canvas-pixbuf.c index 79dc9bb7c0..9b9021da84 100644 --- a/gdk-pixbuf/gnome-canvas-pixbuf.c +++ b/gdk-pixbuf/gnome-canvas-pixbuf.c @@ -21,6 +21,7 @@ */ #include +#include #include "gdk-pixbuf.h" #include "gnome-canvas-pixbuf.h" @@ -42,6 +43,12 @@ typedef struct { guint width_pixels : 1; guint height_set : 1; guint height_pixels : 1; + + /* Whether the pixbuf has changed */ + guint need_pixbuf_update : 1; + + /* Whether the size has changed */ + guint need_size_update : 1; } PixbufPrivate; @@ -64,17 +71,26 @@ static void gnome_canvas_pixbuf_destroy (GtkObject *object); static void gnome_canvas_pixbuf_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); static void gnome_canvas_pixbuf_get_arg (GtkObject *object, GtkArg *arg, guint arg_id); +static void gnome_canvas_pixbuf_update (GnomeCanvasItem *item, double *affine, + ArtSVP *clip_path, int flags); +static void gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable, + int x, int y, int width, int height); +static double gnome_canvas_pixbuf_point (GnomeCanvasItem *item, double x, double y, int cx, int cy, + GnomeCanvasItem **actual_item); +static void gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item, + double *x1, double *y1, double *x2, double *y2); + static GnomeCanvasItemClass *parent_class; /** * gnome_canvas_pixbuf_get_type: - * @void: - * + * @void: + * * Registers the &GnomeCanvasPixbuf class if necessary, and returns the type ID * associated to it. - * + * * Return value: The type ID of the &GnomeCanvasPixbuf class. **/ GtkType @@ -151,11 +167,320 @@ gnome_canvas_pixbuf_init (GnomeCanvasPixbuf *gcp) priv->height = 0.0; } +/* Destroy handler for the pixbuf canvas item */ static void gnome_canvas_pixbuf_destroy (GtkObject *object) { + GnomeCanvasPixbuf *gcp; + PixbufPrivate *priv; + g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object)); + gcp = (GNOME_CANVAS_PIXBUF (object)); + priv = gcp->priv; + + /* FIXME: redraw area */ + + if (priv->pixbuf) + gdk_pixbuf_unref (priv->pixbuf); + + g_free (priv); + + if (GTK_OBJECT_CLASS (parent_class)->destroy) + (* GTK_OBJECT_CLASS (parent_class)->destroy) (object); +} + + + +/* Set_arg handler for the pixbuf canvas item */ +static void +gnome_canvas_pixbuf_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + GnomeCanvasPixbuf *gcp; + PixbufPrivate *priv; + GdkPixbuf *pixbuf; + double val; + + item = GNOME_CANVAS_ITEM (object); + gcp = GNOME_CANVAS_PIXBUF (object); + priv = gcp->priv; + + switch (arg_id) { + case ARG_PIXBUF: + pixbuf = GTK_VALUE_POINTER (*arg); + if (pixbuf != priv->pixbuf) { + if (pixbuf) + gdk_pixbuf_ref (pixbuf); + + if (priv->pixbuf) + gdk_pixbuf_unref (priv->pixbuf); + + priv->pixbuf = pixbuf; + } + + priv->need_pixbuf_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_WIDTH: + val = GTK_VALUE_DOUBLE (*arg); + g_return_if_fail (val >= 0.0); + priv->width = val; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_WIDTH_SET: + priv->width_set = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_WIDTH_PIXELS: + priv->width_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_HEIGHT: + val = GTK_VALUE_DOUBLE (*arg); + g_return_if_fail (val >= 0.0); + priv->height = val; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_HEIGHT_SET: + priv->height_set = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + case ARG_HEIGHT_PIXELS: + priv->height_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE; + priv->need_size_update = TRUE; + gnome_canvas_item_request_update (item); + break; + + default: + break; + } +} + +/* Get_arg handler for the pixbuf canvasi item */ +static void +gnome_canvas_pixbuf_get_arg (GtkObject *object, GtkArg *arg, guint arg_id) +{ + GnomeCanvasItem *item; + GnomeCanvasPixbuf *gcp; + PixbufPrivate *priv; + + item = GNOME_CANVAS_ITEM (object); + gcp = GNOME_CANVAS_PIXBUF (object); + priv = gcp->priv; + + switch (arg_id) { + case ARG_PIXBUF: + GTK_VALUE_POINTER (*arg) = priv->pixbuf; + break; + + case ARG_WIDTH: + GTK_VALUE_DOUBLE (*arg) = priv->width; + break; + + case ARG_WIDTH_SET: + GTK_VALUE_BOOL (*arg) = priv->width_set; + break; + + case ARG_WIDTH_PIXELS: + GTK_VALUE_BOOL (*arg) = priv->width_pixels; + break; + + case ARG_HEIGHT: + GTK_VALUE_DOUBLE (*arg) = priv->height; + break; + + case ARG_HEIGHT_SET: + GTK_VALUE_BOOL (*arg) = priv->height_set; + break; + + case ARG_HEIGHT_PIXELS: + GTK_VALUE_BOOL (*arg) = priv->height_pixels; + break; + + default: + arg->type = GTK_TYPE_INVALID; + break; + } +} + + + +/* Recomputes the bounding box of a pixbuf canvas item. The horizontal and + * vertical dimensions may be specified in units or pixels, separately, so we + * have to compute the components individually for each dimension. + */ +static void +recompute_bounding_box (GnomeCanvasPixbuf *gcp) +{ + GnomeCanvasItem *item; + PixbufPrivate *priv; + double i2c[6]; + ArtPoint orig, orig_c; + ArtPoint i, i_c; + ArtPoint j, j_c; + double w, h; + double length; + double x1, y1, x2, y2, x3, y3, x4, y4; + double mx1, my1, mx2, my2; + + item = GNOME_CANVAS_ITEM (gcp); + priv = gcp->priv; + + if (!priv->pixbuf) { + item->x1 = item->y1 = item->x2 = item->y2 = 0.0; + return; + } + + gnome_canvas_item_i2c_affine (item, i2c); + + /* Our "origin" */ + + orig.x = 0.0; + orig.y = 0.0; + art_affine_point (&orig_c, &orig, i2c); + + /* Horizontal and vertical vectors */ + + i.x = 1.0; + i.y = 0.0; + art_affine_point (&i_c, &i, i2c); + + j.x = 0.0; + j.y = 1.0; + art_affine_point (&j_c, &j, i2c); + + /* Compute size components. If a dimension is specified in pixels, we + * normalize the base vector first so that it will represent the size in + * pixels when scaled. + */ + + /* Width */ + + w = 0.0; + + if (priv->width_set) { + w = priv->width; + + if (priv->width_pixels) { + length = sqrt (i_c.x * i_c.x + i_c.y * i_c.y); + + if (length > GNOME_CANVAS_EPSILON) { + i_c.x /= length; + i_c.y /= length; + } else + i_c.x = i_c.y = 0.0; + } + } else if (priv->pixbuf) + w = priv->pixbuf->art_pixbuf->width; + + i_c.x *= w; + i_c.y *= w; + + /* Height */ + + h = 0.0; + + if (priv->height_set) { + h = priv->height; + + if (priv->height_pixels) { + length = sqrt (j_c.x * j_c.x + j_c.y * j_c.y); + + if (length > GNOME_CANVAS_EPSILON) { + j_c.x /= length; + j_c.y /= length; + } else + j_c.x = j_c.y = 0.0; + } + } else if (priv->pixbuf) + h = priv->pixbuf->art_pixbuf->height; + + j_c.x *= h; + j_c.y *= h; + + /* Compute vertices */ + + x1 = orig.x; + y1 = orig.y; + + x2 = orig.x + i_c.x; + y2 = orig.y + i_c.y;; + + x3 = orig.x + j_c.x; + y3 = orig.y + j_c.y; + + x4 = orig.x + i_c.x + j_c.x; + y4 = orig.y + i_c.y + j_c.y; + + /* Compute bounds */ + + mx1 = MIN (x1, x2); + my1 = MIN (y1, y2); + mx2 = MAX (x3, x4); + my2 = MAX (y3, y4); + + if (mx1 < mx2) { + item->x1 = mx1; + item->x2 = mx2; + } else { + item->x1 = mx2; + item->x2 = mx1; + } + + if (my1 < my2) { + item->y1 = my1; + item->y2 = my2; + } else { + item->y1 = my2; + item->y2 = my1; + } +} + +/* Update handler for the pixbuf canvas item */ +static void +gnome_canvas_pixbuf_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) +{ + GnomeCanvasPixbuf *gcp; + PixbufPrivate *priv; + + gcp = GNOME_CANVAS_PIXBUF (item); + priv = gcp->priv; + + if (parent_class->update) + (* parent_class->update) (item, affine, clip_path, flags); + + if (((flags & GNOME_CANVAS_UPDATE_VISIBILITY) + && !(GTK_OBJECT_FLAGS (item) & GNOME_CANVAS_ITEM_VISIBLE)) + || (flags & GNOME_CANVAS_UPDATE_AFFINE) + || priv->need_pixbuf_update + || priv->need_size_update) + gnome_canvas_request_redraw (item, item->x1, item->y1, item->x2, item->y2); + + /* If we need a pixbuf update, or if the item changed visibility to + * shown, recompute the bounding box. + */ + if (priv->need_pixbuf_update + || priv->need_size_update + || ((flags & GNOME_CANVAS_UPDATE_VISIBILITY) + && (GTK_OBJECT_FLAGS (ii) & GNOME_CANVAS_ITEM_VISIBLE)) + || (flags & GNOME_CANVAS_UPDATE_AFFINE)) { + recompute_bounding_box (gcp); + gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2); + priv->need_pixbuf_update = FALSE; + priv->need_size_update = FALSE; + } }