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>
21 #include <libgnomecanvas/gnome-canvastypebuiltins.h>
36 static void gnome_canvas_imageframe_class_init(GnomeCanvasImageFrameClass* class) ;
37 static void gnome_canvas_imageframe_init(GnomeCanvasImageFrame* image) ;
38 static void gnome_canvas_imageframe_destroy(GtkObject* object) ;
39 static void gnome_canvas_imageframe_set_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
40 static void gnome_canvas_imageframe_get_arg(GtkObject* object, GtkArg* arg, guint arg_id) ;
42 static void gnome_canvas_imageframe_update(GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags) ;
43 static void gnome_canvas_imageframe_realize(GnomeCanvasItem *item) ;
44 static void gnome_canvas_imageframe_unrealize(GnomeCanvasItem *item) ;
45 static void gnome_canvas_imageframe_draw(GnomeCanvasItem *item, GdkDrawable *drawable, int x, int y, int width, int height) ;
46 static double gnome_canvas_imageframe_point(GnomeCanvasItem *item, double x, double y, int cx, int cy, GnomeCanvasItem **actual_item) ;
47 static void gnome_canvas_imageframe_translate(GnomeCanvasItem *item, double dx, double dy) ;
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->translate = gnome_canvas_imageframe_translate;
106 item_class->bounds = gnome_canvas_imageframe_bounds;
107 item_class->render = gnome_canvas_imageframe_render;
111 gnome_canvas_imageframe_init (GnomeCanvasImageFrame *image)
117 image->drawwidth = 0.0;
118 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 get_bounds (GnomeCanvasImageFrame *image, double *px1, double *py1, double *px2, double *py2)
212 GnomeCanvasItem *item;
214 ArtDRect i_bbox, c_bbox;
216 item = GNOME_CANVAS_ITEM (image);
218 gnome_canvas_item_i2c_affine (item, i2c);
220 get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
221 art_drect_affine_transform (&c_bbox, &i_bbox, i2c);
223 /* add a fudge factor */
224 *px1 = c_bbox.x0 - 1;
225 *py1 = c_bbox.y0 - 1;
226 *px2 = c_bbox.x1 + 1;
227 *py2 = c_bbox.y1 + 1;
232 recalc_bounds (GnomeCanvasImageFrame *image)
234 GnomeCanvasItem *item;
236 item = GNOME_CANVAS_ITEM (image);
238 get_bounds (image, &item->x1, &item->y1, &item->x2, &item->y2);
240 item->x1 = image->cx;
241 item->y1 = image->cy;
242 item->x2 = image->cx + image->cwidth;
243 item->y2 = image->cy + image->cheight;
245 gnome_canvas_group_child_bounds (GNOME_CANVAS_GROUP (item->parent), item);
249 gnome_canvas_imageframe_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
251 GnomeCanvasItem *item;
252 GnomeCanvasImageFrame *image;
256 item = GNOME_CANVAS_ITEM (object);
257 image = GNOME_CANVAS_IMAGEFRAME (object);
264 if (item->canvas->aa && GTK_VALUE_BOXED (*arg)) {
265 if (image->pixbuf != NULL)
266 art_pixbuf_free (image->pixbuf);
267 image->pixbuf = GTK_VALUE_BOXED (*arg);
273 image->x = GTK_VALUE_DOUBLE (*arg);
278 image->y = GTK_VALUE_DOUBLE (*arg);
283 image->width = fabs (GTK_VALUE_DOUBLE (*arg));
288 image->height = fabs (GTK_VALUE_DOUBLE (*arg));
293 image->drawwidth = fabs (GTK_VALUE_DOUBLE (*arg));
298 image->anchor = GTK_VALUE_ENUM (*arg);
308 (* GNOME_CANVAS_ITEM_CLASS (item->object.klass)->update) (item, NULL, NULL, 0);
311 recalc_bounds (image);
314 gnome_canvas_item_request_update (item);
319 gnome_canvas_imageframe_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
321 GnomeCanvasImageFrame *image;
323 image = GNOME_CANVAS_IMAGEFRAME (object);
328 GTK_VALUE_DOUBLE (*arg) = image->x;
332 GTK_VALUE_DOUBLE (*arg) = image->y;
336 GTK_VALUE_DOUBLE (*arg) = image->width;
340 GTK_VALUE_DOUBLE (*arg) = image->height;
344 GTK_VALUE_DOUBLE (*arg) = image->drawwidth;
348 GTK_VALUE_ENUM (*arg) = image->anchor;
352 arg->type = GTK_TYPE_INVALID;
358 gnome_canvas_imageframe_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
360 GnomeCanvasImageFrame *image;
361 ArtDRect i_bbox, c_bbox;
365 image = GNOME_CANVAS_IMAGEFRAME (item);
367 if (parent_class->update)
368 (* parent_class->update) (item, affine, clip_path, flags);
370 /* only works for non-rotated, non-skewed transforms */
371 image->cwidth = (int) (image->width * affine[0] + 0.5);
372 image->cheight = (int) (image->height * affine[3] + 0.5);
375 image->need_recalc = TRUE ;
379 recalc_bounds (image);
381 get_bounds_item_relative (image, &i_bbox.x0, &i_bbox.y0, &i_bbox.x1, &i_bbox.y1);
382 art_drect_affine_transform (&c_bbox, &i_bbox, affine);
384 /* these values only make sense in the non-rotated, non-skewed case */
385 image->cx = c_bbox.x0;
386 image->cy = c_bbox.y0;
388 /* add a fudge factor */
394 gnome_canvas_update_bbox (item, c_bbox.x0, c_bbox.y0, c_bbox.x1, c_bbox.y1);
397 w = image->pixbuf->width;
398 h = image->pixbuf->height;
401 image->affine[0] = (affine[0] * image->width) / w;
402 image->affine[1] = (affine[1] * image->height) / h;
403 image->affine[2] = (affine[2] * image->width) / w;
404 image->affine[3] = (affine[3] * image->height) / h;
405 image->affine[4] = i_bbox.x0 * affine[0] + i_bbox.y0 * affine[2] + affine[4];
406 image->affine[5] = i_bbox.x0 * affine[1] + i_bbox.y0 * affine[3] + affine[5];
412 gnome_canvas_imageframe_realize (GnomeCanvasItem *item)
414 GnomeCanvasImageFrame *image;
416 image = GNOME_CANVAS_IMAGEFRAME (item);
418 if (parent_class->realize)
419 (* parent_class->realize) (item);
424 gnome_canvas_imageframe_unrealize (GnomeCanvasItem *item)
426 GnomeCanvasImageFrame *image;
428 image = GNOME_CANVAS_IMAGEFRAME(item);
430 if (parent_class->unrealize)
431 (* parent_class->unrealize) (item);
435 recalc_if_needed (GnomeCanvasImageFrame *image)
439 gnome_canvas_imageframe_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
440 int x, int y, int width, int height)
442 fprintf(stderr, "please don't use the CanvasImageFrame item in a non-aa Canvas\n") ;
447 gnome_canvas_imageframe_point (GnomeCanvasItem *item, double x, double y,
448 int cx, int cy, GnomeCanvasItem **actual_item)
450 GnomeCanvasImageFrame *image;
454 image = GNOME_CANVAS_IMAGEFRAME (item);
458 recalc_if_needed (image);
460 x1 = image->cx - item->canvas->close_enough;
461 y1 = image->cy - item->canvas->close_enough;
462 x2 = image->cx + image->cwidth - 1 + item->canvas->close_enough;
463 y2 = image->cy + image->cheight - 1 + item->canvas->close_enough;
465 /* Hard case: is point inside image's gravity region? */
467 //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2))
468 //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit;
470 /* Point is outside image */
472 x1 += item->canvas->close_enough;
473 y1 += item->canvas->close_enough;
474 x2 -= item->canvas->close_enough;
475 y2 -= item->canvas->close_enough;
491 return sqrt (dx * dx + dy * dy) / item->canvas->pixels_per_unit;
495 gnome_canvas_imageframe_translate (GnomeCanvasItem *item, double dx, double dy)
498 GnomeCanvasImageFrame *image;
500 image = GNOME_CANVAS_IMAGEFRAME (item);
505 recalc_bounds (image);
510 gnome_canvas_imageframe_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
512 GnomeCanvasImageFrame *image;
514 image = GNOME_CANVAS_IMAGEFRAME (item);
519 switch (image->anchor) {
526 case GTK_ANCHOR_CENTER:
528 *x1 -= image->width / 2.0;
538 switch (image->anchor) {
545 case GTK_ANCHOR_CENTER:
547 *y1 -= image->height / 2.0;
553 *y1 -= image->height;
557 *x2 = *x1 + image->width;
558 *y2 = *y1 + image->height;
562 gnome_canvas_imageframe_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
564 GnomeCanvasImageFrame *image;
566 image = GNOME_CANVAS_IMAGEFRAME (item);
568 gnome_canvas_buf_ensure_buf (buf);
573 art_affine_to_string (str, image->affine);
574 g_print ("gnome_canvas_imageframe_render %s\n", str);
578 art_rgb_pixbuf_affine (buf->buf,
579 buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
583 ART_FILTER_NEAREST, NULL);