1 /* Image item type for GnomeCanvas widget
3 * GnomeCanvas is basically a port of the Tk toolkit's most excellent canvas widget. Tk is
4 * copyrighted by the Regents of the University of California, Sun Microsystems, and other parties.
6 * Copyright (C) 1998 The Free Software Foundation
8 * Author: Federico Mena <federico@nuclecu.unam.mx>
12 #include <string.h> /* for memcpy() */
15 #include "libart_lgpl/art_misc.h"
16 #include "libart_lgpl/art_affine.h"
17 #include "libart_lgpl/art_pixbuf.h"
18 #include "libart_lgpl/art_rgb_pixbuf_affine.h"
19 #include "canvas-imageframe.h"
20 #include <libgnomecanvas/gnome-canvas-util.h>
22 //#include <libgnomecanvas/gnome-canvastypebuiltins.h>
37 static void gnome_canvas_imageframe_class_init(GnomeCanvasImageFrameClass* class) ;
38 static void gnome_canvas_imageframe_init(GnomeCanvasImageFrame* image) ;
39 static void gnome_canvas_imageframe_destroy(GtkObject* object) ;
40 static void gnome_canvas_imageframe_set_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
41 static void gnome_canvas_imageframe_get_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
43 static void gnome_canvas_imageframe_update(GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) ;
44 static void gnome_canvas_imageframe_realize(GnomeCanvasItem *item) ;
45 static void gnome_canvas_imageframe_unrealize(GnomeCanvasItem *item) ;
46 static void gnome_canvas_imageframe_draw(GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) ;
47 static double gnome_canvas_imageframe_point(GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) ;
48 static void gnome_canvas_imageframe_bounds(GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) ;
49 static void gnome_canvas_imageframe_render(GnomeCanvasItem *item, GnomeCanvasBuf *buf) ;
51 static GnomeCanvasItemClass *parent_class;
55 gnome_canvas_imageframe_get_type (void)
57 static GtkType imageframe_type = 0;
59 if (!imageframe_type) {
60 GtkTypeInfo imageframe_info = {
61 "GnomeCanvasImageFrame",
62 sizeof (GnomeCanvasImageFrame),
63 sizeof (GnomeCanvasImageFrameClass),
64 (GtkClassInitFunc) gnome_canvas_imageframe_class_init,
65 (GtkObjectInitFunc) gnome_canvas_imageframe_init,
66 NULL, /* reserved_1 */
67 NULL, /* reserved_2 */
68 (GtkClassInitFunc) NULL
71 imageframe_type = gtk_type_unique (gnome_canvas_item_get_type (), &imageframe_info);
74 return imageframe_type;
78 gnome_canvas_imageframe_class_init (GnomeCanvasImageFrameClass *class)
80 GtkObjectClass *object_class;
81 GnomeCanvasItemClass *item_class;
83 object_class = (GtkObjectClass *) class;
84 item_class = (GnomeCanvasItemClass *) class;
86 parent_class = gtk_type_class (gnome_canvas_item_get_type ());
88 gtk_object_add_arg_type ("GnomeCanvasImageFrame::pixbuf", GTK_TYPE_BOXED, GTK_ARG_WRITABLE, ARG_PIXBUF);
89 gtk_object_add_arg_type ("GnomeCanvasImageFrame::x", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X);
90 gtk_object_add_arg_type ("GnomeCanvasImageFrame::y", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y);
91 gtk_object_add_arg_type ("GnomeCanvasImageFrame::width", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH);
92 gtk_object_add_arg_type ("GnomeCanvasImageFrame::drawwidth", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_DRAWWIDTH);
93 gtk_object_add_arg_type ("GnomeCanvasImageFrame::height", GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT);
94 gtk_object_add_arg_type ("GnomeCanvasImageFrame::anchor", GTK_TYPE_ANCHOR_TYPE, GTK_ARG_READWRITE, ARG_ANCHOR);
96 object_class->destroy = gnome_canvas_imageframe_destroy;
97 object_class->set_arg = gnome_canvas_imageframe_set_arg;
98 object_class->get_arg = gnome_canvas_imageframe_get_arg;
100 item_class->update = gnome_canvas_imageframe_update;
101 item_class->realize = gnome_canvas_imageframe_realize;
102 item_class->unrealize = gnome_canvas_imageframe_unrealize;
103 item_class->draw = gnome_canvas_imageframe_draw;
104 item_class->point = gnome_canvas_imageframe_point;
105 item_class->bounds = gnome_canvas_imageframe_bounds;
106 item_class->render = gnome_canvas_imageframe_render;
110 gnome_canvas_imageframe_init (GnomeCanvasImageFrame *image)
116 image->drawwidth = 0.0;
117 image->anchor = GTK_ANCHOR_CENTER;
119 // GNOME_CANVAS_ITEM(image)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
123 gnome_canvas_imageframe_destroy (GtkObject *object)
125 GnomeCanvasImageFrame *image;
127 g_return_if_fail (object != NULL);
128 g_return_if_fail (GNOME_CANVAS_IS_CANVAS_IMAGEFRAME (object));
130 image = GNOME_CANVAS_IMAGEFRAME (object);
137 art_pixbuf_free (image->pixbuf);
138 image->pixbuf = NULL;
141 if(GTK_OBJECT_CLASS (parent_class)->destroy)
143 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
147 /* Get's the image bounds expressed as item-relative coordinates. */
149 get_bounds_item_relative (GnomeCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2)
151 GnomeCanvasItem *item;
154 item = GNOME_CANVAS_ITEM (image);
156 /* Get item coordinates */
163 switch (image->anchor) {
170 case GTK_ANCHOR_CENTER:
172 x -= image->width / 2;
182 switch (image->anchor) {
189 case GTK_ANCHOR_CENTER:
191 y -= image->height / 2;
205 *px2 = x + image->width;
206 *py2 = y + image->height;
210 gnome_canvas_imageframe_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
212 GnomeCanvasItem *item;
213 GnomeCanvasImageFrame *image;
217 item = GNOME_CANVAS_ITEM (object);
218 image = GNOME_CANVAS_IMAGEFRAME (object);
225 if (item->canvas->aa && GTK_VALUE_BOXED (*arg)) {
226 if (image->pixbuf != NULL)
227 art_pixbuf_free (image->pixbuf);
228 image->pixbuf = GTK_VALUE_BOXED (*arg);
234 image->x = GTK_VALUE_DOUBLE (*arg);
239 image->y = GTK_VALUE_DOUBLE (*arg);
244 image->width = fabs (GTK_VALUE_DOUBLE (*arg));
249 image->height = fabs (GTK_VALUE_DOUBLE (*arg));
254 image->drawwidth = fabs (GTK_VALUE_DOUBLE (*arg));
259 image->anchor = GTK_VALUE_ENUM (*arg);
268 gnome_canvas_item_request_update (item);
272 gnome_canvas_imageframe_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
274 GnomeCanvasImageFrame *image;
276 image = GNOME_CANVAS_IMAGEFRAME (object);
281 GTK_VALUE_DOUBLE (*arg) = image->x;
285 GTK_VALUE_DOUBLE (*arg) = image->y;
289 GTK_VALUE_DOUBLE (*arg) = image->width;
293 GTK_VALUE_DOUBLE (*arg) = image->height;
297 GTK_VALUE_DOUBLE (*arg) = image->drawwidth;
301 GTK_VALUE_ENUM (*arg) = image->anchor;
305 arg->type = GTK_TYPE_INVALID;
311 gnome_canvas_imageframe_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
313 GnomeCanvasImageFrame *image;
314 ArtDRect i_bbox, c_bbox;
318 image = GNOME_CANVAS_IMAGEFRAME (item);
320 if (parent_class->update)
321 (* parent_class->update) (item, affine, clip_path, flags);
323 /* only works for non-rotated, non-skewed transforms */
324 image->cwidth = (int) (image->width * affine[0] + 0.5);
325 image->cheight = (int) (image->height * affine[3] + 0.5);
328 image->need_recalc = TRUE ;
331 get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
332 art_drect_affine_transform (&c_bbox, &i_bbox, affine);
334 /* these values only make sense in the non-rotated, non-skewed case */
335 image->cx = c_bbox.x0;
336 image->cy = c_bbox.y0;
338 /* add a fudge factor */
344 gnome_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1);
347 w = image->pixbuf->width;
348 h = image->pixbuf->height;
351 image->affine[0] = (affine[0] * image->width) / w;
352 image->affine[1] = (affine[1] * image->height) / h;
353 image->affine[2] = (affine[2] * image->width) / w;
354 image->affine[3] = (affine[3] * image->height) / h;
355 image->affine[4] = i_bbox.x0 * affine[0] + i_bbox.y0 * affine[2] + affine[4];
356 image->affine[5] = i_bbox.x0 * affine[1] + i_bbox.y0 * affine[3] + affine[5];
360 gnome_canvas_imageframe_realize (GnomeCanvasItem *item)
362 GnomeCanvasImageFrame *image;
364 image = GNOME_CANVAS_IMAGEFRAME (item);
366 if (parent_class->realize)
367 (* parent_class->realize) (item);
372 gnome_canvas_imageframe_unrealize (GnomeCanvasItem *item)
374 GnomeCanvasImageFrame *image;
376 image = GNOME_CANVAS_IMAGEFRAME(item);
378 if (parent_class->unrealize)
379 (* parent_class->unrealize) (item);
383 recalc_if_needed (GnomeCanvasImageFrame *image)
387 gnome_canvas_imageframe_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
388 int x, int y, int width, int height)
390 fprintf(stderr, "please don't use the CanvasImageFrame item in a non-aa Canvas\n") ;
395 gnome_canvas_imageframe_point (GnomeCanvasItem *item, double x, double y,
396 int cx, int cy, GnomeCanvasItem **actual_item)
398 GnomeCanvasImageFrame *image;
402 image = GNOME_CANVAS_IMAGEFRAME (item);
406 recalc_if_needed (image);
408 x1 = image->cx - item->canvas->close_enough;
409 y1 = image->cy - item->canvas->close_enough;
410 x2 = image->cx + image->cwidth - 1 + item->canvas->close_enough;
411 y2 = image->cy + image->cheight - 1 + item->canvas->close_enough;
413 /* Hard case: is point inside image's gravity region? */
415 //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2))
416 //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit;
418 /* Point is outside image */
420 x1 += item->canvas->close_enough;
421 y1 += item->canvas->close_enough;
422 x2 -= item->canvas->close_enough;
423 y2 -= item->canvas->close_enough;
439 return sqrt (dx * dx + dy * dy) / item->canvas->pixels_per_unit;
443 gnome_canvas_imageframe_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
445 GnomeCanvasImageFrame *image;
447 image = GNOME_CANVAS_IMAGEFRAME (item);
452 switch (image->anchor) {
459 case GTK_ANCHOR_CENTER:
461 *x1 -= image->width / 2.0;
471 switch (image->anchor) {
478 case GTK_ANCHOR_CENTER:
480 *y1 -= image->height / 2.0;
486 *y1 -= image->height;
490 *x2 = *x1 + image->width;
491 *y2 = *y1 + image->height;
495 gnome_canvas_imageframe_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
497 GnomeCanvasImageFrame *image;
499 image = GNOME_CANVAS_IMAGEFRAME (item);
501 gnome_canvas_buf_ensure_buf (buf);
506 art_affine_to_string (str, image->affine);
507 g_print ("gnome_canvas_imageframe_render %s\n", str);
511 art_rgb_pixbuf_affine (buf->buf,
512 buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
516 ART_FILTER_NEAREST, NULL);