mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:06:04 +00:00
[WIN32SS]
- Fix an assert in new cursoricon implementation - Fix CreateIconIndirect behaviour regarding bits per pixel and bitmap dimensions - Fix LookupIconIdFromDirectoryEx behaviour to fulfill last commited tests CORE-7575 #comment LookupIconDirectoryEx and CreateIconIndirect now works as per tests svn path=/trunk/; revision=60999
This commit is contained in:
parent
225b2406ac
commit
ccf756f902
2 changed files with 140 additions and 36 deletions
|
@ -25,7 +25,7 @@ DBG_DEFAULT_CHANNEL(UserIcon);
|
|||
SYSTEM_CURSORINFO gSysCursorInfo;
|
||||
|
||||
BOOL
|
||||
InitCursorImpl()
|
||||
InitCursorImpl(VOID)
|
||||
{
|
||||
gSysCursorInfo.Enabled = FALSE;
|
||||
gSysCursorInfo.ButtonsDown = 0;
|
||||
|
@ -154,7 +154,8 @@ IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, BOOLEAN bForce)
|
|||
{
|
||||
if(CurIcon->CURSORF_flags & CURSORF_CURRENT)
|
||||
{
|
||||
/* Mark the object as destroyed, and fail, as per wine tests */
|
||||
/* Mark the object as destroyed, and fail, as per tests */
|
||||
TRACE("Cursor is current, marking as destroyed.\n");
|
||||
UserDeleteObject(CurIcon->head.h, TYPE_CURSOR);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -238,7 +239,9 @@ IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
|
|||
{
|
||||
CurIcon = Win32Process->pCursorCache;
|
||||
Win32Process->pCursorCache = CurIcon->pcurNext;
|
||||
ASSERT(CurIcon->head.cLockObj == 2);
|
||||
/* One ref for the handle, one for the list,
|
||||
* and potentially one from an other process via SetCursor */
|
||||
ASSERT(CurIcon->head.cLockObj <= 3);
|
||||
IntDestroyCurIconObject(CurIcon, TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -1004,8 +1007,8 @@ NtUserSetCursorIconData(
|
|||
if(IsShared)
|
||||
{
|
||||
/* Update process cache in case of shared cursor */
|
||||
UserReferenceObject(CurIcon);
|
||||
PPROCESSINFO ppi = CurIcon->head.ppi;
|
||||
UserReferenceObject(CurIcon);
|
||||
CurIcon->pcurNext = ppi->pCursorCache;
|
||||
ppi->pCursorCache = CurIcon;
|
||||
}
|
||||
|
@ -1038,7 +1041,7 @@ done:
|
|||
UserDereferenceObject(CurIcon);
|
||||
TRACE("Leave NtUserSetCursorIconData, ret=%i\n",Ret);
|
||||
UserLeave();
|
||||
|
||||
|
||||
return Ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -175,6 +175,52 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* copy an icon bitmap, even when it can't be selected into a DC */
|
||||
/* helper for CreateIconIndirect */
|
||||
static void stretch_blt_icon(HDC hdc_dst, int dst_width, int dst_height, HBITMAP src)
|
||||
{
|
||||
HDC hdc = CreateCompatibleDC( 0 );
|
||||
BITMAP bm;
|
||||
HBITMAP hbmpPrev;
|
||||
|
||||
GetObjectW(src, sizeof(bm), &bm);
|
||||
|
||||
hbmpPrev = SelectObject(hdc, src);
|
||||
|
||||
if (!hbmpPrev) /* do it the hard way */
|
||||
{
|
||||
BITMAPINFO *info;
|
||||
void *bits;
|
||||
|
||||
if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) return;
|
||||
info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
info->bmiHeader.biWidth = bm.bmWidth;
|
||||
info->bmiHeader.biHeight = bm.bmHeight;
|
||||
info->bmiHeader.biPlanes = GetDeviceCaps( hdc_dst, PLANES );
|
||||
info->bmiHeader.biBitCount = GetDeviceCaps( hdc_dst, BITSPIXEL );
|
||||
info->bmiHeader.biCompression = BI_RGB;
|
||||
info->bmiHeader.biSizeImage = get_dib_image_size( bm.bmWidth, bm.bmHeight, info->bmiHeader.biBitCount );
|
||||
info->bmiHeader.biXPelsPerMeter = 0;
|
||||
info->bmiHeader.biYPelsPerMeter = 0;
|
||||
info->bmiHeader.biClrUsed = 0;
|
||||
info->bmiHeader.biClrImportant = 0;
|
||||
bits = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
|
||||
if (bits && GetDIBits( hdc, src, 0, bm.bmHeight, bits, info, DIB_RGB_COLORS ))
|
||||
StretchDIBits( hdc_dst, 0, 0, dst_width, dst_height,
|
||||
0, 0, bm.bmWidth, bm.bmHeight, bits, info, DIB_RGB_COLORS, SRCCOPY );
|
||||
|
||||
HeapFree( GetProcessHeap(), 0, bits );
|
||||
HeapFree( GetProcessHeap(), 0, info );
|
||||
}
|
||||
else
|
||||
{
|
||||
StretchBlt( hdc_dst, 0, 0, dst_width, dst_height, hdc, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY );
|
||||
SelectObject(hdc, hbmpPrev);
|
||||
}
|
||||
|
||||
DeleteDC( hdc );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* bmi_has_alpha
|
||||
*/
|
||||
|
@ -576,12 +622,41 @@ static BOOL CURSORICON_GetCursorDataFromIconInfo(
|
|||
BITMAP bm;
|
||||
|
||||
ZeroMemory(pCursorData, sizeof(*pCursorData));
|
||||
/* Use the CopyImage function, as it will gracefully convert our bitmap to the screen bit depth */
|
||||
if(pIconInfo->hbmColor)
|
||||
{
|
||||
pCursorData->hbmColor = CopyImage(pIconInfo->hbmColor, IMAGE_BITMAP, 0, 0, 0);
|
||||
if(!pCursorData->hbmColor)
|
||||
/* We must convert the color bitmap to screen format */
|
||||
HDC hdcScreen, hdcMem;
|
||||
HBITMAP hbmpPrev;
|
||||
|
||||
/* The mask dictates its dimensions */
|
||||
if (!GetObject(pIconInfo->hbmMask, sizeof(bm), &bm))
|
||||
return FALSE;
|
||||
hdcScreen = CreateDCW(DISPLAYW, NULL, NULL, NULL);
|
||||
if(!hdcScreen)
|
||||
return FALSE;
|
||||
hdcMem = CreateCompatibleDC(hdcScreen);
|
||||
if(!hdcMem)
|
||||
{
|
||||
DeleteDC(hdcScreen);
|
||||
return FALSE;
|
||||
}
|
||||
pCursorData->hbmColor = CreateCompatibleBitmap(hdcScreen, bm.bmWidth, bm.bmHeight);
|
||||
DeleteDC(hdcScreen);
|
||||
if (!pCursorData->hbmColor)
|
||||
{
|
||||
DeleteDC(hdcMem);
|
||||
return FALSE;
|
||||
}
|
||||
hbmpPrev = SelectObject(hdcMem, pCursorData->hbmColor);
|
||||
if (!hbmpPrev)
|
||||
{
|
||||
DeleteDC(hdcMem);
|
||||
DeleteObject(pCursorData->hbmColor);
|
||||
return FALSE;
|
||||
}
|
||||
stretch_blt_icon( hdcMem, bm.bmWidth, bm.bmHeight, pIconInfo->hbmColor);
|
||||
SelectObject(hdcMem, hbmpPrev);
|
||||
DeleteDC(hdcMem);
|
||||
}
|
||||
pCursorData->hbmMask = CopyImage(pIconInfo->hbmMask, IMAGE_BITMAP, 0, 0, LR_MONOCHROME);
|
||||
if(!pCursorData->hbmMask)
|
||||
|
@ -1318,7 +1393,7 @@ CURSORICON_LoadImageW(
|
|||
if(!dir)
|
||||
goto done;
|
||||
|
||||
wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad & LR_MONOCHROME);
|
||||
wResId = LookupIconIdFromDirectoryEx((PBYTE)dir, bIcon, cxDesired, cyDesired, fuLoad);
|
||||
FreeResource(handle);
|
||||
|
||||
/* Get the relevant resource pointer */
|
||||
|
@ -2008,11 +2083,11 @@ int WINAPI LookupIconIdFromDirectoryEx(
|
|||
WORD bppDesired;
|
||||
CURSORICONDIR* dir = (CURSORICONDIR*)presbits;
|
||||
CURSORICONDIRENTRY* entry;
|
||||
int i, numMatch, iIndex = -1;
|
||||
WORD width, height;
|
||||
USHORT bitcount;
|
||||
ULONG cxyDiff, cxyDiffTmp;
|
||||
|
||||
int i, numMatch = 0, iIndex = -1;
|
||||
WORD width, height, BitCount = 0;
|
||||
BOOL notPaletted = FALSE;
|
||||
ULONG bestScore = 0xFFFFFFFF, score;
|
||||
|
||||
TRACE("%p, %x, %i, %i, %x.\n", presbits, fIcon, cxDesired, cyDesired, Flags);
|
||||
|
||||
if(!(dir && !dir->idReserved && (dir->idType & 3)))
|
||||
|
@ -2035,13 +2110,11 @@ int WINAPI LookupIconIdFromDirectoryEx(
|
|||
}
|
||||
|
||||
if(!cxDesired)
|
||||
cxDesired = GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR);
|
||||
cxDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics(fIcon ? SM_CXICON : SM_CXCURSOR) : 256;
|
||||
if(!cyDesired)
|
||||
cyDesired = GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR);
|
||||
cyDesired = Flags & LR_DEFAULTSIZE ? GetSystemMetrics(fIcon ? SM_CYICON : SM_CYCURSOR) : 256;
|
||||
|
||||
/* Find the best match for the desired size */
|
||||
cxyDiff = 0xFFFFFFFF;
|
||||
numMatch = 0;
|
||||
for(i = 0; i < dir->idCount; i++)
|
||||
{
|
||||
entry = &dir->idEntries[i];
|
||||
|
@ -2051,27 +2124,41 @@ int WINAPI LookupIconIdFromDirectoryEx(
|
|||
/* 0 represents 256 */
|
||||
if(!width) width = 256;
|
||||
if(!height) height = 256;
|
||||
/* Let it be a 1-norm */
|
||||
cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
|
||||
if( cxyDiffTmp > cxyDiff)
|
||||
/* Calculate the "score" (lower is better) */
|
||||
score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
|
||||
if( score > bestScore)
|
||||
continue;
|
||||
if( cxyDiffTmp == cxyDiff)
|
||||
/* Bigger than requested lowers the score */
|
||||
if(width > cxDesired)
|
||||
score -= width - cxDesired;
|
||||
if(height > cyDesired)
|
||||
score -= height - cyDesired;
|
||||
if(score > bestScore)
|
||||
continue;
|
||||
if(score == bestScore)
|
||||
{
|
||||
if(entry->wBitCount > BitCount)
|
||||
BitCount = entry->wBitCount;
|
||||
numMatch++;
|
||||
continue;
|
||||
}
|
||||
iIndex = i;
|
||||
numMatch = 1;
|
||||
cxyDiff = cxyDiffTmp;
|
||||
bestScore = score;
|
||||
BitCount = entry->wBitCount;
|
||||
}
|
||||
|
||||
if(numMatch == 1)
|
||||
{
|
||||
/* Only one entry fit the asked dimensions */
|
||||
/* Only one entry fits the asked dimensions */
|
||||
return dir->idEntries[iIndex].wResId;
|
||||
}
|
||||
|
||||
/* Avoid paletted icons on non-paletted device */
|
||||
if (bppDesired > 8 && BitCount > 8)
|
||||
notPaletted = TRUE;
|
||||
|
||||
bitcount = 0;
|
||||
BitCount = 0;
|
||||
iIndex = -1;
|
||||
/* Now find the entry with the best depth */
|
||||
for(i = 0; i < dir->idCount; i++)
|
||||
|
@ -2083,25 +2170,33 @@ int WINAPI LookupIconIdFromDirectoryEx(
|
|||
if(!width) width = 256;
|
||||
if(!height) height = 256;
|
||||
/* Check if this is the best match we had */
|
||||
cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
|
||||
if(cxyDiffTmp != cxyDiff)
|
||||
score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
|
||||
if(width > cxDesired)
|
||||
score -= width - cxDesired;
|
||||
if(height > cyDesired)
|
||||
score -= height - cyDesired;
|
||||
if(score != bestScore)
|
||||
continue;
|
||||
/* Exact match? */
|
||||
if(entry->wBitCount == bppDesired)
|
||||
return entry->wResId;
|
||||
/* We take the highest possible but smaller than the display depth */
|
||||
if((entry->wBitCount > bitcount) && (entry->wBitCount < bppDesired))
|
||||
if((entry->wBitCount > BitCount) && (entry->wBitCount < bppDesired))
|
||||
{
|
||||
/* Avoid paletted icons on non paletted devices */
|
||||
if ((entry->wBitCount <= 8) && notPaletted)
|
||||
continue;
|
||||
iIndex = i;
|
||||
bitcount = entry->wBitCount;
|
||||
BitCount = entry->wBitCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(iIndex >= 0)
|
||||
return dir->idEntries[iIndex].wResId;
|
||||
|
||||
/* No inferior or equal depth available. Get the smallest one */
|
||||
bitcount = 0x7FFF;
|
||||
/* No inferior or equal depth available. Get the smallest bigger one */
|
||||
BitCount = 0xFFFF;
|
||||
iIndex = 0;
|
||||
for(i = 0; i < dir->idCount; i++)
|
||||
{
|
||||
entry = &dir->idEntries[i];
|
||||
|
@ -2111,14 +2206,20 @@ int WINAPI LookupIconIdFromDirectoryEx(
|
|||
if(!width) width = 256;
|
||||
if(!height) height = 256;
|
||||
/* Check if this is the best match we had */
|
||||
cxyDiffTmp = max(abs(width - cxDesired), abs(height - cyDesired));
|
||||
if(cxyDiffTmp != cxyDiff)
|
||||
score = 2*(abs(width - cxDesired) + abs(height - cyDesired));
|
||||
if(width > cxDesired)
|
||||
score -= width - cxDesired;
|
||||
if(height > cyDesired)
|
||||
score -= height - cyDesired;
|
||||
if(score != bestScore)
|
||||
continue;
|
||||
/* Check the bit depth */
|
||||
if(entry->wBitCount < bitcount)
|
||||
if(entry->wBitCount < BitCount)
|
||||
{
|
||||
if((entry->wBitCount <= 8) && notPaletted)
|
||||
continue;
|
||||
iIndex = i;
|
||||
bitcount = entry->wBitCount;
|
||||
BitCount = entry->wBitCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue