user32: Added DrawIconEx alpha blending support.
This commit is contained in:
parent
a0232508b3
commit
d1c89d0a78
|
@ -2273,25 +2273,33 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
|
|||
INT cxWidth, INT cyWidth, UINT istep,
|
||||
HBRUSH hbr, UINT flags )
|
||||
{
|
||||
CURSORICONINFO *ptr = GlobalLock16(HICON_16(hIcon));
|
||||
CURSORICONINFO *ptr;
|
||||
HDC hDC_off = 0, hMemDC;
|
||||
BOOL result = FALSE, DoOffscreen;
|
||||
HBITMAP hB_off = 0, hOld = 0;
|
||||
unsigned char *xorBitmapBits;
|
||||
unsigned int xorLength;
|
||||
BOOL has_alpha = FALSE;
|
||||
|
||||
if (!ptr) return FALSE;
|
||||
TRACE_(icon)("(hdc=%p,pos=%d.%d,hicon=%p,extend=%d.%d,istep=%d,br=%p,flags=0x%08x)\n",
|
||||
hdc,x0,y0,hIcon,cxWidth,cyWidth,istep,hbr,flags );
|
||||
|
||||
hMemDC = CreateCompatibleDC (hdc);
|
||||
if (!(ptr = GlobalLock16(HICON_16(hIcon)))) return FALSE;
|
||||
if (!(hMemDC = CreateCompatibleDC( hdc ))) return FALSE;
|
||||
|
||||
if (istep)
|
||||
FIXME_(icon)("Ignoring istep=%d\n", istep);
|
||||
if (flags & DI_NOMIRROR)
|
||||
FIXME_(icon)("Ignoring flag DI_NOMIRROR\n");
|
||||
|
||||
if (!flags) {
|
||||
FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
|
||||
flags = DI_NORMAL;
|
||||
}
|
||||
xorLength = ptr->nHeight * get_bitmap_width_bytes(
|
||||
ptr->nWidth, ptr->bBitsPerPixel);
|
||||
xorBitmapBits = (unsigned char *)(ptr + 1) + ptr->nHeight *
|
||||
get_bitmap_width_bytes(ptr->nWidth, 1);
|
||||
|
||||
if (flags & DI_IMAGE)
|
||||
has_alpha = bitmap_has_alpha_channel(
|
||||
ptr->bBitsPerPixel, xorBitmapBits, xorLength);
|
||||
|
||||
/* Calculate the size of the destination image. */
|
||||
if (cxWidth == 0)
|
||||
|
@ -2329,50 +2337,90 @@ BOOL WINAPI DrawIconEx( HDC hdc, INT x0, INT y0, HICON hIcon,
|
|||
|
||||
if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
|
||||
{
|
||||
HBITMAP hXorBits, hAndBits;
|
||||
HBITMAP hBitTemp;
|
||||
HBITMAP hXorBits = NULL, hAndBits = NULL;
|
||||
COLORREF oldFg, oldBg;
|
||||
INT nStretchMode;
|
||||
|
||||
nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
|
||||
|
||||
hXorBits = CreateBitmap ( ptr->nWidth, ptr->nHeight,
|
||||
ptr->bPlanes, ptr->bBitsPerPixel,
|
||||
(char *)(ptr + 1)
|
||||
+ ptr->nHeight *
|
||||
get_bitmap_width_bytes(ptr->nWidth,1) );
|
||||
hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 );
|
||||
oldFg = SetTextColor( hdc, RGB(0,0,0) );
|
||||
oldBg = SetBkColor( hdc, RGB(255,255,255) );
|
||||
|
||||
if (hXorBits && hAndBits)
|
||||
if (((flags & DI_MASK) && !(flags & DI_IMAGE)) ||
|
||||
((flags & DI_MASK) && !has_alpha))
|
||||
{
|
||||
HBITMAP hBitTemp = SelectObject( hMemDC, hAndBits );
|
||||
if (flags & DI_MASK)
|
||||
hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 );
|
||||
if (hAndBits)
|
||||
{
|
||||
hBitTemp = SelectObject( hMemDC, hAndBits );
|
||||
if (DoOffscreen)
|
||||
StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
|
||||
else
|
||||
StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
|
||||
SelectObject( hMemDC, hBitTemp );
|
||||
}
|
||||
SelectObject( hMemDC, hXorBits );
|
||||
if (flags & DI_IMAGE)
|
||||
{
|
||||
if (DoOffscreen)
|
||||
StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
|
||||
else
|
||||
StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
|
||||
}
|
||||
SelectObject( hMemDC, hBitTemp );
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
if (flags & DI_IMAGE)
|
||||
{
|
||||
BITMAPINFOHEADER bmih;
|
||||
unsigned char *dibBits;
|
||||
|
||||
memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
|
||||
bmih.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmih.biWidth = ptr->nWidth;
|
||||
bmih.biHeight = -ptr->nHeight;
|
||||
bmih.biPlanes = ptr->bPlanes;
|
||||
bmih.biBitCount = ptr->bBitsPerPixel;
|
||||
bmih.biCompression = BI_RGB;
|
||||
|
||||
hXorBits = CreateDIBSection(hdc, (BITMAPINFO*)&bmih, DIB_RGB_COLORS,
|
||||
(void*)&dibBits, NULL, 0);
|
||||
|
||||
if (hXorBits && dibBits)
|
||||
{
|
||||
if(has_alpha)
|
||||
{
|
||||
BLENDFUNCTION pixelblend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
|
||||
|
||||
/* Do the alpha blending render */
|
||||
premultiply_alpha_channel(dibBits, xorBitmapBits, xorLength);
|
||||
hBitTemp = SelectObject( hMemDC, hXorBits );
|
||||
|
||||
if (DoOffscreen)
|
||||
GdiAlphaBlend(hDC_off, 0, 0, cxWidth, cyWidth, hMemDC,
|
||||
0, 0, ptr->nWidth, ptr->nHeight, pixelblend);
|
||||
else
|
||||
GdiAlphaBlend(hdc, x0, y0, cxWidth, cyWidth, hMemDC,
|
||||
0, 0, ptr->nWidth, ptr->nHeight, pixelblend);
|
||||
|
||||
SelectObject( hMemDC, hBitTemp );
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(dibBits, xorBitmapBits, xorLength);
|
||||
hBitTemp = SelectObject( hMemDC, hXorBits );
|
||||
if (DoOffscreen)
|
||||
StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
|
||||
else
|
||||
StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
|
||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCPAINT);
|
||||
SelectObject( hMemDC, hBitTemp );
|
||||
}
|
||||
|
||||
DeleteObject( hXorBits );
|
||||
}
|
||||
}
|
||||
|
||||
result = TRUE;
|
||||
|
||||
SetTextColor( hdc, oldFg );
|
||||
SetBkColor( hdc, oldBg );
|
||||
if (hXorBits) DeleteObject( hXorBits );
|
||||
|
||||
if (hAndBits) DeleteObject( hAndBits );
|
||||
SetStretchBltMode (hdc, nStretchMode);
|
||||
if (DoOffscreen) {
|
||||
|
|
|
@ -1167,11 +1167,8 @@ static void test_DrawIconEx(void)
|
|||
bmpOld = SelectObject(hdcDst, bmpDst);
|
||||
|
||||
/* Test null, image only, and mask only drawing */
|
||||
todo_wine
|
||||
{
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
|
||||
}
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
|
||||
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, 0x00000000, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
|
||||
|
@ -1189,25 +1186,22 @@ static void test_DrawIconEx(void)
|
|||
|
||||
/* Test alpha blending */
|
||||
/* Windows 2000 and up will alpha blend, earlier Windows versions will not */
|
||||
todo_wine check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
|
||||
|
||||
todo_wine
|
||||
{
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
|
||||
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
|
||||
}
|
||||
check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
|
||||
check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
|
||||
|
||||
/* Test detecting of alpha channel */
|
||||
/* If a single pixel's alpha channel is non-zero, the icon
|
||||
will be alpha blended, otherwise it will be draw with
|
||||
and + xor blts. */
|
||||
check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
|
||||
todo_wine check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
|
||||
check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
|
||||
|
||||
cleanup:
|
||||
if(bmpOld)
|
||||
|
|
Loading…
Reference in New Issue