From bfdac3e885f12dfd4b16c0c16f4767c451d0994d Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 17 Oct 2011 13:25:05 +0200 Subject: [PATCH] gdi32: Add a fall back implementation of BlendImage using client-side blending. --- dlls/gdi32/bitblt.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++ dlls/gdi32/dibdrv/bitblt.c | 14 +++++++++++ dlls/gdi32/driver.c | 6 ----- dlls/gdi32/gdi_private.h | 5 ++++ 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/dlls/gdi32/bitblt.c b/dlls/gdi32/bitblt.c index eee6fa26fc0..28b1a7385bc 100644 --- a/dlls/gdi32/bitblt.c +++ b/dlls/gdi32/bitblt.c @@ -198,6 +198,24 @@ static DWORD stretch_bits( const BITMAPINFO *src_info, struct bitblt_coords *src return err; } +static DWORD blend_bits( const BITMAPINFO *src_info, const struct gdi_image_bits *src_bits, + struct bitblt_coords *src, BITMAPINFO *dst_info, + struct gdi_image_bits *dst_bits, struct bitblt_coords *dst, BLENDFUNCTION blend ) +{ + if (!dst_bits->is_copy) + { + int size = get_dib_image_size( dst_info ); + void *ptr = HeapAlloc( GetProcessHeap(), 0, size ); + if (!ptr) return ERROR_OUTOFMEMORY; + memcpy( ptr, dst_bits->ptr, size ); + if (dst_bits->free) dst_bits->free( dst_bits ); + dst_bits->ptr = ptr; + dst_bits->is_copy = TRUE; + dst_bits->free = free_heap_bits; + } + return blend_bitmapinfo( src_info, src_bits->ptr, src, dst_info, dst_bits->ptr, dst, blend ); +} + /*********************************************************************** * null driver fallback implementations */ @@ -328,6 +346,51 @@ done: } +DWORD nulldrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits, + struct bitblt_coords *src, struct bitblt_coords *dst, BLENDFUNCTION blend ) +{ + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info = (BITMAPINFO *)buffer; + struct gdi_image_bits dst_bits; + struct bitblt_coords orig_dst; + DC *dc = get_nulldrv_dc( dev ); + DWORD err; + + if (info->bmiHeader.biPlanes != 1) goto update_format; + if (info->bmiHeader.biBitCount != 32) goto update_format; + if (info->bmiHeader.biCompression == BI_BITFIELDS) + { + DWORD *masks = (DWORD *)info->bmiColors; + if (masks[0] != 0xff0000 || masks[1] != 0x00ff00 || masks[2] != 0x0000ff) + goto update_format; + } + + if (!bits) return ERROR_SUCCESS; + if ((src->width != dst->width) || (src->height != dst->height)) return ERROR_TRANSFORM_NOT_SUPPORTED; + + dev = GET_DC_PHYSDEV( dc, pGetImage ); + orig_dst = *dst; + err = dev->funcs->pGetImage( dev, 0, dst_info, &dst_bits, dst ); + if (err) return err; + + dev = GET_DC_PHYSDEV( dc, pPutImage ); + err = blend_bits( info, bits, src, dst_info, &dst_bits, dst, blend ); + if (!err) err = dev->funcs->pPutImage( dev, 0, 0, dst_info, &dst_bits, dst, &orig_dst, SRCCOPY ); + + if (dst_bits.free) dst_bits.free( &dst_bits ); + return err; + +update_format: + if (blend.AlphaFormat & AC_SRC_ALPHA) /* source alpha requires A8R8G8B8 format */ + return ERROR_INVALID_PARAMETER; + + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = 32; + info->bmiHeader.biCompression = BI_RGB; + info->bmiHeader.biClrUsed = 0; + return ERROR_BAD_FORMAT; +} + /*********************************************************************** * PatBlt (GDI32.@) */ diff --git a/dlls/gdi32/dibdrv/bitblt.c b/dlls/gdi32/dibdrv/bitblt.c index bf1256ea1b1..de60f474b1a 100644 --- a/dlls/gdi32/dibdrv/bitblt.c +++ b/dlls/gdi32/dibdrv/bitblt.c @@ -1202,6 +1202,20 @@ DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bit return ERROR_SUCCESS; } +DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src, + const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst, + BLENDFUNCTION blend ) +{ + dib_info src_dib, dst_dib; + + if (!init_dib_info_from_bitmapinfo( &src_dib, src_info, src_bits, 0 ) ) + return ERROR_BAD_FORMAT; + if (!init_dib_info_from_bitmapinfo( &dst_dib, dst_info, dst_bits, 0 ) ) + return ERROR_BAD_FORMAT; + + return blend_rect( &dst_dib, &dst->visrect, &src_dib, &src->visrect, NULL, blend ); +} + /*********************************************************************** * dibdrv_StretchBlt */ diff --git a/dlls/gdi32/driver.c b/dlls/gdi32/driver.c index 4f111c3f8f2..8647b955813 100644 --- a/dlls/gdi32/driver.c +++ b/dlls/gdi32/driver.c @@ -196,12 +196,6 @@ static BOOL nulldrv_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, return TRUE; } -static DWORD nulldrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits, - struct bitblt_coords *src, struct bitblt_coords *dst, BLENDFUNCTION func ) -{ - return TRUE; -} - static INT nulldrv_ChoosePixelFormat( PHYSDEV dev, const PIXELFORMATDESCRIPTOR *descr ) { return 0; diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 76e146bd04b..d8648efa32c 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -257,6 +257,9 @@ extern DWORD convert_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, str extern DWORD stretch_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src, const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst, INT mode ) DECLSPEC_HIDDEN; +extern DWORD blend_bitmapinfo( const BITMAPINFO *src_info, void *src_bits, struct bitblt_coords *src, + const BITMAPINFO *dst_info, void *dst_bits, struct bitblt_coords *dst, + BLENDFUNCTION blend ) DECLSPEC_HIDDEN; /* driver.c */ extern const DC_FUNCTIONS null_driver DECLSPEC_HIDDEN; @@ -388,6 +391,8 @@ extern BOOL nulldrv_AlphaBlend( PHYSDEV dst_dev, struct bitblt_coords *dst, extern BOOL nulldrv_AngleArc( PHYSDEV dev, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) DECLSPEC_HIDDEN; extern BOOL nulldrv_ArcTo( PHYSDEV dev, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; extern BOOL nulldrv_BeginPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern DWORD nulldrv_BlendImage( PHYSDEV dev, BITMAPINFO *info, const struct gdi_image_bits *bits, + struct bitblt_coords *src, struct bitblt_coords *dst, BLENDFUNCTION func ) DECLSPEC_HIDDEN; extern BOOL nulldrv_CloseFigure( PHYSDEV dev ) DECLSPEC_HIDDEN; extern BOOL nulldrv_EndPath( PHYSDEV dev ) DECLSPEC_HIDDEN; extern INT nulldrv_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; -- 2.11.4.GIT