Zhiyi Zhang : gdi32: Implement EMFDRV_AlphaBlend().

Alexandre Julliard julliard at winehq.org
Tue Apr 20 16:27:44 CDT 2021


Module: wine
Branch: master
Commit: 8ae18d055a8af864087f08f127d7d93ad6eafbae
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=8ae18d055a8af864087f08f127d7d93ad6eafbae

Author: Zhiyi Zhang <zzhang at codeweavers.com>
Date:   Tue Apr 20 09:09:19 2021 +0100

gdi32: Implement EMFDRV_AlphaBlend().

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>
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/gdi32/enhmfdrv/bitblt.c         | 88 ++++++++++++++++++++++++++++++++++++
 dlls/gdi32/enhmfdrv/enhmetafiledrv.h |  2 +
 dlls/gdi32/enhmfdrv/init.c           |  2 +-
 dlls/gdi32/tests/metafile.c          |  4 +-
 4 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/dlls/gdi32/enhmfdrv/bitblt.c b/dlls/gdi32/enhmfdrv/bitblt.c
index 1fc5c0b1040..597a6110abd 100644
--- a/dlls/gdi32/enhmfdrv/bitblt.c
+++ b/dlls/gdi32/enhmfdrv/bitblt.c
@@ -27,6 +27,94 @@
 #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 )
+{
+    unsigned char src_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])];
+    BITMAPINFO *src_info = (BITMAPINFO *)src_buffer;
+    UINT bits_size, bmi_size, emr_size, size, bpp;
+    struct gdi_image_bits bits;
+    EMRALPHABLEND *emr;
+    BITMAPINFO *bmi;
+    DC *dc_src;
+    DWORD err;
+    BOOL ret = FALSE;
+
+    dc_src = get_physdev_dc(dev_src);
+    dev_src = GET_DC_PHYSDEV(dc_src, pGetImage);
+    err = dev_src->funcs->pGetImage(dev_src, src_info, &bits, src);
+    if (err)
+    {
+        SetLastError(err);
+        return FALSE;
+    }
+
+    bpp = src_info->bmiHeader.biBitCount;
+    if (bpp <= 8)
+        bmi_size = sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD);
+    else if (bpp == 16 || bpp == 32)
+        bmi_size = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD);
+    else
+        bmi_size = sizeof(BITMAPINFOHEADER);
+    emr_size = sizeof(EMRALPHABLEND);
+    bits_size = src_info->bmiHeader.biSizeImage;
+    size = emr_size + bmi_size + bits_size;
+
+    emr = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!emr) goto err;
+
+    emr->emr.iType = EMR_ALPHABLEND;
+    emr->emr.nSize = size;
+    emr->rclBounds.left = dst->log_x;
+    emr->rclBounds.top = dst->log_y;
+    emr->rclBounds.right = dst->log_x + dst->log_width - 1;
+    emr->rclBounds.bottom = dst->log_y + dst->log_height - 1;
+    emr->xDest = dst->log_x;
+    emr->yDest = dst->log_y;
+    emr->cxDest = dst->log_width;
+    emr->cyDest = dst->log_height;
+    emr->xSrc = src->log_x;
+    emr->ySrc = src->log_y;
+    emr->cxSrc = src->log_width;
+    emr->cySrc = src->log_height;
+    emr->dwRop = *(DWORD *)&func;
+    GetTransform(dev_src->hdc, 0x204, &emr->xformSrc);
+    emr->crBkColorSrc = GetBkColor(dev_src->hdc);
+    emr->iUsageSrc = DIB_RGB_COLORS;
+    emr->offBmiSrc = emr_size;
+    emr->cbBmiSrc = bmi_size;
+    emr->offBitsSrc = emr_size + bmi_size;
+    emr->cbBitsSrc = bits_size;
+
+    bmi = (BITMAPINFO *)((BYTE *)emr + emr->offBmiSrc);
+    memcpy(bmi, src_info, bmi_size);
+    memcpy((BYTE *)emr + emr->offBitsSrc, bits.ptr, bits_size);
+
+    bmi->bmiHeader.biClrUsed = 0;
+    if (bmi->bmiHeader.biCompression == BI_RGB && bmi->bmiHeader.biBitCount == 16)
+    {
+        bmi->bmiHeader.biCompression = BI_BITFIELDS;
+        ((DWORD *)bmi->bmiColors)[0] = 0xf800;
+        ((DWORD *)bmi->bmiColors)[1] = 0x07e0;
+        ((DWORD *)bmi->bmiColors)[2] = 0x001f;
+    }
+    else if (bmi->bmiHeader.biCompression == BI_RGB && bmi->bmiHeader.biBitCount == 32)
+    {
+        bmi->bmiHeader.biCompression = BI_BITFIELDS;
+        ((DWORD *)bmi->bmiColors)[0] = 0xff0000;
+        ((DWORD *)bmi->bmiColors)[1] = 0x00ff00;
+        ((DWORD *)bmi->bmiColors)[2] = 0x0000ff;
+    }
+
+    ret = EMFDRV_WriteRecord(dev_dst, (EMR *)emr);
+    if (ret) EMFDRV_UpdateBBox(dev_dst, &emr->rclBounds);
+
+err:
+    HeapFree(GetProcessHeap(), 0, emr);
+    if (bits.free) bits.free(&bits);
+    return ret;
+}
+
 BOOL CDECL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop )
 {
     EMRBITBLT emr;
diff --git a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
index ec83d29c735..253f96cd8ec 100644
--- a/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
+++ b/dlls/gdi32/enhmfdrv/enhmetafiledrv.h
@@ -58,6 +58,8 @@ extern DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) DECLSPEC_H
 
 /* Metafile driver functions */
 extern BOOL     CDECL EMFDRV_AbortPath( PHYSDEV dev ) DECLSPEC_HIDDEN;
