[PATCH 2/5] gdi32: Implement EMFDRV_AlphaBlend().
Zhiyi Zhang
zzhang at codeweavers.com
Sun Apr 18 08:00:44 CDT 2021
On 4/15/21 3:31 PM, Huw Davies wrote:
> On Wed, Apr 14, 2021 at 03:27:57PM +0800, Zhiyi Zhang wrote:
>> Fix a bug that Tally produces a blank print preview when images have to be scaled.
>>
>> Signed-off-by: Zhiyi Zhang <zzhang at codeweavers.com>
>> ---
>> dlls/gdi32/enhmfdrv/bitblt.c | 85 ++++++++++++++++++++++++++++
>> dlls/gdi32/enhmfdrv/enhmetafiledrv.h | 2 +
>> dlls/gdi32/enhmfdrv/init.c | 2 +-
>> dlls/gdi32/tests/metafile.c | 4 +-
>> 4 files changed, 89 insertions(+), 4 deletions(-)
>>
>> diff --git a/dlls/gdi32/enhmfdrv/bitblt.c b/dlls/gdi32/enhmfdrv/bitblt.c
>> index 1fc5c0b1040..f0be2b52fc0 100644
>> --- a/dlls/gdi32/enhmfdrv/bitblt.c
>> +++ b/dlls/gdi32/enhmfdrv/bitblt.c
>> @@ -27,6 +27,91 @@
>> #include "enhmetafiledrv.h"
>> #include "wine/debug.h"
>>
>> +BOOL CDECL EMFDRV_AlphaBlend( PHYSDEV dev_dst, struct bitblt_coords *dst, PHYSDEV dev_src,
>> + struct bitblt_coords *src, BLENDFUNCTION func )
>> +{
>> + UINT bits_size, bmi_size, emr_size, size, bpp;
>> + BITMAPINFOHEADER *bmih;
>> + EMRALPHABLEND *emr;
>> + HBITMAP hbitmap;
>> + BITMAP bitmap;
>> + BOOL ret;
>> +
>> + /* can't use a metafile DC as source */
>> + if (dev_src->funcs == dev_dst->funcs)
>> + return FALSE;
>> +
>> + hbitmap = GetCurrentObject(dev_src->hdc, OBJ_BITMAP);
>> + if (GetObjectW(hbitmap, sizeof(BITMAP), &bitmap) != sizeof(BITMAP))
>> + return FALSE;
> This would likely be cleaner using the BlendImage entry point
> (likewise I suspect StretchBlt would benefit from using PutImage).
>
> Huw.
Hi Huw,
I am afraid that it's not cleaner in practice. There are a few issues that make it less intuitive if I use the BlendImage entry point.
1. EMR_ALPHABLEND needs source DC to get world transform and background color, so we need to add a src_dev parameter to all BlendImage function calls.
2. EMR_ALPHABLEND records always use BI_BITFIELDS compression when the source image is 16 bit or 32 bit. Something like the following in gdi32/dib.c#line 1367 in GetDIBits()
needs to be added to the EMR_BlendImage entry point. So we can't copy BITMAPINFOHEADER directly using memcpy().
> /* if the src and dst are the same depth, copy the colour info across */
> if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
> {
> switch (src_info->bmiHeader.biBitCount)
> {
> case 16:
> if (src_info->bmiHeader.biCompression == BI_RGB)
> {
> src_info->bmiHeader.biCompression = BI_BITFIELDS;
> memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
> }
> break;
> case 32:
> if (src_info->bmiHeader.biCompression == BI_RGB)
> {
> src_info->bmiHeader.biCompression = BI_BITFIELDS;
> memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
> }
> break;
> }
> copy_color_info( dst_info, src_info, coloruse );
> }
Also need to reset biClrUsed to 0 as gdi32/dib.c#line 1462 in GetDIBits() to pass all the tests.
> if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
> {
> info->bmiHeader.biClrUsed = 0;
> info->bmiHeader.biSizeImage = get_dib_image_size( info );
> }
So it turns out messier than using EMFDRV_AlphaBlend() if we need to add these special handling for bitmaps in different format.
I think it's better to stick with EMFDRV_AlphaBlend().
Thanks,
Zhiyi
More information about the wine-devel
mailing list