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 #define _(Text) dgettext (PACKAGE,Text)
25 //#include <libgnomecanvas/gnome-canvastypebuiltins.h>
40 static void gnome_canvas_imageframe_class_init(GnomeCanvasImageFrameClass* class) ;
41 static void gnome_canvas_imageframe_init(GnomeCanvasImageFrame* image) ;
42 static void gnome_canvas_imageframe_destroy(GtkObject* object) ;
43 static void gnome_canvas_imageframe_set_property(GObject* object,
47 static void gnome_canvas_imageframe_get_property(GObject* object,
51 static void gnome_canvas_imageframe_update(GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) ;
52 static void gnome_canvas_imageframe_realize(GnomeCanvasItem *item) ;
53 static void gnome_canvas_imageframe_unrealize(GnomeCanvasItem *item) ;
54 static void gnome_canvas_imageframe_draw(GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) ;
55 static double gnome_canvas_imageframe_point(GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) ;
56 static void gnome_canvas_imageframe_bounds(GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2) ;
57 static void gnome_canvas_imageframe_render(GnomeCanvasItem *item, GnomeCanvasBuf *buf) ;
59 static GnomeCanvasItemClass *parent_class;
63 gnome_canvas_imageframe_get_type (void)
65 static GType imageframe_type = 0;
67 if (!imageframe_type) {
68 GtkTypeInfo imageframe_info = {
69 "GnomeCanvasImageFrame",
70 sizeof (GnomeCanvasImageFrame),
71 sizeof (GnomeCanvasImageFrameClass),
72 (GtkClassInitFunc) gnome_canvas_imageframe_class_init,
73 (GtkObjectInitFunc) gnome_canvas_imageframe_init,
74 NULL, /* reserved_1 */
75 NULL, /* reserved_2 */
76 (GtkClassInitFunc) NULL
79 imageframe_type = gtk_type_unique (gnome_canvas_item_get_type (), &imageframe_info);
82 return imageframe_type;
86 gnome_canvas_imageframe_class_init (GnomeCanvasImageFrameClass *class)
88 GObjectClass *gobject_class;
89 GtkObjectClass *object_class;
90 GnomeCanvasItemClass *item_class;
92 gobject_class = (GObjectClass *) class;
93 object_class = (GtkObjectClass *) class;
94 item_class = (GnomeCanvasItemClass *) class;
96 parent_class = gtk_type_class (gnome_canvas_item_get_type ());
98 gobject_class->set_property = gnome_canvas_imageframe_set_property;
99 gobject_class->get_property = gnome_canvas_imageframe_get_property;
101 g_object_class_install_property (gobject_class,
103 g_param_spec_boxed ("pixbuf",
108 g_object_class_install_property (gobject_class,
110 g_param_spec_double ("x",
112 _("x coordinate of upper left corner of rect"),
118 g_object_class_install_property (gobject_class,
120 g_param_spec_double ("y",
122 _("y coordinate of upper left corner of rect "),
127 g_object_class_install_property (gobject_class,
129 g_param_spec_double ("width",
137 g_object_class_install_property (gobject_class,
139 g_param_spec_double ("drawwidth",
146 g_object_class_install_property (gobject_class,
148 g_param_spec_double ("height",
155 g_object_class_install_property (gobject_class,
157 g_param_spec_enum ("anchor",
160 GTK_TYPE_ANCHOR_TYPE,
164 object_class->destroy = gnome_canvas_imageframe_destroy;
166 item_class->update = gnome_canvas_imageframe_update;
167 item_class->realize = gnome_canvas_imageframe_realize;
168 item_class->unrealize = gnome_canvas_imageframe_unrealize;
169 item_class->draw = gnome_canvas_imageframe_draw;
170 item_class->point = gnome_canvas_imageframe_point;
171 item_class->bounds = gnome_canvas_imageframe_bounds;
172 item_class->render = gnome_canvas_imageframe_render;
176 gnome_canvas_imageframe_init (GnomeCanvasImageFrame *image)
182 image->drawwidth = 0.0;
183 image->anchor = GTK_ANCHOR_CENTER;
185 // GNOME_CANVAS_ITEM(image)->object.flags |= GNOME_CANVAS_ITEM_NO_AUTO_REDRAW;
189 gnome_canvas_imageframe_destroy (GtkObject *object)
191 GnomeCanvasImageFrame *image;
193 g_return_if_fail (object != NULL);
194 g_return_if_fail (GNOME_CANVAS_IS_CANVAS_IMAGEFRAME (object));
196 image = GNOME_CANVAS_IMAGEFRAME (object);
203 art_pixbuf_free (image->pixbuf);
204 image->pixbuf = NULL;
207 if(GTK_OBJECT_CLASS (parent_class)->destroy)
209 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
213 /* Get's the image bounds expressed as item-relative coordinates. */
215 get_bounds_item_relative (GnomeCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2)
217 GnomeCanvasItem *item;
220 item = GNOME_CANVAS_ITEM (image);
222 /* Get item coordinates */
229 switch (image->anchor) {
236 case GTK_ANCHOR_CENTER:
238 x -= image->width / 2;
248 switch (image->anchor) {
255 case GTK_ANCHOR_CENTER:
257 y -= image->height / 2;
271 *px2 = x + image->width;
272 *py2 = y + image->height;
276 gnome_canvas_imageframe_set_property (GObject *object,
281 GnomeCanvasItem *item;
282 GnomeCanvasImageFrame *image;
286 item = GNOME_CANVAS_ITEM (object);
287 image = GNOME_CANVAS_IMAGEFRAME (object);
294 if (item->canvas->aa && g_value_get_boxed (value)) {
295 if (image->pixbuf != NULL)
296 art_pixbuf_free (image->pixbuf);
297 image->pixbuf = g_value_get_boxed (value);
303 image->x = g_value_get_double (value);
308 image->y = g_value_get_double (value);
313 image->width = fabs (g_value_get_double (value));
318 image->height = fabs (g_value_get_double (value));
323 image->drawwidth = fabs (g_value_get_double (value));
328 image->anchor = g_value_get_enum (value);
337 gnome_canvas_item_request_update (item);
341 gnome_canvas_imageframe_get_property (GObject *object,
346 GnomeCanvasImageFrame *image;
348 image = GNOME_CANVAS_IMAGEFRAME (object);
353 g_value_set_double (value, image->x);
357 g_value_set_double (value, image->y);
361 g_value_set_double (value, image->width);
365 g_value_set_double (value, image->height);
369 g_value_set_double (value, image->drawwidth);
373 g_value_set_enum (value, image->anchor);
377 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
383 gnome_canvas_imageframe_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
385 GnomeCanvasImageFrame *image;
386 ArtDRect i_bbox, c_bbox;
390 image = GNOME_CANVAS_IMAGEFRAME (item);
392 if (parent_class->update)
393 (* parent_class->update) (item, affine, clip_path, flags);
395 /* only works for non-rotated, non-skewed transforms */
396 image->cwidth = (int) (image->width * affine[0] + 0.5);
397 image->cheight = (int) (image->height * affine[3] + 0.5);
400 image->need_recalc = TRUE ;
403 get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
404 art_drect_affine_transform (&c_bbox, &i_bbox, affine);
406 /* these values only make sense in the non-rotated, non-skewed case */
407 image->cx = c_bbox.x0;
408 image->cy = c_bbox.y0;
410 /* add a fudge factor */
416 gnome_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1);
419 w = image->pixbuf->width;
420 h = image->pixbuf->height;
423 image->affine[0] = (affine[0] * image->width) / w;
424 image->affine[1] = (affine[1] * image->height) / h;
425 image->affine[2] = (affine[2] * image->width) / w;
426 image->affine[3] = (affine[3] * image->height) / h;
427 image->affine[4] = i_bbox.x0 * affine[0] + i_bbox.y0 * affine[2] + affine[4];
428 image->affine[5] = i_bbox.x0 * affine[1] + i_bbox.y0 * affine[3] + affine[5];
432 gnome_canvas_imageframe_realize (GnomeCanvasItem *item)
434 GnomeCanvasImageFrame *image;
436 image = GNOME_CANVAS_IMAGEFRAME (item);
438 if (parent_class->realize)
439 (* parent_class->realize) (item);
444 gnome_canvas_imageframe_unrealize (GnomeCanvasItem *item)
446 GnomeCanvasImageFrame *image;
448 image = GNOME_CANVAS_IMAGEFRAME(item);
450 if (parent_class->unrealize)
451 (* parent_class->unrealize) (item);
455 recalc_if_needed (GnomeCanvasImageFrame *image)
459 gnome_canvas_imageframe_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
460 int x, int y, int width, int height)
462 fprintf(stderr, "please don't use the CanvasImageFrame item in a non-aa Canvas\n") ;
467 gnome_canvas_imageframe_point (GnomeCanvasItem *item, double x, double y,
468 int cx, int cy, GnomeCanvasItem **actual_item)
470 GnomeCanvasImageFrame *image;
474 image = GNOME_CANVAS_IMAGEFRAME (item);
478 recalc_if_needed (image);
480 x1 = image->cx - item->canvas->close_enough;
481 y1 = image->cy - item->canvas->close_enough;
482 x2 = image->cx + image->cwidth - 1 + item->canvas->close_enough;
483 y2 = image->cy + image->cheight - 1 + item->canvas->close_enough;
485 /* Hard case: is point inside image's gravity region? */
487 //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2))
488 //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit;
490 /* Point is outside image */
492 x1 += item->canvas->close_enough;
493 y1 += item->canvas->close_enough;
494 x2 -= item->canvas->close_enough;
495 y2 -= item->canvas->close_enough;
511 return sqrt (dx * dx + dy * dy) / item->canvas->pixels_per_unit;
515 gnome_canvas_imageframe_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
517 GnomeCanvasImageFrame *image;
519 image = GNOME_CANVAS_IMAGEFRAME (item);
524 switch (image->anchor) {
531 case GTK_ANCHOR_CENTER:
533 *x1 -= image->width / 2.0;
543 switch (image->anchor) {
550 case GTK_ANCHOR_CENTER:
552 *y1 -= image->height / 2.0;
558 *y1 -= image->height;
562 *x2 = *x1 + image->width;
563 *y2 = *y1 + image->height;
567 gnome_canvas_imageframe_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
569 GnomeCanvasImageFrame *image;
571 image = GNOME_CANVAS_IMAGEFRAME (item);
573 gnome_canvas_buf_ensure_buf (buf);
578 art_affine_to_string (str, image->affine);
579 g_print ("gnome_canvas_imageframe_render %s\n", str);
583 art_rgb_pixbuf_affine (buf->buf,
584 buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
588 ART_FILTER_NEAREST, NULL);