[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