From f7767b0f25c8b06498031c63109ef13c2d87f0f5 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Fri, 15 Oct 2010 13:21:15 +0200 Subject: gnome-canvas: Simplify GnomeCanvasPixbuf Get rid of all the layout properties. They are unused, and if they are needed should be done in a separate object. Also do the drawing with Cairo. --- libgnomecanvas/gnome-canvas-pixbuf.c | 540 +++-------------------------------- 1 file changed, 37 insertions(+), 503 deletions(-) (limited to 'libgnomecanvas') diff --git a/libgnomecanvas/gnome-canvas-pixbuf.c b/libgnomecanvas/gnome-canvas-pixbuf.c index 07c9415e26..1fc7760315 100644 --- a/libgnomecanvas/gnome-canvas-pixbuf.c +++ b/libgnomecanvas/gnome-canvas-pixbuf.c @@ -25,50 +25,18 @@ #include #include #include -#include -#include #include "gnome-canvas-pixbuf.h" /* Private part of the GnomeCanvasPixbuf structure */ struct _GnomeCanvasPixbufPrivate { /* Our gdk-pixbuf */ GdkPixbuf *pixbuf; - - /* Width value */ - gdouble width; - - /* Height value */ - gdouble height; - - /* X translation */ - gdouble x; - - /* Y translation */ - gdouble y; - - /* Whether dimensions are set and whether they are in pixels or units */ - guint width_set : 1; - guint width_in_pixels : 1; - guint height_set : 1; - guint height_in_pixels : 1; - guint x_in_pixels : 1; - guint y_in_pixels : 1; }; /* Object argument IDs */ enum { PROP_0, - PROP_PIXBUF, - PROP_WIDTH, - PROP_WIDTH_SET, - PROP_WIDTH_IN_PIXELS, - PROP_HEIGHT, - PROP_HEIGHT_SET, - PROP_HEIGHT_IN_PIXELS, - PROP_X, - PROP_X_IN_PIXELS, - PROP_Y, - PROP_Y_IN_PIXELS + PROP_PIXBUF }; static void gnome_canvas_pixbuf_destroy (GnomeCanvasItem *object); @@ -116,66 +84,6 @@ gnome_canvas_pixbuf_class_init (GnomeCanvasPixbufClass *class) g_param_spec_object ("pixbuf", NULL, NULL, GDK_TYPE_PIXBUF, (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_WIDTH, - g_param_spec_double ("width", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_SET, - g_param_spec_boolean ("width_set", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_WIDTH_IN_PIXELS, - g_param_spec_boolean ("width_in_pixels", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_HEIGHT, - g_param_spec_double ("height", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_HEIGHT_SET, - g_param_spec_boolean ("height_set", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_HEIGHT_IN_PIXELS, - g_param_spec_boolean ("height_in_pixels", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_X, - g_param_spec_double ("x", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_X_IN_PIXELS, - g_param_spec_boolean ("x_in_pixels", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_Y, - g_param_spec_double ("y", NULL, NULL, - -G_MAXDOUBLE, G_MAXDOUBLE, 0, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); - g_object_class_install_property - (gobject_class, - PROP_Y_IN_PIXELS, - g_param_spec_boolean ("y_in_pixels", NULL, NULL, - FALSE, - (G_PARAM_READABLE | G_PARAM_WRITABLE))); item_class->destroy = gnome_canvas_pixbuf_destroy; item_class->update = gnome_canvas_pixbuf_update; @@ -195,11 +103,6 @@ gnome_canvas_pixbuf_init (GnomeCanvasPixbuf *gcp) priv = gcp->priv = G_TYPE_INSTANCE_GET_PRIVATE (gcp, GNOME_TYPE_CANVAS_PIXBUF, GnomeCanvasPixbufPrivate); - - priv->width = 0.0; - priv->height = 0.0; - priv->x = 0.0; - priv->y = 0.0; } /* Destroy handler for the pixbuf canvas item */ @@ -240,7 +143,6 @@ gnome_canvas_pixbuf_set_property (GObject *object, GnomeCanvasPixbuf *gcp; GnomeCanvasPixbufPrivate *priv; GdkPixbuf *pixbuf; - gdouble val; g_return_if_fail (object != NULL); g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object)); @@ -262,60 +164,6 @@ gnome_canvas_pixbuf_set_property (GObject *object, gnome_canvas_item_request_update (item); break; - case PROP_WIDTH: - val = g_value_get_double (value); - g_return_if_fail (val >= 0.0); - priv->width = val; - gnome_canvas_item_request_update (item); - break; - - case PROP_WIDTH_SET: - priv->width_set = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_WIDTH_IN_PIXELS: - priv->width_in_pixels = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_HEIGHT: - val = g_value_get_double (value); - g_return_if_fail (val >= 0.0); - priv->height = val; - gnome_canvas_item_request_update (item); - break; - - case PROP_HEIGHT_SET: - priv->height_set = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_HEIGHT_IN_PIXELS: - priv->height_in_pixels = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_X: - priv->x = g_value_get_double (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_X_IN_PIXELS: - priv->x_in_pixels = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_Y: - priv->y = g_value_get_double (value); - gnome_canvas_item_request_update (item); - break; - - case PROP_Y_IN_PIXELS: - priv->y_in_pixels = g_value_get_boolean (value); - gnome_canvas_item_request_update (item); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -343,46 +191,6 @@ gnome_canvas_pixbuf_get_property (GObject *object, g_value_set_object (value, priv->pixbuf); break; - case PROP_WIDTH: - g_value_set_double (value, priv->width); - break; - - case PROP_WIDTH_SET: - g_value_set_boolean (value, priv->width_set); - break; - - case PROP_WIDTH_IN_PIXELS: - g_value_set_boolean (value, priv->width_in_pixels); - break; - - case PROP_HEIGHT: - g_value_set_double (value, priv->height); - break; - - case PROP_HEIGHT_SET: - g_value_set_boolean (value, priv->height_set); - break; - - case PROP_HEIGHT_IN_PIXELS: - g_value_set_boolean (value, priv->height_in_pixels); - break; - - case PROP_X: - g_value_set_double (value, priv->x); - break; - - case PROP_X_IN_PIXELS: - g_value_set_boolean (value, priv->x_in_pixels); - break; - - case PROP_Y: - g_value_set_double (value, priv->y); - break; - - case PROP_Y_IN_PIXELS: - g_value_set_boolean (value, priv->y_in_pixels); - break; - default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; @@ -393,154 +201,17 @@ gnome_canvas_pixbuf_get_property (GObject *object, /* Bounds and utilities */ -/* Computes the amount by which the unit horizontal and vertical vectors will be - * scaled by an affine transformation. - */ -static void -compute_xform_scaling (gdouble *affine, ArtPoint *i_c, ArtPoint *j_c) -{ - ArtPoint orig, orig_c; - ArtPoint i, j; - - /* Origin */ - - orig.x = 0.0; - orig.y = 0.0; - art_affine_point (&orig_c, &orig, affine); - - /* Horizontal and vertical vectors */ - - i.x = 1.0; - i.y = 0.0; - art_affine_point (i_c, &i, affine); - i_c->x -= orig_c.x; - i_c->y -= orig_c.y; - - j.x = 0.0; - j.y = 1.0; - art_affine_point (j_c, &j, affine); - j_c->x -= orig_c.x; - j_c->y -= orig_c.y; -} - -/* computes the addtional resolution dependent affine needed to - * fit the image within its viewport defined by x,y,width and height - * args - */ -static void -compute_viewport_affine (GnomeCanvasPixbuf *gcp, - gdouble *viewport_affine, - gdouble *i2c) -{ - GnomeCanvasPixbufPrivate *priv; - ArtPoint i_c, j_c; - gdouble i_len, j_len; - gdouble si_len, sj_len; - gdouble ti_len, tj_len; - gdouble scale[6], translate[6]; - gdouble w, h; - gdouble x, y; - - priv = gcp->priv; - - /* Compute scaling vectors and required width/height */ - - compute_xform_scaling (i2c, &i_c, &j_c); - - i_len = sqrt (i_c.x * i_c.x + i_c.y * i_c.y); - j_len = sqrt (j_c.x * j_c.x + j_c.y * j_c.y); - - if (priv->width_set) - w = priv->width; - else - w = gdk_pixbuf_get_width (priv->pixbuf); - - if (priv->height_set) - h = priv->height; - else - h = gdk_pixbuf_get_height (priv->pixbuf); - - x = priv->x; - y = priv->y; - - /* Convert i_len and j_len into scaling factors */ - - if (priv->width_in_pixels) { - if (i_len > GNOME_CANVAS_EPSILON) - si_len = 1.0 / i_len; - else - si_len = 0.0; - } else - si_len = 1.0; - - si_len *= w / gdk_pixbuf_get_width (priv->pixbuf); - - if (priv->height_in_pixels) { - if (j_len > GNOME_CANVAS_EPSILON) - sj_len = 1.0 / j_len; - else - sj_len = 0.0; - } else - sj_len = 1.0; - - sj_len *= h / gdk_pixbuf_get_height (priv->pixbuf); - - /* Calculate translation offsets */ - - if (priv->x_in_pixels) { - if (i_len > GNOME_CANVAS_EPSILON) - ti_len = 1.0 / i_len; - else - ti_len = 0.0; - } else - ti_len = 1.0; - - if (priv->y_in_pixels) { - if (j_len > GNOME_CANVAS_EPSILON) - tj_len = 1.0 / j_len; - else - tj_len = 0.0; - } else - tj_len = 1.0; - - /* Compute the final affine */ - - art_affine_scale (scale, si_len, sj_len); - art_affine_translate (translate, ti_len, tj_len); - art_affine_multiply (viewport_affine, scale, translate); -} - -/* Computes the affine transformation with which the pixbuf needs to be - * transformed to render it on the canvas. This is not the same as the - * item_to_canvas transformation because we may need to scale the pixbuf - * by some other amount. - */ -static void -compute_render_affine (GnomeCanvasPixbuf *gcp, gdouble *ra, gdouble *i2c) -{ - gdouble va[6]; - - compute_viewport_affine (gcp, va, i2c); -#ifdef GNOME_CANVAS_PIXBUF_VERBOSE - g_print ("va %g %g %g %g %g %g\n", va[0], va[1], va[2], va[3], va[4], va[5]); -#endif - art_affine_multiply (ra, va, i2c); -#ifdef GNOME_CANVAS_PIXBUF_VERBOSE - g_print ("ra %g %g %g %g %g %g\n", ra[0], ra[1], ra[2], ra[3], ra[4], ra[5]); -#endif -} - /* Recomputes the bounding box of a pixbuf canvas item. The horizontal and * vertical dimensions may be specified in units or pixels, separately, so we * have to compute the components individually for each dimension. */ static void -recompute_bounding_box (GnomeCanvasPixbuf *gcp, gdouble *i2c) +recompute_bounding_box (GnomeCanvasPixbuf *gcp) { GnomeCanvasItem *item; GnomeCanvasPixbufPrivate *priv; - gdouble ra[6]; - ArtDRect rect; + cairo_matrix_t i2c; + double x1, x2, y1, y2; item = GNOME_CANVAS_ITEM (gcp); priv = gcp->priv; @@ -550,29 +221,18 @@ recompute_bounding_box (GnomeCanvasPixbuf *gcp, gdouble *i2c) return; } - rect.x0 = 0.0; - rect.x1 = gdk_pixbuf_get_width (priv->pixbuf); - - rect.y0 = 0.0; - rect.y1 = gdk_pixbuf_get_height (priv->pixbuf); - -#ifdef GNOME_CANVAS_PIXBUF_VERBOSE - g_print ("i2c %g %g %g %g %g %g\n", i2c[0], i2c[1], i2c[2], i2c[3], i2c[4], i2c[5]); -#endif - gnome_canvas_item_i2c_affine (item, i2c); -#ifdef GNOME_CANVAS_PIXBUF_VERBOSE - g_print ("i2c %g %g %g %g %g %g\n", i2c[0], i2c[1], i2c[2], i2c[3], i2c[4], i2c[5]); -#endif - compute_render_affine (gcp, ra, i2c); -#ifdef GNOME_CANVAS_PIXBUF_VERBOSE - g_print ("ra %g %g %g %g %g %g\n", ra[0], ra[1], ra[2], ra[3], ra[4], ra[5]); -#endif - art_drect_affine_transform (&rect, &rect, ra); - - item->x1 = floor (rect.x0); - item->y1 = floor (rect.y0); - item->x2 = ceil (rect.x1); - item->y2 = ceil (rect.y1); + x1 = 0.0; + x2 = gdk_pixbuf_get_width (priv->pixbuf); + y1 = 0.0; + y2 = gdk_pixbuf_get_height (priv->pixbuf); + + gnome_canvas_item_i2c_matrix (item, &i2c); + gnome_canvas_matrix_transform_rect (&i2c, &x1, &y1, &x2, &y2); + + item->x1 = floor (x1); + item->y1 = floor (y1); + item->x2 = ceil (x2); + item->y2 = ceil (y2); } @@ -598,76 +258,13 @@ gnome_canvas_pixbuf_update (GnomeCanvasItem *item, /* ordinary update logic */ gnome_canvas_request_redraw ( item->canvas, item->x1, item->y1, item->x2, item->y2); - recompute_bounding_box (gcp, affine); + recompute_bounding_box (gcp); gnome_canvas_request_redraw ( item->canvas, item->x1, item->y1, item->x2, item->y2); } -/* Rendering */ - -/* This is private to libart, but we need it. Sigh. */ -extern void art_rgb_affine_run (gint *p_x0, - gint *p_x1, - gint y, - gint src_width, - gint src_height, - const gdouble affine[6]); - -/* Fills the specified buffer with the transformed version of a pixbuf */ -static void -transform_pixbuf (guchar *dest, - gint x, - gint y, - gint width, - gint height, - gint rowstride, - GdkPixbuf *pixbuf, - gdouble *affine) -{ - gint xx, yy; - gdouble inv[6]; - guchar *src, *d; - ArtPoint src_p, dest_p; - gint run_x1, run_x2; - gint src_x, src_y; - gint i; - - art_affine_invert (inv, affine); - - for (yy = 0; yy < height; yy++) { - dest_p.y = y + yy + 0.5; - - run_x1 = x; - run_x2 = x + width; - art_rgb_affine_run (&run_x1, &run_x2, yy + y, - gdk_pixbuf_get_width (pixbuf), - gdk_pixbuf_get_height (pixbuf), - inv); - - d = dest + yy * rowstride + (run_x1 - x) * 4; - - for (xx = run_x1; xx < run_x2; xx++) { - dest_p.x = xx + 0.5; - art_affine_point (&src_p, &dest_p, inv); - src_x = floor (src_p.x); - src_y = floor (src_p.y); - - src = - gdk_pixbuf_get_pixels (pixbuf) + src_y * - gdk_pixbuf_get_rowstride (pixbuf) + src_x * - gdk_pixbuf_get_n_channels (pixbuf); - - for (i = 0; i < gdk_pixbuf_get_n_channels (pixbuf); i++) - *d++ = *src++; - - if (!gdk_pixbuf_get_has_alpha (pixbuf)) - *d++ = 255; /* opaque */ - } - } -} - /* Draw handler for the pixbuf canvas item */ static void gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable, @@ -675,11 +272,8 @@ gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable, { GnomeCanvasPixbuf *gcp; GnomeCanvasPixbufPrivate *priv; - gdouble i2c[6], render_affine[6]; - guchar *buf; - GdkPixbuf *pixbuf; - ArtIRect p_rect, a_rect, d_rect; - gint w, h; + cairo_matrix_t matrix; + cairo_t *cr; gcp = GNOME_CANVAS_PIXBUF (item); priv = gcp->priv; @@ -687,52 +281,16 @@ gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable, if (!priv->pixbuf) return; - gnome_canvas_item_i2c_affine (item, i2c); - compute_render_affine (gcp, render_affine, i2c); - - /* Compute the area we need to repaint */ - - p_rect.x0 = item->x1; - p_rect.y0 = item->y1; - p_rect.x1 = item->x2; - p_rect.y1 = item->y2; - - a_rect.x0 = x; - a_rect.y0 = y; - a_rect.x1 = x + width; - a_rect.y1 = y + height; - - art_irect_intersect (&d_rect, &p_rect, &a_rect); - if (art_irect_empty (&d_rect)) - return; + cr = gdk_cairo_create (drawable); + gnome_canvas_item_i2c_matrix (item, &matrix); + if (cairo_matrix_invert (&matrix)) + return; + cairo_transform (cr, &matrix); + + gdk_cairo_set_source_pixbuf (cr, priv->pixbuf, 0, 0); + cairo_paint (cr); - /* Create a temporary buffer and transform the pixbuf there */ - - w = d_rect.x1 - d_rect.x0; - h = d_rect.y1 - d_rect.y0; - - buf = g_new0 (guchar, w * h * 4); - transform_pixbuf (buf, - d_rect.x0, d_rect.y0, - w, h, - w * 4, - priv->pixbuf, render_affine); - - pixbuf = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, - TRUE, - 8, w, h, - w * 4, - NULL, NULL); - - gdk_draw_pixbuf (drawable, NULL, pixbuf, - 0, 0, - d_rect.x0 - x, d_rect.y0 - y, - w, h, - GDK_RGB_DITHER_MAX, - d_rect.x0, d_rect.y0); - - g_object_unref (pixbuf); - g_free (buf); + cairo_destroy (cr); } @@ -747,31 +305,19 @@ gnome_canvas_pixbuf_point (GnomeCanvasItem *item, { GnomeCanvasPixbuf *gcp; GnomeCanvasPixbufPrivate *priv; - gdouble i2c[6], render_affine[6], inv[6]; - ArtPoint c, p; - gint px, py; - gdouble no_hit; - guchar *src; - GdkPixbuf *pixbuf; + GdkPixbuf *pixbuf; + int px, py; + guchar *src; gcp = GNOME_CANVAS_PIXBUF (item); priv = gcp->priv; pixbuf = priv->pixbuf; - no_hit = item->canvas->pixels_per_unit * 2 + 10; - if (!priv->pixbuf) return NULL; - gnome_canvas_item_i2c_affine (item, i2c); - compute_render_affine (gcp, render_affine, i2c); - art_affine_invert (inv, render_affine); - - c.x = cx; - c.y = cy; - art_affine_point (&p, &c, inv); - px = p.x; - py = p.y; + px = x; + py = y; if (px < 0 || px >= gdk_pixbuf_get_width (pixbuf) || py < 0 || py >= gdk_pixbuf_get_height (pixbuf)) @@ -802,8 +348,6 @@ gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item, { GnomeCanvasPixbuf *gcp; GnomeCanvasPixbufPrivate *priv; - gdouble i2c[6], viewport_affine[6]; - ArtDRect rect; gcp = GNOME_CANVAS_PIXBUF (item); priv = gcp->priv; @@ -813,18 +357,8 @@ gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item, return; } - rect.x0 = 0.0; - rect.x1 = gdk_pixbuf_get_width (priv->pixbuf); - - rect.y0 = 0.0; - rect.y1 = gdk_pixbuf_get_height (priv->pixbuf); - - gnome_canvas_item_i2c_affine (item, i2c); - compute_viewport_affine (gcp, viewport_affine, i2c); - art_drect_affine_transform (&rect, &rect, viewport_affine); - - *x1 = rect.x0; - *y1 = rect.y0; - *x2 = rect.x1; - *y2 = rect.y1; + *x1 = 0; + *y1 = 0; + *x2 = gdk_pixbuf_get_width (priv->pixbuf); + *y2 = gdk_pixbuf_get_height (priv->pixbuf); } -- cgit