[5/6] USER: More preparation for loading animated cursors.

H. Verbeet hverbeet at gmail.com
Tue Apr 18 16:50:34 CDT 2006


This patch changes CreateIconFromResourceEx so that the code for
loading cursors / icons into memory can be called in a loop.

Changelog:
  - Allow multiple cursors / icons to be loaded in CreateIconFromResourceEx.
-------------- next part --------------
diff --git a/dlls/user/cursoricon.c b/dlls/user/cursoricon.c
index b85f4ae..e61ded8 100644
--- a/dlls/user/cursoricon.c
+++ b/dlls/user/cursoricon.c
@@ -673,6 +673,38 @@ static CURSORICONFILEDIRENTRY *CURSORICO
 }
 
 /**********************************************************************
+ *      .ANI cursor support
+ */
+typedef struct {
+    DWORD header_size;
+    DWORD num_frames;
+    DWORD num_steps;
+    DWORD width;
+    DWORD height;
+    DWORD bpp;
+    DWORD num_planes;
+    DWORD display_rate;
+    DWORD flags;
+} ani_header;
+
+typedef struct {
+    ani_header  header;
+    LPBYTE      *data;
+    LPDWORD     seq;
+} ani_info;
+
+static void free_ani_info(ani_info *info)
+{
+    DWORD i;
+    for (i = 0; i < info->header.num_frames; ++i)
+    {
+        HeapFree(GetProcessHeap(), 0, info->data[i]);
+    }
+    HeapFree(GetProcessHeap(), 0, info->data);
+    HeapFree(GetProcessHeap(), 0, info->seq);
+}
+
+/**********************************************************************
  *		CreateIconFromResourceEx (USER32.@)
  *
  * FIXME: Convert to mono when cFlag is LR_MONOCHROME. Do something
@@ -692,9 +724,13 @@ HICON WINAPI CreateIconFromResourceEx( L
     BITMAPINFO *bmi;
     BOOL DoStretch;
     INT size;
-
-    hotspot.x = ICON_HOTSPOT;
-    hotspot.y = ICON_HOTSPOT;
+    INT bpp;
+    DWORD i, frame_idx;
+    CURSORICONINFO *info;
+    CURSORANIINFO *cursor_ani_info;
+    LPBYTE data_ptr;
+    DWORD data_size;
+    ani_info ani_info = {{0}, 0, 0};
 
     TRACE_(cursor)("%p (%u bytes), ver %08x, %ix%i %s %s\n",
                    bits, cbSize, (unsigned)dwVersion, width, height,
@@ -702,22 +738,68 @@ HICON WINAPI CreateIconFromResourceEx( L
     if (dwVersion == 0x00020000)
     {
         FIXME_(cursor)("\t2.xx resources are not supported\n");
+        free_ani_info(&ani_info);
         return 0;
     }
 
+    bmi = (BITMAPINFO *)(bits + (bIcon ? 0 : sizeof(POINT16)));
+
+    /* Check bitmap header */
+    if ((bmi->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
+        && (bmi->bmiHeader.biSize != sizeof(BITMAPINFOHEADER)
+        || bmi->bmiHeader.biCompression != BI_RGB))
     {
+        WARN_(cursor)("\tinvalid resource bitmap header.\n");
+        free_ani_info(&ani_info);
+        return 0;
+    }
+
+    ani_info.header.num_steps = 1;
+    ani_info.header.num_frames = 1;
+    ani_info.header.bpp = bmi->bmiHeader.biBitCount;
+    ani_info.header.width = bmi->bmiHeader.biWidth;
+    ani_info.header.height = bmi->bmiHeader.biHeight >> 1;
+    ani_info.data = HeapAlloc(GetProcessHeap(), 0, sizeof(LPBYTE));
+    ani_info.data[0] = bits;
+
+    if (!width) width = ani_info.header.width;
+    if (!height) height = ani_info.header.height;;
+
+    /* Calculate the amount of required memory */
+    if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
+    bpp = (ani_info.header.bpp == 1) ? 1 : GetDeviceCaps(screen_dc, BITSPIXEL);
+    sizeAnd = get_dib_width_bytes(width, 1) * height;
+    sizeXor = get_dib_width_bytes(width, bpp) * height;
+    data_size = (sizeof(CURSORICONINFO) + sizeAnd + sizeXor) * ani_info.header.num_steps;
+
+    /* Now create the CURSORICONINFO structure */
+    hObj = GlobalAlloc16( GMEM_MOVEABLE, sizeof(CURSORANIINFO) + data_size);
+    data_ptr = GlobalLock16( hObj );
+    cursor_ani_info = (CURSORANIINFO *)data_ptr;
+    cursor_ani_info->num_frames    = ani_info.header.num_steps;
+    cursor_ani_info->delay         = (100 * ani_info.header.display_rate) / 6;
+    data_ptr += sizeof(CURSORANIINFO);
+
+    for (i = 0; i < ani_info.header.num_steps; ++i)
+    {
+        if (ani_info.seq) frame_idx = ani_info.seq[i];
+        else frame_idx = i;
+
+        info = (CURSORICONINFO *)data_ptr;
+        data_ptr += sizeof(CURSORICONINFO);
+
         if (bIcon)
-            bmi = (BITMAPINFO *)bits;
-        else /* get the hotspot */
         {
-            POINT16 *pt = (POINT16 *)bits;
+            hotspot.x = ICON_HOTSPOT;
+            hotspot.y = ICON_HOTSPOT;
+            bmi = (BITMAPINFO *)ani_info.data[frame_idx];
+        } else { /* get the hotspot */
+            POINT16 *pt = (POINT16 *)ani_info.data[frame_idx];
             hotspot = *pt;
             bmi = (BITMAPINFO *)(pt + 1);
         }
         size = bitmap_info_size( bmi, DIB_RGB_COLORS );
 
-        if (!width) width = bmi->bmiHeader.biWidth;
-        if (!height) height = bmi->bmiHeader.biHeight/2;
         DoStretch = (bmi->bmiHeader.biHeight/2 != height) ||
           (bmi->bmiHeader.biWidth != width);
 
@@ -728,10 +810,10 @@ HICON WINAPI CreateIconFromResourceEx( L
               bmi->bmiHeader.biCompression != BI_RGB) )
         {
               WARN_(cursor)("\tinvalid resource bitmap header.\n");
+              free_ani_info(&ani_info);
               return 0;
         }
 
-        if (!screen_dc) screen_dc = CreateDCW( DISPLAYW, NULL, NULL, NULL );
         if (screen_dc)
         {
             BITMAPINFO* pInfo;
@@ -847,26 +929,15 @@ HICON WINAPI CreateIconFromResourceEx( L
         if( !hXorBits || !hAndBits )
         {
             WARN_(cursor)("\tunable to create an icon bitmap.\n");
+            free_ani_info(&ani_info);
             return 0;
         }
 
-        /* Now create the CURSORICONINFO structure */
         GetObjectA( hXorBits, sizeof(bmpXor), &bmpXor );
         GetObjectA( hAndBits, sizeof(bmpAnd), &bmpAnd );
-        sizeXor = bmpXor.bmHeight * bmpXor.bmWidthBytes;
-        sizeAnd = bmpAnd.bmHeight * bmpAnd.bmWidthBytes;
 
-        hObj = GlobalAlloc16( GMEM_MOVEABLE,
-                         sizeof(CURSORANIINFO) + sizeof(CURSORICONINFO) + sizeXor + sizeAnd );
         if (hObj)
         {
-            CURSORANIINFO *ani_info;
-            CURSORICONINFO *info;
-
-            ani_info = (CURSORANIINFO *)GlobalLock16( hObj );
-            ani_info->num_frames = 1;
-            ani_info->delay = 0;
-            info = (CURSORICONINFO *)(ani_info + 1);
             info->ptHotSpot.x   = hotspot.x;
             info->ptHotSpot.y   = hotspot.y;
             info->nWidth        = bmpXor.bmWidth;
@@ -876,14 +947,19 @@ HICON WINAPI CreateIconFromResourceEx( L
             info->bBitsPerPixel = bmpXor.bmBitsPixel;
 
             /* Transfer the bitmap bits to the CURSORICONINFO structure */
-            GetBitmapBits( hAndBits, sizeAnd, (char *)(info + 1) );
-            GetBitmapBits( hXorBits, sizeXor, (char *)(info + 1) + sizeAnd );
-            GlobalUnlock16( hObj );
+            GetBitmapBits(hAndBits, sizeAnd, data_ptr);
+            data_ptr += sizeAnd;
+            GetBitmapBits(hXorBits, sizeXor, data_ptr);
+            data_ptr += sizeXor;
         }
 
         DeleteObject( hAndBits );
         DeleteObject( hXorBits );
     }
+
+    GlobalUnlock16( hObj );
+
+    free_ani_info(&ani_info);
     return HICON_32((HICON16)hObj);
 }
 




More information about the wine-patches mailing list