gdi32: Save/restore internal EMF playing state on EMR_SAVEDC/EMR_RESTOREDC, add a test for this.
This commit is contained in:
parent
d01438bd53
commit
c871d9a81d
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue