gdi32: Save/restore internal EMF playing state on EMR_SAVEDC/EMR_RESTOREDC, add a test for this
Dmitry Timoshkov
dmitry at codeweavers.com
Mon Apr 28 02:02:31 CDT 2008
Hello,
this patch makes another part of an EMF sent to me by a customer look similar
to the one under my XP box.
This implementation is based on the SaveDC/RestoreDC one.
Changelog:
gdi32: Save/restore internal EMF playing state on EMR_SAVEDC/EMR_RESTOREDC,
add a test for this.
---
dlls/gdi32/enhmetafile.c | 244 ++++++++++++++++++++++++++-----------------
dlls/gdi32/tests/metafile.c | 210 ++++++++++++++++++++++++++++++++++++-
2 files changed, 355 insertions(+), 99 deletions(-)
diff --git a/dlls/gdi32/enhmetafile.c b/dlls/gdi32/enhmetafile.c
index a3e7aa5..7c6068d 100644
--- a/dlls/gdi32/enhmetafile.c
+++ b/dlls/gdi32/enhmetafile.c
@@ -491,10 +491,9 @@ UINT WINAPI GetEnhMetaFileBits(
return size;
}
-typedef struct enum_emh_data
+typedef struct EMF_dc_state
{
INT mode;
- XFORM init_transform;
XFORM world_transform;
INT wndOrgX;
INT wndOrgY;
@@ -504,6 +503,15 @@ typedef struct enum_emh_data
INT vportOrgY;
INT vportExtX;
INT vportExtY;
+ struct EMF_dc_state *next;
+} EMF_dc_state;
+
+typedef struct enum_emh_data
+{
+ XFORM init_transform;
+ EMF_dc_state state;
+ INT save_level;
+ EMF_dc_state *saved_state;
} enum_emh_data;
#define ENUM_GET_PRIVATE_DATA(ht) \
@@ -519,16 +527,16 @@ static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info)
XFORM mapping_mode_trans, final_trans;
FLOAT scaleX, scaleY;
- scaleX = (FLOAT)info->vportExtX / (FLOAT)info->wndExtX;
- scaleY = (FLOAT)info->vportExtY / (FLOAT)info->wndExtY;
+ scaleX = (FLOAT)info->state.vportExtX / (FLOAT)info->state.wndExtX;
+ scaleY = (FLOAT)info->state.vportExtY / (FLOAT)info->state.wndExtY;
mapping_mode_trans.eM11 = scaleX;
mapping_mode_trans.eM12 = 0.0;
mapping_mode_trans.eM21 = 0.0;
mapping_mode_trans.eM22 = scaleY;
- mapping_mode_trans.eDx = (FLOAT)info->vportOrgX - scaleX * (FLOAT)info->wndOrgX;
- mapping_mode_trans.eDy = (FLOAT)info->vportOrgY - scaleY * (FLOAT)info->wndOrgY;
+ mapping_mode_trans.eDx = (FLOAT)info->state.vportOrgX - scaleX * (FLOAT)info->state.wndOrgX;
+ mapping_mode_trans.eDy = (FLOAT)info->state.vportOrgY - scaleY * (FLOAT)info->state.wndOrgY;
- CombineTransform(&final_trans, &info->world_transform, &mapping_mode_trans);
+ CombineTransform(&final_trans, &info->state.world_transform, &mapping_mode_trans);
CombineTransform(&final_trans, &final_trans, &info->init_transform);
if (!SetWorldTransform(hdc, &final_trans))
@@ -537,6 +545,40 @@ static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info)
}
}
+static void EMF_RestoreDC( enum_emh_data *info, INT level )
+{
+ if (abs(level) > info->save_level || level == 0) return;
+
+ if (level < 0) level = info->save_level + level + 1;
+
+ while (info->save_level >= level)
+ {
+ EMF_dc_state *state = info->saved_state;
+ info->saved_state = state->next;
+ state->next = NULL;
+ if (--info->save_level < level)
+ {
+ EMF_dc_state *next = info->state.next;
+ info->state = *state;
+ info->state.next = next;
+ }
+ HeapFree( GetProcessHeap(), 0, state );
+ }
+}
+
+static void EMF_SaveDC( enum_emh_data *info )
+{
+ EMF_dc_state *state = HeapAlloc( GetProcessHeap(), 0, sizeof(*state));
+ if (state)
+ {
+ *state = info->state;
+ state->next = info->saved_state;
+ info->saved_state = state;
+ info->save_level++;
+ TRACE("save_level %d\n", info->save_level);
+ }
+}
+
static void EMF_SetMapMode(HDC hdc, enum_emh_data *info)
{
INT horzSize = GetDeviceCaps( hdc, HORZSIZE );
@@ -544,46 +586,46 @@ static void EMF_SetMapMode(HDC hdc, enum_emh_data *info)
INT horzRes = GetDeviceCaps( hdc, HORZRES );
INT vertRes = GetDeviceCaps( hdc, VERTRES );
- TRACE("%d\n",info->mode);
+ TRACE("%d\n", info->state.mode);
- switch(info->mode)
+ switch(info->state.mode)
{
case MM_TEXT:
- info->wndExtX = 1;
- info->wndExtY = 1;
- info->vportExtX = 1;
- info->vportExtY = 1;
+ info->state.wndExtX = 1;
+ info->state.wndExtY = 1;
+ info->state.vportExtX = 1;
+ info->state.vportExtY = 1;
break;
case MM_LOMETRIC:
case MM_ISOTROPIC:
- info->wndExtX = horzSize * 10;
- info->wndExtY = vertSize * 10;
- info->vportExtX = horzRes;
- info->vportExtY = -vertRes;
+ info->state.wndExtX = horzSize * 10;
+ info->state.wndExtY = vertSize * 10;
+ info->state.vportExtX = horzRes;
+ info->state.vportExtY = -vertRes;
break;
case MM_HIMETRIC:
- info->wndExtX = horzSize * 100;
- info->wndExtY = vertSize * 100;
- info->vportExtX = horzRes;
- info->vportExtY = -vertRes;
+ info->state.wndExtX = horzSize * 100;
+ info->state.wndExtY = vertSize * 100;
+ info->state.vportExtX = horzRes;
+ info->state.vportExtY = -vertRes;
break;
case MM_LOENGLISH:
- info->wndExtX = MulDiv(1000, horzSize, 254);
- info->wndExtY = MulDiv(1000, vertSize, 254);
- info->vportExtX = horzRes;
- info->vportExtY = -vertRes;
+ info->state.wndExtX = MulDiv(1000, horzSize, 254);
+ info->state.wndExtY = MulDiv(1000, vertSize, 254);
+ info->state.vportExtX = horzRes;
+ info->state.vportExtY = -vertRes;
break;
case MM_HIENGLISH:
- info->wndExtX = MulDiv(10000, horzSize, 254);
- info->wndExtY = MulDiv(10000, vertSize, 254);
- info->vportExtX = horzRes;
- info->vportExtY = -vertRes;
+ info->state.wndExtX = MulDiv(10000, horzSize, 254);
+ info->state.wndExtY = MulDiv(10000, vertSize, 254);
+ info->state.vportExtX = horzRes;
+ info->state.vportExtY = -vertRes;
break;
case MM_TWIPS:
- info->wndExtX = MulDiv(14400, horzSize, 254);
- info->wndExtY = MulDiv(14400, vertSize, 254);
- info->vportExtX = horzRes;
- info->vportExtY = -vertRes;
+ info->state.wndExtX = MulDiv(14400, horzSize, 254);
+ info->state.wndExtY = MulDiv(14400, vertSize, 254);
+ info->state.vportExtX = horzRes;
+ info->state.vportExtY = -vertRes;
break;
case MM_ANISOTROPIC:
break;
@@ -600,22 +642,22 @@ static void EMF_SetMapMode(HDC hdc, enum_emh_data *info)
static void EMF_FixIsotropic(HDC hdc, enum_emh_data *info)
{
- double xdim = fabs((double)info->vportExtX * GetDeviceCaps( hdc, HORZSIZE ) /
- (GetDeviceCaps( hdc, HORZRES ) * info->wndExtX));
- double ydim = fabs((double)info->vportExtY * GetDeviceCaps( hdc, VERTSIZE ) /
- (GetDeviceCaps( hdc, VERTRES ) * info->wndExtY));
+ double xdim = fabs((double)info->state.vportExtX * GetDeviceCaps( hdc, HORZSIZE ) /
+ (GetDeviceCaps( hdc, HORZRES ) * info->state.wndExtX));
+ double ydim = fabs((double)info->state.vportExtY * GetDeviceCaps( hdc, VERTSIZE ) /
+ (GetDeviceCaps( hdc, VERTRES ) * info->state.wndExtY));
if (xdim > ydim)
{
- INT mincx = (info->vportExtX >= 0) ? 1 : -1;
- info->vportExtX = floor(info->vportExtX * ydim / xdim + 0.5);
- if (!info->vportExtX) info->vportExtX = mincx;
+ INT mincx = (info->state.vportExtX >= 0) ? 1 : -1;
+ info->state.vportExtX = floor(info->state.vportExtX * ydim / xdim + 0.5);
+ if (!info->state.vportExtX) info->state.vportExtX = mincx;
}
else
{
- INT mincy = (info->vportExtY >= 0) ? 1 : -1;
- info->vportExtY = floor(info->vportExtY * xdim / ydim + 0.5);
- if (!info->vportExtY) info->vportExtY = mincy;
+ INT mincy = (info->state.vportExtY >= 0) ? 1 : -1;
+ info->state.vportExtY = floor(info->state.vportExtY * xdim / ydim + 0.5);
+ if (!info->state.vportExtY) info->state.vportExtY = mincy;
}
}
@@ -740,9 +782,10 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETMAPMODE *pSetMapMode = (const EMRSETMAPMODE *)mr;
- if(info->mode == pSetMapMode->iMode && (info->mode == MM_ISOTROPIC || info->mode == MM_ANISOTROPIC))
+ if (info->state.mode == pSetMapMode->iMode &&
+ (info->state.mode == MM_ISOTROPIC || info->state.mode == MM_ANISOTROPIC))
break;
- info->mode = pSetMapMode->iMode;
+ info->state.mode = pSetMapMode->iMode;
EMF_SetMapMode(hdc, info);
break;
}
@@ -790,14 +833,16 @@ BOOL WINAPI PlayEnhMetaFileRecord(
}
case EMR_SAVEDC:
{
- SaveDC(hdc);
+ if (SaveDC( hdc ))
+ EMF_SaveDC( info );
break;
}
case EMR_RESTOREDC:
{
const EMRRESTOREDC *pRestoreDC = (const EMRRESTOREDC *)mr;
TRACE("EMR_RESTORE: %d\n", pRestoreDC->iRelative);
- RestoreDC(hdc, pRestoreDC->iRelative);
+ if (RestoreDC( hdc, pRestoreDC->iRelative ))
+ EMF_RestoreDC( info, pRestoreDC->iRelative );
break;
}
case EMR_INTERSECTCLIPRECT:
@@ -839,48 +884,46 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSETWINDOWORGEX *pSetWindowOrgEx = (const EMRSETWINDOWORGEX *)mr;
- info->wndOrgX = pSetWindowOrgEx->ptlOrigin.x;
- info->wndOrgY = pSetWindowOrgEx->ptlOrigin.y;
+ info->state.wndOrgX = pSetWindowOrgEx->ptlOrigin.x;
+ info->state.wndOrgY = pSetWindowOrgEx->ptlOrigin.y;
- TRACE("SetWindowOrgEx: %d,%d\n",info->wndOrgX,info->wndOrgY);
+ TRACE("SetWindowOrgEx: %d,%d\n", info->state.wndOrgX, info->state.wndOrgY);
break;
}
case EMR_SETWINDOWEXTEX:
{
const EMRSETWINDOWEXTEX *pSetWindowExtEx = (const EMRSETWINDOWEXTEX *)mr;
- if(info->mode != MM_ISOTROPIC && info->mode != MM_ANISOTROPIC)
+ if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
break;
- info->wndExtX = pSetWindowExtEx->szlExtent.cx;
- info->wndExtY = pSetWindowExtEx->szlExtent.cy;
- if (info->mode == MM_ISOTROPIC)
+ info->state.wndExtX = pSetWindowExtEx->szlExtent.cx;
+ info->state.wndExtY = pSetWindowExtEx->szlExtent.cy;
+ if (info->state.mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
- TRACE("SetWindowExtEx: %d,%d\n",info->wndExtX,info->wndExtY);
+ TRACE("SetWindowExtEx: %d,%d\n",info->state.wndExtX, info->state.wndExtY);
break;
}
case EMR_SETVIEWPORTORGEX:
{
const EMRSETVIEWPORTORGEX *pSetViewportOrgEx = (const EMRSETVIEWPORTORGEX *)mr;
- enum_emh_data *info = ENUM_GET_PRIVATE_DATA(handletable);
- info->vportOrgX = pSetViewportOrgEx->ptlOrigin.x;
- info->vportOrgY = pSetViewportOrgEx->ptlOrigin.y;
- TRACE("SetViewportOrgEx: %d,%d\n",info->vportOrgX,info->vportOrgY);
+ info->state.vportOrgX = pSetViewportOrgEx->ptlOrigin.x;
+ info->state.vportOrgY = pSetViewportOrgEx->ptlOrigin.y;
+ TRACE("SetViewportOrgEx: %d,%d\n", info->state.vportOrgX, info->state.vportOrgY);
break;
}
case EMR_SETVIEWPORTEXTEX:
{
const EMRSETVIEWPORTEXTEX *pSetViewportExtEx = (const EMRSETVIEWPORTEXTEX *)mr;
- enum_emh_data *info = ENUM_GET_PRIVATE_DATA(handletable);
- if(info->mode != MM_ISOTROPIC && info->mode != MM_ANISOTROPIC)
+ if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC)
break;
- info->vportExtX = pSetViewportExtEx->szlExtent.cx;
- info->vportExtY = pSetViewportExtEx->szlExtent.cy;
- if (info->mode == MM_ISOTROPIC)
+ info->state.vportExtX = pSetViewportExtEx->szlExtent.cx;
+ info->state.vportExtY = pSetViewportExtEx->szlExtent.cy;
+ if (info->state.mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
- TRACE("SetViewportExtEx: %d,%d\n",info->vportExtX,info->vportExtY);
+ TRACE("SetViewportExtEx: %d,%d\n", info->state.vportExtX, info->state.vportExtY);
break;
}
case EMR_CREATEPEN:
@@ -1193,7 +1236,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
case EMR_SETWORLDTRANSFORM:
{
const EMRSETWORLDTRANSFORM *lpXfrm = (const EMRSETWORLDTRANSFORM *)mr;
- info->world_transform = lpXfrm->xform;
+ info->state.world_transform = lpXfrm->xform;
break;
}
@@ -1331,18 +1374,18 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSCALEVIEWPORTEXTEX *lpScaleViewportExtEx = (const EMRSCALEVIEWPORTEXTEX *)mr;
- if ((info->mode != MM_ISOTROPIC) && (info->mode != MM_ANISOTROPIC))
+ if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
break;
if (!lpScaleViewportExtEx->xNum || !lpScaleViewportExtEx->xDenom ||
!lpScaleViewportExtEx->yNum || !lpScaleViewportExtEx->yDenom)
break;
- info->vportExtX = MulDiv(info->vportExtX, lpScaleViewportExtEx->xNum,
+ info->state.vportExtX = MulDiv(info->state.vportExtX, lpScaleViewportExtEx->xNum,
lpScaleViewportExtEx->xDenom);
- info->vportExtY = MulDiv(info->vportExtY, lpScaleViewportExtEx->yNum,
+ info->state.vportExtY = MulDiv(info->state.vportExtY, lpScaleViewportExtEx->yNum,
lpScaleViewportExtEx->yDenom);
- if (info->vportExtX == 0) info->vportExtX = 1;
- if (info->vportExtY == 0) info->vportExtY = 1;
- if (info->mode == MM_ISOTROPIC)
+ if (info->state.vportExtX == 0) info->state.vportExtX = 1;
+ if (info->state.vportExtY == 0) info->state.vportExtY = 1;
+ if (info->state.mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
TRACE("EMRSCALEVIEWPORTEXTEX %d/%d %d/%d\n",
@@ -1356,18 +1399,18 @@ BOOL WINAPI PlayEnhMetaFileRecord(
{
const EMRSCALEWINDOWEXTEX *lpScaleWindowExtEx = (const EMRSCALEWINDOWEXTEX *)mr;
- if ((info->mode != MM_ISOTROPIC) && (info->mode != MM_ANISOTROPIC))
+ if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC))
break;
if (!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->xDenom ||
!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->yDenom)
break;
- info->wndExtX = MulDiv(info->wndExtX, lpScaleWindowExtEx->xNum,
+ info->state.wndExtX = MulDiv(info->state.wndExtX, lpScaleWindowExtEx->xNum,
lpScaleWindowExtEx->xDenom);
- info->wndExtY = MulDiv(info->wndExtY, lpScaleWindowExtEx->yNum,
+ info->state.wndExtY = MulDiv(info->state.wndExtY, lpScaleWindowExtEx->yNum,
lpScaleWindowExtEx->yDenom);
- if (info->wndExtX == 0) info->wndExtX = 1;
- if (info->wndExtY == 0) info->wndExtY = 1;
- if (info->mode == MM_ISOTROPIC)
+ if (info->state.wndExtX == 0) info->state.wndExtX = 1;
+ if (info->state.wndExtY == 0) info->state.wndExtY = 1;
+ if (info->state.mode == MM_ISOTROPIC)
EMF_FixIsotropic(hdc, info);
TRACE("EMRSCALEWINDOWEXTEX %d/%d %d/%d\n",
@@ -1383,16 +1426,16 @@ BOOL WINAPI PlayEnhMetaFileRecord(
switch(lpModifyWorldTrans->iMode) {
case MWT_IDENTITY:
- info->world_transform.eM11 = info->world_transform.eM22 = 1;
- info->world_transform.eM12 = info->world_transform.eM21 = 0;
- info->world_transform.eDx = info->world_transform.eDy = 0;
+ info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
+ info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0;
+ info->state.world_transform.eDx = info->state.world_transform.eDy = 0;
break;
case MWT_LEFTMULTIPLY:
- CombineTransform(&info->world_transform, &lpModifyWorldTrans->xform,
- &info->world_transform);
+ CombineTransform(&info->state.world_transform, &lpModifyWorldTrans->xform,
+ &info->state.world_transform);
break;
case MWT_RIGHTMULTIPLY:
- CombineTransform(&info->world_transform, &info->world_transform,
+ CombineTransform(&info->state.world_transform, &info->state.world_transform,
&lpModifyWorldTrans->xform);
break;
default:
@@ -2243,17 +2286,20 @@ BOOL WINAPI EnumEnhMetaFile(
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
- info->wndOrgX = 0;
- info->wndOrgY = 0;
- info->wndExtX = 1;
- info->wndExtY = 1;
- info->vportOrgX = 0;
- info->vportOrgY = 0;
- info->vportExtX = 1;
- info->vportExtY = 1;
- info->world_transform.eM11 = info->world_transform.eM22 = 1;
- info->world_transform.eM12 = info->world_transform.eM21 = 0;
- info->world_transform.eDx = info->world_transform.eDy = 0;
+ info->state.wndOrgX = 0;
+ info->state.wndOrgY = 0;
+ info->state.wndExtX = 1;
+ info->state.wndExtY = 1;
+ info->state.vportOrgX = 0;
+ info->state.vportOrgY = 0;
+ info->state.vportExtX = 1;
+ info->state.vportExtY = 1;
+ info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1;
+ info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0;
+ info->state.world_transform.eDx = info->state.world_transform.eDy = 0;
+
+ info->save_level = 0;
+ info->saved_state = NULL;
ht = (HANDLETABLE*) &info[1];
ht->objectHandle[0] = hmf;
@@ -2282,7 +2328,7 @@ BOOL WINAPI EnumEnhMetaFile(
old_stretchblt = SetStretchBltMode(hdc, BLACKONWHITE);
}
- info->mode = MM_TEXT;
+ info->state.mode = MM_TEXT;
if ( IS_WIN9X() )
{
@@ -2386,6 +2432,12 @@ BOOL WINAPI EnumEnhMetaFile(
if( (ht->objectHandle)[i] )
DeleteObject( (ht->objectHandle)[i] );
+ while (info->saved_state)
+ {
+ EMF_dc_state *state = info->saved_state;
+ info->saved_state = info->saved_state->next;
+ HeapFree( GetProcessHeap(), 0, state );
+ }
HeapFree( GetProcessHeap(), 0, info );
return ret;
}
diff --git a/dlls/gdi32/tests/metafile.c b/dlls/gdi32/tests/metafile.c
index 473f7e3..0b50d58 100644
--- a/dlls/gdi32/tests/metafile.c
+++ b/dlls/gdi32/tests/metafile.c
@@ -261,37 +261,174 @@ static void test_ExtTextOut(void)
DestroyWindow(hwnd);
}
+static void check_dc_state(HDC hdc, int restore_no,
+ int wnd_org_x, int wnd_org_y, int wnd_ext_x, int wnd_ext_y,
+ int vp_org_x, int vp_org_y, int vp_ext_x, int vp_ext_y)
+{
+ BOOL ret;
+ XFORM xform;
+ POINT vp_org, win_org;
+ SIZE vp_size, win_size;
+ FLOAT xscale, yscale, edx, edy;
+
+ SetLastError(0xdeadbeef);
+ ret = GetWorldTransform(hdc, &xform);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) goto win9x_here;
+ ok(ret, "GetWorldTransform error %u\n", GetLastError());
+
+ trace("%d: eM11 %f, eM22 %f, eDx %f, eDy %f\n", restore_no, xform.eM11, xform.eM22, xform.eDx, xform.eDy);
+
+ ok(xform.eM12 == 0.0, "%d: expected eM12 0.0, got %f\n", restore_no, xform.eM12);
+ ok(xform.eM21 == 0.0, "%d: expected eM21 0.0, got %f\n", restore_no, xform.eM21);
+
+ xscale = (FLOAT)vp_ext_x / (FLOAT)wnd_ext_x;
+ trace("x scale %f\n", xscale);
+ ok(fabs(xscale - xform.eM11) < 0.01, "%d: vp_ext_x %d, wnd_ext_cx %d, eM11 %f\n",
+ restore_no, vp_ext_x, wnd_ext_x, xform.eM11);
+
+ yscale = (FLOAT)vp_ext_y / (FLOAT)wnd_ext_y;
+ trace("y scale %f\n", yscale);
+ ok(fabs(yscale - xform.eM22) < 0.01, "%d: vp_ext_y %d, wnd_ext_y %d, eM22 %f\n",
+ restore_no, vp_ext_y, wnd_ext_y, xform.eM22);
+
+ edx = (FLOAT)vp_org_x - xform.eM11 * (FLOAT)wnd_org_x;
+ ok(fabs(edx - xform.eDx) < 0.01, "%d: edx %f != eDx %f\n", restore_no, edx, xform.eDx);
+ edy = (FLOAT)vp_org_y - xform.eM22 * (FLOAT)wnd_org_y;
+ ok(fabs(edy - xform.eDy) < 0.01, "%d: edy %f != eDy %f\n", restore_no, edy, xform.eDy);
+
+ return;
+
+win9x_here:
+
+ GetWindowOrgEx(hdc, &win_org);
+ GetViewportOrgEx(hdc, &vp_org);
+ GetWindowExtEx(hdc, &win_size);
+ GetViewportExtEx(hdc, &vp_size);
+
+ ok(wnd_org_x == win_org.x, "%d: wnd_org_x: %d != %d\n", restore_no, wnd_org_x, win_org.x);
+ ok(wnd_org_y == win_org.y, "%d: wnd_org_y: %d != %d\n", restore_no, wnd_org_y, win_org.y);
+
+ ok(vp_org_x == vp_org.x, "%d: vport_org_x: %d != %d\n", restore_no, vp_org_x, vp_org.x);
+ ok(vp_org_y == vp_org.y, "%d: vport_org_y: %d != %d\n", restore_no, vp_org_y, vp_org.y);
+
+ ok(wnd_ext_x == win_size.cx, "%d: wnd_ext_x: %d != %d\n", restore_no, wnd_ext_x, win_size.cx);
+ ok(wnd_ext_y == win_size.cy, "%d: wnd_ext_y: %d != %d\n", restore_no, wnd_ext_y, win_size.cy);
+
+ ok(vp_ext_x == vp_size.cx, "%d: vport_ext_x: %d != %d\n", restore_no, vp_ext_x, vp_size.cx);
+ ok(vp_ext_y == vp_size.cy, "%d: vport_ext_y: %d != %d\n", restore_no, vp_ext_y, vp_size.cy);
+}
+
static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
const ENHMETARECORD *emr, int n_objs, LPARAM param)
{
+ BOOL ret;
+ XFORM xform;
+ POINT pt;
+ SIZE size;
static int save_state;
static int restore_no;
+ trace("hdc %p, emr->iType %d, emr->nSize %d, param %p\n",
+ hdc, emr->iType, emr->nSize, (void *)param);
+
+ trace("BEFORE:\n");
+ SetLastError(0xdeadbeef);
+ ret = GetWorldTransform(hdc, &xform);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
+ trace("window org (%d,%d)\n", pt.x, pt.y);
+ ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
+ trace("vport org (%d,%d)\n", pt.x, pt.y);
+ ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
+ trace("window ext (%d,%d)\n", size.cx, size.cy);
+ ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
+ trace("vport ext (%d,%d)\n", size.cx, size.cy);
+ }
+ else
+ {
+ ok(ret, "GetWorldTransform error %u\n", GetLastError());
+ trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
+ }
+
+ PlayEnhMetaFileRecord(hdc, handle_table, emr, n_objs);
+
switch (emr->iType)
{
case EMR_HEADER:
+ {
+ static RECT exp_bounds = { 0, 0, 150, 150 };
+ RECT bounds;
+ const ENHMETAHEADER *emf = (const ENHMETAHEADER *)emr;
+
+ trace("bounds %d,%d-%d,%d, frame %d,%d-%d,%d\n",
+ emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom,
+ emf->rclFrame.left, emf->rclFrame.top, emf->rclFrame.right, emf->rclFrame.bottom);
+ trace("mm %d x %d, device %d x %d\n", emf->szlMillimeters.cx, emf->szlMillimeters.cy,
+ emf->szlDevice.cx, emf->szlDevice.cy);
+
+ SetRect(&bounds, emf->rclBounds.left, emf->rclBounds.top, emf->rclBounds.right, emf->rclBounds.bottom);
+ ok(EqualRect(&bounds, &exp_bounds), "wrong bounds\n");
+
save_state = 0;
restore_no = 0;
+ check_dc_state(hdc, restore_no, 0, 0, 1, 1, 0, 0, 1, 1);
break;
+ }
+ case EMR_LINETO:
+ {
+ const EMRLINETO *line = (const EMRLINETO *)emr;
+ trace("EMR_LINETO %d,%d\n", line->ptl.x, line->ptl.x);
+ break;
+ }
+ case EMR_SETWINDOWORGEX:
+ {
+ const EMRSETWINDOWORGEX *org = (const EMRSETWINDOWORGEX *)emr;
+ trace("EMR_SETWINDOWORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
+ break;
+ }
+ case EMR_SETWINDOWEXTEX:
+ {
+ const EMRSETWINDOWEXTEX *ext = (const EMRSETWINDOWEXTEX *)emr;
+ trace("EMR_SETWINDOWEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
+ break;
+ }
+ case EMR_SETVIEWPORTORGEX:
+ {
+ const EMRSETVIEWPORTORGEX *org = (const EMRSETVIEWPORTORGEX *)emr;
+ trace("EMR_SETVIEWPORTORGEX: %d,%d\n", org->ptlOrigin.x, org->ptlOrigin.y);
+ break;
+ }
+ case EMR_SETVIEWPORTEXTEX:
+ {
+ const EMRSETVIEWPORTEXTEX *ext = (const EMRSETVIEWPORTEXTEX *)emr;
+ trace("EMR_SETVIEWPORTEXTEX: %d,%d\n", ext->szlExtent.cx, ext->szlExtent.cy);
+ break;
+ }
case EMR_SAVEDC:
save_state++;
+ trace("EMR_SAVEDC\n");
break;
case EMR_RESTOREDC:
{
const EMRRESTOREDC *restoredc = (const EMRRESTOREDC *)emr;
+ trace("EMR_RESTOREDC: %d\n", restoredc->iRelative);
+
switch(++restore_no)
{
case 1:
ok(restoredc->iRelative == -1, "first restore %d\n", restoredc->iRelative);
+ check_dc_state(hdc, restore_no, -2, -2, 8192, 8192, 20, 20, 20479, 20478);
break;
-
case 2:
ok(restoredc->iRelative == -3, "second restore %d\n", restoredc->iRelative);
+ check_dc_state(hdc, restore_no, 0, 0, 16384, 16384, 0, 0, 17873, 17872);
break;
case 3:
ok(restoredc->iRelative == -2, "third restore %d\n", restoredc->iRelative);
+ check_dc_state(hdc, restore_no, -4, -4, 32767, 32767, 40, 40, 3276, 3276);
break;
}
ok(restore_no <= 3, "restore_no %d\n", restore_no);
@@ -302,6 +439,27 @@ static int CALLBACK savedc_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
ok(save_state == 0, "EOF save_state %d\n", save_state);
break;
}
+
+ trace("AFTER:\n");
+ SetLastError(0xdeadbeef);
+ ret = GetWorldTransform(hdc, &xform);
+ if (!ret && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
+ {
+ ok(GetWindowOrgEx(hdc, &pt), "GetWindowOrgEx error %u\n", GetLastError());
+ trace("window org (%d,%d)\n", pt.x, pt.y);
+ ok(GetViewportOrgEx(hdc, &pt), "GetViewportOrgEx error %u\n", GetLastError());
+ trace("vport org (%d,%d)\n", pt.x, pt.y);
+ ok(GetWindowExtEx(hdc, &size), "GetWindowExtEx error %u\n", GetLastError());
+ trace("window ext (%d,%d)\n", size.cx, size.cy);
+ ok(GetViewportExtEx(hdc, &size), "GetViewportExtEx error %u\n", GetLastError());
+ trace("vport ext (%d,%d)\n", size.cx, size.cy);
+ }
+ else
+ {
+ ok(ret, "GetWorldTransform error %u\n", GetLastError());
+ trace("eM11 %f, eM22 %f, eDx %f, eDy %f\n", xform.eM11, xform.eM22, xform.eDx, xform.eDy);
+ }
+
return 1;
}
@@ -311,7 +469,7 @@ static void test_SaveDC(void)
HENHMETAFILE hMetafile;
HWND hwnd;
int ret;
- static const RECT rc = { 0, 0, 100, 100 };
+ static const RECT rc = { 0, 0, 150, 150 };
/* Win9x doesn't play EMFs on invisible windows */
hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP | WS_VISIBLE,
@@ -324,18 +482,52 @@ static void test_SaveDC(void)
hdcMetafile = CreateEnhMetaFileA(hdcDisplay, NULL, NULL, NULL);
ok(hdcMetafile != 0, "CreateEnhMetaFileA error %d\n", GetLastError());
+ SetMapMode(hdcMetafile, MM_ANISOTROPIC);
+
/* Need to write something to the emf, otherwise Windows won't play it back */
- LineTo(hdcMetafile, 100, 100);
+ LineTo(hdcMetafile, 150, 150);
+
+ SetWindowOrgEx(hdcMetafile, 0, 0, NULL);
+ SetViewportOrgEx(hdcMetafile, 0, 0, NULL);
+ SetWindowExtEx(hdcMetafile, 110, 110, NULL );
+ SetViewportExtEx(hdcMetafile, 120, 120, NULL );
+
+ /* Force Win9x to update DC state */
+ SetPixelV(hdcMetafile, 50, 50, 0);
ret = SaveDC(hdcMetafile);
ok(ret == 1, "ret = %d\n", ret);
+ SetWindowOrgEx(hdcMetafile, -1, -1, NULL);
+ SetViewportOrgEx(hdcMetafile, 10, 10, NULL);
+ SetWindowExtEx(hdcMetafile, 150, 150, NULL );
+ SetViewportExtEx(hdcMetafile, 200, 200, NULL );
+
+ /* Force Win9x to update DC state */
+ SetPixelV(hdcMetafile, 50, 50, 0);
+
ret = SaveDC(hdcMetafile);
ok(ret == 2, "ret = %d\n", ret);
+ SetWindowOrgEx(hdcMetafile, -2, -2, NULL);
+ SetViewportOrgEx(hdcMetafile, 20, 20, NULL);
+ SetWindowExtEx(hdcMetafile, 120, 120, NULL );
+ SetViewportExtEx(hdcMetafile, 300, 300, NULL );
+
+ /* Force Win9x to update DC state */
+ SetPixelV(hdcMetafile, 50, 50, 0);
+
ret = SaveDC(hdcMetafile);
ok(ret == 3, "ret = %d\n", ret);
+ SetWindowOrgEx(hdcMetafile, -3, -3, NULL);
+ SetViewportOrgEx(hdcMetafile, 30, 30, NULL);
+ SetWindowExtEx(hdcMetafile, 200, 200, NULL );
+ SetViewportExtEx(hdcMetafile, 400, 400, NULL );
+
+ /* Force Win9x to update DC state */
+ SetPixelV(hdcMetafile, 50, 50, 0);
+
ret = RestoreDC(hdcMetafile, -1);
ok(ret, "ret = %d\n", ret);
@@ -345,6 +537,14 @@ static void test_SaveDC(void)
ret = RestoreDC(hdcMetafile, 1);
ok(ret, "ret = %d\n", ret);
+ SetWindowOrgEx(hdcMetafile, -4, -4, NULL);
+ SetViewportOrgEx(hdcMetafile, 40, 40, NULL);
+ SetWindowExtEx(hdcMetafile, 500, 500, NULL );
+ SetViewportExtEx(hdcMetafile, 50, 50, NULL );
+
+ /* Force Win9x to update DC state */
+ SetPixelV(hdcMetafile, 50, 50, 0);
+
ret = SaveDC(hdcMetafile);
ok(ret == 1, "ret = %d\n", ret);
@@ -1282,12 +1482,16 @@ static int CALLBACK clip_emf_enum_proc(HDC hdc, HANDLETABLE *handle_table,
rect = rgn2.data.rdh.rcBound;
rc_transformed = *rc;
translate((POINT *)&rc_transformed, 2, &xform);
+ trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
+ rc_transformed.right, rc_transformed.bottom);
ok(EqualRect(&rect, &rc_transformed), "rects don't match\n");
rect = *(const RECT *)rgn2.data.Buffer;
trace("rect (%d,%d-%d,%d)\n", rect.left, rect.top, rect.right, rect.bottom);
rc_transformed = *rc;
translate((POINT *)&rc_transformed, 2, &xform);
+ trace("transformed (%d,%d-%d,%d)\n", rc_transformed.left, rc_transformed.top,
+ rc_transformed.right, rc_transformed.bottom);
ok(EqualRect(&rect, &rc_transformed), "rects don't match\n");
ok(rgn2.data.rdh.dwSize == sizeof(rgn1->data.rdh), "expected sizeof(rdh), got %u", rgn2.data.rdh.dwSize);
--
1.5.5.1
More information about the wine-patches
mailing list