Alexandre Julliard : user32: Support creating cursors and icons from DIB section bitmaps.

Alexandre Julliard julliard at winehq.org
Wed May 21 05:22:45 CDT 2008


Module: wine
Branch: master
Commit: 0528a2b660f3aa01d274ecae5f2de02d5fb52ae8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=0528a2b660f3aa01d274ecae5f2de02d5fb52ae8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Wed May 21 11:39:38 2008 +0200

user32: Support creating cursors and icons from DIB section bitmaps.

---

 dlls/user32/cursoricon.c       |   76 +++++++++++++++++++++++++++++++++------
 dlls/user32/tests/cursoricon.c |   66 ++++++++++++++++++++++++++++++++++-
 2 files changed, 129 insertions(+), 13 deletions(-)

diff --git a/dlls/user32/cursoricon.c b/dlls/user32/cursoricon.c
index c5d192d..a1ba570 100644
--- a/dlls/user32/cursoricon.c
+++ b/dlls/user32/cursoricon.c
@@ -1790,9 +1790,10 @@ BOOL WINAPI GetIconInfo(HICON hIcon, PICONINFO iconinfo)
  */
 HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 {
-    BITMAP bmpXor,bmpAnd;
+    DIBSECTION bmpXor;
+    BITMAP bmpAnd;
     HICON16 hObj;
-    int	sizeXor,sizeAnd;
+    int xor_objsize = 0, sizeXor = 0, sizeAnd, planes, bpp;
 
     TRACE("color %p, mask %p, hotspot %ux%u, fIcon %d\n",
            iconinfo->hbmColor, iconinfo->hbmMask,
@@ -1800,19 +1801,24 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 
     if (!iconinfo->hbmMask) return 0;
 
+    planes = GetDeviceCaps( screen_dc, PLANES );
+    bpp = GetDeviceCaps( screen_dc, BITSPIXEL );
+
     if (iconinfo->hbmColor)
     {
-        GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
+        xor_objsize = GetObjectW( iconinfo->hbmColor, sizeof(bmpXor), &bmpXor );
         TRACE("color: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
-               bmpXor.bmWidth, bmpXor.bmHeight, bmpXor.bmWidthBytes,
-               bmpXor.bmPlanes, bmpXor.bmBitsPixel);
+               bmpXor.dsBm.bmWidth, bmpXor.dsBm.bmHeight, bmpXor.dsBm.bmWidthBytes,
+               bmpXor.dsBm.bmPlanes, bmpXor.dsBm.bmBitsPixel);
+        /* we can use either depth 1 or screen depth for xor bitmap */
+        if (bmpXor.dsBm.bmPlanes == 1 && bmpXor.dsBm.bmBitsPixel == 1) planes = bpp = 1;
+        sizeXor = bmpXor.dsBm.bmHeight * planes * get_bitmap_width_bytes( bmpXor.dsBm.bmWidth, bpp );
     }
     GetObjectW( iconinfo->hbmMask, sizeof(bmpAnd), &bmpAnd );
     TRACE("mask: width %d, height %d, width bytes %d, planes %u, bpp %u\n",
            bmpAnd.bmWidth, bmpAnd.bmHeight, bmpAnd.bmWidthBytes,
            bmpAnd.bmPlanes, bmpAnd.bmBitsPixel);
 
-    sizeXor = iconinfo->hbmColor ? (bmpXor.bmHeight * bmpXor.bmWidthBytes) : 0;
     sizeAnd = bmpAnd.bmHeight * get_bitmap_width_bytes(bmpAnd.bmWidth, 1);
 
     hObj = GlobalAlloc16( GMEM_MOVEABLE,
@@ -1837,11 +1843,11 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
 
         if (iconinfo->hbmColor)
         {
-            info->nWidth        = bmpXor.bmWidth;
-            info->nHeight       = bmpXor.bmHeight;
-            info->nWidthBytes   = bmpXor.bmWidthBytes;
-            info->bPlanes       = bmpXor.bmPlanes;
-            info->bBitsPerPixel = bmpXor.bmBitsPixel;
+            info->nWidth        = bmpXor.dsBm.bmWidth;
+            info->nHeight       = bmpXor.dsBm.bmHeight;
+            info->nWidthBytes   = bmpXor.dsBm.bmWidthBytes;
+            info->bPlanes       = planes;
+            info->bBitsPerPixel = bpp;
         }
         else
         {
@@ -1883,7 +1889,53 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
             GetBitmapBits( hbmp_mono, sizeAnd, (char*)(info + 1) );
             DeleteObject( hbmp_mono );
         }
-        if (iconinfo->hbmColor) GetBitmapBits( iconinfo->hbmColor, sizeXor, (char*)(info + 1) + sizeAnd );
+
+        if (iconinfo->hbmColor)
+        {
+            char *dst_bits = (char*)(info + 1) + sizeAnd;
+
+            if (bmpXor.dsBm.bmPlanes == planes && bmpXor.dsBm.bmBitsPixel == bpp)
+                GetBitmapBits( iconinfo->hbmColor, sizeXor, dst_bits );
+            else
+            {
+                BITMAPINFO bminfo;
+                int dib_width = get_dib_width_bytes( info->nWidth, info->bBitsPerPixel );
+                int bitmap_width = get_bitmap_width_bytes( info->nWidth, info->bBitsPerPixel );
+
+                bminfo.bmiHeader.biSize = sizeof(bminfo);
+                bminfo.bmiHeader.biWidth = info->nWidth;
+                bminfo.bmiHeader.biHeight = info->nHeight;
+                bminfo.bmiHeader.biPlanes = info->bPlanes;
+                bminfo.bmiHeader.biBitCount = info->bBitsPerPixel;
+                bminfo.bmiHeader.biCompression = BI_RGB;
+                bminfo.bmiHeader.biSizeImage = info->nHeight * dib_width;
+                bminfo.bmiHeader.biXPelsPerMeter = 0;
+                bminfo.bmiHeader.biYPelsPerMeter = 0;
+                bminfo.bmiHeader.biClrUsed = 0;
+                bminfo.bmiHeader.biClrImportant = 0;
+
+                /* swap lines for dib sections */
+                if (xor_objsize == sizeof(DIBSECTION))
+                    bminfo.bmiHeader.biHeight = -bminfo.bmiHeader.biHeight;
+
+                if (dib_width != bitmap_width)  /* need to fixup alignment */
+                {
+                    char *src_bits = HeapAlloc( GetProcessHeap(), 0, bminfo.bmiHeader.biSizeImage );
+
+                    if (src_bits && GetDIBits( screen_dc, iconinfo->hbmColor, 0, info->nHeight,
+                                               src_bits, &bminfo, DIB_RGB_COLORS ))
+                    {
+                        int y;
+                        for (y = 0; y < info->nHeight; y++)
+                            memcpy( dst_bits + y * bitmap_width, src_bits + y * dib_width, bitmap_width );
+                    }
+                    HeapFree( GetProcessHeap(), 0, src_bits );
+                }
+                else
+                    GetDIBits( screen_dc, iconinfo->hbmColor, 0, info->nHeight,
+                               dst_bits, &bminfo, DIB_RGB_COLORS );
+            }
+        }
         GlobalUnlock16( hObj );
     }
     return HICON_32(hObj);
diff --git a/dlls/user32/tests/cursoricon.c b/dlls/user32/tests/cursoricon.c
index 40f3a14..dcac002 100644
--- a/dlls/user32/tests/cursoricon.c
+++ b/dlls/user32/tests/cursoricon.c
@@ -504,13 +504,14 @@ static void test_CreateIcon(void)
     static const BYTE bmp_bits[1024];
     HICON hIcon;
     HBITMAP hbmMask, hbmColor;
+    BITMAPINFO bmpinfo;
     ICONINFO info;
     HDC hdc;
+    void *bits;
     UINT display_bpp;
 
     hdc = GetDC(0);
     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
-    ReleaseDC(0, hdc);
 
     /* these crash under XP
     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
@@ -581,6 +582,69 @@ static void test_CreateIcon(void)
 
     DeleteObject(hbmMask);
     DeleteObject(hbmColor);
+
+    /* test creating an icon from a DIB section */
+
+    memset( &bmpinfo, 0, sizeof(bmpinfo) );
+    bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    bmpinfo.bmiHeader.biWidth = 32;
+    bmpinfo.bmiHeader.biHeight = 32;
+    bmpinfo.bmiHeader.biPlanes = 1;
+    bmpinfo.bmiHeader.biBitCount = 8;
+    bmpinfo.bmiHeader.biCompression = BI_RGB;
+    hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
+    memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
+    bmpinfo.bmiHeader.biBitCount = 1;
+    hbmMask = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
+    memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
+
+    info.fIcon = TRUE;
+    info.xHotspot = 8;
+    info.yHotspot = 8;
+    info.hbmMask = hbmColor;
+    info.hbmColor = hbmMask;
+    SetLastError(0xdeadbeaf);
+    hIcon = CreateIconIndirect(&info);
+    ok(hIcon != 0, "CreateIconIndirect failed\n");
+    test_icon_info(hIcon, 32, 32, 8);
+    DestroyIcon(hIcon);
+    DeleteObject(hbmColor);
+
+    bmpinfo.bmiHeader.biBitCount = 16;
+    hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
+    memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
+
+    info.fIcon = TRUE;
+    info.xHotspot = 8;
+    info.yHotspot = 8;
+    info.hbmMask = hbmColor;
+    info.hbmColor = hbmMask;
+    SetLastError(0xdeadbeaf);
+    hIcon = CreateIconIndirect(&info);
+    ok(hIcon != 0, "CreateIconIndirect failed\n");
+    test_icon_info(hIcon, 32, 32, 8);
+    DestroyIcon(hIcon);
+    DeleteObject(hbmColor);
+
+    bmpinfo.bmiHeader.biBitCount = 32;
+    hbmColor = CreateDIBSection( hdc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
+    memset( bits, 0x55, 32 * 32 * bmpinfo.bmiHeader.biBitCount / 8 );
+
+    info.fIcon = TRUE;
+    info.xHotspot = 8;
+    info.yHotspot = 8;
+    info.hbmMask = hbmColor;
+    info.hbmColor = hbmMask;
+    SetLastError(0xdeadbeaf);
+    hIcon = CreateIconIndirect(&info);
+    ok(hIcon != 0, "CreateIconIndirect failed\n");
+    test_icon_info(hIcon, 32, 32, 8);
+    DestroyIcon(hIcon);
+
+    DeleteObject(hbmMask);
+    DeleteObject(hbmColor);
+
+    ReleaseDC(0, hdc);
 }
 
 /* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */




More information about the wine-cvs mailing list