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