diff options
Diffstat (limited to 'gdk/gdkpixbuf-render.c')
-rw-r--r-- | gdk/gdkpixbuf-render.c | 91 |
1 files changed, 71 insertions, 20 deletions
diff --git a/gdk/gdkpixbuf-render.c b/gdk/gdkpixbuf-render.c index 5ad39f7607..9ef7bb6f6b 100644 --- a/gdk/gdkpixbuf-render.c +++ b/gdk/gdkpixbuf-render.c @@ -246,6 +246,11 @@ gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, * the alpha channel of the image. If performance is crucial, consider handling * the alpha channel yourself (possibly by caching it in your application) and * using gdk_pixbuf_render_to_drawable() or GdkRGB directly instead. + * + * The #GDK_PIXBUF_ALPHA_FULL mode involves round trips to the X + * server, and may also be somewhat slow in its current implementation + * (though in the future it could be made significantly faster, in + * principle). **/ void gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, @@ -260,7 +265,8 @@ gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, { GdkBitmap *bitmap = NULL; GdkGC *gc; - + GdkPixbuf *composited = NULL; + g_return_if_fail (pixbuf != NULL); g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); @@ -278,31 +284,76 @@ gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, if (pixbuf->has_alpha) { - /* Right now we only support GDK_PIXBUF_ALPHA_BILEVEL, so we - * unconditionally create the clipping mask. - */ - - bitmap = gdk_pixmap_new (NULL, width, height, 1); - gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap, - src_x, src_y, - 0, 0, - width, height, - alpha_threshold); - - gdk_gc_set_clip_mask (gc, bitmap); - gdk_gc_set_clip_origin (gc, dest_x, dest_y); + if (alpha_mode == GDK_PIXBUF_ALPHA_BILEVEL) + { + bitmap = gdk_pixmap_new (NULL, width, height, 1); + gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap, + src_x, src_y, + 0, 0, + width, height, + alpha_threshold); + + gdk_gc_set_clip_mask (gc, bitmap); + gdk_gc_set_clip_origin (gc, dest_x, dest_y); + } + else if (alpha_mode == GDK_PIXBUF_ALPHA_FULL) + { + GdkPixbuf *sub = NULL; + + composited = gdk_pixbuf_get_from_drawable (NULL, + drawable, + NULL, + dest_x, dest_y, + 0, 0, + width, height); + + if (src_x != 0 || src_y != 0) + { + sub = gdk_pixbuf_new_subpixbuf (pixbuf, src_x, src_y, + width, height); + } + + gdk_pixbuf_composite (sub ? sub : pixbuf, + composited, + 0, 0, + width, height, + 0, 0, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + 255); + + if (sub) + g_object_unref (G_OBJECT (sub)); + } } - gdk_pixbuf_render_to_drawable (pixbuf, drawable, gc, - src_x, src_y, - dest_x, dest_y, - width, height, - dither, - x_dither, y_dither); + if (composited) + { + gdk_pixbuf_render_to_drawable (composited, + drawable, gc, + 0, 0, + dest_x, dest_y, + width, height, + dither, + x_dither, y_dither); + } + else + { + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, gc, + src_x, src_y, + dest_x, dest_y, + width, height, + dither, + x_dither, y_dither); + } if (bitmap) gdk_bitmap_unref (bitmap); + if (composited) + g_object_unref (G_OBJECT (composited)); + gdk_gc_unref (gc); } |