Module: wine Branch: master Commit: 3e8ad9a064cfce36752233a7a7439b11dac01074 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3e8ad9a064cfce36752233a7a7...
Author: Alexandre Julliard julliard@winehq.org Date: Fri May 11 13:48:19 2012 +0200
winex11: Add a helper to create a pixmap from an image.
---
dlls/winex11.drv/bitblt.c | 126 +++++++++++++++++++++++++++++++++++++++++++++ dlls/winex11.drv/x11drv.h | 2 + 2 files changed, 128 insertions(+), 0 deletions(-)
diff --git a/dlls/winex11.drv/bitblt.c b/dlls/winex11.drv/bitblt.c index 413f4e4..6dec77f 100644 --- a/dlls/winex11.drv/bitblt.c +++ b/dlls/winex11.drv/bitblt.c @@ -937,6 +937,16 @@ static void free_ximage_bits( struct gdi_image_bits *bits ) wine_tsx11_unlock(); }
+/* only for use on sanitized BITMAPINFO structures */ +static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse ) +{ + if (info->bmiHeader.biCompression == BI_BITFIELDS) + return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD); + if (coloruse == DIB_PAL_COLORS) + return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD); + return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] ); +} + /* store the palette or color mask data in the bitmap info structure */ static void set_color_info( const XVisualInfo *vis, BITMAPINFO *info ) { @@ -1464,6 +1474,122 @@ DWORD X11DRV_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
/*********************************************************************** + * put_pixmap_image + * + * Simplified equivalent of X11DRV_PutImage that writes directly to a pixmap. + */ +static DWORD put_pixmap_image( Pixmap pixmap, const XVisualInfo *vis, + BITMAPINFO *info, const struct gdi_image_bits *bits ) +{ + DWORD ret; + XImage *image; + struct bitblt_coords coords; + struct gdi_image_bits dst_bits; + const XPixmapFormatValues *format = pixmap_formats[vis->depth]; + const int *mapping = NULL; + + if (!format) return ERROR_INVALID_PARAMETER; + if (info->bmiHeader.biPlanes != 1) goto update_format; + if (info->bmiHeader.biBitCount != format->bits_per_pixel) goto update_format; + /* FIXME: could try to handle 1-bpp using XCopyPlane */ + if (!matching_color_info( vis, info )) goto update_format; + if (!bits) return ERROR_SUCCESS; /* just querying the format */ + + coords.x = 0; + coords.y = 0; + coords.width = info->bmiHeader.biWidth; + coords.height = abs( info->bmiHeader.biHeight ); + SetRect( &coords.visrect, 0, 0, coords.width, coords.height ); + + wine_tsx11_lock(); + image = XCreateImage( gdi_display, visual, vis->depth, ZPixmap, 0, NULL, + coords.width, coords.height, 32, 0 ); + wine_tsx11_unlock(); + if (!image) return ERROR_OUTOFMEMORY; + + if (image->bits_per_pixel == 4 || image->bits_per_pixel == 8) + mapping = X11DRV_PALETTE_PaletteToXPixel; + + if (!(ret = copy_image_bits( info, is_r8g8b8(vis), image, bits, &dst_bits, &coords, mapping, ~0u ))) + { + image->data = dst_bits.ptr; + wine_tsx11_lock(); + XPutImage( gdi_display, pixmap, get_bitmap_gc( vis->depth ), + image, 0, 0, 0, 0, coords.width, coords.height ); + wine_tsx11_unlock(); + image->data = NULL; + } + + wine_tsx11_lock(); + XDestroyImage( image ); + wine_tsx11_unlock(); + if (dst_bits.free) dst_bits.free( &dst_bits ); + return ret; + +update_format: + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = format->bits_per_pixel; + if (info->bmiHeader.biHeight > 0) info->bmiHeader.biHeight = -info->bmiHeader.biHeight; + set_color_info( vis, info ); + return ERROR_BAD_FORMAT; +} + + +/*********************************************************************** + * create_pixmap_from_image + */ +Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info, + const struct gdi_image_bits *bits, UINT coloruse ) +{ + static const RGBQUAD default_colortable[2] = { { 0x00, 0x00, 0x00 }, { 0xff, 0xff, 0xff } }; + char dst_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + char src_buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info = (BITMAPINFO *)dst_buffer; + BITMAPINFO *src_info = (BITMAPINFO *)src_buffer; + struct gdi_image_bits dst_bits; + Pixmap pixmap; + DWORD err; + HBITMAP dib; + + wine_tsx11_lock(); + pixmap = XCreatePixmap( gdi_display, root_window, + info->bmiHeader.biWidth, abs(info->bmiHeader.biHeight), vis->depth ); + wine_tsx11_unlock(); + if (!pixmap) return 0; + + memcpy( src_info, info, get_dib_info_size( info, coloruse )); + memcpy( dst_info, info, get_dib_info_size( info, coloruse )); + + if (coloruse == DIB_PAL_COLORS || + (err = put_pixmap_image( pixmap, vis, dst_info, bits )) == ERROR_BAD_FORMAT) + { + if (dst_info->bmiHeader.biBitCount == 1) /* set a default color table for 1-bpp */ + memcpy( dst_info->bmiColors, default_colortable, sizeof(default_colortable) ); + dib = CreateDIBSection( hdc, dst_info, coloruse, &dst_bits.ptr, 0, 0 ); + if (dib) + { + if (src_info->bmiHeader.biBitCount == 1 && !src_info->bmiHeader.biClrUsed) + memcpy( src_info->bmiColors, default_colortable, sizeof(default_colortable) ); + SetDIBits( hdc, dib, 0, abs(info->bmiHeader.biHeight), bits->ptr, src_info, coloruse ); + dst_bits.free = NULL; + dst_bits.is_copy = TRUE; + err = put_pixmap_image( pixmap, vis, dst_info, &dst_bits ); + DeleteObject( dib ); + } + else err = ERROR_OUTOFMEMORY; + } + + if (!err) return pixmap; + + wine_tsx11_lock(); + XFreePixmap( gdi_display, pixmap ); + wine_tsx11_unlock(); + return 0; + +} + + +/*********************************************************************** * get_pixmap_image * * Equivalent of X11DRV_GetImage that reads directly from a pixmap. diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index d17565b..7ed4bdd 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -229,6 +229,8 @@ extern Pixmap X11DRV_get_pixmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern DWORD copy_image_bits( BITMAPINFO *info, BOOL is_r8g8b8, XImage *image, const struct gdi_image_bits *src_bits, struct gdi_image_bits *dst_bits, struct bitblt_coords *coords, const int *mapping, unsigned int zeropad_mask ) DECLSPEC_HIDDEN; +extern Pixmap create_pixmap_from_image( HDC hdc, const XVisualInfo *vis, const BITMAPINFO *info, + const struct gdi_image_bits *bits, UINT coloruse ) DECLSPEC_HIDDEN; extern DWORD get_pixmap_image( Pixmap pixmap, int width, int height, const XVisualInfo *vis, BITMAPINFO *info, struct gdi_image_bits *bits ) DECLSPEC_HIDDEN;