forked from Mirrors/wine-wine
comctl32: Create an internal copy for 32-bpp bitmaps with an alpha channel for Static control.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47018 Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
0caf5af18e
commit
e2f179d84f
|
@ -60,6 +60,7 @@ struct static_extra_info
|
|||
HBITMAP hbitmap;
|
||||
HENHMETAFILE hemf;
|
||||
} image;
|
||||
BOOL image_has_alpha;
|
||||
};
|
||||
|
||||
typedef void (*pfPaint)( HWND hwnd, HDC hdc, DWORD style );
|
||||
|
@ -163,6 +164,52 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
|
|||
return prevIcon;
|
||||
}
|
||||
|
||||
static HBITMAP create_alpha_bitmap( HBITMAP hbitmap )
|
||||
{
|
||||
BITMAP bm;
|
||||
HBITMAP alpha;
|
||||
BITMAPINFO info;
|
||||
HDC hdc;
|
||||
void *bits;
|
||||
DWORD i;
|
||||
BYTE *ptr;
|
||||
BOOL has_alpha = FALSE;
|
||||
|
||||
GetObjectW( hbitmap, sizeof(bm), &bm );
|
||||
if (bm.bmBitsPixel != 32) return 0;
|
||||
|
||||
if (!(hdc = CreateCompatibleDC( 0 ))) return 0;
|
||||
|
||||
info.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
info.bmiHeader.biWidth = bm.bmWidth;
|
||||
info.bmiHeader.biHeight = -bm.bmHeight;
|
||||
info.bmiHeader.biPlanes = 1;
|
||||
info.bmiHeader.biBitCount = 32;
|
||||
info.bmiHeader.biCompression = BI_RGB;
|
||||
info.bmiHeader.biSizeImage = bm.bmWidth * bm.bmHeight * 4;
|
||||
info.bmiHeader.biXPelsPerMeter = 0;
|
||||
info.bmiHeader.biYPelsPerMeter = 0;
|
||||
info.bmiHeader.biClrUsed = 0;
|
||||
info.bmiHeader.biClrImportant = 0;
|
||||
if ((alpha = CreateDIBSection( hdc, &info, DIB_RGB_COLORS, &bits, NULL, 0 )))
|
||||
{
|
||||
GetDIBits( hdc, hbitmap, 0, bm.bmHeight, bits, &info, DIB_RGB_COLORS );
|
||||
|
||||
for (i = 0, ptr = bits; i < bm.bmWidth * bm.bmHeight; i++, ptr += 4)
|
||||
if ((has_alpha = (ptr[3] != 0))) break;
|
||||
|
||||
if (!has_alpha)
|
||||
{
|
||||
DeleteObject( alpha );
|
||||
alpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteDC( hdc );
|
||||
|
||||
return alpha;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* STATIC_SetBitmap
|
||||
*
|
||||
|
@ -170,7 +217,7 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
|
|||
*/
|
||||
static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
|
||||
{
|
||||
HBITMAP hOldBitmap;
|
||||
HBITMAP hOldBitmap, alpha;
|
||||
struct static_extra_info *extra;
|
||||
|
||||
if ((style & SS_TYPEMASK) != SS_BITMAP) return 0;
|
||||
|
@ -185,10 +232,23 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
|
|||
|
||||
hOldBitmap = extra->image.hbitmap;
|
||||
extra->image.hbitmap = hBitmap;
|
||||
extra->image_has_alpha = FALSE;
|
||||
|
||||
if (hBitmap)
|
||||
{
|
||||
alpha = create_alpha_bitmap( hBitmap );
|
||||
if (alpha)
|
||||
{
|
||||
extra->image.hbitmap = alpha;
|
||||
extra->image_has_alpha = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
|
||||
{
|
||||
BITMAP bm;
|
||||
GetObjectW(hBitmap, sizeof(bm), &bm);
|
||||
|
||||
/* Windows currently doesn't implement SS_RIGHTJUST */
|
||||
/*
|
||||
if ((style & SS_RIGHTJUST) != 0)
|
||||
|
@ -386,7 +446,12 @@ static LRESULT CALLBACK STATIC_WindowProc( HWND hwnd, UINT uMsg, WPARAM wParam,
|
|||
if (style == SS_ICON)
|
||||
{
|
||||
struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
|
||||
heap_free( extra );
|
||||
if (extra)
|
||||
{
|
||||
if (extra->image_has_alpha)
|
||||
DeleteObject( extra->image.hbitmap );
|
||||
heap_free( extra );
|
||||
}
|
||||
/*
|
||||
* FIXME
|
||||
* DestroyIcon32( STATIC_SetIcon( wndPtr, 0 ) );
|
||||
|
@ -765,6 +830,8 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
|
|||
BITMAP bm;
|
||||
RECT rcClient;
|
||||
LOGBRUSH brush;
|
||||
BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA };
|
||||
struct static_extra_info *extra = get_extra_ptr( hwnd, FALSE );
|
||||
|
||||
GetObjectW(hBitmap, sizeof(bm), &bm);
|
||||
oldbitmap = SelectObject(hMemDC, hBitmap);
|
||||
|
@ -785,7 +852,13 @@ static void STATIC_PaintBitmapfn(HWND hwnd, HDC hdc, DWORD style )
|
|||
rcClient.right = rcClient.left + bm.bmWidth;
|
||||
rcClient.bottom = rcClient.top + bm.bmHeight;
|
||||
}
|
||||
StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
|
||||
|
||||
if (extra->image_has_alpha)
|
||||
GdiAlphaBlend(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
|
||||
rcClient.bottom - rcClient.top, hMemDC,
|
||||
0, 0, bm.bmWidth, bm.bmHeight, blend);
|
||||
else
|
||||
StretchBlt(hdc, rcClient.left, rcClient.top, rcClient.right - rcClient.left,
|
||||
rcClient.bottom - rcClient.top, hMemDC,
|
||||
0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY);
|
||||
SelectObject(hMemDC, oldbitmap);
|
||||
|
|
|
@ -147,18 +147,15 @@ static void test_image(HBITMAP image, BOOL is_dib, BOOL is_premult)
|
|||
ok(bm.bmBitsPixel == 32, "got %d\n", bm.bmBitsPixel);
|
||||
if (is_dib)
|
||||
{
|
||||
todo_wine
|
||||
ok(bm.bmBits != NULL, "bmBits is NULL\n");
|
||||
if (bm.bmBits)
|
||||
{
|
||||
memcpy(bits, bm.bmBits, 4);
|
||||
if (is_premult)
|
||||
todo_wine
|
||||
ok(bits[0] == 0x05 && bits[1] == 0x09 && bits[2] == 0x0e && bits[3] == 0x44,
|
||||
"bits: %02x %02x %02x %02x\n", bits[0], bits[1], bits[2], bits[3]);
|
||||
else
|
||||
ok(bits[0] == 0x11 && bits[1] == 0x22 && bits[2] == 0x33 && bits[3] == 0x44,
|
||||
"bits: %02x %02x %02x %02x\n", bits[0], bits[1], bits[2], bits[3]);
|
||||
}
|
||||
}
|
||||
else
|
||||
ok(bm.bmBits == NULL, "bmBits is not NULL\n");
|
||||
|
@ -206,13 +203,11 @@ static void test_set_image(void)
|
|||
|
||||
bmp1 = (HBITMAP)SendMessageW(hwnd, STM_GETIMAGE, IMAGE_BITMAP, 0);
|
||||
ok(bmp1 != NULL, "got NULL\n");
|
||||
todo_wine
|
||||
ok(bmp1 != image, "bmp == image\n");
|
||||
test_image(bmp1, TRUE, TRUE);
|
||||
|
||||
bmp2 = (HBITMAP)SendMessageW(hwnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)image);
|
||||
ok(bmp2 != NULL, "got NULL\n");
|
||||
todo_wine
|
||||
ok(bmp2 != image, "bmp == image\n");
|
||||
ok(bmp1 == bmp2, "bmp1 != bmp2\n");
|
||||
test_image(bmp2, TRUE, TRUE);
|
||||
|
|
Loading…
Reference in New Issue