[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