Alexandre Julliard : gdi32: Use GetImage to retrieve the brush bits in metafiles.
Alexandre Julliard
julliard at winehq.org
Wed Aug 3 12:48:10 CDT 2011
Module: wine
Branch: master
Commit: 91976a5b7461d7cae28f1c7622fb2eea3a2ef395
URL: http://source.winehq.org/git/wine.git/?a=commit;h=91976a5b7461d7cae28f1c7622fb2eea3a2ef395
Author: Alexandre Julliard <julliard at winehq.org>
Date: Wed Aug 3 13:01:29 2011 +0200
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 cfe9fc1..3d7e1a2 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 4479316..f0fb825 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 d9c9f95..674e7e1 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 = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
- sizeof(RGBQUAD) + bmSize;
+ size = FIELD_OFFSET( METARECORD, rdParm[2] ) +
+ FIELD_OFFSET( BITMAPINFO, bmiColors[2] ) + src_info->bmiHeader.biSizeImage;
- 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;
}
More information about the wine-cvs
mailing list