Fix a bug that Tally produces a blank print preview when images have to be scaled.
Signed-off-by: Zhiyi Zhang zzhang@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);