gdi32: Use GetImage to retrieve the brush bits in metafiles.

This commit is contained in:
Alexandre Julliard 2011-08-03 13:01:29 +02:00
parent 6d00196aea
commit 91976a5b74
3 changed files with 59 additions and 103 deletions

View File

@ -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.@]
*

View File

@ -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;

View File

@ -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;
}