From 91976a5b7461d7cae28f1c7622fb2eea3a2ef395 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 3 Aug 2011 13:01:29 +0200 Subject: [PATCH] gdi32: Use GetImage to retrieve the brush bits in metafiles. --- dlls/gdi32/bitmap.c | 20 ++++++ dlls/gdi32/gdi_private.h | 1 + dlls/gdi32/mfdrv/objects.c | 141 ++++++++++--------------------------- 3 files changed, 59 insertions(+), 103 deletions(-) diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index cfe9fc1e4e6..3d7e1a2f8f2 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -414,6 +414,26 @@ HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp ) } +/* convenience wrapper for GetImage to retrieve the full contents of a bitmap */ +BOOL get_bitmap_image( HBITMAP hbitmap, BITMAPINFO *info, struct gdi_image_bits *bits ) +{ + struct bitblt_coords src; + BOOL ret = FALSE; + BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ); + + if (bmp) + { + src.visrect.left = src.x = 0; + src.visrect.top = src.y = 0; + src.visrect.right = src.width = bmp->bitmap.bmWidth; + src.visrect.bottom = src.height = bmp->bitmap.bmHeight; + ret = !bmp->funcs->pGetImage( NULL, hbitmap, info, bits, &src ); + GDI_ReleaseObj( hbitmap ); + } + return ret; +} + + /*********************************************************************** * GetBitmapBits [GDI32.@] * diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index 4479316c3dd..f0fb8259622 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -309,6 +309,7 @@ extern BOOL BIDI_Reorder( HDC hDC, LPCWSTR lpString, INT uCount, DWORD dwFlags, LPWSTR lpOutString, INT uCountOut, UINT *lpOrder, WORD **lpGlyphs, INT* cGlyphs ) DECLSPEC_HIDDEN; /* bitmap.c */ +extern BOOL get_bitmap_image( HBITMAP hbitmap, BITMAPINFO *info, struct gdi_image_bits *bits ) DECLSPEC_HIDDEN; extern HBITMAP BITMAP_CopyBitmap( HBITMAP hbitmap ) DECLSPEC_HIDDEN; extern BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev ) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/mfdrv/objects.c b/dlls/gdi32/mfdrv/objects.c index d9c9f959b1d..674e7e1f9c0 100644 --- a/dlls/gdi32/mfdrv/objects.c +++ b/dlls/gdi32/mfdrv/objects.c @@ -142,69 +142,6 @@ HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap ) return 0; } -/*********************************************************************** - * Internal helper for MFDRV_CreateBrushIndirect(): - * Change the padding of a bitmap from 16 (BMP) to 32 (DIB) bits. - */ -static inline void MFDRV_PadTo32(LPBYTE lpRows, int height, int width) -{ - int bytes16 = 2 * ((width + 15) / 16); - int bytes32 = 4 * ((width + 31) / 32); - LPBYTE lpSrc, lpDst; - int i; - - if (!height) - return; - - height = abs(height) - 1; - lpSrc = lpRows + height * bytes16; - lpDst = lpRows + height * bytes32; - - /* Note that we work backwards so we can re-pad in place */ - while (height >= 0) - { - for (i = bytes32; i > bytes16; i--) - lpDst[i - 1] = 0; /* Zero the padding bytes */ - for (; i > 0; i--) - lpDst[i - 1] = lpSrc[i - 1]; /* Move image bytes into alignment */ - lpSrc -= bytes16; - lpDst -= bytes32; - height--; - } -} - -/*********************************************************************** - * Internal helper for MFDRV_CreateBrushIndirect(): - * Reverse order of bitmap rows in going from BMP to DIB. - */ -static inline void MFDRV_Reverse(LPBYTE lpRows, int height, int width) -{ - int bytes = 4 * ((width + 31) / 32); - LPBYTE lpSrc, lpDst; - BYTE temp; - int i; - - if (!height) - return; - - lpSrc = lpRows; - lpDst = lpRows + (height-1) * bytes; - height = height/2; - - while (height > 0) - { - for (i = 0; i < bytes; i++) - { - temp = lpDst[i]; - lpDst[i] = lpSrc[i]; - lpSrc[i] = temp; - } - lpSrc += bytes; - lpDst -= bytes; - height--; - } -} - /****************************************************************** * MFDRV_CreateBrushIndirect */ @@ -238,59 +175,57 @@ INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) } case BS_PATTERN: { - BITMAP bm; - BITMAPINFO *info; - DWORD bmSize; + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; + struct gdi_image_bits bits; COLORREF cref; - GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm); - if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) { + if (!get_bitmap_image( (HANDLE)logbrush.lbHatch, src_info, &bits )) goto done; + if (src_info->bmiHeader.biBitCount != 1) + { FIXME("Trying to store a colour pattern brush\n"); + if (bits.free) bits.free( &bits ); goto done; } - bmSize = get_dib_stride( bm.bmWidth, bm.bmBitsPixel) * bm.bmHeight; + size = FIELD_OFFSET( METARECORD, rdParm[2] ) + + FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage; - size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) + - sizeof(RGBQUAD) + bmSize; - - mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); - if(!mr) goto done; + if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) + { + if (bits.free) bits.free( &bits ); + goto done; + } mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = size / 2; mr->rdParm[0] = BS_PATTERN; mr->rdParm[1] = DIB_RGB_COLORS; - info = (BITMAPINFO *)(mr->rdParm + 2); - - info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - info->bmiHeader.biWidth = bm.bmWidth; - info->bmiHeader.biHeight = bm.bmHeight; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biBitCount = 1; - info->bmiHeader.biSizeImage = bmSize; - - GetBitmapBits((HANDLE)logbrush.lbHatch, - bm.bmHeight * get_bitmap_stride(bm.bmWidth, bm.bmBitsPixel), - (LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD)); - - /* Change the padding to be DIB compatible if needed */ - if(bm.bmWidth & 31) - MFDRV_PadTo32((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), - bm.bmWidth, bm.bmHeight); - /* BMP and DIB have opposite row order conventions */ - MFDRV_Reverse((LPBYTE)info + sizeof(BITMAPINFO) + sizeof(RGBQUAD), - bm.bmWidth, bm.bmHeight); - + dst_info = (BITMAPINFO *)(mr->rdParm + 2); + dst_info->bmiHeader = src_info->bmiHeader; cref = GetTextColor( dev->hdc ); - info->bmiColors[0].rgbRed = GetRValue(cref); - info->bmiColors[0].rgbGreen = GetGValue(cref); - info->bmiColors[0].rgbBlue = GetBValue(cref); - info->bmiColors[0].rgbReserved = 0; + dst_info->bmiColors[0].rgbRed = GetRValue(cref); + dst_info->bmiColors[0].rgbGreen = GetGValue(cref); + dst_info->bmiColors[0].rgbBlue = GetBValue(cref); + dst_info->bmiColors[0].rgbReserved = 0; cref = GetBkColor( dev->hdc ); - info->bmiColors[1].rgbRed = GetRValue(cref); - info->bmiColors[1].rgbGreen = GetGValue(cref); - info->bmiColors[1].rgbBlue = GetBValue(cref); - info->bmiColors[1].rgbReserved = 0; + dst_info->bmiColors[1].rgbRed = GetRValue(cref); + dst_info->bmiColors[1].rgbGreen = GetGValue(cref); + dst_info->bmiColors[1].rgbBlue = GetBValue(cref); + dst_info->bmiColors[1].rgbReserved = 0; + + /* always return a bottom-up DIB */ + if (dst_info->bmiHeader.biHeight < 0) + { + int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, + dst_info->bmiHeader.biBitCount ); + char *dst_ptr = (char *)&dst_info->bmiColors[2]; + dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; + dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; + for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) + memcpy( dst_ptr, (char *)bits.ptr + i * width_bytes, width_bytes ); + } + else memcpy( &dst_info->bmiColors[2], bits.ptr, dst_info->bmiHeader.biSizeImage ); + if (bits.free) bits.free( &bits ); break; }