- exchange mask and color bitmaps if needed in CreateIconIndirect
[WIN32K]
  - Simplify a bit UserDrawIconEx

svn path=/branches/reactos-yarotows/; revision=48026
This commit is contained in:
Jérôme Gardou 2010-07-13 18:32:33 +00:00
parent 9370b362e1
commit d25782346f
2 changed files with 111 additions and 90 deletions

View file

@ -1393,6 +1393,7 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
{
BITMAP ColorBitmap;
BITMAP MaskBitmap;
ICONINFO safeIconInfo;
if(!iconinfo)
{
@ -1400,13 +1401,15 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
return (HICON)0;
}
if(!GetObjectW(iconinfo->hbmMask, sizeof(BITMAP), &MaskBitmap))
safeIconInfo = *iconinfo;
if(!GetObjectW(safeIconInfo.hbmMask, sizeof(BITMAP), &MaskBitmap))
{
return (HICON)0;
}
/* Try to get color bitmap */
if (GetObjectW(iconinfo->hbmColor, sizeof(BITMAP), &ColorBitmap))
if (GetObjectW(safeIconInfo.hbmColor, sizeof(BITMAP), &ColorBitmap))
{
/* Compare size of color and mask bitmap*/
if (ColorBitmap.bmWidth != MaskBitmap.bmWidth ||
@ -1416,8 +1419,22 @@ HICON WINAPI CreateIconIndirect(PICONINFO iconinfo)
SetLastError(ERROR_INVALID_PARAMETER);
return (HICON)0;
}
/* Test if they are inverted */
if(ColorBitmap.bmBitsPixel == 1)
{
if(MaskBitmap.bmBitsPixel != 1)
{
safeIconInfo.hbmMask = iconinfo->hbmColor;
safeIconInfo.hbmColor = iconinfo->hbmMask;
}
else
{
/* Wine tests say so */
safeIconInfo.hbmColor = NULL;
}
}
}
return (HICON)NtUserCreateCursorIconHandle(iconinfo, TRUE);
return (HICON)NtUserCreateCursorIconHandle(&safeIconInfo, TRUE);
}
/******************************************************************************

View file

@ -528,8 +528,8 @@ NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL, BOOL Indirect)
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL);
if(CurIcon->IconInfo.hbmColor)
{
CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor);
GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL);
}
}
if (CurIcon->IconInfo.hbmColor &&
@ -1376,7 +1376,7 @@ UserDrawIconEx(
hDestDC = NtGdiCreateCompatibleDC(hDc);
if(!hDestDC)
{
DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
DPRINT1("NtGdiCreateCompatibleDC failed!\n");
Ret = FALSE;
goto Cleanup ;
}
@ -1397,7 +1397,92 @@ UserDrawIconEx(
iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black
iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white
if ((diFlags & DI_MASK) && (!bAlpha || !(diFlags & DI_IMAGE)))
if(bAlpha && (diFlags & DI_IMAGE))
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
DWORD Pixel;
BYTE Red, Green, Blue, Alpha;
DWORD Count = 0;
INT i, j;
PSURFACE psurf;
PBYTE pBits ;
HBITMAP hMemBmp = NULL;
pBits = ExAllocatePoolWithTag(PagedPool,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
TAG_BITMAP);
if (pBits == NULL)
{
Ret = FALSE;
goto CleanupAlpha;
}
hMemBmp = BITMAP_CopyBitmap(hbmColor);
if(!hMemBmp)
{
DPRINT1("BITMAP_CopyBitmap failed!");
goto CleanupAlpha;
}
psurf = SURFACE_LockSurface(hMemBmp);
if(!psurf)
{
DPRINT1("SURFACE_LockSurface failed!\n");
goto CleanupAlpha;
}
/* get color bits */
IntGetBitmapBits(psurf,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
pBits);
/* premultiply with the alpha channel value */
for (i = 0; i < cyHeight; i++)
{
for (j = 0; j < cxWidth; j++)
{
Pixel = *(DWORD *)(pBits + Count);
Alpha = ((BYTE)(Pixel >> 24) & 0xff);
Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
*(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
Count += sizeof(DWORD);
}
}
/* set mem bits */
IntSetBitmapBits(psurf,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
pBits);
SURFACE_UnlockSurface(psurf);
hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
Ret = NtGdiAlphaBlend(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
0,
pIcon->Size.cx,
pIcon->Size.cy,
pixelblend,
NULL);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
CleanupAlpha:
if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
if(Ret) goto done;
}
if (diFlags & DI_MASK)
{
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
NtGdiStretchBlt(hDestDC,
@ -1417,89 +1502,7 @@ UserDrawIconEx(
if(diFlags & DI_IMAGE)
{
if (bAlpha)
{
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
DWORD Pixel;
BYTE Red, Green, Blue, Alpha;
DWORD Count = 0;
INT i, j;
PSURFACE psurf;
PBYTE pBits ;
HBITMAP hMemBmp = NULL;
pBits = ExAllocatePoolWithTag(PagedPool,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
TAG_BITMAP);
if (pBits == NULL)
{
Ret = FALSE;
goto CleanupAlpha;
}
hMemBmp = BITMAP_CopyBitmap(hbmColor);
if(!hMemBmp)
{
DPRINT1("BITMAP_CopyBitmap failed!");
goto CleanupAlpha;
}
psurf = SURFACE_LockSurface(hMemBmp);
if(!psurf)
{
DPRINT1("SURFACE_LockSurface failed!\n");
goto CleanupAlpha;
}
/* get color bits */
IntGetBitmapBits(psurf,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
pBits);
/* premultiply with the alpha channel value */
for (i = 0; i < cyHeight; i++)
{
for (j = 0; j < cxWidth; j++)
{
Pixel = *(DWORD *)(pBits + Count);
Alpha = ((BYTE)(Pixel >> 24) & 0xff);
Red = (((BYTE)(Pixel >> 0)) * Alpha) / 0xff;
Green = (((BYTE)(Pixel >> 8)) * Alpha) / 0xff;
Blue = (((BYTE)(Pixel >> 16)) * Alpha) / 0xff;
*(DWORD *)(pBits + Count) = (DWORD)(Red | (Green << 8) | (Blue << 16) | (Alpha << 24));
Count += sizeof(DWORD);
}
}
/* set mem bits */
IntSetBitmapBits(psurf,
bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
pBits);
SURFACE_UnlockSurface(psurf);
hTmpBmp = NtGdiSelectBitmap(hMemDC, hMemBmp);
NtGdiAlphaBlend(hDestDC,
x,
y,
cxWidth,
cyHeight,
hMemDC,
0,
0,
pIcon->Size.cx,
pIcon->Size.cy,
pixelblend,
NULL);
NtGdiSelectBitmap(hMemDC, hTmpBmp);
CleanupAlpha:
if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP);
if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp);
}
else if (hbmColor)
if (hbmColor)
{
DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
@ -1538,6 +1541,7 @@ UserDrawIconEx(
}
}
done:
if(hDestDC != hDc)
{
NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);