[PATCH 2/5] gdi32: Implement EMFDRV_AlphaBlend().
Zhiyi Zhang
zzhang at codeweavers.com
Wed Apr 14 02:27:57 CDT 2021
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;
+
+ bpp = bitmap.bmPlanes * bitmap.bmBitsPixel;
+ bits_size = get_dib_stride(bitmap.bmWidth, bpp) * bitmap.bmHeight;
+ 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);
+ size = emr_size + bmi_size + bits_size;
+
+ emr = HeapAlloc(GetProcessHeap(), 0, size);
+ if (!emr)
+ return FALSE;
+
+ 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;
+
+ bmih = (BITMAPINFOHEADER *)((BYTE *)emr + emr->offBmiSrc);
+ bmih->biSize = sizeof(BITMAPINFOHEADER);
+ bmih->biWidth = bitmap.bmWidth;
+ bmih->biHeight = bitmap.bmHeight;
+ bmih->biPlanes = bitmap.bmPlanes;
+ bmih->biBitCount = bpp;
+ bmih->biCompression = (bpp == 16 || bpp == 32) ? BI_BITFIELDS : BI_RGB;
+ bmih->biSizeImage = bits_size;
+ bmih->biYPelsPerMeter = 0;
+ bmih->biXPelsPerMeter = 0;
+ bmih->biClrUsed = bpp <= 8 ? 1 << bpp : 0;
+ bmih->biClrImportant = 0;
+
+ if (GetDIBits(dev_src->hdc, hbitmap, 0, (UINT)bmih->biHeight, (BYTE *)emr + emr->offBitsSrc,
+ (BITMAPINFO *)bmih, DIB_RGB_COLORS))
+ {
+ ret = EMFDRV_WriteRecord(dev_dst, (EMR *)emr);
+ if (ret)
+ EMFDRV_UpdateBBox(dev_dst, &emr->rclBounds);
+ }
+ else
+ {
+ ret = FALSE;
+ }
+
+ HeapFree(GetProcessHeap(), 0, emr);
+ 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);
--
2.27.0
More information about the wine-devel
mailing list