API: Remove gdk_draw_pixbuf()

This commit is contained in:
Benjamin Otte 2010-07-12 16:50:00 +02:00
parent 11ee2abacc
commit 4f8dbd4a8d
12 changed files with 7 additions and 1697 deletions

View File

@ -413,7 +413,6 @@ gdk_draw_point
gdk_draw_points
gdk_draw_line
gdk_draw_lines
gdk_draw_pixbuf
gdk_draw_segments
GdkSegment
gdk_draw_rectangle

View File

@ -129,19 +129,6 @@ static gboolean accelerated_alpha_blending = FALSE;
static gpointer parent_class = NULL;
static const cairo_user_data_key_t gdk_directfb_cairo_key;
static void (*real_draw_pixbuf) (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
/**********************************************************
* DirectFB specific implementations of generic functions *
@ -963,438 +950,6 @@ gdk_directfb_draw_image (GdkDrawable *drawable,
temp_region_deinit( &clip );
}
static void
composite (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
while (height--)
{
gint twidth = width;
guchar *p = src;
guchar *q = dest;
while (twidth--)
{
guchar a = p[3];
guint t;
t = a * p[0] + (255 - a) * q[0] + 0x80;
q[0] = (t + (t >> 8)) >> 8;
t = a * p[1] + (255 - a) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = a * p[2] + (255 - a) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
p += 4;
q += 3;
}
src += src_rowstride;
dest += dest_rowstride;
}
}
static void
composite_0888 (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
while (height--)
{
gint twidth = width;
guchar *p = src;
guchar *q = dest;
if (dest_byte_order == GDK_LSB_FIRST)
{
while (twidth--)
{
guint t;
t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
q[0] = (t + (t >> 8)) >> 8;
t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
p += 4;
q += 4;
}
}
else
{
while (twidth--)
{
guint t;
t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
q[3] = (t + (t >> 8)) >> 8;
p += 4;
q += 4;
}
}
src += src_rowstride;
dest += dest_rowstride;
}
}
/* change the last value to adjust the size of the device (1-4) */
#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \
SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 2 )
/* From DirectFB's gfx/generic/generic.c" */
#define SET_PIXEL( D, S ) \
switch (S >> 26) { \
case 0: \
break; \
case 0x3f: \
D = ((S << 8) & 0xF800) | \
((S >> 5) & 0x07E0) | \
((S >> 19) & 0x001F); \
break; \
default: \
D = (((( (((S<<8) & 0xf800) | ((S>>19) & 0x001f)) \
- (D & 0xf81f)) * ((S>>26)+1) + ((D & 0xf81f)<<6)) & 0x003e07c0) \
+ \
((( ((S>>5) & 0x07e0) \
- (D & 0x07e0)) * ((S>>26)+1) + ((D & 0x07e0)<<6)) & 0x0001f800)) >> 6; \
}
static void
composite_565 (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height)
{
while (height--) {
int w = width;
u16 *D = (u16*) dest_buf;
u32 *S = (u32*) src_buf;
#if 1
if ((unsigned long)D & 2) {
SET_PIXEL( D[0], S[0] );
w--;
D++;
S++;
}
int i;
int w2 = w / 2;
u32 *D32 = (u32*) D;
for (i=0; i<w2; i++) {
register u32 S0 = S[(i << 1) + 0];
register u32 S1 = S[(i << 1) + 1];
if ((S0 >> 26) == 0x3f && (S1 >> 26) == 0x3f) {
D32[i] = ((S0 << 8) & 0x0000F800) |
((S0 >> 5) & 0x000007E0) |
((S0 >> 19) & 0x0000001F) |
((S1 << 24) & 0xF8000000) |
((S1 << 11) & 0x07E00000) |
((S1 >> 3) & 0x001F0000);
}
else {
SET_PIXEL( D[(i << 1) + 0], S0 );
SET_PIXEL( D[(i << 1) + 1], S1 );
}
}
if (w & 1)
SET_PIXEL( D[w-1], S[w-1] );
#else
SET_PIXEL_DUFFS_DEVICE( D, S, w );
#endif
dest_buf += dest_rowstride;
src_buf += src_rowstride;
}
}
#undef SET_PIXEL
#undef SET_PIXEL_DUFFS_DEVICE
static void
gdk_directfb_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkPixbuf *composited = NULL;
#if 0
cairo_region_t *clip;
cairo_region_t *drect;
GdkRectangle tmp_rect;
#endif
GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
g_return_if_fail (pixbuf->bits_per_sample == 8);
g_return_if_fail (drawable != NULL);
if (width == -1)
width = pixbuf->width;
if (height == -1)
height = pixbuf->height;
g_return_if_fail (width >= 0 && height >= 0);
g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %4d,%4d -> %4d,%4d - %dx%d )\n", G_STRFUNC,
drawable, gc, pixbuf, src_x, src_y, dest_x, dest_y, width, height );
/* Clip to the drawable; this is required for get_from_drawable() so
* can't be done implicitly
*/
if (dest_x < 0)
{
src_x -= dest_x;
width += dest_x;
dest_x = 0;
}
if (dest_y < 0)
{
src_y -= dest_y;
height += dest_y;
dest_y = 0;
}
if ((dest_x + width) > impl->width)
width = impl->width - dest_x;
if ((dest_y + height) > impl->height)
height = impl->height - dest_y;
if (width <= 0 || height <= 0)
return;
#if 0
/* Clip to the clip region; this avoids getting more
* image data from the server than we need to.
*/
tmp_rect.x = dest_x;
tmp_rect.y = dest_y;
tmp_rect.width = width;
tmp_rect.height = height;
drect = cairo_region_create_rectangle (&tmp_rect);
clip = gdk_drawable_get_clip_region (drawable);
cairo_region_intersect (drect, clip);
cairo_region_get_extents (drect, &tmp_rect);
cairo_region_destroy (drect);
cairo_region_destroy (clip);
if (tmp_rect.width == 0 ||
tmp_rect.height == 0)
return;
#endif
if (pixbuf->has_alpha && impl->format == DSPF_RGB16) {
void *data;
int pitch;
if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) {
composite_565( pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
pixbuf->rowstride,
data + dest_y * pitch + dest_x * 2,
pitch,
#if G_BYTE_ORDER == G_BIG_ENDIAN
GDK_MSB_FIRST,
#else
GDK_LSB_FIRST,
#endif
width, height );
impl->surface->Unlock( impl->surface );
return;
}
}
/* Actually draw */
if (!gc)
gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
if (pixbuf->has_alpha)
{
GdkVisual *visual = gdk_drawable_get_visual (drawable);
void (*composite_func) (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height) = NULL;
/* First we see if we have a visual-specific composition function that can composite
* the pixbuf data directly onto the image
*/
if (visual)
{
gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
visual->depth);
if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
visual->depth == 16 &&
visual->red_mask == 0xf800 &&
visual->green_mask == 0x07e0 &&
visual->blue_mask == 0x001f)
composite_func = composite_565;
else if (visual->depth == 24 && bits_per_pixel == 32 &&
visual->red_mask == 0xff0000 &&
visual->green_mask == 0x00ff00 &&
visual->blue_mask == 0x0000ff)
composite_func = composite_0888;
}
/* We can't use our composite func if we are required to dither
*/
if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
{
#if 0
gint x0, y0;
for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
{
gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
{
gint xs0, ys0;
gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
width1, height1,
gdk_drawable_get_depth (drawable), &xs0, &ys0);
gdk_drawable_copy_to_image (drawable, image,
dest_x + x0, dest_y + y0,
xs0, ys0,
width1, height1);
(*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4,
pixbuf->rowstride,
(guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
image->bpl,
visual->byte_order,
width1, height1);
gdk_draw_image (drawable, gc, image,
xs0, ys0,
dest_x + x0, dest_y + y0,
width1, height1);
}
}
#else
void *data;
int pitch;
if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) {
(*composite_func) (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
pixbuf->rowstride,
data + dest_y * pitch + DFB_BYTES_PER_LINE( impl->format, dest_x ),
pitch,
visual->byte_order,
width, height);
impl->surface->Unlock( impl->surface );
}
#endif
goto out;
}
else
{
/* No special composition func, convert dest to 24 bit RGB data, composite against
* that, and convert back.
*/
composited = gdk_pixbuf_get_from_drawable (NULL,
drawable,
NULL,
dest_x, dest_y,
0, 0,
width, height);
if (composited)
composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
pixbuf->rowstride,
composited->pixels,
composited->rowstride,
width, height);
}
}
if (composited)
{
src_x = 0;
src_y = 0;
pixbuf = composited;
}
if (pixbuf->n_channels == 4)
{
guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4;
gdk_draw_rgb_32_image_dithalign (drawable, gc,
dest_x, dest_y,
width, height,
dither,
buf, pixbuf->rowstride,
x_dither, y_dither);
}
else /* n_channels == 3 */
{
guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3;
gdk_draw_rgb_image_dithalign (drawable, gc,
dest_x, dest_y,
width, height,
dither,
buf, pixbuf->rowstride,
x_dither, y_dither);
}
out:
if (composited)
g_object_unref (composited);
}
static inline void
convert_rgba_pixbuf_to_image (guint32 *src,
guint src_pitch,

View File

@ -560,7 +560,6 @@ gdk_draw_glyphs_transformed
gdk_draw_image
gdk_draw_line
gdk_draw_lines
gdk_draw_pixbuf
gdk_draw_point
gdk_draw_points
gdk_draw_polygon

View File

@ -49,18 +49,6 @@ static GdkDrawable* gdk_drawable_real_get_composite_drawable (GdkDrawable *draw
gint *composite_x_offset,
gint *composite_y_offset);
static cairo_region_t * gdk_drawable_real_get_visible_region (GdkDrawable *drawable);
static void gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
static void gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
GdkGC *gc,
GdkDrawable *src,
@ -82,7 +70,6 @@ gdk_drawable_class_init (GdkDrawableClass *klass)
/* Default implementation for clip and visible region is the same */
klass->get_clip_region = gdk_drawable_real_get_visible_region;
klass->get_visible_region = gdk_drawable_real_get_visible_region;
klass->draw_pixbuf = gdk_drawable_real_draw_pixbuf;
klass->draw_drawable = gdk_drawable_real_draw_drawable;
}
@ -551,71 +538,6 @@ gdk_draw_image (GdkDrawable *drawable,
xdest, ydest, width, height);
}
/**
* gdk_draw_pixbuf:
* @drawable: Destination drawable.
* @gc: (allow-none): a #GdkGC, used for clipping, or %NULL
* @pixbuf: a #GdkPixbuf
* @src_x: Source X coordinate within pixbuf.
* @src_y: Source Y coordinates within pixbuf.
* @dest_x: Destination X coordinate within drawable.
* @dest_y: Destination Y coordinate within drawable.
* @width: Width of region to render, in pixels, or -1 to use pixbuf width.
* @height: Height of region to render, in pixels, or -1 to use pixbuf height.
* @dither: Dithering mode for #GdkRGB.
* @x_dither: X offset for dither.
* @y_dither: Y offset for dither.
*
* Renders a rectangular portion of a pixbuf to a drawable. The destination
* drawable must have a colormap. All windows have a colormap, however, pixmaps
* only have colormap by default if they were created with a non-%NULL window
* argument. Otherwise a colormap must be set on them with
* gdk_drawable_set_colormap().
*
* On older X servers, rendering pixbufs with an alpha channel involves round
* trips to the X server, and may be somewhat slow.
*
* If GDK is built with the Sun mediaLib library, the gdk_draw_pixbuf
* function is accelerated using mediaLib, which provides hardware
* acceleration on Intel, AMD, and Sparc chipsets. If desired, mediaLib
* support can be turned off by setting the GDK_DISABLE_MEDIALIB environment
* variable.
*
* Since: 2.2
**/
void
gdk_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
const GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
g_return_if_fail (GDK_IS_DRAWABLE (drawable));
g_return_if_fail (gc == NULL || GDK_IS_GC (gc));
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
if (width == 0 || height == 0)
return;
if (width == -1)
width = gdk_pixbuf_get_width (pixbuf);
if (height == -1)
height = gdk_pixbuf_get_height (pixbuf);
GDK_DRAWABLE_GET_CLASS (drawable)->draw_pixbuf (drawable, gc,
(GdkPixbuf *) pixbuf,
src_x, src_y, dest_x, dest_y,
width, height,
dither, x_dither, y_dither);
}
/**
* gdk_draw_points:
* @drawable: a #GdkDrawable (a #GdkWindow or a #GdkPixmap).
@ -1121,214 +1043,6 @@ _gdk_drawable_ref_cairo_surface (GdkDrawable *drawable)
return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable);
}
static void
composite (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
while (height--)
{
gint twidth = width;
guchar *p = src;
guchar *q = dest;
while (twidth--)
{
guchar a = p[3];
guint t;
t = a * p[0] + (255 - a) * q[0] + 0x80;
q[0] = (t + (t >> 8)) >> 8;
t = a * p[1] + (255 - a) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = a * p[2] + (255 - a) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
p += 4;
q += 3;
}
src += src_rowstride;
dest += dest_rowstride;
}
}
static void
composite_0888 (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
while (height--)
{
gint twidth = width;
guchar *p = src;
guchar *q = dest;
if (dest_byte_order == GDK_LSB_FIRST)
{
while (twidth--)
{
guint t;
t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
q[0] = (t + (t >> 8)) >> 8;
t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
p += 4;
q += 4;
}
}
else
{
while (twidth--)
{
guint t;
t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
q[1] = (t + (t >> 8)) >> 8;
t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
q[2] = (t + (t >> 8)) >> 8;
t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
q[3] = (t + (t >> 8)) >> 8;
p += 4;
q += 4;
}
}
src += src_rowstride;
dest += dest_rowstride;
}
}
#ifdef USE_MEDIALIB
static void
composite_0888_medialib (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
mlib_image img_src, img_dst;
mlib_ImageSetStruct (&img_dst,
MLIB_BYTE,
4,
width,
height,
dest_rowstride,
dest_buf);
mlib_ImageSetStruct (&img_src,
MLIB_BYTE,
4,
width,
height,
src_rowstride,
src_buf);
if (dest_byte_order == GDK_LSB_FIRST)
mlib_ImageBlendRGBA2BGRA (&img_dst, &img_src);
else
mlib_ImageBlendRGBA2ARGB (&img_dst, &img_src);
}
#endif
static void
composite_565 (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height)
{
guchar *src = src_buf;
guchar *dest = dest_buf;
while (height--)
{
gint twidth = width;
guchar *p = src;
gushort *q = (gushort *)dest;
while (twidth--)
{
guchar a = p[3];
guint tr, tg, tb;
guint tr1, tg1, tb1;
guint tmp = *q;
#if 1
/* This is fast, and corresponds to what composite() above does
* if we converted to 8-bit first.
*/
tr = (tmp & 0xf800);
tr1 = a * p[0] + (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
tg = (tmp & 0x07e0);
tg1 = a * p[1] + (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
tb = (tmp & 0x001f);
tb1 = a * p[2] + (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
*q = (((tr1 + (tr1 >> 8)) & 0xf800) |
(((tg1 + (tg1 >> 8)) & 0xfc00) >> 5) |
((tb1 + (tb1 >> 8)) >> 11));
#else
/* This version correspond to the result we get with XRENDER -
* a bit of precision is lost since we convert to 8 bit after premultiplying
* instead of at the end
*/
guint tr2, tg2, tb2;
guint tr3, tg3, tb3;
tr = (tmp & 0xf800);
tr1 = (255 - a) * ((tr >> 8) + (tr >> 13)) + 0x80;
tr2 = a * p[0] + 0x80;
tr3 = ((tr1 + (tr1 >> 8)) >> 8) + ((tr2 + (tr2 >> 8)) >> 8);
tg = (tmp & 0x07e0);
tg1 = (255 - a) * ((tg >> 3) + (tg >> 9)) + 0x80;
tg2 = a * p[0] + 0x80;
tg3 = ((tg1 + (tg1 >> 8)) >> 8) + ((tg2 + (tg2 >> 8)) >> 8);
tb = (tmp & 0x001f);
tb1 = (255 - a) * ((tb << 3) + (tb >> 2)) + 0x80;
tb2 = a * p[0] + 0x80;
tb3 = ((tb1 + (tb1 >> 8)) >> 8) + ((tb2 + (tb2 >> 8)) >> 8);
*q = (((tr3 & 0xf8) << 8) |
((tg3 & 0xfc) << 3) |
((tb3 >> 3)));
#endif
p += 4;
q++;
}
src += src_rowstride;
dest += dest_rowstride;
}
}
/* Implementation of the old vfunc in terms of the new one
in case someone calls it directly (which they shouldn't!) */
static void
@ -1354,246 +1068,6 @@ gdk_drawable_real_draw_drawable (GdkDrawable *drawable,
src);
}
static void
gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkPixbuf *composited = NULL;
gint dwidth, dheight;
cairo_region_t *clip;
cairo_region_t *drect;
GdkRectangle tmp_rect;
GdkDrawable *real_drawable;
g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
g_return_if_fail (gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB);
g_return_if_fail (gdk_pixbuf_get_n_channels (pixbuf) == 3 ||
gdk_pixbuf_get_n_channels (pixbuf) == 4);
g_return_if_fail (gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
g_return_if_fail (drawable != NULL);
if (width == -1)
width = gdk_pixbuf_get_width (pixbuf);
if (height == -1)
height = gdk_pixbuf_get_height (pixbuf);
g_return_if_fail (width >= 0 && height >= 0);
g_return_if_fail (src_x >= 0 && src_x + width <= gdk_pixbuf_get_width (pixbuf));
g_return_if_fail (src_y >= 0 && src_y + height <= gdk_pixbuf_get_height (pixbuf));
/* Clip to the drawable; this is required for get_from_drawable() so
* can't be done implicitly
*/
if (dest_x < 0)
{
src_x -= dest_x;
width += dest_x;
dest_x = 0;
}
if (dest_y < 0)
{
src_y -= dest_y;
height += dest_y;
dest_y = 0;
}
gdk_drawable_get_size (drawable, &dwidth, &dheight);
if ((dest_x + width) > dwidth)
width = dwidth - dest_x;
if ((dest_y + height) > dheight)
height = dheight - dest_y;
if (width <= 0 || height <= 0)
return;
/* Clip to the clip region; this avoids getting more
* image data from the server than we need to.
*/
tmp_rect.x = dest_x;
tmp_rect.y = dest_y;
tmp_rect.width = width;
tmp_rect.height = height;
drect = cairo_region_create_rectangle (&tmp_rect);
clip = gdk_drawable_get_clip_region (drawable);
cairo_region_intersect (drect, clip);
cairo_region_get_extents (drect, &tmp_rect);
cairo_region_destroy (drect);
cairo_region_destroy (clip);
if (tmp_rect.width == 0 ||
tmp_rect.height == 0)
return;
/* Actually draw */
if (!gc)
gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
/* Drawable is a wrapper here, but at this time we
have already retargeted the destination to any
impl window and set the clip, so what we really
want to do is draw directly on the impl, ignoring
client side subwindows. We also use the impl
in the pixmap target case to avoid resetting the
already set clip on the GC. */
if (GDK_IS_WINDOW (drawable))
real_drawable = GDK_WINDOW_OBJECT (drawable)->impl;
else
real_drawable = GDK_PIXMAP_OBJECT (drawable)->impl;
if (gdk_pixbuf_get_has_alpha (pixbuf))
{
GdkVisual *visual = gdk_drawable_get_visual (drawable);
void (*composite_func) (guchar *src_buf,
gint src_rowstride,
guchar *dest_buf,
gint dest_rowstride,
GdkByteOrder dest_byte_order,
gint width,
gint height) = NULL;
/* First we see if we have a visual-specific composition function that can composite
* the pixbuf data directly onto the image
*/
if (visual)
{
gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
visual->depth);
if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
visual->depth == 16 &&
visual->red_mask == 0xf800 &&
visual->green_mask == 0x07e0 &&
visual->blue_mask == 0x001f)
composite_func = composite_565;
else if (visual->depth == 24 && bits_per_pixel == 32 &&
visual->red_mask == 0xff0000 &&
visual->green_mask == 0x00ff00 &&
visual->blue_mask == 0x0000ff)
{
#ifdef USE_MEDIALIB
if (_gdk_use_medialib ())
composite_func = composite_0888_medialib;
else
composite_func = composite_0888;
#else
composite_func = composite_0888;
#endif
}
}
/* We can't use our composite func if we are required to dither
*/
if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
{
gint x0, y0;
for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
{
gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
{
gint xs0, ys0;
gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
width1, height1,
gdk_drawable_get_depth (drawable), &xs0, &ys0);
gdk_drawable_copy_to_image (drawable, image,
dest_x + x0, dest_y + y0,
xs0, ys0,
width1, height1);
(*composite_func) (gdk_pixbuf_get_pixels (pixbuf) + (src_y + y0) * gdk_pixbuf_get_rowstride (pixbuf) + (src_x + x0) * 4,
gdk_pixbuf_get_rowstride (pixbuf),
(guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
image->bpl,
visual->byte_order,
width1, height1);
gdk_draw_image (real_drawable, gc, image,
xs0, ys0,
dest_x + x0, dest_y + y0,
width1, height1);
}
}
goto out;
}
else
{
/* No special composition func, convert dest to 24 bit RGB data, composite against
* that, and convert back.
*/
composited = gdk_pixbuf_get_from_drawable (NULL,
drawable,
NULL,
dest_x, dest_y,
0, 0,
width, height);
if (composited)
composite (gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4,
gdk_pixbuf_get_rowstride (pixbuf),
gdk_pixbuf_get_pixels (composited),
gdk_pixbuf_get_rowstride (composited),
width, height);
}
}
if (composited)
{
src_x = 0;
src_y = 0;
pixbuf = composited;
}
if (gdk_pixbuf_get_n_channels (pixbuf) == 4)
{
guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 4;
gdk_draw_rgb_32_image_dithalign (real_drawable, gc,
dest_x, dest_y,
width, height,
dither,
buf, gdk_pixbuf_get_rowstride (pixbuf),
x_dither, y_dither);
}
else /* n_channels == 3 */
{
guchar *buf = gdk_pixbuf_get_pixels (pixbuf) + src_y * gdk_pixbuf_get_rowstride (pixbuf) + src_x * 3;
gdk_draw_rgb_image_dithalign (real_drawable, gc,
dest_x, dest_y,
width, height,
dither,
buf, gdk_pixbuf_get_rowstride (pixbuf),
x_dither, y_dither);
}
out:
if (composited)
g_object_unref (composited);
}
/************************************************************************/
/**

View File

@ -151,18 +151,6 @@ struct _GdkDrawableClass
gint *composite_x_offset,
gint *composite_y_offset);
void (*draw_pixbuf) (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
GdkImage* (*_copy_to_image) (GdkDrawable *drawable,
GdkImage *image,
gint src_x,
@ -300,18 +288,6 @@ void gdk_draw_lines (GdkDrawable *drawable,
GdkGC *gc,
const GdkPoint *points,
gint n_points);
void gdk_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
const GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
void gdk_draw_glyphs (GdkDrawable *drawable,
GdkGC *gc,

View File

@ -531,41 +531,6 @@ gdk_offscreen_window_draw_image (GdkDrawable *drawable,
add_damage (offscreen, xdest, ydest, width, height, FALSE);
}
static void
gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
GdkDrawable *real_drawable = get_real_drawable (offscreen);
gdk_draw_pixbuf (real_drawable,
gc,
pixbuf,
src_x,
src_y,
dest_x,
dest_y,
width,
height,
dither,
x_dither,
y_dither);
add_damage (offscreen, dest_x, dest_y, width, height, FALSE);
}
void
_gdk_offscreen_window_new (GdkWindow *window,
GdkScreen *screen,
@ -1199,7 +1164,6 @@ gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
drawable_class->draw_image = gdk_offscreen_window_draw_image;
drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
}
static void

View File

@ -158,7 +158,7 @@ gdk_pixbuf_render_threshold_alpha (GdkPixbuf *pixbuf,
* and @mask_return arguments, respectively, and renders a pixbuf and its
* corresponding thresholded alpha mask to them. This is merely a convenience
* function; applications that need to render pixbufs with dither offsets or to
* given drawables should use gdk_draw_pixbuf() and gdk_pixbuf_render_threshold_alpha().
* given drawables should use Cairo and gdk_pixbuf_render_threshold_alpha().
*
* The pixmap that is created is created for the colormap returned
* by gdk_colormap_get_system(). You normally will want to instead use
@ -219,7 +219,7 @@ remove_alpha_channel (GdkPixbuf *pixbuf)
* and @mask_return arguments, respectively, and renders a pixbuf and its
* corresponding tresholded alpha mask to them. This is merely a convenience
* function; applications that need to render pixbufs with dither offsets or to
* given drawables should use gdk_draw_pixbuf(), and gdk_pixbuf_render_threshold_alpha().
* given drawables should use Cairo and gdk_pixbuf_render_threshold_alpha().
*
* The pixmap that is created uses the #GdkColormap specified by @colormap.
* This colormap must match the colormap of the window where the pixmap

View File

@ -101,18 +101,6 @@ static void gdk_pixmap_draw_image (GdkDrawable *drawable,
gint ydest,
gint width,
gint height);
static void gdk_pixmap_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
static void gdk_pixmap_draw_trapezoids (GdkDrawable *drawable,
GdkGC *gc,
GdkTrapezoid *trapezoids,
@ -194,7 +182,6 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass)
drawable_class->draw_glyphs = gdk_pixmap_draw_glyphs;
drawable_class->draw_glyphs_transformed = gdk_pixmap_draw_glyphs_transformed;
drawable_class->draw_image = gdk_pixmap_draw_image;
drawable_class->draw_pixbuf = gdk_pixmap_draw_pixbuf;
drawable_class->draw_trapezoids = gdk_pixmap_draw_trapezoids;
drawable_class->get_depth = gdk_pixmap_real_get_depth;
drawable_class->get_screen = gdk_pixmap_real_get_screen;
@ -430,29 +417,6 @@ gdk_pixmap_draw_image (GdkDrawable *drawable,
width, height);
}
static void
gdk_pixmap_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkPixmapObject *private = (GdkPixmapObject *)drawable;
if (gc)
_gdk_gc_remove_drawable_clip (gc);
gdk_draw_pixbuf (private->impl, gc, pixbuf,
src_x, src_y, dest_x, dest_y, width, height,
dither, x_dither, y_dither);
}
static void
gdk_pixmap_draw_trapezoids (GdkDrawable *drawable,
GdkGC *gc,
@ -579,7 +543,7 @@ gdk_pixmap_colormap_new_from_pixbuf (GdkColormap *colormap,
{
GdkPixmap *pixmap;
GdkPixbuf *render_pixbuf;
GdkGC *tmp_gc;
cairo_t *cr;
GdkScreen *screen = gdk_colormap_get_screen (colormap);
pixmap = gdk_pixmap_new (gdk_screen_get_root_window (screen),
@ -600,11 +564,10 @@ gdk_pixmap_colormap_new_from_pixbuf (GdkColormap *colormap,
else
render_pixbuf = pixbuf;
tmp_gc = _gdk_drawable_get_scratch_gc (pixmap, FALSE);
gdk_draw_pixbuf (pixmap, tmp_gc, render_pixbuf, 0, 0, 0, 0,
gdk_pixbuf_get_width (render_pixbuf),
gdk_pixbuf_get_height (render_pixbuf),
GDK_RGB_DITHER_NORMAL, 0, 0);
cr = gdk_cairo_create (pixmap);
gdk_cairo_set_source_pixbuf (cr, render_pixbuf, 0, 0);
cairo_paint (cr);
cairo_destroy (cr);
if (render_pixbuf != pixbuf)
g_object_unref (render_pixbuf);

View File

@ -297,19 +297,6 @@ static void gdk_window_draw_image (GdkDrawable *drawable,
gint width,
gint height);
static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
GdkGC *gc,
GdkTrapezoid *trapezoids,
@ -511,7 +498,6 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
drawable_class->draw_glyphs = gdk_window_draw_glyphs;
drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
drawable_class->draw_image = gdk_window_draw_image;
drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
drawable_class->get_depth = gdk_window_real_get_depth;
drawable_class->get_screen = gdk_window_real_get_screen;
@ -4849,48 +4835,6 @@ gdk_window_draw_image (GdkDrawable *drawable,
END_DRAW;
}
static void
gdk_window_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkWindowObject *private = (GdkWindowObject *)drawable;
GdkDrawableClass *klass;
if (GDK_WINDOW_DESTROYED (drawable))
return;
/* If no gc => no user clipping, but we need clipping
for window emulation, so use a scratch gc */
if (!gc)
gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
BEGIN_DRAW;
klass = GDK_DRAWABLE_GET_CLASS (impl);
if (private->paint_stack)
klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
dest_x - x_offset, dest_y - y_offset,
width, height,
dither, x_dither - x_offset, y_dither - y_offset);
else
klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
dest_x - x_offset, dest_y - y_offset,
width, height,
dither, x_dither, y_dither);
END_DRAW;
}
static void
gdk_window_draw_trapezoids (GdkDrawable *drawable,
GdkGC *gc,

View File

@ -506,64 +506,6 @@ gdk_quartz_draw_lines (GdkDrawable *drawable,
gdk_quartz_drawable_release_context (drawable, context);
}
static void
gdk_quartz_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
CGContextRef context = gdk_quartz_drawable_get_context (drawable, FALSE);
CGColorSpaceRef colorspace;
CGDataProviderRef data_provider;
CGImageRef image;
void *data;
int rowstride, pixbuf_width, pixbuf_height;
gboolean has_alpha;
if (!context)
return;
pixbuf_width = gdk_pixbuf_get_width (pixbuf);
pixbuf_height = gdk_pixbuf_get_height (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
data = gdk_pixbuf_get_pixels (pixbuf);
colorspace = CGColorSpaceCreateDeviceRGB ();
data_provider = CGDataProviderCreateWithData (NULL, data, pixbuf_height * rowstride, NULL);
image = CGImageCreate (pixbuf_width, pixbuf_height, 8,
has_alpha ? 32 : 24, rowstride,
colorspace,
has_alpha ? kCGImageAlphaLast : 0,
data_provider, NULL, FALSE,
kCGRenderingIntentDefault);
CGDataProviderRelease (data_provider);
CGColorSpaceRelease (colorspace);
_gdk_quartz_gc_update_cg_context (gc, drawable, context,
GDK_QUARTZ_CONTEXT_STROKE);
CGContextClipToRect (context, CGRectMake (dest_x, dest_y, width, height));
CGContextTranslateCTM (context, dest_x - src_x, dest_y - src_y + pixbuf_height);
CGContextScaleCTM (context, 1, -1);
CGContextDrawImage (context, CGRectMake (0, 0, pixbuf_width, pixbuf_height), image);
CGImageRelease (image);
gdk_quartz_drawable_release_context (drawable, context);
}
static void
gdk_quartz_draw_image (GdkDrawable *drawable,
GdkGC *gc,
@ -640,7 +582,6 @@ gdk_drawable_impl_quartz_class_init (GdkDrawableImplQuartzClass *klass)
drawable_class->draw_segments = gdk_quartz_draw_segments;
drawable_class->draw_lines = gdk_quartz_draw_lines;
drawable_class->draw_image = gdk_quartz_draw_image;
drawable_class->draw_pixbuf = gdk_quartz_draw_pixbuf;
drawable_class->ref_cairo_surface = gdk_quartz_ref_cairo_surface;

View File

@ -100,18 +100,6 @@ static void gdk_win32_draw_image (GdkDrawable *drawable,
gint ydest,
gint width,
gint height);
static void gdk_win32_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
static cairo_surface_t *gdk_win32_ref_cairo_surface (GdkDrawable *drawable);
@ -150,7 +138,6 @@ _gdk_drawable_impl_win32_class_init (GdkDrawableImplWin32Class *klass)
drawable_class->draw_segments = gdk_win32_draw_segments;
drawable_class->draw_lines = gdk_win32_draw_lines;
drawable_class->draw_image = gdk_win32_draw_image;
drawable_class->draw_pixbuf = gdk_win32_draw_pixbuf;
drawable_class->ref_cairo_surface = gdk_win32_ref_cairo_surface;
@ -1634,27 +1621,6 @@ gdk_win32_draw_image (GdkDrawable *drawable,
xsrc, ysrc, xdest, ydest, width, height);
}
static void
gdk_win32_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_WIN32 (drawable)->wrapper;
GDK_DRAWABLE_CLASS (_gdk_drawable_impl_win32_parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
src_x, src_y, dest_x, dest_y,
width, height,
dither, x_dither, y_dither);
}
/**
* _gdk_win32_drawable_acquire_dc
* @drawable: a Win32 #GdkDrawable implementation

View File

@ -101,18 +101,6 @@ static void gdk_x11_draw_image (GdkDrawable *drawable,
gint ydest,
gint width,
gint height);
static void gdk_x11_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither);
static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable);
@ -147,7 +135,6 @@ _gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass)
drawable_class->draw_segments = gdk_x11_draw_segments;
drawable_class->draw_lines = gdk_x11_draw_lines;
drawable_class->draw_image = gdk_x11_draw_image;
drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf;
drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface;
@ -310,79 +297,6 @@ _gdk_x11_have_render (GdkDisplay *display)
return x11display->have_render == GDK_YES;
}
static Picture
gdk_x11_drawable_get_picture (GdkDrawable *drawable)
{
GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
if (!impl->picture)
{
Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
XRenderPictFormat *format;
GdkVisual *visual = gdk_drawable_get_visual (GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper);
if (!visual)
return None;
format = XRenderFindVisualFormat (xdisplay, GDK_VISUAL_XVISUAL (visual));
if (format)
{
XRenderPictureAttributes attributes;
attributes.graphics_exposures = False;
impl->picture = XRenderCreatePicture (xdisplay, impl->xid, format,
CPGraphicsExposure, &attributes);
}
}
return impl->picture;
}
static void
gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
GdkGC *gc)
{
GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
Picture picture = gdk_x11_drawable_get_picture (drawable);
cairo_region_t *clip_region = gc ? _gdk_gc_get_clip_region (gc) : NULL;
if (clip_region)
{
XRectangle *rects;
int n_rects;
_gdk_region_get_xrectangles (clip_region,
gc->clip_x_origin,
gc->clip_y_origin,
&rects,
&n_rects);
XRenderSetPictureClipRectangles (xdisplay, picture,
0, 0, rects, n_rects);
g_free (rects);
}
else
{
XRenderPictureAttributes pa;
GdkBitmap *mask;
gulong pa_mask;
pa_mask = CPClipMask;
if (gc && (mask = _gdk_gc_get_clip_mask (gc)))
{
pa.clip_mask = GDK_PIXMAP_XID (mask);
pa.clip_x_origin = gc->clip_x_origin;
pa.clip_y_origin = gc->clip_y_origin;
pa_mask |= CPClipXOrigin | CPClipYOrigin;
}
else
pa.clip_mask = None;
XRenderChangePicture (xdisplay, picture,
pa_mask, &pa);
}
}
/*****************************************************
* X11 specific implementations of generic functions *
*****************************************************/
@ -846,137 +760,6 @@ gdk_x11_pixmap_get_drawable_impl (GdkPixmap *pixmap)
return ((GdkPixmapObject *)pixmap)->impl;
}
/* Code for accelerated alpha compositing using the RENDER extension.
* It's a bit long because there are lots of possibilities for
* what's the fastest depending on the available picture formats,
* whether we can used shared pixmaps, etc.
*/
static GdkX11FormatType
select_format (GdkDisplay *display,
XRenderPictFormat **format,
XRenderPictFormat **mask)
{
Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
XRenderPictFormat pf;
if (!_gdk_x11_have_render (display))
return GDK_X11_FORMAT_NONE;
/* Look for a 32-bit xRGB and Axxx formats that exactly match the
* in memory data format. We can use them as pixmap and mask
* to deal with non-premultiplied data.
*/
pf.type = PictTypeDirect;
pf.depth = 32;
pf.direct.redMask = 0xff;
pf.direct.greenMask = 0xff;
pf.direct.blueMask = 0xff;
pf.direct.alphaMask = 0;
if (ImageByteOrder (xdisplay) == LSBFirst)
{
/* ABGR */
pf.direct.red = 0;
pf.direct.green = 8;
pf.direct.blue = 16;
}
else
{
/* RGBA */
pf.direct.red = 24;
pf.direct.green = 16;
pf.direct.blue = 8;
}
*format = XRenderFindFormat (xdisplay,
(PictFormatType | PictFormatDepth |
PictFormatRedMask | PictFormatRed |
PictFormatGreenMask | PictFormatGreen |
PictFormatBlueMask | PictFormatBlue |
PictFormatAlphaMask),
&pf,
0);
pf.direct.alphaMask = 0xff;
if (ImageByteOrder (xdisplay) == LSBFirst)
{
/* ABGR */
pf.direct.alpha = 24;
}
else
{
pf.direct.alpha = 0;
}
*mask = XRenderFindFormat (xdisplay,
(PictFormatType | PictFormatDepth |
PictFormatAlphaMask | PictFormatAlpha),
&pf,
0);
if (*format && *mask)
return GDK_X11_FORMAT_EXACT_MASK;
/* OK, that failed, now look for xRGB and Axxx formats in
* RENDER's preferred order
*/
pf.direct.alphaMask = 0;
/* ARGB */
pf.direct.red = 16;
pf.direct.green = 8;
pf.direct.blue = 0;
*format = XRenderFindFormat (xdisplay,
(PictFormatType | PictFormatDepth |
PictFormatRedMask | PictFormatRed |
PictFormatGreenMask | PictFormatGreen |
PictFormatBlueMask | PictFormatBlue |
PictFormatAlphaMask),
&pf,
0);
pf.direct.alphaMask = 0xff;
pf.direct.alpha = 24;
*mask = XRenderFindFormat (xdisplay,
(PictFormatType | PictFormatDepth |
PictFormatAlphaMask | PictFormatAlpha),
&pf,
0);
if (*format && *mask)
return GDK_X11_FORMAT_ARGB_MASK;
/* Finally, if neither of the above worked, fall back to
* looking for combined ARGB -- we'll premultiply ourselves.
*/
pf.type = PictTypeDirect;
pf.depth = 32;
pf.direct.red = 16;
pf.direct.green = 8;
pf.direct.blue = 0;
pf.direct.alphaMask = 0xff;
pf.direct.alpha = 24;
*format = XRenderFindFormat (xdisplay,
(PictFormatType | PictFormatDepth |
PictFormatRedMask | PictFormatRed |
PictFormatGreenMask | PictFormatGreen |
PictFormatBlueMask | PictFormatBlue |
PictFormatAlphaMask | PictFormatAlpha),
&pf,
0);
*mask = NULL;
if (*format)
return GDK_X11_FORMAT_ARGB;
return GDK_X11_FORMAT_NONE;
}
#if 0
static void
list_formats (XRenderPictFormat *pf)
@ -1149,260 +932,6 @@ _gdk_x11_convert_to_format (guchar *src_buf,
}
}
static void
draw_with_images (GdkDrawable *drawable,
GdkGC *gc,
GdkX11FormatType format_type,
XRenderPictFormat *format,
XRenderPictFormat *mask_format,
guchar *src_rgb,
gint src_rowstride,
gint dest_x,
gint dest_y,
gint width,
gint height)
{
GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen;
Display *xdisplay = GDK_SCREEN_XDISPLAY (screen);
GdkImage *image;
GdkPixmap *pix;
GdkGC *pix_gc;
Picture pict;
Picture dest_pict;
Picture mask = None;
gint x0, y0;
pix = gdk_pixmap_new (gdk_screen_get_root_window (screen), width, height, 32);
pict = XRenderCreatePicture (xdisplay,
GDK_PIXMAP_XID (pix),
format, 0, NULL);
if (mask_format)
mask = XRenderCreatePicture (xdisplay,
GDK_PIXMAP_XID (pix),
mask_format, 0, NULL);
dest_pict = gdk_x11_drawable_get_picture (drawable);
pix_gc = _gdk_drawable_get_scratch_gc (pix, FALSE);
for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
{
gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
{
gint xs0, ys0;
gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
image = _gdk_image_get_scratch (screen, width1, height1, 32, &xs0, &ys0);
_gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
(guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
format_type, image->byte_order,
width1, height1);
gdk_draw_image (pix, pix_gc,
image, xs0, ys0, x0, y0, width1, height1);
}
}
XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
0, 0, 0, 0, dest_x, dest_y, width, height);
XRenderFreePicture (xdisplay, pict);
if (mask)
XRenderFreePicture (xdisplay, mask);
g_object_unref (pix);
}
typedef struct _ShmPixmapInfo ShmPixmapInfo;
struct _ShmPixmapInfo
{
Display *display;
Pixmap pix;
Picture pict;
Picture mask;
};
static void
shm_pixmap_info_destroy (gpointer data)
{
ShmPixmapInfo *info = data;
if (info->pict != None)
XRenderFreePicture (info->display, info->pict);
if (info->mask != None)
XRenderFreePicture (info->display, info->mask);
g_free (data);
}
/* Returns FALSE if we can't get a shm pixmap */
static gboolean
get_shm_pixmap_for_image (Display *xdisplay,
GdkImage *image,
XRenderPictFormat *format,
XRenderPictFormat *mask_format,
Pixmap *pix,
Picture *pict,
Picture *mask)
{
ShmPixmapInfo *info;
if (image->type != GDK_IMAGE_SHARED)
return FALSE;
info = g_object_get_data (G_OBJECT (image), "gdk-x11-shm-pixmap");
if (!info)
{
*pix = _gdk_x11_image_get_shm_pixmap (image);
if (!*pix)
return FALSE;
info = g_new (ShmPixmapInfo, 1);
info->display = xdisplay;
info->pix = *pix;
info->pict = XRenderCreatePicture (xdisplay, info->pix,
format, 0, NULL);
if (mask_format)
info->mask = XRenderCreatePicture (xdisplay, info->pix,
mask_format, 0, NULL);
else
info->mask = None;
g_object_set_data_full (G_OBJECT (image), "gdk-x11-shm-pixmap", info,
shm_pixmap_info_destroy);
}
*pix = info->pix;
*pict = info->pict;
*mask = info->mask;
return TRUE;
}
#ifdef USE_SHM
/* Returns FALSE if drawing with ShmPixmaps is not possible */
static gboolean
draw_with_pixmaps (GdkDrawable *drawable,
GdkGC *gc,
GdkX11FormatType format_type,
XRenderPictFormat *format,
XRenderPictFormat *mask_format,
guchar *src_rgb,
gint src_rowstride,
gint dest_x,
gint dest_y,
gint width,
gint height)
{
Display *xdisplay = GDK_SCREEN_XDISPLAY (GDK_DRAWABLE_IMPL_X11 (drawable)->screen);
GdkImage *image;
Pixmap pix;
Picture pict;
Picture dest_pict;
Picture mask = None;
gint x0, y0;
dest_pict = gdk_x11_drawable_get_picture (drawable);
for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
{
gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
{
gint xs0, ys0;
gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
image = _gdk_image_get_scratch (GDK_DRAWABLE_IMPL_X11 (drawable)->screen,
width1, height1, 32, &xs0, &ys0);
if (!get_shm_pixmap_for_image (xdisplay, image, format, mask_format, &pix, &pict, &mask))
return FALSE;
_gdk_x11_convert_to_format (src_rgb + y0 * src_rowstride + 4 * x0, src_rowstride,
(guchar *)image->mem + ys0 * image->bpl + xs0 * image->bpp, image->bpl,
format_type, image->byte_order,
width1, height1);
XRenderComposite (xdisplay, PictOpOver, pict, mask, dest_pict,
xs0, ys0, xs0, ys0, x0 + dest_x, y0 + dest_y,
width1, height1);
}
}
return TRUE;
}
#endif
static void
gdk_x11_draw_pixbuf (GdkDrawable *drawable,
GdkGC *gc,
GdkPixbuf *pixbuf,
gint src_x,
gint src_y,
gint dest_x,
gint dest_y,
gint width,
gint height,
GdkRgbDither dither,
gint x_dither,
gint y_dither)
{
GdkX11FormatType format_type;
XRenderPictFormat *format, *mask_format;
gint rowstride;
#ifdef USE_SHM
gboolean use_pixmaps = TRUE;
#endif /* USE_SHM */
format_type = select_format (gdk_drawable_get_display (drawable),
&format, &mask_format);
if (format_type == GDK_X11_FORMAT_NONE ||
!gdk_pixbuf_get_has_alpha (pixbuf) ||
gdk_drawable_get_depth (drawable) == 1 ||
(dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
gdk_x11_drawable_get_picture (drawable) == None)
{
GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
GDK_DRAWABLE_CLASS (_gdk_drawable_impl_x11_parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
src_x, src_y, dest_x, dest_y,
width, height,
dither, x_dither, y_dither);
return;
}
gdk_x11_drawable_update_picture_clip (drawable, gc);
rowstride = gdk_pixbuf_get_rowstride (pixbuf);
#ifdef USE_SHM
if (use_pixmaps)
{
if (!draw_with_pixmaps (drawable, gc,
format_type, format, mask_format,
gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
rowstride,
dest_x, dest_y, width, height))
use_pixmaps = FALSE;
}
if (!use_pixmaps)
#endif /* USE_SHM */
draw_with_images (drawable, gc,
format_type, format, mask_format,
gdk_pixbuf_get_pixels (pixbuf) + src_y * rowstride + src_x * 4,
rowstride,
dest_x, dest_y, width, height);
}
static void
gdk_x11_cairo_surface_destroy (void *data)
{