Dmitry Timoshkov : comctl32: Create an internal copy for 32-bpp bitmaps with an alpha channel for Static control.
Alexandre Julliard
julliard at winehq.org
Tue Feb 11 15:44:54 CST 2020
Module: wine
Branch: master
Commit: e2f179d84faa00efe6e34952eef48a6a5652ec92
URL: https://source.winehq.org/git/wine.git/?a=commit;h=e2f179d84faa00efe6e34952eef48a6a5652ec92
Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date: Mon Feb 10 16:31:41 2020 +0800
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 at baikal.ru>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/comctl32/static.c | 79 ++++++++++++++++++++++++++++++++++++++++++--
dlls/comctl32/tests/static.c | 7 +---
2 files changed, 77 insertions(+), 9 deletions(-)
diff --git a/dlls/comctl32/static.c b/dlls/comctl32/static.c
index d08710c06f..b3254e5761 100644
--- a/dlls/comctl32/static.c
+++ b/dlls/comctl32/static.c
@@ -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);
diff --git a/dlls/comctl32/tests/static.c b/dlls/comctl32/tests/static.c
index 0e44c4ed7a..0b990d6b39 100644
--- a/dlls/comctl32/tests/static.c
+++ b/dlls/comctl32/tests/static.c
@@ -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);
More information about the wine-cvs
mailing list