+extern BOOL     CDECL EMFDRV_AlphaBlend( PHYSDEV dev_dst, struct bitblt_coords *dst,
+                                         PHYSDEV dev_src, struct bitblt_coords *src, BLENDFUNCTION func ) DECLSPEC_HIDDEN;
 extern BOOL     CDECL EMFDRV_AngleArc( PHYSDEV dev, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) DECLSPEC_HIDDEN;
 extern BOOL     CDECL EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right,
                                   INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN;
diff --git a/dlls/gdi32/enhmfdrv/init.c b/dlls/gdi32/enhmfdrv/init.c
index cf9fb923633..07416db265e 100644
--- a/dlls/gdi32/enhmfdrv/init.c
+++ b/dlls/gdi32/enhmfdrv/init.c
@@ -38,7 +38,7 @@ static const struct gdi_dc_funcs emfdrv_driver =
 {
     NULL,                            /* pAbortDoc */
     EMFDRV_AbortPath,                /* pAbortPath */
-    NULL,                            /* pAlphaBlend */
+    EMFDRV_AlphaBlend,               /* pAlphaBlend */
     EMFDRV_AngleArc,                 /* pAngleArc */
     EMFDRV_Arc,                      /* pArc */
     EMFDRV_ArcTo,                    /* pArcTo */
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index ec9c7894574..9340e20444a 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -5001,15 +5001,13 @@ static void test_emf_AlphaBlend(void)
         ret = BitBlt(hdc_bitmap, 0, 0, bitmap_width, bitmap_height, 0, 0, 0, BLACKNESS);
         ok(ret, "Test %d: BitBlt failed, error %d\n", test_idx, GetLastError());
         ret = GdiAlphaBlend(hdc_emf, 0, 0, bitmap_width, bitmap_height, hdc_bitmap, 0, 0, 400, 400, blend);
-        todo_wine
         ok(ret, "Test %d: GdiAlphaBlend failed, error %d\n", test_idx, GetLastError());
 
         hemf = CloseEnhMetaFile(hdc_emf);
         ok(!!hemf, "Test %d: CloseEnhMetaFile failed, %d\n", test_idx, GetLastError());
 
         sprintf(comment, "test_emf_AlphaBlend() test %d", test_idx);
-        if (ret)
-            ret = compare_emf_bits(hemf, tests[test_idx].bits, tests[test_idx].bits_count, comment, FALSE);
+        ret = compare_emf_bits(hemf, tests[test_idx].bits, tests[test_idx].bits_count, comment, FALSE);
         if (ret)
         {
             dump_emf_bits(hemf, comment);




More information about the wine-cvs mailing list