am-project: Rename AM_PROPERTY_COMPILATION_FLAG
[anjuta.git] / libfoocanvas / foo-canvas-pixbuf.c
blob0816b070624d6ac9561ba52f00f34c29819c325b
1 /* GNOME libraries - GdkPixbuf item for the GNOME canvas
3 * Copyright (C) 1999 The Free Software Foundation
5 * Author: Federico Mena-Quintero <federico@gimp.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 #include <config.h>
24 #include <math.h>
25 #include <libfoocanvas/foo-canvas.h>
26 #include <libfoocanvas/foo-canvas-util.h>
27 #include <gdk-pixbuf/gdk-pixbuf.h>
28 #include "foo-canvas-pixbuf.h"
30 /* Private part of the FooCanvasPixbuf structure */
31 typedef struct {
32 /* Our gdk-pixbuf */
33 GdkPixbuf *pixbuf, *pixbuf_scaled;
35 /* Width value */
36 double width;
38 /* Height value */
39 double height;
41 /* X translation */
42 double x;
44 /* Y translation */
45 double y;
47 /* Whether dimensions are set and whether they are in pixels or units */
48 guint width_set : 1;
49 guint width_in_pixels : 1;
50 guint height_set : 1;
51 guint height_in_pixels : 1;
52 guint x_in_pixels : 1;
53 guint y_in_pixels : 1;
55 /* Whether the pixbuf has changed */
56 guint need_pixbuf_update : 1;
58 /* Whether the transformation or size have changed */
59 guint need_xform_update : 1;
61 /* Should the point method ignore transparent areas */
62 guint point_ignores_alpha : 1;
64 /* Anchor */
65 GtkAnchorType anchor;
67 /* Approximation method used for transformations */
68 GdkInterpType interp_type;
70 } PixbufPrivate;
72 /* Object argument IDs */
73 enum {
74 PROP_0,
75 PROP_PIXBUF,
76 PROP_WIDTH,
77 PROP_WIDTH_SET,
78 PROP_WIDTH_IN_PIXELS,
79 PROP_HEIGHT,
80 PROP_HEIGHT_SET,
81 PROP_HEIGHT_IN_PIXELS,
82 PROP_X,
83 PROP_X_IN_PIXELS,
84 PROP_Y,
85 PROP_Y_IN_PIXELS,
86 PROP_ANCHOR,
87 PROP_INTERP_TYPE,
88 PROP_POINT_IGNORES_ALPHA
91 static void foo_canvas_pixbuf_class_init (FooCanvasPixbufClass *klass);
92 static void foo_canvas_pixbuf_init (FooCanvasPixbuf *cpb);
93 static void foo_canvas_pixbuf_destroy (GtkObject *object);
94 static void foo_canvas_pixbuf_set_property (GObject *object,
95 guint param_id,
96 const GValue *value,
97 GParamSpec *pspec);
98 static void foo_canvas_pixbuf_get_property (GObject *object,
99 guint param_id,
100 GValue *value,
101 GParamSpec *pspec);
103 static void foo_canvas_pixbuf_update (FooCanvasItem *item,
104 double i2w_dx, double i2w_dy,
105 int flags);
106 static void foo_canvas_pixbuf_draw (FooCanvasItem *item, GdkDrawable *drawable,
107 GdkEventExpose *expose);
108 static double foo_canvas_pixbuf_point (FooCanvasItem *item, double x, double y, int cx, int cy,
109 FooCanvasItem **actual_item);
110 static void foo_canvas_pixbuf_translate (FooCanvasItem *item, double dx, double dy);
111 static void foo_canvas_pixbuf_bounds (FooCanvasItem *item,
112 double *x1, double *y1, double *x2, double *y2);
114 static FooCanvasItemClass *parent_class;
116 G_DEFINE_TYPE (FooCanvasPixbuf, foo_canvas_pixbuf, FOO_TYPE_CANVAS_ITEM)
118 /* Class initialization function for the pixbuf canvas item */
119 static void
120 foo_canvas_pixbuf_class_init (FooCanvasPixbufClass *klass)
122 GObjectClass *gobject_class;
123 GtkObjectClass *object_class;
124 FooCanvasItemClass *item_class;
126 gobject_class = (GObjectClass *) klass;
127 object_class = (GtkObjectClass *) klass;
128 item_class = (FooCanvasItemClass *) klass;
130 parent_class = g_type_class_peek (foo_canvas_item_get_type ());
132 gobject_class->set_property = foo_canvas_pixbuf_set_property;
133 gobject_class->get_property = foo_canvas_pixbuf_get_property;
135 g_object_class_install_property
136 (gobject_class,
137 PROP_PIXBUF,
138 g_param_spec_object ("pixbuf", NULL, NULL,
139 GDK_TYPE_PIXBUF,
140 G_PARAM_READWRITE));
141 g_object_class_install_property
142 (gobject_class,
143 PROP_WIDTH,
144 g_param_spec_double ("width", NULL, NULL,
145 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
146 G_PARAM_READWRITE));
147 g_object_class_install_property
148 (gobject_class,
149 PROP_WIDTH_SET,
150 g_param_spec_boolean ("width-set", NULL, NULL,
151 FALSE,
152 G_PARAM_READWRITE));
153 g_object_class_install_property
154 (gobject_class,
155 PROP_WIDTH_IN_PIXELS,
156 g_param_spec_boolean ("width-in-pixels", NULL, NULL,
157 FALSE,
158 G_PARAM_READWRITE));
159 g_object_class_install_property
160 (gobject_class,
161 PROP_HEIGHT,
162 g_param_spec_double ("height", NULL, NULL,
163 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
164 G_PARAM_READWRITE));
165 g_object_class_install_property
166 (gobject_class,
167 PROP_HEIGHT_SET,
168 g_param_spec_boolean ("height-set", NULL, NULL,
169 FALSE,
170 G_PARAM_READWRITE));
171 g_object_class_install_property
172 (gobject_class,
173 PROP_HEIGHT_IN_PIXELS,
174 g_param_spec_boolean ("height-in-pixels", NULL, NULL,
175 FALSE,
176 G_PARAM_READWRITE));
177 g_object_class_install_property
178 (gobject_class,
179 PROP_X,
180 g_param_spec_double ("x", NULL, NULL,
181 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
182 G_PARAM_READWRITE));
183 g_object_class_install_property
184 (gobject_class,
185 PROP_X_IN_PIXELS,
186 g_param_spec_boolean ("x-in-pixels", NULL, NULL,
187 FALSE,
188 G_PARAM_READWRITE));
189 g_object_class_install_property
190 (gobject_class,
191 PROP_Y,
192 g_param_spec_double ("y", NULL, NULL,
193 -G_MAXDOUBLE, G_MAXDOUBLE, 0,
194 G_PARAM_READWRITE));
195 g_object_class_install_property
196 (gobject_class,
197 PROP_Y_IN_PIXELS,
198 g_param_spec_boolean ("y-in-pixels", NULL, NULL,
199 FALSE,
200 G_PARAM_READWRITE));
201 g_object_class_install_property
202 (gobject_class,
203 PROP_ANCHOR,
204 g_param_spec_enum ("anchor", NULL, NULL,
205 GTK_TYPE_ANCHOR_TYPE,
206 GTK_ANCHOR_NW,
207 G_PARAM_READWRITE));
208 g_object_class_install_property
209 (gobject_class,
210 PROP_INTERP_TYPE,
211 g_param_spec_enum ("interp-type", NULL, NULL,
212 GDK_TYPE_INTERP_TYPE,
213 GDK_INTERP_BILINEAR,
214 G_PARAM_READWRITE));
215 g_object_class_install_property
216 (gobject_class,
217 PROP_POINT_IGNORES_ALPHA,
218 g_param_spec_boolean ("point-ignores-alpha", NULL, NULL,
219 FALSE,
220 G_PARAM_READWRITE));
222 object_class->destroy = foo_canvas_pixbuf_destroy;
224 item_class->update = foo_canvas_pixbuf_update;
225 item_class->draw = foo_canvas_pixbuf_draw;
226 item_class->point = foo_canvas_pixbuf_point;
227 item_class->translate = foo_canvas_pixbuf_translate;
228 item_class->bounds = foo_canvas_pixbuf_bounds;
231 /* Object initialization function for the pixbuf canvas item */
232 static void
233 foo_canvas_pixbuf_init (FooCanvasPixbuf *gcp)
235 PixbufPrivate *priv;
237 priv = g_new0 (PixbufPrivate, 1);
238 gcp->priv = priv;
240 priv->width = 0.0;
241 priv->height = 0.0;
242 priv->x = 0.0;
243 priv->y = 0.0;
244 priv->anchor = GTK_ANCHOR_NW;
245 priv->interp_type = GDK_INTERP_BILINEAR;
246 priv->point_ignores_alpha = FALSE;
249 /* Destroy handler for the pixbuf canvas item */
250 static void
251 foo_canvas_pixbuf_destroy (GtkObject *object)
253 FooCanvasItem *item;
254 FooCanvasPixbuf *gcp;
255 PixbufPrivate *priv;
257 g_return_if_fail (object != NULL);
258 g_return_if_fail (FOO_IS_CANVAS_PIXBUF (object));
260 item = FOO_CANVAS_ITEM (object);
261 gcp = (FOO_CANVAS_PIXBUF (object));
262 priv = gcp->priv;
264 /* remember, destroy can be run multiple times! */
266 if (priv) {
267 foo_canvas_item_request_redraw (item);
269 if (priv->pixbuf)
270 g_object_unref (priv->pixbuf);
271 if (priv->pixbuf_scaled)
272 g_object_unref (priv->pixbuf_scaled);
274 g_free (priv);
275 gcp->priv = NULL;
278 if (GTK_OBJECT_CLASS (parent_class)->destroy)
279 (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
284 /* Set_property handler for the pixbuf canvas item */
285 static void
286 foo_canvas_pixbuf_set_property (GObject *object,
287 guint param_id,
288 const GValue *value,
289 GParamSpec *pspec)
291 FooCanvasItem *item;
292 FooCanvasPixbuf *gcp;
293 PixbufPrivate *priv;
294 GdkPixbuf *pixbuf;
295 double val;
297 g_return_if_fail (object != NULL);
298 g_return_if_fail (FOO_IS_CANVAS_PIXBUF (object));
300 item = FOO_CANVAS_ITEM (object);
301 gcp = FOO_CANVAS_PIXBUF (object);
302 priv = gcp->priv;
304 switch (param_id) {
305 case PROP_PIXBUF:
306 if (g_value_get_object (value))
307 pixbuf = GDK_PIXBUF (g_value_get_object (value));
308 else
309 pixbuf = NULL;
310 if (pixbuf != priv->pixbuf) {
311 if (pixbuf) {
312 g_return_if_fail
313 (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
314 g_return_if_fail
315 (gdk_pixbuf_get_n_channels (pixbuf) == 3
316 || gdk_pixbuf_get_n_channels (pixbuf) == 4);
317 g_return_if_fail
318 (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
320 g_object_ref (pixbuf);
323 if (priv->pixbuf)
324 g_object_unref (priv->pixbuf);
325 priv->pixbuf = pixbuf;
327 if (priv->pixbuf_scaled) {
328 g_object_unref (priv->pixbuf_scaled);
329 priv->pixbuf_scaled = NULL;
333 priv->need_pixbuf_update = TRUE;
334 foo_canvas_item_request_update (item);
335 break;
337 case PROP_WIDTH:
338 val = g_value_get_double (value);
339 g_return_if_fail (val >= 0.0);
340 priv->width = val;
341 priv->need_xform_update = TRUE;
342 foo_canvas_item_request_update (item);
343 break;
345 case PROP_WIDTH_SET:
346 priv->width_set = g_value_get_boolean (value);
347 priv->need_xform_update = TRUE;
348 foo_canvas_item_request_update (item);
349 break;
351 case PROP_WIDTH_IN_PIXELS:
352 priv->width_in_pixels = g_value_get_boolean (value);
353 priv->need_xform_update = TRUE;
354 foo_canvas_item_request_update (item);
355 break;
357 case PROP_HEIGHT:
358 val = g_value_get_double (value);
359 g_return_if_fail (val >= 0.0);
360 priv->height = val;
361 priv->need_xform_update = TRUE;
362 foo_canvas_item_request_update (item);
363 break;
365 case PROP_HEIGHT_SET:
366 priv->height_set = g_value_get_boolean (value);
367 priv->need_xform_update = TRUE;
368 foo_canvas_item_request_update (item);
369 break;
371 case PROP_HEIGHT_IN_PIXELS:
372 priv->height_in_pixels = g_value_get_boolean (value);
373 priv->need_xform_update = TRUE;
374 foo_canvas_item_request_update (item);
375 break;
377 case PROP_X:
378 priv->x = g_value_get_double (value);
379 priv->need_xform_update = TRUE;
380 foo_canvas_item_request_update (item);
381 break;
383 case PROP_X_IN_PIXELS:
384 priv->x_in_pixels = g_value_get_boolean (value);
385 priv->need_xform_update = TRUE;
386 foo_canvas_item_request_update (item);
387 break;
389 case PROP_Y:
390 priv->y = g_value_get_double (value);
391 priv->need_xform_update = TRUE;
392 foo_canvas_item_request_update (item);
393 break;
395 case PROP_Y_IN_PIXELS:
396 priv->y_in_pixels = g_value_get_boolean (value);
397 priv->need_xform_update = TRUE;
398 foo_canvas_item_request_update (item);
399 break;
401 case PROP_ANCHOR:
402 priv->anchor = g_value_get_enum (value);
403 priv->need_xform_update = TRUE;
404 foo_canvas_item_request_update (item);
405 break;
407 case PROP_INTERP_TYPE:
408 priv->interp_type = g_value_get_enum (value);
409 priv->need_xform_update = TRUE;
410 foo_canvas_item_request_update (item);
411 break;
413 case PROP_POINT_IGNORES_ALPHA:
414 priv->point_ignores_alpha = g_value_get_boolean (value);
415 break;
417 default:
418 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
419 break;
423 /* Get_property handler for the pixbuf canvasi item */
424 static void
425 foo_canvas_pixbuf_get_property (GObject *object,
426 guint param_id,
427 GValue *value,
428 GParamSpec *pspec)
430 FooCanvasPixbuf *gcp;
431 PixbufPrivate *priv;
433 g_return_if_fail (object != NULL);
434 g_return_if_fail (FOO_IS_CANVAS_PIXBUF (object));
436 gcp = FOO_CANVAS_PIXBUF (object);
437 priv = gcp->priv;
439 switch (param_id) {
440 case PROP_PIXBUF:
441 g_value_set_object (value, G_OBJECT (priv->pixbuf));
442 break;
444 case PROP_WIDTH:
445 g_value_set_double (value, priv->width);
446 break;
448 case PROP_WIDTH_SET:
449 g_value_set_boolean (value, priv->width_set);
450 break;
452 case PROP_WIDTH_IN_PIXELS:
453 g_value_set_boolean (value, priv->width_in_pixels);
454 break;
456 case PROP_HEIGHT:
457 g_value_set_double (value, priv->height);
458 break;
460 case PROP_HEIGHT_SET:
461 g_value_set_boolean (value, priv->height_set);
462 break;
464 case PROP_HEIGHT_IN_PIXELS:
465 g_value_set_boolean (value, priv->height_in_pixels);
466 break;
468 case PROP_X:
469 g_value_set_double (value, priv->x);
470 break;
472 case PROP_X_IN_PIXELS:
473 g_value_set_boolean (value, priv->x_in_pixels);
474 break;
476 case PROP_Y:
477 g_value_set_double (value, priv->y);
478 break;
480 case PROP_Y_IN_PIXELS:
481 g_value_set_boolean (value, priv->y_in_pixels);
482 break;
484 case PROP_ANCHOR:
485 g_value_set_enum (value, priv->anchor);
486 break;
488 case PROP_INTERP_TYPE:
489 g_value_set_enum (value, priv->interp_type);
490 break;
492 case PROP_POINT_IGNORES_ALPHA:
493 g_value_set_boolean (value, priv->point_ignores_alpha);
494 break;
496 default:
497 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
498 break;
504 /* Bounds and utilities */
507 /* Recomputes the bounding box of a pixbuf canvas item. The horizontal and
508 * vertical dimensions may be specified in units or pixels, separately, so we
509 * have to compute the components individually for each dimension.
511 * Returns the coordinates with respect to the parent items coordinates.
513 static void
514 compute_bounding_box (FooCanvasPixbuf *gcp,
515 double i2w_dx, double i2w_dy,
516 double *bbox_x0, double *bbox_y0,
517 double *bbox_x1, double *bbox_y1)
519 FooCanvasItem *item;
520 PixbufPrivate *priv;
521 double x, y;
522 double width, height;
524 item = FOO_CANVAS_ITEM (gcp);
525 priv = gcp->priv;
527 if (!priv->pixbuf) {
528 *bbox_x0 = *bbox_y0 = *bbox_x1 = *bbox_y1 = 0.0;
529 return;
532 if (priv->x_in_pixels) {
533 x = i2w_dx + priv->x / item->canvas->pixels_per_unit;
534 } else {
535 x = i2w_dx + priv->x;
538 if (priv->y_in_pixels) {
539 y = i2w_dy + priv->y / item->canvas->pixels_per_unit;
540 } else {
541 y = i2w_dy + priv->y;
544 if (priv->width_set) {
545 width = priv->width;
546 } else {
547 width = gdk_pixbuf_get_width (priv->pixbuf);
550 if (priv->width_in_pixels)
551 width /= item->canvas->pixels_per_unit;
553 if (priv->height_set) {
554 height = priv->height;
555 } else {
556 height = gdk_pixbuf_get_height (priv->pixbuf);
559 if (priv->height_in_pixels)
560 height /= item->canvas->pixels_per_unit;
563 switch (priv->anchor) {
564 case GTK_ANCHOR_NW:
565 case GTK_ANCHOR_W:
566 case GTK_ANCHOR_SW:
567 break;
569 case GTK_ANCHOR_N:
570 case GTK_ANCHOR_CENTER:
571 case GTK_ANCHOR_S:
572 x -= width / 2.0;
573 break;
575 case GTK_ANCHOR_NE:
576 case GTK_ANCHOR_E:
577 case GTK_ANCHOR_SE:
578 x -= width;
579 break;
581 default:
582 break;
585 switch (priv->anchor) {
586 case GTK_ANCHOR_NW:
587 case GTK_ANCHOR_N:
588 case GTK_ANCHOR_NE:
589 break;
591 case GTK_ANCHOR_W:
592 case GTK_ANCHOR_CENTER:
593 case GTK_ANCHOR_E:
594 y -= height / 2.0;
595 break;
597 case GTK_ANCHOR_SW:
598 case GTK_ANCHOR_S:
599 case GTK_ANCHOR_SE:
600 y -= height;
601 break;
603 default:
604 break;
607 *bbox_x0 = x;
608 *bbox_y0 = y;
609 *bbox_x1 = x + width;
610 *bbox_y1 = y + height;
615 /* Update sequence */
617 /* Update handler for the pixbuf canvas item */
618 static void
619 foo_canvas_pixbuf_update (FooCanvasItem *item,
620 double i2w_dx, double i2w_dy,
621 int flags)
623 FooCanvasPixbuf *gcp;
624 PixbufPrivate *priv;
625 double bbox_x0, bbox_y0, bbox_x1, bbox_y1;
626 int w, h;
628 gcp = FOO_CANVAS_PIXBUF (item);
629 priv = gcp->priv;
631 if (parent_class->update)
632 (* parent_class->update) (item, i2w_dx, i2w_dy, flags);
634 /* If we need a pixbuf update, or if the item changed visibility to
635 * shown, recompute the bounding box.
637 if (priv->need_pixbuf_update || priv->need_xform_update ||
638 (flags & FOO_CANVAS_UPDATE_DEEP)) {
640 foo_canvas_item_request_redraw (item);
642 compute_bounding_box (gcp, i2w_dx, i2w_dy,
643 &bbox_x0, &bbox_y0,
644 &bbox_x1, &bbox_y1);
646 foo_canvas_w2c_d (item->canvas,
647 bbox_x0, bbox_y0,
648 &item->x1, &item->y1);
650 foo_canvas_w2c_d (item->canvas,
651 bbox_x1, bbox_y1,
652 &item->x2, &item->y2);
654 item->x1 = floor (item->x1 + .5);
655 item->y1 = floor (item->y1 + .5);
656 item->x2 = floor (item->x2 + .5);
657 item->y2 = floor (item->y2 + .5);
659 #ifdef FOO_CANVAS_PIXBUF_VERBOSE
660 g_print ("BBox is %g %g %g %g\n", item->x1, item->y1, item->x2, item->y2);
661 #endif
663 if (priv->pixbuf) {
664 w = item->x2 - item->x1;
665 h = item->y2 - item->y1;
667 if (priv->pixbuf_scaled)
668 g_object_unref (priv->pixbuf_scaled);
669 if (gdk_pixbuf_get_width (priv->pixbuf) != w ||
670 gdk_pixbuf_get_height (priv->pixbuf) != h)
671 priv->pixbuf_scaled = gdk_pixbuf_scale_simple (
672 priv->pixbuf, w, h, priv->interp_type);
673 else
674 priv->pixbuf_scaled = g_object_ref (priv->pixbuf);
677 foo_canvas_item_request_redraw (item);
679 priv->need_pixbuf_update = FALSE;
680 priv->need_xform_update = FALSE;
686 /* Draw handler for the pixbuf canvas item */
687 static void
688 foo_canvas_pixbuf_draw (FooCanvasItem *item, GdkDrawable *drawable,
689 GdkEventExpose *expose)
691 FooCanvasPixbuf *gcp;
692 PixbufPrivate *priv;
693 GdkRectangle display_rect, draw_rect;
694 GdkRegion *draw_region;
695 int w, h;
697 gcp = FOO_CANVAS_PIXBUF (item);
698 priv = gcp->priv;
700 if (!priv->pixbuf)
701 return;
703 /* Compute the area we need to repaint */
705 w = item->x2 - item->x1;
706 h = item->y2 - item->y1;
708 display_rect.x = item->x1;
709 display_rect.y = item->y1;
710 display_rect.width = w;
711 display_rect.height = h;
712 draw_region = gdk_region_rectangle (&display_rect);
713 gdk_region_intersect (draw_region, expose->region);
714 if (!gdk_region_empty (draw_region)) {
715 gdk_region_get_clipbox (draw_region, &draw_rect);
716 gdk_draw_pixbuf (drawable, NULL, priv->pixbuf_scaled,
717 /* pixbuf 0, 0 is at pix_rect.x, pix_rect.y */
718 draw_rect.x - display_rect.x,
719 draw_rect.y - display_rect.y,
720 draw_rect.x,
721 draw_rect.y,
722 draw_rect.width,
723 draw_rect.height,
724 GDK_RGB_DITHER_NORMAL, 0, 0);
726 gdk_region_destroy (draw_region);
732 /* Point handler for the pixbuf canvas item */
733 static double
734 foo_canvas_pixbuf_point (FooCanvasItem *item, double x, double y, int cx, int cy,
735 FooCanvasItem **actual_item)
737 FooCanvasPixbuf *gcp;
738 PixbufPrivate *priv;
739 double x1, y1, x2, y2;
740 int px, py;
741 double no_hit;
742 guchar *src;
743 GdkPixbuf *pixbuf;
745 gcp = FOO_CANVAS_PIXBUF (item);
746 priv = gcp->priv;
747 pixbuf = priv->pixbuf;
749 *actual_item = item;
751 no_hit = item->canvas->pixels_per_unit * 2 + 10;
753 if (!priv->pixbuf)
754 return no_hit;
756 compute_bounding_box (gcp, 0.0, 0.0,
757 &x1, &y1, &x2, &y2);
760 if (x < x1 || x >= x2 ||
761 y < y1 || y >= y2)
762 return no_hit;
764 if (!gdk_pixbuf_get_has_alpha (pixbuf) || priv->point_ignores_alpha)
765 return 0.0;
767 px = (x - x1) * gdk_pixbuf_get_width (pixbuf) / (x2 - x1);
768 py = (y - y1) * gdk_pixbuf_get_height (pixbuf) / (y2 - y1);
770 src = gdk_pixbuf_get_pixels (pixbuf) +
771 py * gdk_pixbuf_get_rowstride (pixbuf) +
772 px * gdk_pixbuf_get_n_channels (pixbuf);
774 if (src[3] < 128)
775 return no_hit;
776 else
777 return 0.0;
782 static void
783 foo_canvas_pixbuf_translate (FooCanvasItem *item, double dx, double dy)
785 FooCanvasPixbuf *gcp;
786 PixbufPrivate *priv;
788 gcp = FOO_CANVAS_PIXBUF (item);
789 priv = gcp->priv;
791 if (priv->x_in_pixels) {
792 priv->x += dx * item->canvas->pixels_per_unit;
793 } else {
794 priv->x += dx;
797 if (priv->y_in_pixels) {
798 priv->y += dy * item->canvas->pixels_per_unit;
799 } else {
800 priv->y += dy;
803 priv->need_xform_update = TRUE;
808 /* Bounds handler for the pixbuf canvas item */
809 static void
810 foo_canvas_pixbuf_bounds (FooCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
812 FooCanvasPixbuf *gcp;
813 PixbufPrivate *priv;
815 gcp = FOO_CANVAS_PIXBUF (item);
816 priv = gcp->priv;
818 if (!priv->pixbuf) {
819 *x1 = *y1 = *x2 = *y2 = 0.0;
820 return;
823 compute_bounding_box (gcp, 0.0, 0.0,
824 x1, y1, x2, y2);