forked from Mirrors/wine-wine
user32: Added DrawIconEx alpha blending support.
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,
|
INT cxWidth, INT cyWidth, UINT istep,
|
||||||
HBRUSH hbr, UINT flags )
|
HBRUSH hbr, UINT flags )
|
||||||
{
|
{
|
||||||
CURSORICONINFO *ptr = GlobalLock16(HICON_16(hIcon));
|
CURSORICONINFO *ptr;
|
||||||
HDC hDC_off = 0, hMemDC;
|
HDC hDC_off = 0, hMemDC;
|
||||||
BOOL result = FALSE, DoOffscreen;
|
BOOL result = FALSE, DoOffscreen;
|
||||||
HBITMAP hB_off = 0, hOld = 0;
|
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",
|
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 );
|
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)
|
if (istep)
|
||||||
FIXME_(icon)("Ignoring istep=%d\n", istep);
|
FIXME_(icon)("Ignoring istep=%d\n", istep);
|
||||||
if (flags & DI_NOMIRROR)
|
if (flags & DI_NOMIRROR)
|
||||||
FIXME_(icon)("Ignoring flag DI_NOMIRROR\n");
|
FIXME_(icon)("Ignoring flag DI_NOMIRROR\n");
|
||||||
|
|
||||||
if (!flags) {
|
xorLength = ptr->nHeight * get_bitmap_width_bytes(
|
||||||
FIXME_(icon)("no flags set? setting to DI_NORMAL\n");
|
ptr->nWidth, ptr->bBitsPerPixel);
|
||||||
flags = DI_NORMAL;
|
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. */
|
/* Calculate the size of the destination image. */
|
||||||
if (cxWidth == 0)
|
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)))
|
if (hMemDC && (!DoOffscreen || (hDC_off && hB_off)))
|
||||||
{
|
{
|
||||||
HBITMAP hXorBits, hAndBits;
|
HBITMAP hBitTemp;
|
||||||
|
HBITMAP hXorBits = NULL, hAndBits = NULL;
|
||||||
COLORREF oldFg, oldBg;
|
COLORREF oldFg, oldBg;
|
||||||
INT nStretchMode;
|
INT nStretchMode;
|
||||||
|
|
||||||
nStretchMode = SetStretchBltMode (hdc, STRETCH_DELETESCANS);
|
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) );
|
oldFg = SetTextColor( hdc, RGB(0,0,0) );
|
||||||
oldBg = SetBkColor( hdc, RGB(255,255,255) );
|
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 );
|
hAndBits = CreateBitmap ( ptr->nWidth, ptr->nHeight, 1, 1, ptr + 1 );
|
||||||
if (flags & DI_MASK)
|
if (hAndBits)
|
||||||
{
|
{
|
||||||
|
hBitTemp = SelectObject( hMemDC, hAndBits );
|
||||||
if (DoOffscreen)
|
if (DoOffscreen)
|
||||||
StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
|
StretchBlt (hDC_off, 0, 0, cxWidth, cyWidth,
|
||||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
|
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
|
||||||
else
|
else
|
||||||
StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
|
StretchBlt (hdc, x0, y0, cxWidth, cyWidth,
|
||||||
hMemDC, 0, 0, ptr->nWidth, ptr->nHeight, SRCAND);
|
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 );
|
SetTextColor( hdc, oldFg );
|
||||||
SetBkColor( hdc, oldBg );
|
SetBkColor( hdc, oldBg );
|
||||||
if (hXorBits) DeleteObject( hXorBits );
|
|
||||||
if (hAndBits) DeleteObject( hAndBits );
|
if (hAndBits) DeleteObject( hAndBits );
|
||||||
SetStretchBltMode (hdc, nStretchMode);
|
SetStretchBltMode (hdc, nStretchMode);
|
||||||
if (DoOffscreen) {
|
if (DoOffscreen) {
|
||||||
|
|
|
@ -1167,11 +1167,8 @@ static void test_DrawIconEx(void)
|
||||||
bmpOld = SelectObject(hdcDst, bmpDst);
|
bmpOld = SelectObject(hdcDst, bmpDst);
|
||||||
|
|
||||||
/* Test null, image only, and mask only drawing */
|
/* 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, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, 0x00000000, __LINE__);
|
||||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, __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 */
|
/* Test alpha blending */
|
||||||
/* Windows 2000 and up will alpha blend, earlier Windows versions will not */
|
/* 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, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
|
||||||
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
|
check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __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, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
|
||||||
check_DrawIconEx(hdcDst, TRUE, 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 */
|
/* Test detecting of alpha channel */
|
||||||
/* If a single pixel's alpha channel is non-zero, the icon
|
/* If a single pixel's alpha channel is non-zero, the icon
|
||||||
will be alpha blended, otherwise it will be draw with
|
will be alpha blended, otherwise it will be draw with
|
||||||
and + xor blts. */
|
and + xor blts. */
|
||||||
check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
|
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:
|
cleanup:
|
||||||
if(bmpOld)
|
if(bmpOld)
|
||||||
|
|
Loading…
Reference in New Issue