From 794dbaa38ca12f039350e9211ab3f6ca2b3ae854 Mon Sep 17 00:00:00 2001 From: Robert Shearman Date: Wed, 13 Apr 2005 10:57:59 +0000 Subject: [PATCH] - Fix scaling when converting MF -> EMF. - Tests for conversions (although not for the above bug). --- dlls/gdi/enhmetafile.c | 65 ++++++++++--------- dlls/gdi/tests/metafile.c | 127 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 159 insertions(+), 33 deletions(-) diff --git a/dlls/gdi/enhmetafile.c b/dlls/gdi/enhmetafile.c index 2912ef1d2e5..16a7966ac32 100644 --- a/dlls/gdi/enhmetafile.c +++ b/dlls/gdi/enhmetafile.c @@ -2244,6 +2244,7 @@ BOOL WINAPI EnumEnhMetaFile( WIDTH(emh->rclFrame) * xSrcPixSize; yscale = (FLOAT) HEIGHT(*lpRect) * 100.0 / HEIGHT(emh->rclFrame) * ySrcPixSize; + TRACE("xscale = %f, yscale = %f\n", xscale, yscale); xform.eM11 = xscale; xform.eM12 = 0; @@ -2527,14 +2528,12 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, ) { static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' }; - HMETAFILE hmf = 0; - HENHMETAFILE ret = 0; - HDC hdc = 0, hdcdisp = 0; - METAFILEPICT mfp; + HMETAFILE hmf = NULL; + HENHMETAFILE ret = NULL; + HDC hdc = NULL, hdcdisp = NULL; RECT rc, *prcFrame = NULL; gdi_mf_comment *mfcomment; UINT mfcomment_size; - INT horzres, vertres; TRACE("(%d, %p, %p, %p)\n", cbBuffer, lpbBuffer, hdcRef, lpmfp); @@ -2542,40 +2541,27 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, if(!hmf) { WARN("SetMetaFileBitsEx failed\n"); - return 0; + return NULL; } if(!hdcRef) hdcRef = hdcdisp = CreateDCW(szDisplayW, NULL, NULL, NULL); - if(!lpmfp) { - lpmfp = &mfp; - mfp.mm = MM_ANISOTROPIC; - mfp.xExt = -1; - mfp.yExt = -1; - } + if (lpmfp) + TRACE("mm = %ld %ldx%ld\n", lpmfp->mm, lpmfp->xExt, lpmfp->yExt); - TRACE("mm = %ld %ldx%ld\n", lpmfp->mm, lpmfp->xExt, lpmfp->yExt); - - if((lpmfp->mm == MM_ISOTROPIC || lpmfp->mm == MM_ANISOTROPIC) && - (lpmfp->xExt > 0) && (lpmfp->yExt > 0)) { + if (lpmfp && (lpmfp->mm == MM_ISOTROPIC || lpmfp->mm == MM_ANISOTROPIC)) + { rc.left = rc.top = 0; - rc.right = lpmfp->xExt; - rc.bottom = lpmfp->yExt; - prcFrame = &rc; + rc.right = lpmfp->xExt; + rc.bottom = lpmfp->yExt; + prcFrame = &rc; } - if(!(hdc = CreateEnhMetaFileW(hdcRef, NULL, prcFrame, NULL))) { + if(!(hdc = CreateEnhMetaFileW(hdcRef, NULL, prcFrame, NULL))) + { ERR("CreateEnhMetaFile fails?\n"); - goto end; - } - - horzres = GetDeviceCaps(hdcRef, HORZRES); - vertres = GetDeviceCaps(hdcRef, VERTRES); - - if(hdcdisp) { - DeleteDC(hdcdisp); - hdcRef = 0; + goto end; } /* @@ -2597,17 +2583,30 @@ HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, HeapFree(GetProcessHeap(), 0, mfcomment); } - if(lpmfp->mm != MM_TEXT) + if(lpmfp && lpmfp->mm != MM_TEXT) SetMapMode(hdc, lpmfp->mm); - /* set the initial viewport:window ratio as 1:1 */ - SetViewportExtEx(hdc, horzres, vertres, NULL); - SetWindowExtEx(hdc, horzres, vertres, NULL); + if (lpmfp && (lpmfp->mm == MM_ISOTROPIC || lpmfp->mm == MM_ANISOTROPIC)) + { + INT horzres, vertres, horzsize, vertsize, xext, yext; + + horzres = GetDeviceCaps(hdcRef, HORZRES); + vertres = GetDeviceCaps(hdcRef, VERTRES); + horzsize = GetDeviceCaps(hdcRef, HORZSIZE); + vertsize = GetDeviceCaps(hdcRef, VERTSIZE); + + /* set the initial viewport:window ratio as 1:1 */ + xext = lpmfp->xExt*horzres/(100*horzsize); + yext = lpmfp->yExt*vertres/(100*vertsize); + SetViewportExtEx(hdc, xext, yext, NULL); + SetWindowExtEx(hdc, xext, yext, NULL); + } PlayMetaFile(hdc, hmf); ret = CloseEnhMetaFile(hdc); end: + if (hdcdisp) DeleteDC(hdcdisp); DeleteMetaFile(hmf); return ret; } diff --git a/dlls/gdi/tests/metafile.c b/dlls/gdi/tests/metafile.c index 4ddb9dcd41e..231b0815d7d 100644 --- a/dlls/gdi/tests/metafile.c +++ b/dlls/gdi/tests/metafile.c @@ -20,6 +20,7 @@ #include #include +#include #include "wine/test.h" #include "winbase.h" @@ -30,6 +31,10 @@ static LOGFONTA orig_lf; static BOOL emr_processed = FALSE; +/* Arbitrarily chosen values for the second co-ordinate of a metafile line */ +#define LINE_X 55.0f +#define LINE_Y 15.0f + static int CALLBACK emf_enum_proc(HDC hdc, HANDLETABLE *handle_table, const ENHMETARECORD *emr, int n_objs, LPARAM param) { @@ -438,6 +443,125 @@ static void test_mf_PatternBrush(void) HeapFree (GetProcessHeap(), 0, orig_lb); } +static INT CALLBACK EmfMmTextEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData) +{ + POINT mapping[2] = { { 0, 0 }, { 1000, 1000 } }; + LPtoDP(hdc, mapping, 2); + trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y); + if (lpEMFR->iType == EMR_LINETO) + { + FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale; + INT xframe = LINE_X * (float)GetDeviceCaps(hdc, HORZSIZE) * 100.0f / (float)GetDeviceCaps(hdc, HORZRES); + INT yframe = LINE_Y * (float)GetDeviceCaps(hdc, VERTSIZE) * 100.0f / (float)GetDeviceCaps(hdc, VERTRES); + INT x0 = 0; + INT y0 = 0; + INT x1; + INT y1; + xSrcPixSize = (FLOAT) GetDeviceCaps(hdc, HORZSIZE) / GetDeviceCaps(hdc, HORZRES); + ySrcPixSize = (FLOAT) GetDeviceCaps(hdc, VERTSIZE) / GetDeviceCaps(hdc, VERTRES); + xscale = (FLOAT) 1000 * 100.0 / + xframe * xSrcPixSize; + yscale = (FLOAT) 1000 * 100.0 / + yframe * ySrcPixSize; + x1 = (INT)floor(xscale * 100.0 + 0.5f); + y1 = (INT)floor(yscale * 100.0 + 0.5f); + ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1, + "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n", + mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y, + x0, y0, x1, y1); + } + PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj); + return TRUE; +} + +static INT CALLBACK EmfMmAnisotropicEnumProc(HDC hdc, HANDLETABLE *lpHTable, const ENHMETARECORD *lpEMFR, INT nObj, LPARAM lpData) +{ + POINT mapping[2] = { { 0, 0 }, { 1000, 1000 } }; + LPtoDP(hdc, mapping, 2); + trace("Meta record: iType = %ld, (%ld,%ld)-(%ld,%ld)\n", lpEMFR->iType, mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y); + if (lpEMFR->iType == EMR_LINETO) + { + INT x0 = MulDiv(0, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES)); + INT y0 = MulDiv(0, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES)); + INT x1 = MulDiv(1000, GetDeviceCaps(hdc, HORZSIZE) * 100, GetDeviceCaps(hdc, HORZRES)); + INT y1 = MulDiv(1000, GetDeviceCaps(hdc, VERTSIZE) * 100, GetDeviceCaps(hdc, VERTRES)); + ok(mapping[0].x == x0 && mapping[0].y == y0 && mapping[1].x == x1 && mapping[1].y == y1, + "(%ld,%ld)->(%ld,%ld), expected (%d,%d)->(%d,%d)\n", + mapping[0].x, mapping[0].y, mapping[1].x, mapping[1].y, + x0, y0, x1, y1); + } + PlayEnhMetaFileRecord(hdc, lpHTable, lpEMFR, nObj); + return TRUE; +} + +static HENHMETAFILE create_converted_emf(const METAFILEPICT *mfp) +{ + HDC hdcMf; + HMETAFILE hmf; + BOOL ret; + UINT size; + LPBYTE pBits; + + hdcMf = CreateMetaFile(NULL); + ok(hdcMf != NULL, "CreateMetaFile failed with error %ld\n", GetLastError()); + ret = LineTo(hdcMf, (INT)LINE_X, (INT)LINE_Y); + ok(ret, "LineTo failed with error %ld\n", GetLastError()); + hmf = CloseMetaFile(hdcMf); + ok(hmf != NULL, "CloseMetaFile failed with error %ld\n", GetLastError()); + size = GetMetaFileBitsEx(hmf, 0, NULL); + ok(size, "GetMetaFileBitsEx failed with error %ld\n", GetLastError()); + pBits = HeapAlloc(GetProcessHeap(), 0, size); + GetMetaFileBitsEx(hmf, size, pBits); + DeleteMetaFile(hmf); + return SetWinMetaFileBits(size, pBits, NULL, mfp); +} + +static void test_mf_conversions() +{ + trace("Testing MF->EMF conversion (MM_ANISOTROPIC)\n"); + { + HDC hdcOffscreen = CreateCompatibleDC(NULL); + HENHMETAFILE hemf; + METAFILEPICT mfp; + RECT rect = { 0, 0, 100, 100 }; + mfp.mm = MM_ANISOTROPIC; + mfp.xExt = 100; + mfp.yExt = 100; + mfp.hMF = NULL; + hemf = create_converted_emf(&mfp); + EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmAnisotropicEnumProc, NULL, &rect); + DeleteEnhMetaFile(hemf); + DeleteDC(hdcOffscreen); + } + + trace("Testing MF->EMF conversion (MM_TEXT)\n"); + { + HDC hdcOffscreen = CreateCompatibleDC(NULL); + HENHMETAFILE hemf; + METAFILEPICT mfp; + RECT rect = { 0, 0, 100, 100 }; + mfp.mm = MM_TEXT; + mfp.xExt = 0; + mfp.yExt = 0; + mfp.hMF = NULL; + hemf = create_converted_emf(&mfp); + EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmTextEnumProc, NULL, &rect); + DeleteEnhMetaFile(hemf); + DeleteDC(hdcOffscreen); + } + + trace("Testing MF->EMF conversion (NULL mfp)\n"); + { + HDC hdcOffscreen = CreateCompatibleDC(NULL); + HENHMETAFILE hemf; + RECT rect = { 0, 0, 100, 100 }; + hemf = create_converted_emf(NULL); + EnumEnhMetaFile(hdcOffscreen, hemf, EmfMmTextEnumProc, NULL, &rect); + DeleteEnhMetaFile(hemf); + DeleteDC(hdcOffscreen); + } +} + START_TEST(metafile) { /* For enhanced metafiles (enhmfdrv) */ @@ -447,4 +571,7 @@ START_TEST(metafile) test_mf_Blank(); test_mf_Graphics(); test_mf_PatternBrush(); + + /* For metafile conversions */ + test_mf_conversions(); }