fix icon loading code to load the correct icon for the current display bpp settings

svn path=/trunk/; revision=25466
This commit is contained in:
Ged Murphy 2007-01-15 18:08:37 +00:00
parent d673aa2616
commit 3bd87918a1
2 changed files with 203 additions and 120 deletions

View file

@ -231,10 +231,7 @@ LoadCursorIconImage(
if (IconResDir == NULL) if (IconResDir == NULL)
return NULL; return NULL;
/* /* Find the best fitting in the IconResDir for this resolution */
* Find the best fitting in the IconResDir for this resolution
*/
id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, Icon, width, height, id = LookupIconIdFromDirectoryEx((PBYTE)IconResDir, Icon, width, height,
fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
@ -256,6 +253,7 @@ LoadCursorIconImage(
SizeofResource(hinst, h2Resource), SizeofResource(hinst, h2Resource),
Icon, 0x00030000, width, height, Icon, 0x00030000, width, height,
fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME)); fuLoad & (LR_DEFAULTCOLOR | LR_MONOCHROME));
if (hIcon && 0 != (fuLoad & LR_SHARED)) if (hIcon && 0 != (fuLoad & LR_SHARED))
{ {
NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes, NtUserSetCursorIconData((HICON)hIcon, NULL, NULL, hinst, (HRSRC)hfRes,

View file

@ -440,35 +440,47 @@ LookupIconIdFromDirectory(
PBYTE presbits, PBYTE presbits,
BOOL fIcon) BOOL fIcon)
{ {
return LookupIconIdFromDirectoryEx( presbits, fIcon, return LookupIconIdFromDirectoryEx(presbits,
fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR), fIcon,
fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR), LR_DEFAULTCOLOR ); fIcon ? GetSystemMetrics(SM_CXICON) : GetSystemMetrics(SM_CXCURSOR),
fIcon ? GetSystemMetrics(SM_CYICON) : GetSystemMetrics(SM_CYCURSOR),
LR_DEFAULTCOLOR);
} }
/* Ported from WINE20030408 */
GRPCURSORICONDIRENTRY*
CURSORICON_FindBestCursor( GRPCURSORICONDIR *dir, int width, int height, int colors)
/*
* The following macro function accounts 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 int
CURSORICON_FindBestIcon(LPVOID dir,
fnGetCIEntry get_entry,
int Width,
int Height,
int ColorBits)
{ {
int i; int i, cx, cy, Bits, BestBits = 0, BestEntry = -1;
GRPCURSORICONDIRENTRY *entry, *bestEntry = NULL;
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff; UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
UINT iTempXDiff, iTempYDiff, iTempColorDiff; UINT iTempXDiff, iTempYDiff, iTempColorDiff;
if (dir->idCount < 1)
{
DPRINT("Empty directory!\n");
return NULL;
}
if (dir->idCount == 1)
return &dir->idEntries[0]; /* No choice... */
/* Find Best Fit */ /* Find Best Fit */
iTotalDiff = 0xFFFFFFFF; iTotalDiff = 0xFFFFFFFF;
iColorDiff = 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); iTempXDiff = abs(Width - cx);
iTempYDiff = abs(height - entry->ResInfo.icon.bHeight); iTempYDiff = abs(Height - cy);
if(iTotalDiff > (iTempXDiff + iTempYDiff)) if(iTotalDiff > (iTempXDiff + iTempYDiff))
{ {
@ -479,118 +491,191 @@ CURSORICON_FindBestCursor( GRPCURSORICONDIR *dir, int width, int height, int col
} }
/* Find Best Colors for Best Fit */ /* 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) == (int) iXDiff && if(abs(Width - cx) == iXDiff && abs(Height - cy) == iYDiff)
abs(height - entry->ResInfo.icon.bHeight) == (int) iYDiff)
{ {
iTempColorDiff = abs(colors - entry->ResInfo.icon.bColorCount); iTempColorDiff = abs(ColorBits - Bits);
if(iColorDiff > iTempColorDiff)
{
bestEntry = entry;
iColorDiff = iTempColorDiff;
}
}
}
return bestEntry;
}
/* Ported from WINE20030408 */
GRPCURSORICONDIRENTRY*
CURSORICON_FindBestIcon( GRPCURSORICONDIR *dir, int width, int height, int colorbits)
{
int i;
GRPCURSORICONDIRENTRY *entry, *bestEntry = NULL;
UINT iTotalDiff, iXDiff=0, iYDiff=0, iColorDiff;
UINT iTempXDiff, iTempYDiff, iTempColorDiff;
if (dir->idCount < 1)
{
DPRINT("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++)
{
iTempXDiff = abs(width - entry->ResInfo.icon.bWidth);
iTempYDiff = abs(height - entry->ResInfo.icon.bHeight);
if(iTotalDiff > (iTempXDiff + iTempYDiff))
{
iXDiff = iTempXDiff;
iYDiff = iTempYDiff;
iTotalDiff = iXDiff + iYDiff;
}
}
/* Find Best Colors for Best Fit */
for (i = 0, entry = &dir->idEntries[0]; i < dir->idCount; i++,entry++)
{
if(abs(width - entry->ResInfo.icon.bWidth) == (int) iXDiff &&
abs(height - entry->ResInfo.icon.bHeight) == (int) iYDiff)
{
iTempColorDiff = abs(colorbits - entry->wBitCount);
if(iColorDiff > iTempColorDiff) if(iColorDiff > iTempColorDiff)
{ {
bestEntry = entry; BestEntry = i;
BestBits = Bits;
iColorDiff = iTempColorDiff; iColorDiff = iTempColorDiff;
} }
} }
} }
return bestEntry; DPRINT1("Best Icon: ResId: %d, bits : %d\n", BestEntry, BestBits);
return BestEntry;
} }
/* Ported from WINE20030408 */
/*
* @implemented /**********************************************************************
* CURSORICON_FindBestCursor
*
* Find the cursor closest to the requested size.
* FIXME: parameter 'color' ignored and entries with more than 1 bpp
* ignored too
*/ */
INT STDCALL static int
LookupIconIdFromDirectoryEx( CURSORICON_FindBestCursor(LPVOID dir,
PBYTE presbits, fnGetCIEntry get_entry,
BOOL fIcon, int Width,
int cxDesired, int Height,
int cyDesired, int ColorBits)
UINT Flags)
{ {
GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)presbits; int i, MaxWidth, MaxHeight, cx, cy, Bits, BestEntry = -1;
UINT retVal = 0;
if (dir && !dir->idReserved && (IMAGE_ICON == dir->idType || IMAGE_CURSOR == dir->idType)) /* Double height to account for AND and XOR masks */
{ Height *= 2;
GRPCURSORICONDIRENTRY *entry;
HDC hdc;
int ColorBits;
hdc = CreateICW(NULL, NULL, NULL, NULL); /* First find the largest one smaller than or equal to the requested size*/
if (Flags & LR_MONOCHROME) MaxWidth = MaxHeight = 0;
{ for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
ColorBits = 1; {
} if ((cx <= Width) && (cy <= Height) &&
else (cx > MaxWidth) && (cy > MaxHeight) &&
{ (Bits == 1))
ColorBits = GetDeviceCaps(hdc, BITSPIXEL); {
if (ColorBits > 8) BestEntry = i;
ColorBits = 8; MaxWidth = cx;
} MaxHeight = cy;
DeleteDC(hdc); }
}
if (BestEntry != -1)
return BestEntry;
entry = CURSORICON_FindBestIcon( dir, cxDesired, cyDesired, ColorBits ); /* Now find the smallest one larger than the requested size */
MaxWidth = MaxHeight = 255;
for (i = 0; get_entry(dir, i, &cx, &cy, &Bits); i++ )
{
if (((cx < MaxWidth) && (cy < MaxHeight) && (Bits == 1)) ||
(BestEntry == -1))
{
BestEntry = i;
MaxWidth = cx;
MaxHeight = cy;
}
}
if (entry) return BestEntry;
retVal = entry->nID; }
}
else
{ static BOOL
DbgPrint("invalid resource directory\n"); CURSORICON_GetResIconEntry(LPVOID dir,
} int n,
return retVal; int *Width,
int *Height,
int *Bits)
{
GRPCURSORICONDIR *ResDir = dir;
ICONRESDIR *Icon;
if (ResDir->idCount <= n)
return FALSE;
Icon = &ResDir->idEntries[n].ResInfo.icon;
*Width = Icon->bWidth;
*Height = Icon->bHeight;
*Bits = ResDir->idEntries[n].wBitCount;
return TRUE;
}
static BOOL
CURSORICON_GetResCursorEntry(LPVOID dir,
int n,
int *Width,
int *Height,
int *Bits)
{
GRPCURSORICONDIR *ResDir = dir;
CURSORRESDIR *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 GRPCURSORICONDIRENTRY *
CURSORICON_FindBestIconRes(GRPCURSORICONDIR * dir,
int Width,
int Height,
int ColorBits)
{
int n;
n = CURSORICON_FindBestIcon(dir,
CURSORICON_GetResIconEntry,
Width,
Height,
ColorBits);
if (n < 0)
return NULL;
return &dir->idEntries[n];
}
static GRPCURSORICONDIRENTRY *
CURSORICON_FindBestCursorRes(GRPCURSORICONDIR *dir,
int Width,
int Height,
int ColorBits)
{
int n;
n = CURSORICON_FindBestCursor(dir,
CURSORICON_GetResCursorEntry,
Width,
Height,
ColorBits);
if (n < 0)
return NULL;
return &dir->idEntries[n];
}
INT WINAPI
LookupIconIdFromDirectoryEx(PBYTE xdir,
BOOL bIcon,
INT width,
INT height,
UINT cFlag)
{
GRPCURSORICONDIR *dir = (GRPCURSORICONDIR*)xdir;
UINT retVal = 0;
if(dir && !dir->idReserved && (IMAGE_ICON == dir->idType || IMAGE_CURSOR == dir->idType))
{
GRPCURSORICONDIRENTRY *entry = NULL;
int ColorBits;
if (cFlag & LR_MONOCHROME)
{
ColorBits = 1;
}
else
{
HDC hdc = GetDC(0);
ColorBits = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(0, hdc);
}
if(bIcon)
entry = CURSORICON_FindBestIconRes(dir, width, height, ColorBits);
else
entry = CURSORICON_FindBestCursorRes(dir, width, height, 1);
if (entry)
retVal = entry->nID;
}
else
DPRINT1("%s() : Invalid resource directory\n", __FUNCTION__);
return retVal;
} }