[ros-diffs] [jgardou] 48123: [WIN32K] - rewrite UserDrawIconEx, taken from yarotows, with same small modifications. Fixes a whole bunch of user32:cursoricon tests
jgardou at svn.reactos.org
jgardou at svn.reactos.org
Mon Jul 19 22:41:36 UTC 2010
- Previous message: [ros-diffs] [tkreuzer] 48122: [RTL] - Update amd64 specific code to be MSVC compatible - Remove Leading underscores from symbols
- Next message: [ros-diffs] [tkreuzer] 48124: [FREELDR] Convert freeldr and setupldr to PE format. Previously freeldr was a raw binary file, which made handling by the bootsector very easy, but it disqualified it from proper debugging with gdb using symbols. This is possible with having unstripped PE files. As we don't have any space to do proper PE loading from the bootsector (I already had to trim some strings to get enough space for the new jump code), we need to make sure, that the PE file doesn't contain a .bss section, which is achieved by a linker script. The next thing is to make sure, we don't have any symbols in the output file, because they would make freeldr too big to be loaded into memory and they are useless anyway. On the other hand we like to keep the symbols in the .nostrip.sys files if requested, as this is the primary purpose. This is in theory not a problem, as we could simply strip the file at the end, but binutils throw a monkey wrench in our plans: both strip and objcopy disrespect the file alignment and create unaligned sections, that don't naturally match their VAs. This is solved by hacking rbuild to do invoke ld 2 times, one time without and one time with the symbols (if requested). Now the bootsectors also got some changes: instead of jumping to the loading address (0x8000) they get the address of the entry point from the image optional header. This is slightly simplified, by assuming the NtHeader begins at offset 0xE0. This finally allows source level debugging of freeldr with gdb.
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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/ntuser/cursoricon.c?rev=48123&r1=48122&r2=48123&view=diff
==============================================================================
--- 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;
- Previous message: [ros-diffs] [tkreuzer] 48122: [RTL] - Update amd64 specific code to be MSVC compatible - Remove Leading underscores from symbols
- Next message: [ros-diffs] [tkreuzer] 48124: [FREELDR] Convert freeldr and setupldr to PE format. Previously freeldr was a raw binary file, which made handling by the bootsector very easy, but it disqualified it from proper debugging with gdb using symbols. This is possible with having unstripped PE files. As we don't have any space to do proper PE loading from the bootsector (I already had to trim some strings to get enough space for the new jump code), we need to make sure, that the PE file doesn't contain a .bss section, which is achieved by a linker script. The next thing is to make sure, we don't have any symbols in the output file, because they would make freeldr too big to be loaded into memory and they are useless anyway. On the other hand we like to keep the symbols in the .nostrip.sys files if requested, as this is the primary purpose. This is in theory not a problem, as we could simply strip the file at the end, but binutils throw a monkey wrench in our plans: both strip and objcopy disrespect the file alignment and create unaligned sections, that don't naturally match their VAs. This is solved by hacking rbuild to do invoke ld 2 times, one time without and one time with the symbols (if requested). Now the bootsectors also got some changes: instead of jumping to the loading address (0x8000) they get the address of the entry point from the image optional header. This is slightly simplified, by assuming the NtHeader begins at offset 0xE0. This finally allows source level debugging of freeldr with gdb.
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the Ros-diffs
mailing list