[PATCH 2/3] gdi32: PlayEnhMetaFileRecord should be called with the same HDC as EnumEnhMetaFile
Andrew Eikum
aeikum at codeweavers.com
Thu Aug 24 11:26:55 CDT 2017
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
---
dlls/gdi32/enhmetafile.c | 34 ++++++++++++++++--
dlls/gdi32/tests/metafile.c | 88 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c
index cffac375f9..5153e3932d 100644
--- a/dlls/gdi32/enhmetafile.c
+++ b/dlls/gdi32/enhmetafile.c
@@ -513,6 +513,7 @@ typedef struct EMF_dc_state
typedef struct enum_emh_data
{
+ HDC orig_hdc;
XFORM init_transform;
EMF_dc_state state;
INT save_level;
@@ -758,7 +759,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
TRACE("hdc = %p, handletable = %p, record = %p, numHandles = %d\n",
hdc, handletable, mr, handles);
- if (!mr) return FALSE;
+ if (!mr || !hdc) return FALSE;
type = mr->iType;
@@ -780,6 +781,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETMAPMODE *pSetMapMode = (const EMRSETMAPMODE *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
if (info->state.mode == pSetMapMode->iMode &&
(info->state.mode == MM_ISOTROPIC || info->state.mode == MM_ANISOTROPIC))
break;
@@ -882,6 +886,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETWINDOWORGEX *pSetWindowOrgEx = (const EMRSETWINDOWORGEX *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
info->state.wndOrgX = pSetWindowOrgEx->ptlOrigin.x;
info->state.wndOrgY = pSetWindowOrgEx->ptlOrigin.y;
@@ -891,7 +898,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
case EMR_SETWINDOWEXTEX:
{
const EMRSETWINDOWEXTEX *pSetWindowExtEx = (const EMRSETWINDOWEXTEX *)mr;
-
+
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
break;
info->state.wndExtX = pSetWindowExtEx->szlExtent.cx;
@@ -906,6 +916,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETVIEWPORTORGEX *pSetViewportOrgEx = (const EMRSETVIEWPORTORGEX *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
info->state.vportOrgX = pSetViewportOrgEx->ptlOrigin.x;
info->state.vportOrgY = pSetViewportOrgEx->ptlOrigin.y;
TRACE("SetViewportOrgEx: %d,%d\n", info->state.vportOrgX, info->state.vportOrgY);
@@ -915,6 +928,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETVIEWPORTEXTEX *pSetViewportExtEx = (const EMRSETVIEWPORTEXTEX *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
break;
info->state.vportExtX = pSetViewportExtEx->szlExtent.cx;
@@ -1250,6 +1266,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
case EMR_SETWORLDTRANSFORM:
{
const EMRSETWORLDTRANSFORM *lpXfrm = (const EMRSETWORLDTRANSFORM *)mr;
+
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
info->state.world_transform = lpXfrm->xform;
break;
}
@@ -1388,6 +1408,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSCALEVIEWPORTEXTEX *lpScaleViewportExtEx = (const EMRSCALEVIEWPORTEXTEX *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
break;
if (!lpScaleViewportExtEx->xNum || !lpScaleViewportExtEx->xDenom ||
@@ -1413,6 +1436,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSCALEWINDOWEXTEX *lpScaleWindowExtEx = (const EMRSCALEWINDOWEXTEX *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
break;
if (!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->xDenom ||
@@ -1438,6 +1464,9 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRMODIFYWORLDTRANSFORM *lpModifyWorldTrans = (const EMRMODIFYWORLDTRANSFORM *)mr;
+ if (hdc != info->orig_hdc)
+ return FALSE;
+
switch(lpModifyWorldTrans->iMode) {
case MWT_IDENTITY:
info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
@@ -2299,6 +2328,7 @@ BOOL WINAPI EnumEnhMetaFile(
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
+ info->orig_hdc = hdc;
info->state.mode = MM_TEXT;
info->state.wndOrgX = 0;
info->state.wndOrgY = 0;
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index eeec79c800..dbef7fc61a 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -3912,6 +3912,93 @@ static void test_emf_GradientFill(void)
DeleteEnhMetaFile( hemf );
}
+static void set_rotation_xform(XFORM *out, float rad, int dx, int dy)
+{
+ out->eM11 = cosf(rad);
+ out->eM12 = -1.f * sinf(rad);
+ out->eM21 = sinf(rad);
+ out->eM22 = cosf(rad);
+ out->eDx = dx;
+ out->eDy = dy;
+}
+
+static INT CALLBACK enum_emf_PlayEnhMetaFileRecord(HDC hdc, HANDLETABLE *ht,
+ const ENHMETARECORD *emr, INT nobj, LPARAM param)
+{
+ BOOL ret;
+ HDC local_hdc = (HDC)param;
+
+ ret = PlayEnhMetaFileRecord(NULL, ht, emr, nobj);
+ ok(ret == FALSE, "PlayEnhMetaFileRecord should have failed\n");
+
+ ret = PlayEnhMetaFileRecord(local_hdc, ht, emr, nobj);
+ switch(emr->iType)
+ {
+ /* playing back some EMR types fails, while others succeed. docs say this
+ * is all invalid. */
+ case EMR_SETWORLDTRANSFORM:
+ case EMR_MODIFYWORLDTRANSFORM:
+ ok(ret == FALSE, "PlayEnhMetaFileRecord should have failed\n");
+ break;
+ default:
+ ok(ret == TRUE, "PlayEnhMetaFileRecord failed\n");
+ break;
+ }
+
+ if(hdc != NULL){
+ ret = PlayEnhMetaFileRecord(hdc, ht, emr, nobj);
+ ok(ret == TRUE, "PlayEnhMetaFileRecord should have failed\n");
+ }
+
+ return 1;
+}
+
+static void test_emf_PlayEnhMetaFileRecord(void)
+{
+ HDC hdcMetafile, hdc, local_hdc;
+ HWND hwnd;
+ HENHMETAFILE hemf;
+ XFORM xform;
+ BOOL ret;
+ RECT rect = { 0, 0, 100, 100 };
+
+ hdcMetafile = CreateEnhMetaFileA(GetDC(0), NULL, NULL, NULL);
+ ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
+
+ ret = SetGraphicsMode(hdcMetafile, GM_ADVANCED);
+ ok(ret == TRUE, "SetGraphicsMode failed\n");
+
+ set_rotation_xform(&xform, M_PI / 4.f, 2, 3);
+ ret = SetWorldTransform(hdcMetafile, &xform); /* EMR_SETWORLDTRANSFORM */
+ ok(ret == TRUE, "SetWorldTransform failed\n");
+
+ ret = LineTo(hdcMetafile, 1, 1);
+ ok(ret == TRUE, "LineTo failed\n");
+
+ hemf = CloseEnhMetaFile(hdcMetafile);
+ ok(hemf != 0, "CloseEnhMetaFile error %d\n", GetLastError());
+
+ hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
+ 0, 0, 200, 200, 0, 0, 0, NULL);
+ ok(hwnd != 0, "CreateWindowExA error %d\n", GetLastError());
+
+ hdc = GetDC(hwnd);
+ ok(hdc != 0, "GetDC failed\n");
+
+ ret = EnumEnhMetaFile(NULL, hemf, enum_emf_PlayEnhMetaFileRecord, hdc, &rect);
+ ok(ret == TRUE, "EnumEnhMetaFile failed: %u\n", GetLastError());
+
+ local_hdc = CreateCompatibleDC(NULL);
+
+ ret = EnumEnhMetaFile(local_hdc, hemf, enum_emf_PlayEnhMetaFileRecord, hdc, &rect);
+ ok(ret == TRUE, "EnumEnhMetaFile failed: %u\n", GetLastError());
+
+ ReleaseDC(hwnd, hdc);
+ DestroyWindow(hwnd);
+
+ DeleteEnhMetaFile(hemf);
+}
+
START_TEST(metafile)
{
init_function_pointers();
@@ -3928,6 +4015,7 @@ START_TEST(metafile)
test_emf_paths();
test_emf_PolyPolyline();
test_emf_GradientFill();
+ test_emf_PlayEnhMetaFileRecord();
/* For win-format metafiles (mfdrv) */
test_mf_SaveDC();
--
2.14.1
More information about the wine-patches
mailing list