Modify CURSORICON_FindBestIcon/Cursor to use enumerator functions.

This commit is contained in:
Mike McCormack 2005-07-12 18:11:54 +00:00 committed by Alexandre Julliard
parent 30ff940a68
commit 37a8e0d0c9
1 changed files with 99 additions and 55 deletions

View File

@ -454,33 +454,32 @@ void CURSORICON_FreeModuleIcons( HMODULE16 hMod16 )
LeaveCriticalSection( &IconCrst );
}
/*
* The following macro functions account for the irregularities of
* accessing cursor and icon resources in files and resource entries.
*/
typedef BOOL (*fnGetCIEntry)( LPVOID dir, int n,
int *width, int *height, int *bits );
/**********************************************************************
* CURSORICON_FindBestIcon
*
* Find the icon closest to the requested size and number of colors.
*/
static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width,
int height, int colors )
static int CURSORICON_FindBestIcon( LPVOID dir, fnGetCIEntry get_entry,
int width, int height, int colors )
{
int i;
CURSORICONDIRENTRY *entry, *bestEntry = NULL;
int i, cx, cy, bits, bestEntry = -1;
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
if (dir->idCount < 1)
{
WARN_(icon)("Empty directory!\n" );
return NULL;
}
if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
/* Find Best Fit */
iTotalDiff = 0xFFFFFFFF;
iColorDiff = 0xFFFFFFFF;
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
{
iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
iTempXDiff = abs(width - cx);
iTempYDiff = abs(height - cy);
if(iTotalDiff > (iTempXDiff + iTempYDiff))
{
@ -491,15 +490,14 @@ static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int widt
}
/* Find Best Colors for Best Fit */
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
{
if(abs(width - entry->ResInfo.icon.bWidth) == iXDiff &&
abs(height - entry->ResInfo.icon.bHeight) == iYDiff)
if(abs(width - cx) == iXDiff && abs(height - cy) == iYDiff)
{
iTempColorDiff = abs(colors - (1<<entry->wBitCount));
iTempColorDiff = abs(colors - (1<<bits));
if(iColorDiff > iTempColorDiff)
{
bestEntry = entry;
bestEntry = i;
iColorDiff = iTempColorDiff;
}
}
@ -508,6 +506,20 @@ static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int widt
return bestEntry;
}
static BOOL CURSORICON_GetResIconEntry( LPVOID dir, int n,
int *width, int *height, int *bits )
{
CURSORICONDIR *resdir = dir;
ICONRESDIR *icon;
if ( resdir->idCount <= n )
return FALSE;
icon = &resdir->idEntries[n].ResInfo.icon;
*width = icon->bWidth;
*height = icon->bWidth;
*bits = resdir->idEntries[n].wBitCount;
return TRUE;
}
/**********************************************************************
* CURSORICON_FindBestCursor
@ -516,18 +528,10 @@ static CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int widt
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
* ignored too
*/
static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
int width, int height, int color)
static int CURSORICON_FindBestCursor( LPVOID dir, fnGetCIEntry get_entry,
int width, int height, int color )
{
int i, maxwidth, maxheight;
CURSORICONDIRENTRY *entry, *bestEntry = NULL;
if (dir->idCount < 1)
{
WARN_(cursor)("Empty directory!\n" );
return NULL;
}
if (dir->idCount == 1) return &dir->idEntries[0]; /* No choice... */
int i, maxwidth, maxheight, cx, cy, bits, bestEntry = -1;
/* Double height to account for AND and XOR masks */
@ -536,32 +540,74 @@ static CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir,
/* First find the largest one smaller than or equal to the requested size*/
maxwidth = maxheight = 0;
for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.cursor.wWidth <= width) && (entry->ResInfo.cursor.wHeight <= height) &&
(entry->ResInfo.cursor.wWidth > maxwidth) && (entry->ResInfo.cursor.wHeight > maxheight) &&
(entry->wBitCount == 1))
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
{
if ((cx <= width) && (cy <= height) &&
(cx > maxwidth) && (cy > maxheight) &&
(bits == 1))
{
bestEntry = entry;
maxwidth = entry->ResInfo.cursor.wWidth;
maxheight = entry->ResInfo.cursor.wHeight;
bestEntry = i;
maxwidth = cx;
maxheight = cy;
}
if (bestEntry) return bestEntry;
}
if (bestEntry != -1) return bestEntry;
/* Now find the smallest one larger than the requested size */
maxwidth = maxheight = 255;
for(i = 0,entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
if ((entry->ResInfo.cursor.wWidth < maxwidth) && (entry->ResInfo.cursor.wHeight < maxheight) &&
(entry->wBitCount == 1))
for ( i = 0; get_entry( dir, i, &cx, &cy, &bits ); i++ )
{
if ((cx < maxwidth) && (cy < maxheight) &&
(bits == 1))
{
bestEntry = entry;
maxwidth = entry->ResInfo.cursor.wWidth;
maxheight = entry->ResInfo.cursor.wHeight;
bestEntry = i;
maxwidth = cx;
maxheight = cy;
}
}
return bestEntry;
}
static BOOL CURSORICON_GetResCursorEntry( LPVOID dir, int n,
int *width, int *height, int *bits )
{
CURSORICONDIR *resdir = dir;
CURSORDIR *cursor;
if ( resdir->idCount <= n )
return FALSE;
cursor = &resdir->idEntries[n].ResInfo.cursor;
*width = cursor->wWidth;
*height = cursor->wHeight;
*bits = resdir->idEntries[n].wBitCount;
return TRUE;
}
static CURSORICONDIRENTRY *CURSORICON_FindBestIconRes( CURSORICONDIR * dir,
int width, int height, int colors )
{
int n;
n = CURSORICON_FindBestIcon( dir, CURSORICON_GetResIconEntry,
width, height, colors );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
static CURSORICONDIRENTRY *CURSORICON_FindBestCursorRes( CURSORICONDIR *dir,
int width, int height, int color )
{
int n = CURSORICON_FindBestCursor( dir, CURSORICON_GetResCursorEntry,
width, height, color );
if ( n < 0 )
return NULL;
return &dir->idEntries[n];
}
/*********************************************************************
* The main purpose of this function is to create fake resource directory
* and fake resource entries. There are several reasons for this:
@ -902,9 +948,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
if (!CURSORICON_SimulateLoadingFromResourceW(name, fCursor, &dir, &ptr))
return 0;
if (fCursor)
dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(dir, width, height, 1);
dirEntry = CURSORICON_FindBestCursorRes(dir, width, height, 1);
else
dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(dir, width, height, colors);
dirEntry = CURSORICON_FindBestIconRes(dir, width, height, colors);
bits = ptr[dirEntry->wResId-1];
hIcon = CreateIconFromResourceEx( bits, dirEntry->dwBytesInRes,
!fCursor, 0x00030000, width, height, loadflags);
@ -936,11 +982,9 @@ static HICON CURSORICON_Load(HINSTANCE hInstance, LPCWSTR name,
if (!(handle = LoadResource( hInstance, hRsrc ))) return 0;
if (!(dir = (CURSORICONDIR*)LockResource( handle ))) return 0;
if (fCursor)
dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor( dir,
width, height, 1);
dirEntry = CURSORICON_FindBestCursorRes( dir, width, height, 1);
else
dirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon( dir,
width, height, colors );
dirEntry = CURSORICON_FindBestIconRes( dir, width, height, colors );
if (!dirEntry) return 0;
wResId = dirEntry->wResId;
dwBytesInRes = dirEntry->dwBytesInRes;
@ -1088,12 +1132,12 @@ static HICON CURSORICON_ExtCopy(HICON hIcon, UINT nType,
*/
if(bIsIcon)
{
pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestIcon(
pDir, iDesiredCX, iDesiredCY, 256);
pDirEntry = CURSORICON_FindBestIconRes(
pDir, iDesiredCX, iDesiredCY, 256 );
}
else
{
pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursor(
pDirEntry = (CURSORICONDIRENTRY *)CURSORICON_FindBestCursorRes(
pDir, iDesiredCX, iDesiredCY, 1);
}
@ -1582,9 +1626,9 @@ INT WINAPI LookupIconIdFromDirectoryEx( LPBYTE xdir, BOOL bIcon,
ReleaseDC(0, hdc);
if( bIcon )
entry = CURSORICON_FindBestIcon( dir, width, height, colors );
entry = CURSORICON_FindBestIconRes( dir, width, height, colors );
else
entry = CURSORICON_FindBestCursor( dir, width, height, 1);
entry = CURSORICON_FindBestCursorRes( dir, width, height, 1);
if( entry ) retVal = entry->wResId;
}