Author: jgardou
Date: Mon Jul 19 22:41:35 2010
New Revision: 48123
URL:
http://svn.reactos.org/svn/reactos?rev=48123&view=rev
Log:
[WIN32K]
- rewrite UserDrawIconEx, taken from yarotows, with same small modifications.
Fixes a whole bunch of user32:cursoricon tests
Modified:
trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c [iso-8859-1] Mon Jul 19
22:41:35 2010
@@ -1181,6 +1181,7 @@
return FALSE;
}
+/* Mostly inspired from wine code */
BOOL
UserDrawIconEx(
HDC hDc,
@@ -1195,19 +1196,16 @@
{
BOOL Ret = FALSE;
HBITMAP hbmMask, hbmColor;
- BITMAP bmpMask, bmpColor;
+ BITMAP bmpColor, bm;
BOOL DoFlickerFree;
- SIZE IconSize;
-
- HDC hdcOff;
+ INT iOldBkColor = 0, iOldTxtColor = 0;
+
+ HDC hMemDC, hDestDC = hDc;
HGDIOBJ hOldOffBrush = 0;
HGDIOBJ hOldOffBmp = 0;
- HBITMAP hbmOff = 0;
- HDC hdcMask = 0;
- HGDIOBJ hOldMask = NULL;
- HDC hdcImage = 0;
- HGDIOBJ hOldImage = NULL;
+ HBITMAP hTmpBmp = 0, hOffBmp = 0;
BOOL bAlpha = FALSE;
+ INT x=xLeft, y=yTop;
hbmMask = pIcon->IconInfo.hbmMask;
hbmColor = pIcon->IconInfo.hbmColor;
@@ -1215,7 +1213,7 @@
if (istepIfAniCur)
DPRINT1("NtUserDrawIconEx: istepIfAniCur is not supported!\n");
- if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bmpMask))
+ if (!hbmMask || !IntGdiGetObject(hbmMask, sizeof(BITMAP), (PVOID)&bm))
{
return FALSE;
}
@@ -1225,38 +1223,34 @@
return FALSE;
}
- if (hbmColor)
- {
- IconSize.cx = bmpColor.bmWidth;
- IconSize.cy = bmpColor.bmHeight;
- }
- else
- {
- IconSize.cx = bmpMask.bmWidth;
- IconSize.cy = bmpMask.bmHeight / 2;
- }
-
- /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap
- when cxWidth or cyHeight is 0 */
- if ((bmpColor.bmBitsPixel == 32) && (cxWidth != 0) && (cyHeight !=
0))
+ if(!(hMemDC = NtGdiCreateCompatibleDC(hDc)))
+ {
+ DPRINT1("NtGdiCreateCompatibleDC failed!\n");
+ return FALSE;
+ }
+
+ /* Check for alpha */
+ if (hbmColor
+ && (bmpColor.bmBitsPixel == 32)
+ && (diFlags & DI_IMAGE))
{
SURFACE *psurfOff = NULL;
PFN_DIB_GetPixel fnSource_GetPixel = NULL;
- INT x, y;
+ INT i, j;
/* In order to correctly display 32 bit icons Windows first scans the image,
because information about transparency is not stored in any image's
headers */
- psurfOff = SURFACE_LockSurface(hbmColor ? hbmColor : hbmMask);
+ psurfOff = SURFACE_LockSurface(hbmColor);
if (psurfOff)
{
fnSource_GetPixel =
DibFunctionsForBitmapFormat[psurfOff->SurfObj.iBitmapFormat].DIB_GetPixel;
if (fnSource_GetPixel)
{
- for (x = 0; x < psurfOff->SurfObj.sizlBitmap.cx; x++)
+ for (i = 0; i < psurfOff->SurfObj.sizlBitmap.cx; i++)
{
- for (y = 0; y < psurfOff->SurfObj.sizlBitmap.cy; y++)
+ for (j = 0; j < psurfOff->SurfObj.sizlBitmap.cy; j++)
{
- bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, x,
y) >> 24) & 0xff);
+ bAlpha = ((BYTE)(fnSource_GetPixel(&psurfOff->SurfObj, i,
j) >> 24) & 0xff);
if (bAlpha)
break;
}
@@ -1268,172 +1262,86 @@
}
}
- if (!diFlags)
- diFlags = DI_NORMAL;
-
if (!cxWidth)
cxWidth = ((diFlags & DI_DEFAULTSIZE) ?
- UserGetSystemMetrics(SM_CXICON) : IconSize.cx);
+ UserGetSystemMetrics(SM_CXICON) : pIcon->Size.cx);
if (!cyHeight)
cyHeight = ((diFlags & DI_DEFAULTSIZE) ?
- UserGetSystemMetrics(SM_CYICON) : IconSize.cy);
+ UserGetSystemMetrics(SM_CYICON) : pIcon->Size.cy);
DoFlickerFree = (hbrFlickerFreeDraw &&
(GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) ==
GDI_OBJECT_TYPE_BRUSH));
- if (DoFlickerFree || bAlpha)
- {
- RECTL r;
- BITMAP bm;
- SURFACE *psurfOff = NULL;
-
- r.right = cxWidth;
- r.bottom = cyHeight;
-
- hdcOff = NtGdiCreateCompatibleDC(hDc);
- if (!hdcOff)
- {
- DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
- return FALSE;
- }
-
- hbmOff = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
- if (!hbmOff)
- {
- DPRINT1("NtGdiCreateCompatibleBitmap() failed!\n");
- goto cleanup;
- }
-
- /* make sure we have a 32 bit offscreen bitmap
- otherwise we can't do alpha blending */
- psurfOff = SURFACE_LockSurface(hbmOff);
- if (psurfOff == NULL)
- {
- DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
- goto cleanup;
- }
- BITMAP_GetObject(psurfOff, sizeof(BITMAP), (PVOID)&bm);
-
- if (bm.bmBitsPixel != 32)
- bAlpha = FALSE;
-
- SURFACE_UnlockSurface(psurfOff);
-
- hOldOffBmp = NtGdiSelectBitmap(hdcOff, hbmOff);
- if (!hOldOffBmp)
- {
- DPRINT1("NtGdiSelectBitmap() failed!\n");
- goto cleanup;
- }
-
- if (DoFlickerFree)
- {
- hOldOffBrush = NtGdiSelectBrush(hdcOff, hbrFlickerFreeDraw);
- if (!hOldOffBrush)
- {
- DPRINT1("NtGdiSelectBrush() failed!\n");
- goto cleanup;
- }
-
- NtGdiPatBlt(hdcOff, 0, 0, r.right, r.bottom, PATCOPY);
- }
- }
- else
- hdcOff = hDc;
-
- if (diFlags & DI_IMAGE)
- {
- hdcImage = NtGdiCreateCompatibleDC(hDc);
- if (!hdcImage)
- {
- DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
- goto cleanup;
- }
- hOldImage = NtGdiSelectBitmap(hdcImage, (hbmColor ? hbmColor : hbmMask));
- if (!hOldImage)
- {
- DPRINT("NtGdiSelectBitmap() failed!\n");
- goto cleanup;
- }
- }
-
- /* If DI_IMAGE flag is specified and hbmMask exists, then always use mask for drawing
*/
- if (diFlags & DI_MASK || (diFlags & DI_IMAGE && hbmMask))
- {
- hdcMask = NtGdiCreateCompatibleDC(hDc);
- if (!hdcMask)
- {
- DPRINT1("NtGdiCreateCompatibleDC() failed!\n");
- goto cleanup;
- }
-
- hOldMask = NtGdiSelectBitmap(hdcMask, hbmMask);
- if (!hOldMask)
- {
- DPRINT("NtGdiSelectBitmap() failed!\n");
- goto cleanup;
- }
- }
-
- if (hdcMask || hdcImage)
- {
- GreStretchBltMask(hdcOff,
- (DoFlickerFree || bAlpha) ? 0 : xLeft,
- (DoFlickerFree || bAlpha) ? 0 : yTop,
- cxWidth,
- cyHeight,
- hdcImage ? hdcImage : hdcMask,
- 0,
- 0,
- IconSize.cx,
- IconSize.cy,
- SRCCOPY,
- 0,
- hdcMask,
- 0,
- hdcImage ? 0 : IconSize.cy);
- }
-
- if (hOldMask) NtGdiSelectBitmap(hdcMask, hOldMask);
- if (hOldImage) NtGdiSelectBitmap(hdcImage, hOldImage);
- if (hdcImage) NtGdiDeleteObjectApp(hdcImage);
- if (hdcMask) NtGdiDeleteObjectApp(hdcMask);
-
- if (bAlpha)
- {
- BITMAP bm;
- SURFACE *psurfOff = NULL;
- PBYTE pBits = NULL;
- BLENDFUNCTION BlendFunc;
+ if (DoFlickerFree)
+ {
+ hDestDC = NtGdiCreateCompatibleDC(hDc);
+ if(!hDestDC)
+ {
+ DPRINT1("NtGdiCreateCompatibleDC failed!\n");
+ Ret = FALSE;
+ goto Cleanup ;
+ }
+ hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight);
+ if(!hOffBmp)
+ {
+ DPRINT1("NtGdiCreateCompatibleBitmap failed!\n");
+ goto Cleanup ;
+ }
+ hOldOffBmp = NtGdiSelectBitmap(hDestDC, hOffBmp);
+ hOldOffBrush = NtGdiSelectBrush(hDestDC, hbrFlickerFreeDraw);
+ NtGdiPatBlt(hDestDC, 0, 0, cxWidth, cyHeight, PATCOPY);
+ NtGdiSelectBrush(hDestDC, hOldOffBrush);
+ x=y=0;
+ }
+
+ /* Set Background/foreground colors */
+ iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black
+ iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white
+
+ 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;
-
- psurfOff = SURFACE_LockSurface(hbmOff);
- if (psurfOff == NULL)
- {
- DPRINT1("BITMAPOBJ_LockBitmap() failed!\n");
- goto cleanup;
- }
- BITMAP_GetObject(psurfOff, sizeof(BITMAP), (PVOID)&bm);
-
- pBits = ExAllocatePoolWithTag(PagedPool, bm.bmWidthBytes * abs(bm.bmHeight),
TAG_BITMAP);
+ PSURFACE psurf;
+ PBYTE pBits ;
+ HBITMAP hMemBmp = NULL;
+
+ pBits = ExAllocatePoolWithTag(PagedPool,
+ bmpColor.bmWidthBytes * abs(bmpColor.bmHeight),
+ TAG_BITMAP);
if (pBits == NULL)
{
- DPRINT1("ExAllocatePoolWithTag() failed!\n");
- SURFACE_UnlockSurface(psurfOff);
- goto cleanup;
- }
-
- /* get icon bits */
- IntGetBitmapBits(psurfOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
+ 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++)
+ for (i = 0; i < abs(bmpColor.bmHeight); i++)
+ {
+ Count = i*bmpColor.bmWidthBytes;
+ for (j = 0; j < bmpColor.bmWidth; j++)
{
Pixel = *(DWORD *)(pBits + Count);
@@ -1449,35 +1357,112 @@
}
}
- /* set icon bits */
- IntSetBitmapBits(psurfOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
- ExFreePoolWithTag(pBits, TAG_BITMAP);
-
- SURFACE_UnlockSurface(psurfOff);
-
- BlendFunc.BlendOp = AC_SRC_OVER;
- BlendFunc.BlendFlags = 0;
- BlendFunc.SourceConstantAlpha = 255;
- BlendFunc.AlphaFormat = AC_SRC_ALPHA;
-
- NtGdiAlphaBlend(hDc, xLeft, yTop, cxWidth, cyHeight,
- hdcOff, 0, 0, cxWidth, cyHeight, BlendFunc, 0);
- }
- else if (DoFlickerFree)
- {
- NtGdiBitBlt(hDc, xLeft, yTop, cxWidth,
- cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0);
- }
-
- Ret = TRUE;
-
-cleanup:
- if (DoFlickerFree || bAlpha)
- {
- if (hOldOffBmp) NtGdiSelectBitmap(hdcOff, hOldOffBmp);
- if (hOldOffBrush) NtGdiSelectBrush(hdcOff, hOldOffBrush);
- if (hbmOff) GreDeleteObject(hbmOff);
- if (hdcOff) NtGdiDeleteObjectApp(hdcOff);
+ /* 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,
+ x,
+ y,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ 0,
+ pIcon->Size.cx,
+ pIcon->Size.cy,
+ SRCAND,
+ 0);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ }
+
+ if(diFlags & DI_IMAGE)
+ {
+ if (hbmColor)
+ {
+ DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
+ hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor);
+ NtGdiStretchBlt(hDestDC,
+ x,
+ y,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ 0,
+ pIcon->Size.cx,
+ pIcon->Size.cy,
+ rop,
+ 0);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ }
+ else
+ {
+ /* Mask bitmap holds the information in its second half */
+ DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ;
+ hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask);
+ NtGdiStretchBlt(hDestDC,
+ x,
+ y,
+ cxWidth,
+ cyHeight,
+ hMemDC,
+ 0,
+ pIcon->Size.cy,
+ pIcon->Size.cx,
+ pIcon->Size.cy,
+ rop,
+ 0);
+ NtGdiSelectBitmap(hMemDC, hTmpBmp);
+ }
+ }
+
+done:
+ if(hDestDC != hDc)
+ {
+ NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hDestDC, 0, 0, SRCCOPY, 0, 0);
+ }
+
+ /* Restore foreground and background colors */
+ IntGdiSetBkColor(hDc, iOldBkColor);
+ IntGdiSetTextColor(hDc, iOldTxtColor);
+
+ Ret = TRUE ;
+
+Cleanup:
+ NtGdiDeleteObjectApp(hMemDC);
+ if(hDestDC != hDc)
+ {
+ if(hOldOffBmp) NtGdiSelectBitmap(hDestDC, hOldOffBmp);
+ NtGdiDeleteObjectApp(hDestDC);
+ if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp);
}
return Ret;