mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-11-21 16:46:54 -08:00
153 lines
5.2 KiB
Diff
153 lines
5.2 KiB
Diff
|
From 334262255a66b05a852c90ebc722815b8a0eb7e9 Mon Sep 17 00:00:00 2001
|
||
|
From: Dmitry Timoshkov <dmitry@baikal.ru>
|
||
|
Date: Sat, 4 May 2019 19:46:35 +0800
|
||
|
Subject: [PATCH 2/2] comctl32: Paint 32-bpp bitmaps with an alpha channel
|
||
|
using GdiAlphaBlend.
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
To: wine-devel@winehq.org
|
||
|
|
||
|
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
|
||
|
---
|
||
|
dlls/comctl32/static.c | 83 ++++++++++++++++++++++++++++++++++++++++--
|
||
|
1 file changed, 79 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/dlls/comctl32/static.c b/dlls/comctl32/static.c
|
||
|
index d08710c06f..fe566645d3 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,56 @@ static HICON STATIC_SetIcon( HWND hwnd, HICON hicon, DWORD style )
|
||
|
return prevIcon;
|
||
|
}
|
||
|
|
||
|
+static HBITMAP create_alpha_bitmap( HBITMAP hbitmap )
|
||
|
+{
|
||
|
+ HBITMAP alpha = 0;
|
||
|
+ BITMAPINFO *info = NULL;
|
||
|
+ BITMAP bm;
|
||
|
+ HDC src, dst;
|
||
|
+ void *bits;
|
||
|
+ DWORD i;
|
||
|
+ const unsigned char *ptr;
|
||
|
+ BOOL has_alpha = FALSE;
|
||
|
+
|
||
|
+ if (!GetObjectW( hbitmap, sizeof(bm), &bm )) return 0;
|
||
|
+ if (bm.bmBitsPixel != 32) return 0;
|
||
|
+
|
||
|
+ if (!(src = CreateCompatibleDC( 0 ))) return 0;
|
||
|
+ if (!(dst = CreateCompatibleDC( src ))) goto done;
|
||
|
+ if (!(info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] )))) goto done;
|
||
|
+ 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( dst, info, DIB_RGB_COLORS, &bits, NULL, 0 ))) goto done;
|
||
|
+
|
||
|
+ SelectObject( src, hbitmap );
|
||
|
+ SelectObject( dst, alpha );
|
||
|
+ BitBlt(dst, 0, 0, bm.bmWidth, bm.bmHeight, src, 0, 0, SRCCOPY);
|
||
|
+
|
||
|
+ for (i = 0, ptr = bits; i < bm.bmWidth * bm.bmHeight; i++, ptr += 4)
|
||
|
+ if ((has_alpha = (ptr[3] != 0))) break;
|
||
|
+
|
||
|
+done:
|
||
|
+ DeleteDC( src );
|
||
|
+ DeleteDC( dst );
|
||
|
+ HeapFree( GetProcessHeap(), 0, info );
|
||
|
+
|
||
|
+ if (!has_alpha)
|
||
|
+ {
|
||
|
+ DeleteObject( alpha );
|
||
|
+ alpha = 0;
|
||
|
+ }
|
||
|
+ return alpha;
|
||
|
+}
|
||
|
+
|
||
|
/***********************************************************************
|
||
|
* STATIC_SetBitmap
|
||
|
*
|
||
|
@@ -170,7 +221,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;
|
||
|
@@ -184,7 +235,18 @@ static HBITMAP STATIC_SetBitmap( HWND hwnd, HBITMAP hBitmap, DWORD style )
|
||
|
if (!extra) return 0;
|
||
|
|
||
|
hOldBitmap = extra->image.hbitmap;
|
||
|
- extra->image.hbitmap = hBitmap;
|
||
|
+ alpha = create_alpha_bitmap( hBitmap );
|
||
|
+ if (alpha)
|
||
|
+ {
|
||
|
+ extra->image.hbitmap = alpha;
|
||
|
+ extra->image_has_alpha = TRUE;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ extra->image.hbitmap = hBitmap;
|
||
|
+ extra->image_has_alpha = FALSE;
|
||
|
+ }
|
||
|
+
|
||
|
if (hBitmap && !(style & SS_CENTERIMAGE) && !(style & SS_REALSIZECONTROL))
|
||
|
{
|
||
|
BITMAP bm;
|
||
|
@@ -386,7 +448,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 +832,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 +854,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);
|
||
|
--
|
||
|
2.20.1
|
||
|
|