user32: Use create_cursoricon_object in CURSORICON_CreateIconFromANI.

Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Jacek Caban 2022-02-22 13:42:16 +01:00 committed by Alexandre Julliard
parent a37a0a94d4
commit a771eb4405
1 changed files with 24 additions and 98 deletions

View File

@ -109,34 +109,6 @@ static int get_display_bpp(void)
return ret; return ret;
} }
static HICON alloc_icon_handle( BOOL is_ani, UINT num_steps )
{
struct cursoricon_object *obj;
HICON handle;
if (!(obj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*obj) ))) return NULL;
obj->delay = 0;
obj->is_ani = is_ani;
if (is_ani)
{
if (!(obj->ani.frames = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
num_steps * sizeof(*obj->ani.frames) )))
{
HeapFree( GetProcessHeap(), 0, obj );
return NULL;
}
obj->ani.num_steps = num_steps;
obj->ani.num_frames = num_steps; /* changed later for some animated cursors */
}
if (!(handle = alloc_user_handle( &obj->obj, NTUSER_OBJ_ICON )))
{
if (obj->is_ani) HeapFree( GetProcessHeap(), 0, obj->ani.frames );
HeapFree( GetProcessHeap(), 0, obj );
}
return handle;
}
static struct cursoricon_object *get_icon_ptr( HICON handle ) static struct cursoricon_object *get_icon_ptr( HICON handle )
{ {
struct cursoricon_object *obj = get_user_handle_ptr( handle, NTUSER_OBJ_ICON ); struct cursoricon_object *obj = get_user_handle_ptr( handle, NTUSER_OBJ_ICON );
@ -990,6 +962,7 @@ BOOL WINAPI NtUserSetCursorIconData( HCURSOR cursor, UNICODE_STRING *module, UNI
memset( &frame_desc, 0, sizeof(frame_desc) ); memset( &frame_desc, 0, sizeof(frame_desc) );
frame_desc.delay = desc->frame_rates ? desc->frame_rates[i] : desc->delay; frame_desc.delay = desc->frame_rates ? desc->frame_rates[i] : desc->delay;
frame_desc.frames = &desc->frames[frame_id]; frame_desc.frames = &desc->frames[frame_id];
frame_desc.frames->delay = frame_desc.delay; /* FIXME */
if (!(obj->ani.frames[i] = alloc_cursoricon_handle( obj->is_icon )) || if (!(obj->ani.frames[i] = alloc_cursoricon_handle( obj->is_icon )) ||
!NtUserSetCursorIconData( obj->ani.frames[i], NULL, NULL, &frame_desc )) !NtUserSetCursorIconData( obj->ani.frames[i], NULL, NULL, &frame_desc ))
{ {
@ -1446,15 +1419,11 @@ static void riff_find_chunk( DWORD chunk_id, DWORD chunk_type, const riff_chunk_
static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, INT width, INT height, static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size, INT width, INT height,
INT depth, BOOL is_icon, UINT loadflags ) INT depth, BOOL is_icon, UINT loadflags )
{ {
struct cursoricon_object *info; struct cursoricon_desc desc = { 0 };
DWORD *frame_rates = NULL;
DWORD *frame_seq = NULL;
ani_header header; ani_header header;
BOOL use_seq = FALSE;
HCURSOR cursor; HCURSOR cursor;
UINT i; UINT i;
BOOL error = FALSE; BOOL error = FALSE;
HICON *frames;
riff_chunk_t root_chunk = { bits_size, bits }; riff_chunk_t root_chunk = { bits_size, bits };
riff_chunk_t ACON_chunk = {0}; riff_chunk_t ACON_chunk = {0};
@ -1494,8 +1463,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size,
riff_find_chunk( ANI_seq__ID, 0, &ACON_chunk, &seq_chunk ); riff_find_chunk( ANI_seq__ID, 0, &ACON_chunk, &seq_chunk );
if (seq_chunk.data) if (seq_chunk.data)
{ {
frame_seq = (DWORD *) seq_chunk.data; desc.frame_seq = (DWORD *)seq_chunk.data;
use_seq = TRUE;
} }
else else
{ {
@ -1506,7 +1474,7 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size,
riff_find_chunk( ANI_rate_ID, 0, &ACON_chunk, &rate_chunk ); riff_find_chunk( ANI_rate_ID, 0, &ACON_chunk, &rate_chunk );
if (rate_chunk.data) if (rate_chunk.data)
frame_rates = (DWORD *) rate_chunk.data; desc.frame_rates = (DWORD *)rate_chunk.data;
riff_find_chunk( ANI_fram_ID, ANI_LIST_ID, &ACON_chunk, &fram_chunk ); riff_find_chunk( ANI_fram_ID, ANI_LIST_ID, &ACON_chunk, &fram_chunk );
if (!fram_chunk.data) if (!fram_chunk.data)
@ -1515,25 +1483,16 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size,
return 0; return 0;
} }
cursor = alloc_icon_handle( TRUE, header.num_steps );
if (!cursor) return 0;
frames = HeapAlloc( GetProcessHeap(), 0, sizeof(*frames) * header.num_frames );
if (!frames)
{
free_icon_handle( cursor );
return 0;
}
info = get_icon_ptr( cursor );
info->is_icon = is_icon;
info->ani.num_frames = header.num_frames;
/* The .ANI stores the display rate in jiffies (1/60s) */ /* The .ANI stores the display rate in jiffies (1/60s) */
info->delay = header.display_rate; desc.delay = header.display_rate;
desc.num_frames = header.num_frames;
desc.num_steps = header.num_steps;
if (!(desc.frames = HeapAlloc( GetProcessHeap(), 0, sizeof(*desc.frames) * desc.num_frames )))
return 0;
icon_chunk = fram_chunk.data; icon_chunk = fram_chunk.data;
icon_data = fram_chunk.data + (2 * sizeof(DWORD)); icon_data = fram_chunk.data + (2 * sizeof(DWORD));
for (i=0; i<header.num_frames; i++) for (i = 0; i < desc.num_frames; i++)
{ {
const DWORD chunk_size = *(const DWORD *)(icon_chunk + sizeof(DWORD)); const DWORD chunk_size = *(const DWORD *)(icon_chunk + sizeof(DWORD));
const CURSORICONFILEDIRENTRY *entry; const CURSORICONFILEDIRENTRY *entry;
@ -1558,29 +1517,28 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size,
frameHeight = header.height; frameHeight = header.height;
} }
frames[i] = NULL; if (!(error = entry->dwDIBOffset >= bits + bits_size - icon_data))
if (entry->dwDIBOffset < bits + bits_size - icon_data)
{ {
bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset); bmi = (const BITMAPINFO *) (icon_data + entry->dwDIBOffset);
/* Grab a frame from the animation */ /* Grab a frame from the animation */
frames[i] = create_icon_from_bmi( bmi, bits + bits_size - (const BYTE *)bmi, error = !create_icon_frame( bmi, bits + bits_size - (const BYTE *)bmi, hotspot,
NULL, NULL, NULL, hotspot, is_icon, frameWidth, frameHeight, loadflags, &desc.frames[i] );
is_icon, frameWidth, frameHeight, loadflags );
} }
if (!frames[i]) if (error)
{ {
FIXME_(cursor)("failed to convert animated cursor frame.\n");
error = TRUE;
if (i == 0) if (i == 0)
{ {
FIXME_(cursor)("Completely failed to create animated cursor!\n"); FIXME_(cursor)("Completely failed to create animated cursor!\n");
info->ani.num_frames = 0; HeapFree( GetProcessHeap(), 0, desc.frames );
release_user_handle_ptr( info );
free_icon_handle( cursor );
HeapFree( GetProcessHeap(), 0, frames );
return 0; return 0;
} }
/* There was an error but we at least decoded the first frame, so just use that frame */
FIXME_(cursor)("Error creating animated cursor, only using first frame!\n");
while (i > 1) free_icon_frame( &desc.frames[--i] );
desc.num_frames = desc.num_steps = 1;
desc.frame_seq = NULL;
desc.delay = 0;
break; break;
} }
@ -1589,41 +1547,9 @@ static HCURSOR CURSORICON_CreateIconFromANI( const BYTE *bits, DWORD bits_size,
icon_data = icon_chunk + (2 * sizeof(DWORD)); icon_data = icon_chunk + (2 * sizeof(DWORD));
} }
/* There was an error but we at least decoded the first frame, so just use that frame */ cursor = create_cursoricon_object( &desc, is_icon, 0, 0, 0 );
if (error) if (!cursor) for (i = 0; i < desc.num_frames; i++) free_icon_frame( &desc.frames[i] );
{ HeapFree( GetProcessHeap(), 0, desc.frames );
FIXME_(cursor)("Error creating animated cursor, only using first frame!\n");
for (i=1; i < info->ani.num_frames; i++)
free_icon_handle( info->ani.frames[i] );
use_seq = FALSE;
info->delay = 0;
info->ani.num_steps = 1;
info->ani.num_frames = 1;
}
/* Setup the animated frames in the correct sequence */
for (i=0; i < info->ani.num_steps; i++)
{
DWORD frame_id = use_seq ? frame_seq[i] : i;
struct cursoricon_frame *frame;
if (frame_id >= info->ani.num_frames)
{
frame_id = info->ani.num_frames-1;
ERR_(cursor)("Sequence indicates frame past end of list, corrupt?\n");
}
info->ani.frames[i] = frames[frame_id];
frame = get_icon_frame( info, i );
if (frame_rates)
frame->delay = frame_rates[i];
else
frame->delay = ~0;
release_icon_frame( info, frame );
}
HeapFree( GetProcessHeap(), 0, frames );
release_user_handle_ptr( info );
return cursor; return cursor;
} }