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_pointer ("pixbuf",
107 g_object_class_install_property (gobject_class
,
109 g_param_spec_double ("x",
111 _("x coordinate of upper left corner of rect"),
117 g_object_class_install_property (gobject_class
,
119 g_param_spec_double ("y",
121 _("y coordinate of upper left corner of rect "),
126 g_object_class_install_property (gobject_class
,
128 g_param_spec_double ("width",
136 g_object_class_install_property (gobject_class
,
138 g_param_spec_double ("drawwidth",
145 g_object_class_install_property (gobject_class
,
147 g_param_spec_double ("height",
154 g_object_class_install_property (gobject_class
,
156 g_param_spec_enum ("anchor",
159 GTK_TYPE_ANCHOR_TYPE
,
163 object_class
->destroy
= gnome_canvas_imageframe_destroy
;
165 item_class
->update
= gnome_canvas_imageframe_update
;
166 item_class
->realize
= gnome_canvas_imageframe_realize
;
167 item_class
->unrealize
= gnome_canvas_imageframe_unrealize
;
168 item_class
->draw
= gnome_canvas_imageframe_draw
;
169 item_class
->point
= gnome_canvas_imageframe_point
;
170 item_class
->bounds
= gnome_canvas_imageframe_bounds
;
171 item_class
->render
= gnome_canvas_imageframe_render
;
175 gnome_canvas_imageframe_init (GnomeCanvasImageFrame
*image
)
181 image
->drawwidth
= 0.0;
182 image
->anchor
= GTK_ANCHOR_CENTER
;
186 gnome_canvas_imageframe_destroy (GtkObject
*object
)
188 GnomeCanvasImageFrame
*image
;
190 g_return_if_fail (object
!= NULL
);
191 g_return_if_fail (GNOME_CANVAS_IS_CANVAS_IMAGEFRAME (object
));
193 image
= GNOME_CANVAS_IMAGEFRAME (object
);
200 art_pixbuf_free (image
->pixbuf
);
201 image
->pixbuf
= NULL
;
204 if(GTK_OBJECT_CLASS (parent_class
)->destroy
)
206 (* GTK_OBJECT_CLASS (parent_class
)->destroy
) (object
);
210 /* Get's the image bounds expressed as item-relative coordinates. */
212 get_bounds_item_relative (GnomeCanvasImageFrame
*image
, double *px1
, double *py1
, double *px2
, double *py2
)
214 GnomeCanvasItem
*item
;
217 item
= GNOME_CANVAS_ITEM (image
);
219 /* Get item coordinates */
226 switch (image
->anchor
) {
233 case GTK_ANCHOR_CENTER
:
235 x
-= image
->width
/ 2;
245 switch (image
->anchor
) {
252 case GTK_ANCHOR_CENTER
:
254 y
-= image
->height
/ 2;
268 *px2
= x
+ image
->width
;
269 *py2
= y
+ image
->height
;
273 gnome_canvas_imageframe_set_property (GObject
*object
,
278 GnomeCanvasItem
*item
;
279 GnomeCanvasImageFrame
*image
;
283 item
= GNOME_CANVAS_ITEM (object
);
284 image
= GNOME_CANVAS_IMAGEFRAME (object
);
291 if (item
->canvas
->aa
&& g_value_get_pointer (value
)) {
292 if (image
->pixbuf
!= NULL
)
293 art_pixbuf_free (image
->pixbuf
);
294 image
->pixbuf
= g_value_get_pointer (value
);
300 image
->x
= g_value_get_double (value
);
305 image
->y
= g_value_get_double (value
);
310 image
->width
= fabs (g_value_get_double (value
));
315 image
->height
= fabs (g_value_get_double (value
));
320 image
->drawwidth
= fabs (g_value_get_double (value
));
325 image
->anchor
= g_value_get_enum (value
);
334 gnome_canvas_item_request_update (item
);
338 gnome_canvas_imageframe_get_property (GObject
*object
,
343 GnomeCanvasImageFrame
*image
;
345 image
= GNOME_CANVAS_IMAGEFRAME (object
);
350 g_value_set_double (value
, image
->x
);
354 g_value_set_double (value
, image
->y
);
358 g_value_set_double (value
, image
->width
);
362 g_value_set_double (value
, image
->height
);
366 g_value_set_double (value
, image
->drawwidth
);
370 g_value_set_enum (value
, image
->anchor
);
374 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
380 gnome_canvas_imageframe_update (GnomeCanvasItem
*item
, double *affine
, ArtSVP
*clip_path
, int flags
)
382 GnomeCanvasImageFrame
*image
;
383 ArtDRect i_bbox
, c_bbox
;
387 image
= GNOME_CANVAS_IMAGEFRAME (item
);
389 if (parent_class
->update
)
390 (* parent_class
->update
) (item
, affine
, clip_path
, flags
);
392 /* only works for non-rotated, non-skewed transforms */
393 image
->cwidth
= (int) (image
->width
* affine
[0] + 0.5);
394 image
->cheight
= (int) (image
->height
* affine
[3] + 0.5);
397 image
->need_recalc
= TRUE
;
400 get_bounds_item_relative (image
, &i_bbox
.x0
, &i_bbox
.y0
, &i_bbox
.x1
, &i_bbox
.y1
);
401 art_drect_affine_transform (&c_bbox
, &i_bbox
, affine
);
403 /* these values only make sense in the non-rotated, non-skewed case */
404 image
->cx
= c_bbox
.x0
;
405 image
->cy
= c_bbox
.y0
;
407 /* add a fudge factor */
413 gnome_canvas_update_bbox (item
, c_bbox
.x0
, c_bbox
.y0
, c_bbox
.x1
, c_bbox
.y1
);
416 w
= image
->pixbuf
->width
;
417 h
= image
->pixbuf
->height
;
420 image
->affine
[0] = (affine
[0] * image
->width
) / w
;
421 image
->affine
[1] = (affine
[1] * image
->height
) / h
;
422 image
->affine
[2] = (affine
[2] * image
->width
) / w
;
423 image
->affine
[3] = (affine
[3] * image
->height
) / h
;
424 image
->affine
[4] = i_bbox
.x0
* affine
[0] + i_bbox
.y0
* affine
[2] + affine
[4];
425 image
->affine
[5] = i_bbox
.x0
* affine
[1] + i_bbox
.y0
* affine
[3] + affine
[5];
429 gnome_canvas_imageframe_realize (GnomeCanvasItem
*item
)
431 GnomeCanvasImageFrame
*image
;
433 image
= GNOME_CANVAS_IMAGEFRAME (item
);
435 if (parent_class
->realize
)
436 (* parent_class
->realize
) (item
);
441 gnome_canvas_imageframe_unrealize (GnomeCanvasItem
*item
)
443 GnomeCanvasImageFrame
*image
;
445 image
= GNOME_CANVAS_IMAGEFRAME(item
);
447 if (parent_class
->unrealize
)
448 (* parent_class
->unrealize
) (item
);
452 recalc_if_needed (GnomeCanvasImageFrame
*image
)
456 gnome_canvas_imageframe_draw (GnomeCanvasItem
*item
, GdkDrawable
*drawable
,
457 int x
, int y
, int width
, int height
)
462 gnome_canvas_imageframe_point (GnomeCanvasItem
*item
, double x
, double y
,
463 int cx
, int cy
, GnomeCanvasItem
**actual_item
)
465 GnomeCanvasImageFrame
*image
;
469 image
= GNOME_CANVAS_IMAGEFRAME (item
);
473 recalc_if_needed (image
);
475 x1
= image
->cx
- item
->canvas
->close_enough
;
476 y1
= image
->cy
- item
->canvas
->close_enough
;
477 x2
= image
->cx
+ image
->cwidth
- 1 + item
->canvas
->close_enough
;
478 y2
= image
->cy
+ image
->cheight
- 1 + item
->canvas
->close_enough
;
480 /* Hard case: is point inside image's gravity region? */
482 //if ((cx >= x1) && (cy >= y1) && (cx <= x2) && (cy <= y2))
483 //return dist_to_mask (image, cx, cy) / item->canvas->pixels_per_unit;
485 /* Point is outside image */
487 x1
+= item
->canvas
->close_enough
;
488 y1
+= item
->canvas
->close_enough
;
489 x2
-= item
->canvas
->close_enough
;
490 y2
-= item
->canvas
->close_enough
;
506 return sqrt (dx
* dx
+ dy
* dy
) / item
->canvas
->pixels_per_unit
;
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
);