From c3f13756b260e262d10b8bb328773c614eb4d562 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Gardou?= Date: Sun, 9 May 2010 11:35:36 +0000 Subject: [PATCH] [WIN32K] - Set NULL owner to copied bitmap when creating indirect icons - Rewrite UserDrawIconEx, inspired from wine code - fix palette creation for 16 bits DIB - Always assign a palette to bitmap created with BITMAP_CopyBitmap and IntCreateCompatibeBitmap. [USER32] - Use DIB section when creating icons - Use something called "header" Now mode switching is almost glitchless. svn path=/branches/reactos-yarotows/; revision=47140 --- dll/win32/user32/include/cursor.h | 32 +- dll/win32/user32/windows/bitmap.c | 28 +- dll/win32/user32/windows/icon.c | 94 +++-- subsystems/win32/win32k/ntuser/cursoricon.c | 400 ++++++++++---------- subsystems/win32/win32k/objects/bitmaps.c | 29 +- subsystems/win32/win32k/objects/dibobj.c | 26 +- 6 files changed, 321 insertions(+), 288 deletions(-) diff --git a/dll/win32/user32/include/cursor.h b/dll/win32/user32/include/cursor.h index 67d3053f3be..3654767c5f9 100644 --- a/dll/win32/user32/include/cursor.h +++ b/dll/win32/user32/include/cursor.h @@ -1,2 +1,32 @@ HCURSOR -CursorIconToCursor(HICON hIcon, BOOL SemiTransparent); +CursorIconToCursor(HICON hIcon, + BOOL SemiTransparent); + +HICON CreateCursorIconFromData(PVOID ImageData, + ICONIMAGE* IconImage, + int cxDesired, + int cyDesired, + int xHotspot, + int yHotspot, + BOOL fIcon); + +/* + * 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 ); + +int +CURSORICON_FindBestCursor(LPVOID dir, + fnGetCIEntry get_entry, + int Width, + int Height, + int ColorBits); +int +CURSORICON_FindBestIcon(LPVOID dir, + fnGetCIEntry get_entry, + int Width, + int Height, + int ColorBits); + diff --git a/dll/win32/user32/windows/bitmap.c b/dll/win32/user32/windows/bitmap.c index ab8f3e461fa..c63e43e1164 100644 --- a/dll/win32/user32/windows/bitmap.c +++ b/dll/win32/user32/windows/bitmap.c @@ -56,11 +56,6 @@ typedef struct #include "poppack.h" -/* forward declarations... actually in user32\windows\icon.c but useful here */ -HICON CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon); -CURSORICONDIRENTRY *CURSORICON_FindBestIcon( CURSORICONDIR *dir, int width, int height, int colors); -CURSORICONDIRENTRY *CURSORICON_FindBestCursor( CURSORICONDIR *dir, int width, int height, int colors); - /* FUNCTIONS *****************************************************************/ /* @@ -96,13 +91,6 @@ LoadImageA(HINSTANCE hinst, } -/* - * The following macro functions account 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_FindBestCursor2 * @@ -311,16 +299,6 @@ LoadCursorIconImage( return NULL; } - /* Get a handle to the screen dc, the icon we create is going to be - * compatable with this. */ - hScreenDc = CreateDCW(NULL, NULL, NULL, NULL); - if (hScreenDc == NULL) - { - UnmapViewOfFile(IconDIR); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return NULL; - } - if (fuLoad & LR_MONOCHROME) { ColorBits = 1; @@ -334,14 +312,12 @@ LoadCursorIconImage( dirEntry = CURSORICON_FindBestCursorFile( IconDIR, width, height, ColorBits ); if (!dirEntry) { - DeleteDC(hScreenDc); UnmapViewOfFile(IconDIR); return NULL; } if ( dirEntry->dwDIBOffset > filesize ) { - DeleteDC(hScreenDc); UnmapViewOfFile(IconDIR); return NULL; } @@ -355,7 +331,6 @@ LoadCursorIconImage( SafeIconImage = RtlAllocateHeap(GetProcessHeap(), 0, dirEntry->dwDIBSize); if (SafeIconImage == NULL) { - DeleteDC(hScreenDc); UnmapViewOfFile(IconDIR); return NULL; } @@ -384,9 +359,8 @@ LoadCursorIconImage( /* Make data point to the start of the XOR image data. */ Data = (PBYTE)SafeIconImage + HeaderSize; - hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, width, height, width/2, height/2, Icon); + hIcon = CreateCursorIconFromData(Data, SafeIconImage, width, height, width/2, height/2, Icon); RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - DeleteDC(hScreenDc); return hIcon; } diff --git a/dll/win32/user32/windows/icon.c b/dll/win32/user32/windows/icon.c index cd9766a4f92..cd740de8d02 100644 --- a/dll/win32/user32/windows/icon.c +++ b/dll/win32/user32/windows/icon.c @@ -36,11 +36,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32); HICON -CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon) +CreateCursorIconFromData(PVOID ImageData, ICONIMAGE* IconImage, int cxDesired, int cyDesired, int xHotspot, int yHotspot, BOOL fIcon) { - BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)]; - BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer; ICONINFO IconInfo; + PVOID pBits ; + HICON res; IconInfo.fIcon = fIcon; IconInfo.xHotspot = xHotspot; @@ -50,16 +50,40 @@ CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxD { IconInfo.hbmColor = (HBITMAP)0; IconImage->icHeader.biHeight *= 2; - IconInfo.hbmMask = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT, - ImageData, (BITMAPINFO*)IconImage, - DIB_RGB_COLORS); + IconInfo.hbmMask = CreateDIBSection(0, + (BITMAPINFO*)IconImage, + DIB_RGB_COLORS, + &pBits, + NULL, + 0); + if(!pBits) + { + ERR("Could not create a DIB section\n"); + return NULL; + } + CopyMemory(pBits, + ImageData, + (((IconImage->icHeader.biWidth + 31) & ~31 ) >> 3) * IconImage->icHeader.biHeight) ; } else { + BYTE BitmapInfoBuffer[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)]; + BITMAPINFO *bwBIH = (BITMAPINFO *)BitmapInfoBuffer; /* Create the XOR bitmap */ - IconInfo.hbmColor = CreateDIBitmap(hDC, &IconImage->icHeader, CBM_INIT, - ImageData, (BITMAPINFO*)IconImage, - DIB_RGB_COLORS); + IconInfo.hbmColor = CreateDIBSection(0, + (BITMAPINFO*)IconImage, + DIB_RGB_COLORS, + &pBits, + NULL, + 0); + if(!pBits) + { + ERR("Could not create a DIB section\n"); + return NULL; + } + CopyMemory(pBits, + ImageData, + (((IconImage->icHeader.biWidth * IconImage->icHeader.biBitCount+ 31) & ~31 ) >> 3) * IconImage->icHeader.biHeight) ; /* Make ImageData point to the start of the AND image data. */ ImageData = ((PBYTE)ImageData) + (((IconImage->icHeader.biWidth * @@ -89,17 +113,30 @@ CreateCursorIconFromData(HDC hDC, PVOID ImageData, ICONIMAGE* IconImage, int cxD bwBIH->bmiColors[1].rgbRed = 0xff; bwBIH->bmiColors[1].rgbReserved = 0; - /* Create the AND bitmap. */ - IconInfo.hbmMask = CreateDIBitmap(hDC, &bwBIH->bmiHeader, 0, - ImageData, bwBIH, DIB_RGB_COLORS); - - SetDIBits(hDC, IconInfo.hbmMask, 0, IconImage->icHeader.biHeight, - ImageData, bwBIH, DIB_RGB_COLORS); + IconInfo.hbmMask = CreateDIBSection(0, + bwBIH, + DIB_RGB_COLORS, + &pBits, + NULL, + 0); + if(!pBits) + { + ERR("Could not create a DIB section\n"); + DeleteObject(IconInfo.hbmColor); + return NULL; + } + CopyMemory(pBits, + ImageData, + (((IconImage->icHeader.biWidth + 31) & ~31 ) >> 3) * IconImage->icHeader.biHeight) ; } - /* Create the icon based on everything we have so far */ - return NtUserCreateCursorIconHandle(&IconInfo, FALSE); + /* Use indirect creation, as DIBSection can't be shared between processes */ + res = NtUserCreateCursorIconHandle(&IconInfo, TRUE); + DeleteObject(IconInfo.hbmMask); + if(IconInfo.hbmColor) DeleteObject(IconInfo.hbmColor); + + return res; } /* @@ -203,7 +240,6 @@ CreateIconFromResourceEx( ULONG HeaderSize; ULONG ColourCount; PVOID Data; - HDC hScreenDc; WORD wXHotspot; WORD wYHotspot; @@ -259,17 +295,8 @@ CreateIconFromResourceEx( /* make data point to the start of the XOR image data */ Data = (PBYTE)SafeIconImage + HeaderSize; - /* get a handle to the screen dc, the icon we create is going to be compatable with this */ - hScreenDc = CreateDCW(L"DISPLAY", NULL, NULL, NULL); - if (hScreenDc == NULL) - { + hIcon = CreateCursorIconFromData(Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot, fIcon); RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - return(NULL); - } - - hIcon = CreateCursorIconFromData(hScreenDc, Data, SafeIconImage, cxDesired, cyDesired, wXHotspot, wYHotspot, fIcon); - RtlFreeHeap(GetProcessHeap(), 0, SafeIconImage); - DeleteDC(hScreenDc); return hIcon; } @@ -427,19 +454,12 @@ LookupIconIdFromDirectory( -/* - * 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 +int CURSORICON_FindBestIcon(LPVOID dir, fnGetCIEntry get_entry, int Width, @@ -495,7 +515,7 @@ CURSORICON_FindBestIcon(LPVOID dir, * FIXME: parameter 'color' ignored and entries with more than 1 bpp * ignored too */ -static int +int CURSORICON_FindBestCursor(LPVOID dir, fnGetCIEntry get_entry, int Width, diff --git a/subsystems/win32/win32k/ntuser/cursoricon.c b/subsystems/win32/win32k/ntuser/cursoricon.c index ea604887bc3..dc77f411b94 100644 --- a/subsystems/win32/win32k/ntuser/cursoricon.c +++ b/subsystems/win32/win32k/ntuser/cursoricon.c @@ -110,7 +110,7 @@ UserSetCursor( HCURSOR hOldCursor = (HCURSOR)0; HDC hdcScreen; BOOL bResult; - + CurInfo = IntGetSysCursorInfo(); OldCursor = CurInfo->CurrentCursorObject; @@ -522,26 +522,34 @@ NtUserCreateCursorIconHandle(PICONINFO IconInfo OPTIONAL, BOOL Indirect) { // FIXME: WTF? CurIcon->IconInfo.hbmMask = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmMask); - CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor); + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL); + if(CurIcon->IconInfo.hbmColor) + { + CurIcon->IconInfo.hbmColor = BITMAP_CopyBitmap(CurIcon->IconInfo.hbmColor); + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL); + } } - if (CurIcon->IconInfo.hbmColor && - (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor))) + else { - CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; - SURFACE_UnlockSurface(psurfBmp); - GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL); - } - if (CurIcon->IconInfo.hbmMask && - (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask))) - { - if (CurIcon->IconInfo.hbmColor == NULL) + if (CurIcon->IconInfo.hbmColor && + (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmColor))) { CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; - CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy >> 1; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy; + SURFACE_UnlockSurface(psurfBmp); + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmColor, NULL); + } + if (CurIcon->IconInfo.hbmMask && + (psurfBmp = SURFACE_LockSurface(CurIcon->IconInfo.hbmMask))) + { + if(!CurIcon->IconInfo.hbmColor) + { + CurIcon->Size.cx = psurfBmp->SurfObj.sizlBitmap.cx; + CurIcon->Size.cy = psurfBmp->SurfObj.sizlBitmap.cy*2; + } + SURFACE_UnlockSurface(psurfBmp); + GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL); } - SURFACE_UnlockSurface(psurfBmp); - GDIOBJ_SetOwnership(CurIcon->IconInfo.hbmMask, NULL); } /* Calculate icon hotspot */ @@ -789,8 +797,8 @@ UserClipCursor( DesktopWindow = UserGetDesktopWindow(); - if (prcl != NULL && - (prcl->right > prcl->left) && + if (prcl != NULL && + (prcl->right > prcl->left) && (prcl->bottom > prcl->top) && DesktopWindow != NULL) { @@ -1268,6 +1276,7 @@ NtUserSetSystemCursor( return FALSE; } +/* Mostly inspired from wine code */ BOOL UserDrawIconEx( HDC hDc, @@ -1282,18 +1291,15 @@ UserDrawIconEx( { BOOL Ret = FALSE; HBITMAP hbmMask, hbmColor; - BITMAP bmpMask, bmpColor; + BITMAP bmpColor, bm; BOOL DoFlickerFree; SIZE IconSize; + INT iOldBkColor = 0, iOldTxtColor = 0; - HDC hdcOff; + HDC hMemDC, hOffDC = NULL; 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; hbmMask = pIcon->IconInfo.hbmMask; @@ -1302,7 +1308,7 @@ UserDrawIconEx( 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; } @@ -1312,20 +1318,33 @@ UserDrawIconEx( return FALSE; } + if(!(hMemDC = NtGdiCreateCompatibleDC(hDc))) + { + DPRINT1("NtGdiCreateCompatibleDC failed!\n"); + return FALSE; + } + if (hbmColor) { IconSize.cx = bmpColor.bmWidth; IconSize.cy = bmpColor.bmHeight; } - else + else /* take it from mask */ { - IconSize.cx = bmpMask.bmWidth; - IconSize.cy = bmpMask.bmHeight / 2; + IconSize.cx = bm.bmWidth; + IconSize.cy = bm.bmHeight/2; } + if (!diFlags) + diFlags = DI_NORMAL; + /* NtGdiCreateCompatibleBitmap will create a monochrome bitmap when cxWidth or cyHeight is 0 */ - if ((bmpColor.bmBitsPixel == 32) && (cxWidth != 0) && (cyHeight != 0)) + if (hbmColor + && (bmpColor.bmBitsPixel == 32) + && (cxWidth != 0) + && (cyHeight != 0) + && (diFlags & DI_IMAGE)) { SURFACE *psurfOff = NULL; PFN_DIB_GetPixel fnSource_GetPixel = NULL; @@ -1333,7 +1352,7 @@ UserDrawIconEx( /* 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; @@ -1355,9 +1374,6 @@ UserDrawIconEx( } } - if (!diFlags) - diFlags = DI_NORMAL; - if (!cxWidth) cxWidth = ((diFlags & DI_DEFAULTSIZE) ? UserGetSystemMetrics(SM_CXICON) : IconSize.cx); @@ -1369,204 +1385,174 @@ UserDrawIconEx( DoFlickerFree = (hbrFlickerFreeDraw && (GDI_HANDLE_GET_TYPE(hbrFlickerFreeDraw) == GDI_OBJECT_TYPE_BRUSH)); - if (DoFlickerFree || bAlpha) + if (DoFlickerFree) { - RECTL r; - BITMAP bm; - SURFACE *psurfOff = NULL; - - r.right = cxWidth; - r.bottom = cyHeight; - - hdcOff = NtGdiCreateCompatibleDC(hDc); - if (!hdcOff) + hOffDC = NtGdiCreateCompatibleDC(hDc); + if(!hOffDC) { - DPRINT1("NtGdiCreateCompatibleDC() failed!\n"); - return FALSE; + DPRINT1("NtGdiCreateCompatibleBitmap failed!\n"); + Ret = FALSE; + goto Cleanup ; } - - hbmOff = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight); - if (!hbmOff) + hOffBmp = NtGdiCreateCompatibleBitmap(hDc, cxWidth, cyHeight); + if(!hOffBmp) { - 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); + DPRINT1("NtGdiCreateCompatibleBitmap failed!\n"); + goto Cleanup ; } + hOldOffBmp = NtGdiSelectBitmap(hOffDC, hOffBmp); + hOldOffBrush = NtGdiSelectBrush(hOffDC, hbrFlickerFreeDraw); + NtGdiPatBlt(hOffDC, 0, 0, cxWidth, cyHeight, PATCOPY); + NtGdiSelectBrush(hOffDC, hOldOffBrush); } 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; - } + /* Set Background/foreground colors */ + iOldTxtColor = IntGdiSetTextColor(hDc, 0); //black + iOldBkColor = IntGdiSetBkColor(hDc, 0x00FFFFFF); //white } - /* 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 (hbmMask && (diFlags & DI_MASK) && !bAlpha) + { + hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmMask); + NtGdiStretchBlt(hOffDC ? hOffDC : hDc, + hOffDC ? 0 : xLeft, + hOffDC ? 0 : yTop, + cxWidth, + cyHeight, + hMemDC, + 0, + 0, + IconSize.cx, + IconSize.cy, + SRCAND, + 0); + NtGdiSelectBitmap(hMemDC, hTmpBmp); } - if (hdcMask || hdcImage) + if(diFlags & DI_IMAGE) { - 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; - DWORD Pixel; - BYTE Red, Green, Blue, Alpha; - DWORD Count = 0; - INT i, j; - - psurfOff = SURFACE_LockSurface(hbmOff); - if (psurfOff == NULL) + if (bAlpha) { - DPRINT1("BITMAPOBJ_LockBitmap() failed!\n"); - goto cleanup; - } - BITMAP_GetObject(psurfOff, sizeof(BITMAP), (PVOID)&bm); + 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, bm.bmWidthBytes * abs(bm.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); - - /* premultiply with the alpha channel value */ - for (i = 0; i < cyHeight; i++) - { - for (j = 0; j < cxWidth; j++) + pBits = ExAllocatePoolWithTag(PagedPool, + bmpColor.bmWidthBytes * abs(bmpColor.bmHeight), + TAG_BITMAP); + if (pBits == NULL) { - 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); + 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(hOffDC ? hOffDC : hDc, + hOffDC ? 0 : xLeft, + hOffDC ? 0 : yTop, + cxWidth, + cyHeight, + hMemDC, + 0, + 0, + IconSize.cx, + IconSize.cy, + pixelblend, + NULL); + NtGdiSelectBitmap(hMemDC, hTmpBmp); + CleanupAlpha: + if(pBits) ExFreePoolWithTag(pBits, TAG_BITMAP); + if(hMemBmp) NtGdiDeleteObjectApp(hMemBmp); + } + else if (hbmColor) + { + DWORD rop = (diFlags & DI_MASK) ? SRCINVERT : SRCCOPY ; + hTmpBmp = NtGdiSelectBitmap(hMemDC, hbmColor); + NtGdiStretchBlt(hOffDC ? hOffDC : hDc, + hOffDC ? 0 : xLeft, + hOffDC ? 0 : yTop, + cxWidth, + cyHeight, + hMemDC, + 0, + 0, + IconSize.cx, + IconSize.cy, + rop, + 0); + NtGdiSelectBitmap(hMemDC, hTmpBmp); } - - /* 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) + + if(hOffDC) { - NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, - cyHeight, hdcOff, 0, 0, SRCCOPY, 0, 0); + NtGdiBitBlt(hDc, xLeft, yTop, cxWidth, cyHeight, hOffDC, 0, 0, SRCCOPY, 0, 0); } - - Ret = TRUE; - -cleanup: - if (DoFlickerFree || bAlpha) + else { - if (hOldOffBmp) NtGdiSelectBitmap(hdcOff, hOldOffBmp); - if (hOldOffBrush) NtGdiSelectBrush(hdcOff, hOldOffBrush); - if (hbmOff) GreDeleteObject(hbmOff); - if (hdcOff) NtGdiDeleteObjectApp(hdcOff); + IntGdiSetBkColor(hDc, iOldBkColor); + IntGdiSetTextColor(hDc, iOldTxtColor); } + Ret = TRUE ; + +Cleanup: + NtGdiDeleteObjectApp(hMemDC); + if(hOldOffBmp) NtGdiSelectBitmap(hOffDC, hOldOffBmp); + if(hOffDC) NtGdiDeleteObjectApp(hOffDC); + if(hOffBmp) NtGdiDeleteObjectApp(hOffBmp); + return Ret; } diff --git a/subsystems/win32/win32k/objects/bitmaps.c b/subsystems/win32/win32k/objects/bitmaps.c index c4bb3857cc8..b8756ab6973 100644 --- a/subsystems/win32/win32k/objects/bitmaps.c +++ b/subsystems/win32/win32k/objects/bitmaps.c @@ -151,15 +151,9 @@ IntCreateCompatibleBitmap( NULL); /* Set palette */ psurf = SURFACE_LockSurface(Bmp); - if(!psurf) - { - DPRINT1("Could not lock surface?\n"); - } - else - { - psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault); - SURFACE_UnlockSurface(psurf); - } + ASSERT(psurf); + psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault); + SURFACE_UnlockSurface(psurf); } else { @@ -190,6 +184,15 @@ IntCreateCompatibleBitmap( dibs.dsBm.bmPlanes, dibs.dsBm.bmBitsPixel, NULL); + /* Assign palette */ + if(Bmp && psurf->ppal) + { + PSURFACE psurfBmp = SURFACE_LockSurface(Bmp); + ASSERT(psurfBmp); + psurfBmp->ppal = psurf->ppal; + GDIOBJ_IncrementShareCount((POBJ)psurf->ppal); + SURFACE_UnlockSurface(psurfBmp); + } } else { @@ -890,6 +893,14 @@ BITMAP_CopyBitmap(HBITMAP hBitmap) IntSetBitmapBits(resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf); ExFreePoolWithTag(buf,TAG_BITMAP); resBitmap->flFlags = Bitmap->flFlags; + /* Copy palette */ + if(Bitmap->hDIBPalette) + resBitmap->ppal = PALETTE_ShareLockPalette(Bitmap->hDIBPalette); + else if (Bitmap->ppal) + { + resBitmap->ppal = Bitmap->ppal ; + GDIOBJ_IncrementShareCount(&Bitmap->ppal->BaseObject); + } GDIOBJ_UnlockObjByPtr((POBJ)resBitmap); } else diff --git a/subsystems/win32/win32k/objects/dibobj.c b/subsystems/win32/win32k/objects/dibobj.c index c27d08b60e2..149491908c4 100644 --- a/subsystems/win32/win32k/objects/dibobj.c +++ b/subsystems/win32/win32k/objects/dibobj.c @@ -1473,17 +1473,22 @@ DIB_CreateDIBSection( switch (bi->biBitCount) { case 15: + dsBitfields[0] = 0x7c00; + dsBitfields[1] = 0x03e0; + dsBitfields[2] = 0x001f; + break; + case 16: - dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0x7c00; - dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x03e0; - dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x001f; + dsBitfields[0] = 0xF800; + dsBitfields[1] = 0x07e0; + dsBitfields[2] = 0x001f; break; case 24: case 32: - dsBitfields[0] = (bi->biCompression == BI_BITFIELDS) ? *(DWORD *)lpRGB : 0xff0000; - dsBitfields[1] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 1) : 0x00ff00; - dsBitfields[2] = (bi->biCompression == BI_BITFIELDS) ? *((DWORD *)lpRGB + 2) : 0x0000ff; + dsBitfields[0] = 0xff0000; + dsBitfields[1] = 0x00ff00; + dsBitfields[2] = 0x0000ff; break; } } @@ -1741,13 +1746,20 @@ BuildDIBPalette(CONST BITMAPINFO *bmi, PINT paletteType) GreenMask = ((ULONG *)bmi->bmiColors)[1]; BlueMask = ((ULONG *)bmi->bmiColors)[2]; } - else if (bits < 24) + else if (bits == 15) { *paletteType = PAL_BITFIELDS; RedMask = 0x7c00; GreenMask = 0x03e0; BlueMask = 0x001f; } + else if (bits == 16) + { + *paletteType = PAL_BITFIELDS; + RedMask = 0xF800; + GreenMask = 0x07e0; + BlueMask = 0x001f; + } else { *paletteType = PAL_BGR;