evolution-3.6.4/libgnomecanvas/gnome-canvas-pixbuf.c

No issues found

  1 /* GNOME libraries - GdkPixbuf item for the GNOME canvas
  2  *
  3  * Copyright (C) 1999 The Free Software Foundation
  4  *
  5  * Author: Federico Mena-Quintero <federico@gimp.org>
  6  *
  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.
 11  *
 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.
 16  *
 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.
 21  */
 22 
 23 #ifdef HAVE_CONFIG_H
 24 #include <config.h>
 25 #endif
 26 
 27 #include <math.h>
 28 #include <libgnomecanvas/gnome-canvas.h>
 29 #include <libgnomecanvas/gnome-canvas-util.h>
 30 #include <gdk-pixbuf/gdk-pixbuf.h>
 31 #include "gnome-canvas-pixbuf.h"
 32 
 33 #define GNOME_CANVAS_PIXBUF_GET_PRIVATE(obj) \
 34 	(G_TYPE_INSTANCE_GET_PRIVATE \
 35 	((obj), GNOME_TYPE_CANVAS_PIXBUF, GnomeCanvasPixbufPrivate))
 36 
 37 /* Private part of the GnomeCanvasPixbuf structure */
 38 struct _GnomeCanvasPixbufPrivate {
 39 	/* Our gdk-pixbuf */
 40 	GdkPixbuf *pixbuf;
 41 };
 42 
 43 /* Object argument IDs */
 44 enum {
 45 	PROP_0,
 46 	PROP_PIXBUF
 47 };
 48 
 49 static void gnome_canvas_pixbuf_dispose (GnomeCanvasItem *object);
 50 static void gnome_canvas_pixbuf_set_property (GObject *object,
 51 					      guint param_id,
 52 					      const GValue *value,
 53 					      GParamSpec *pspec);
 54 static void gnome_canvas_pixbuf_get_property (GObject *object,
 55 					      guint param_id,
 56 					      GValue *value,
 57 					      GParamSpec *pspec);
 58 
 59 static void gnome_canvas_pixbuf_update (GnomeCanvasItem *item,
 60 					const cairo_matrix_t *i2c,
 61 					gint flags);
 62 static void gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, cairo_t *cr,
 63 				      gint x, gint y, gint width, gint height);
 64 static GnomeCanvasItem *gnome_canvas_pixbuf_point (GnomeCanvasItem *item,
 65                                                    gdouble x,
 66                                                    gdouble y,
 67                                                    gint cx,
 68                                                    gint cy);
 69 static void gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item,
 70 					gdouble *x1, gdouble *y1, gdouble *x2, gdouble *y2);
 71 
 72 G_DEFINE_TYPE (GnomeCanvasPixbuf, gnome_canvas_pixbuf, GNOME_TYPE_CANVAS_ITEM)
 73 
 74 /* Class initialization function for the pixbuf canvas item */
 75 static void
 76 gnome_canvas_pixbuf_class_init (GnomeCanvasPixbufClass *class)
 77 {
 78 	GObjectClass *gobject_class;
 79 	GnomeCanvasItemClass *item_class;
 80 
 81 	gobject_class = (GObjectClass *) class;
 82 	item_class = (GnomeCanvasItemClass *) class;
 83 
 84 	gobject_class->set_property = gnome_canvas_pixbuf_set_property;
 85 	gobject_class->get_property = gnome_canvas_pixbuf_get_property;
 86 
 87 	g_object_class_install_property
 88 		(gobject_class,
 89 		 PROP_PIXBUF,
 90 		 g_param_spec_object ("pixbuf", NULL, NULL,
 91 				      GDK_TYPE_PIXBUF,
 92 				      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
 93 
 94 	item_class->dispose = gnome_canvas_pixbuf_dispose;
 95 	item_class->update = gnome_canvas_pixbuf_update;
 96 	item_class->draw = gnome_canvas_pixbuf_draw;
 97 	item_class->point = gnome_canvas_pixbuf_point;
 98 	item_class->bounds = gnome_canvas_pixbuf_bounds;
 99 
100 	g_type_class_add_private (class, sizeof (GnomeCanvasPixbufPrivate));
101 }
102 
103 /* Object initialization function for the pixbuf canvas item */
104 static void
105 gnome_canvas_pixbuf_init (GnomeCanvasPixbuf *gcp)
106 {
107 	gcp->priv = GNOME_CANVAS_PIXBUF_GET_PRIVATE (gcp);
108 }
109 
110 /* Dispose handler for the pixbuf canvas item */
111 static void
112 gnome_canvas_pixbuf_dispose (GnomeCanvasItem *object)
113 {
114 	GnomeCanvasPixbuf *gcp;
115 	GnomeCanvasPixbufPrivate *priv;
116 
117 	g_return_if_fail (object != NULL);
118 	g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object));
119 
120 	gcp = GNOME_CANVAS_PIXBUF (object);
121 	priv = gcp->priv;
122 
123 	if (priv->pixbuf != NULL) {
124 		g_object_unref (priv->pixbuf);
125 		priv->pixbuf = NULL;
126 	}
127 
128 	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_pixbuf_parent_class)->dispose)
129 		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_pixbuf_parent_class)->dispose (object);
130 }
131 
132 /* Set_property handler for the pixbuf canvas item */
133 static void
134 gnome_canvas_pixbuf_set_property (GObject *object,
135                                   guint param_id,
136                                   const GValue *value,
137                                   GParamSpec *pspec)
138 {
139 	GnomeCanvasItem *item;
140 	GnomeCanvasPixbuf *gcp;
141 	GnomeCanvasPixbufPrivate *priv;
142 	GdkPixbuf *pixbuf;
143 
144 	g_return_if_fail (object != NULL);
145 	g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object));
146 
147 	item = GNOME_CANVAS_ITEM (object);
148 	gcp = GNOME_CANVAS_PIXBUF (object);
149 	priv = gcp->priv;
150 
151 	switch (param_id) {
152 	case PROP_PIXBUF:
153 		pixbuf = g_value_get_object (value);
154 		if (pixbuf != priv->pixbuf) {
155 			if (priv->pixbuf)
156 				g_object_unref (priv->pixbuf);
157 
158 			priv->pixbuf = g_object_ref (pixbuf);
159 		}
160 
161 		gnome_canvas_item_request_update (item);
162 		break;
163 
164 	default:
165 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
166 		break;
167 	}
168 }
169 
170 /* Get_property handler for the pixbuf canvasi item */
171 static void
172 gnome_canvas_pixbuf_get_property (GObject *object,
173                                   guint param_id,
174                                   GValue *value,
175                                   GParamSpec *pspec)
176 {
177 	GnomeCanvasPixbuf *gcp;
178 	GnomeCanvasPixbufPrivate *priv;
179 
180 	g_return_if_fail (object != NULL);
181 	g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object));
182 
183 	gcp = GNOME_CANVAS_PIXBUF (object);
184 	priv = gcp->priv;
185 
186 	switch (param_id) {
187 	case PROP_PIXBUF:
188 		g_value_set_object (value, priv->pixbuf);
189 		break;
190 
191 	default:
192 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
193 		break;
194 	}
195 }
196 
197 /* Bounds and utilities */
198 
199 /* Recomputes the bounding box of a pixbuf canvas item.  The horizontal and
200  * vertical dimensions may be specified in units or pixels, separately, so we
201  * have to compute the components individually for each dimension.
202  */
203 static void
204 recompute_bounding_box (GnomeCanvasPixbuf *gcp)
205 {
206 	GnomeCanvasItem *item;
207 	GnomeCanvasPixbufPrivate *priv;
208 	cairo_matrix_t i2c;
209 	gdouble x1, x2, y1, y2;
210 
211 	item = GNOME_CANVAS_ITEM (gcp);
212 	priv = gcp->priv;
213 
214 	if (!priv->pixbuf) {
215 		item->x1 = item->y1 = item->x2 = item->y2 = 0.0;
216 		return;
217 	}
218 
219 	x1 = 0.0;
220 	x2 = gdk_pixbuf_get_width (priv->pixbuf);
221 	y1 = 0.0;
222 	y2 = gdk_pixbuf_get_height (priv->pixbuf);
223 
224 	gnome_canvas_item_i2c_matrix (item, &i2c);
225 	gnome_canvas_matrix_transform_rect (&i2c, &x1, &y1, &x2, &y2);
226 
227 	item->x1 = floor (x1);
228 	item->y1 = floor (y1);
229 	item->x2 = ceil (x2);
230 	item->y2 = ceil (y2);
231 }
232 
233 /* Update sequence */
234 
235 /* Update handler for the pixbuf canvas item */
236 static void
237 gnome_canvas_pixbuf_update (GnomeCanvasItem *item,
238                             const cairo_matrix_t *i2c,
239                             gint flags)
240 {
241 	GnomeCanvasPixbuf *gcp;
242 
243 	gcp = GNOME_CANVAS_PIXBUF (item);
244 
245 	if (GNOME_CANVAS_ITEM_CLASS (gnome_canvas_pixbuf_parent_class)->update)
246 		GNOME_CANVAS_ITEM_CLASS (gnome_canvas_pixbuf_parent_class)->
247 			update (item, i2c, flags);
248 
249 	/* ordinary update logic */
250 	gnome_canvas_request_redraw (
251 		item->canvas, item->x1, item->y1, item->x2, item->y2);
252 	recompute_bounding_box (gcp);
253 	gnome_canvas_request_redraw (
254 		item->canvas, item->x1, item->y1, item->x2, item->y2);
255 }
256 
257 /* Draw handler for the pixbuf canvas item */
258 static void
259 gnome_canvas_pixbuf_draw (GnomeCanvasItem *item,
260                           cairo_t *cr,
261                           gint x,
262                           gint y,
263                           gint width,
264                           gint height)
265 {
266 	GnomeCanvasPixbuf *gcp;
267 	GnomeCanvasPixbufPrivate *priv;
268 	cairo_matrix_t matrix;
269 
270 	gcp = GNOME_CANVAS_PIXBUF (item);
271 	priv = gcp->priv;
272 
273 	if (!priv->pixbuf)
274 		return;
275 
276 	gnome_canvas_item_i2c_matrix (item, &matrix);
277 
278 	cairo_save (cr);
279 	cairo_transform (cr, &matrix);
280 
281 	gdk_cairo_set_source_pixbuf (cr, priv->pixbuf, 0, 0);
282 	cairo_paint (cr);
283 	cairo_restore (cr);
284 }
285 
286 /* Point handler for the pixbuf canvas item */
287 static GnomeCanvasItem *
288 gnome_canvas_pixbuf_point (GnomeCanvasItem *item,
289                            gdouble x,
290                            gdouble y,
291                            gint cx,
292                            gint cy)
293 {
294 	GnomeCanvasPixbuf *gcp;
295 	GnomeCanvasPixbufPrivate *priv;
296 	GdkPixbuf *pixbuf;
297 	gint px, py;
298 	guchar *src;
299 
300 	gcp = GNOME_CANVAS_PIXBUF (item);
301 	priv = gcp->priv;
302 	pixbuf = priv->pixbuf;
303 
304 	if (!priv->pixbuf)
305 		return NULL;
306 
307 	px = x;
308 	py = y;
309 
310 	if (px < 0 || px >= gdk_pixbuf_get_width (pixbuf) ||
311 	    py < 0 || py >= gdk_pixbuf_get_height (pixbuf))
312 		return NULL;
313 
314 	if (!gdk_pixbuf_get_has_alpha (pixbuf))
315 		return item;
316 
317 	src = gdk_pixbuf_get_pixels (pixbuf) +
318 	    py * gdk_pixbuf_get_rowstride (pixbuf) +
319 	    px * gdk_pixbuf_get_n_channels (pixbuf);
320 
321 	if (src[3] < 128)
322 		return NULL;
323 	else
324 		return item;
325 }
326 
327 /* Bounds handler for the pixbuf canvas item */
328 static void
329 gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item,
330                             gdouble *x1,
331                             gdouble *y1,
332                             gdouble *x2,
333                             gdouble *y2)
334 {
335 	GnomeCanvasPixbuf *gcp;
336 	GnomeCanvasPixbufPrivate *priv;
337 
338 	gcp = GNOME_CANVAS_PIXBUF (item);
339 	priv = gcp->priv;
340 
341 	if (!priv->pixbuf) {
342 		*x1 = *y1 = *x2 = *y2 = 0.0;
343 		return;
344 	}
345 
346 	*x1 = 0;
347 	*y1 = 0;
348 	*x2 = gdk_pixbuf_get_width (priv->pixbuf);
349 	*y2 = gdk_pixbuf_get_height (priv->pixbuf);
350 }