You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2290 lines
61 KiB
2290 lines
61 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: xformgdi.cxx
|
|
*
|
|
* Contains all the mapping and coordinate functions.
|
|
*
|
|
* Created: 09-Nov-1990 16:49:36
|
|
* Author: Wendy Wu [wendywu]
|
|
*
|
|
* Copyright (c) 1990-1999 Microsoft Corporation
|
|
\**************************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
#define UNITS_PER_MILLIMETER_LOMETRIC 10 // .1 mm/unit
|
|
#define UNITS_PER_MILLIMETER_HIMETRIC 100 // .01 mm/unit
|
|
#define UNITS_PER_METER_LOENGLISH 3937 // (100 units/in) / (0.0254 m/in)
|
|
#define UNITS_PER_METER_HIENGLISH 39370 // (1000 units/in) / (0.0254 mm/in)
|
|
#define UNITS_PER_METER_TWIPS 56693 // (1440 units/in) / (0.0254 mm/in)
|
|
|
|
#if DBG
|
|
int giXformLevel = 0;
|
|
#endif
|
|
|
|
extern "C" BOOL
|
|
ProbeAndConvertXFORM(
|
|
XFORML *kpXform,
|
|
XFORML *pXform
|
|
);
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetMapMode(hdc)
|
|
*
|
|
* Get the mapping mode of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int APIENTRY GreGetMapMode(
|
|
HDC hdc)
|
|
{
|
|
DWORD dw = 0;
|
|
XDCOBJ dco( hdc );
|
|
|
|
if(dco.bValid())
|
|
{
|
|
dw = dco.ulMapMode();
|
|
dco.vUnlockFast();
|
|
}
|
|
else
|
|
{
|
|
WARNING("Invalid DC passed to GreGetMapMode\n");
|
|
}
|
|
|
|
return(dw);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetViewportExt(hdc,pSize)
|
|
*
|
|
* Get the viewport extents of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreGetViewportExt(
|
|
HDC hdc,
|
|
PSIZE pSize)
|
|
{
|
|
return(GreGetDCPoint(hdc,DCPT_VPEXT,(PPOINTL)pSize));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetViewportOrg(hdc,pPoint)
|
|
*
|
|
* Get the viewport origin of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreGetViewportOrg(
|
|
HDC hdc,
|
|
LPPOINT pPoint)
|
|
{
|
|
return(GreGetDCPoint(hdc,DCPT_VPORG,(PPOINTL)pPoint));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetWindowExt(hdc,pSize)
|
|
*
|
|
* Get the window extents of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreGetWindowExt(
|
|
HDC hdc,
|
|
PSIZE pSize)
|
|
{
|
|
return(GreGetDCPoint(hdc,DCPT_WNDEXT,(PPOINTL)pSize));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetWindowOrg(hdc,pPoint)
|
|
*
|
|
* Get the window origin of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreGetWindowOrg(
|
|
HDC hdc,
|
|
LPPOINT pPoint)
|
|
{
|
|
return(GreGetDCPoint(hdc,DCPT_WNDORG,(PPOINTL)pPoint));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSetViewportOrg(hdc,x,y,pPoint)
|
|
*
|
|
* Set the viewport origin of the specified dc.
|
|
*
|
|
* 15-Sep-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Modified since xforms have moved to client side and this routine is
|
|
* now only called by usersrv.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreSetViewportOrg(
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
LPPOINT pPoint)
|
|
{
|
|
|
|
|
|
DCOBJ dcox(hdc); // lock the dc object
|
|
|
|
if (!dcox.bValid()) // check if lock is valid
|
|
return(FALSE);
|
|
|
|
if (MIRRORED_DC(dcox.pdc))
|
|
x = -x;
|
|
|
|
if (BLTOFXOK(x) && BLTOFXOK(y))
|
|
{
|
|
if (!dcox.pdc->bValidPtlCurrent())
|
|
{
|
|
ASSERTGDI(dcox.pdc->bValidPtfxCurrent(), "Both CPs invalid?");
|
|
|
|
EXFORMOBJ exoDtoW(dcox, DEVICE_TO_WORLD);
|
|
|
|
if (exoDtoW.bValid())
|
|
exoDtoW.bXform(&dcox.ptfxCurrent(), &dcox.ptlCurrent(), 1);
|
|
|
|
dcox.pdc->vValidatePtlCurrent();
|
|
}
|
|
|
|
// After the transform, the device space CP will be invalid:
|
|
|
|
dcox.pdc->vInvalidatePtfxCurrent();
|
|
|
|
// x, y of viewport origin can fit into 28 bits.
|
|
|
|
// If we get here it means we've been called by USER and Viewport
|
|
// and Window extents should be (1,1) and Window Orgs should be zero,
|
|
// and the world transform shouldn't be set either.
|
|
|
|
DONTUSE(pPoint); // pPoint is now ignored
|
|
|
|
EXFORMOBJ xoWtoD(dcox, WORLD_TO_DEVICE);
|
|
EFLOATEXT efDx((LONG) x);
|
|
EFLOATEXT efDy((LONG) y);
|
|
|
|
efDx.vTimes16();
|
|
efDy.vTimes16();
|
|
|
|
ASSERTGDI(xoWtoD.efM11().bIs16() ||
|
|
(MIRRORED_DC(dcox.pdc) && xoWtoD.efM11().bIsNeg16()),
|
|
"efM11 not 16 in GreSetViewportOrg or -16 in Mirroring Mode" );
|
|
ASSERTGDI( xoWtoD.efM22().bIs16(),
|
|
"efM22 not 16 in GreSetViewportOrg" );
|
|
|
|
dcox.pdc->flSet_flXform( DEVICE_TO_WORLD_INVALID | PAGE_XLATE_CHANGED);
|
|
//xoWtoD.vSetTranslations( efDx, efDy );
|
|
dcox.pdc->lViewportOrgX(x);
|
|
dcox.pdc->lViewportOrgY(y);
|
|
|
|
xoWtoD.vInit(dcox, DEVICE_TO_WORLD);
|
|
|
|
return(TRUE);
|
|
|
|
}
|
|
else
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSetWindowOrg(hdc,x,y,pPoint)
|
|
*
|
|
* Set the window origin of the specified dc.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreSetWindowOrg(
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
LPPOINT pPoint)
|
|
{
|
|
|
|
|
|
DCOBJ dcox(hdc); // lock the dc object
|
|
|
|
if (!dcox.bValid()) // check if lock is valid
|
|
return(FALSE);
|
|
|
|
// If we get here it means we've been called by USER and Viewport
|
|
// and Window extents should be (1,1) and Viewport Orgs should be zero,
|
|
// and the world transform shouldn't be set either.
|
|
|
|
DONTUSE(pPoint); // pPoint is now ignored
|
|
|
|
EXFORMOBJ xoWtoD(dcox, WORLD_TO_DEVICE);
|
|
EFLOATEXT efDx((LONG) -x);
|
|
EFLOATEXT efDy((LONG) -y);
|
|
|
|
efDx.vTimes16();
|
|
efDy.vTimes16();
|
|
|
|
ASSERTGDI( xoWtoD.efM11().bIs16() ||
|
|
(MIRRORED_DC(dcox.pdc) && xoWtoD.efM11().bIsNeg16()),
|
|
"efM11 not 16 in GreSetViewportOrg" );
|
|
|
|
ASSERTGDI( xoWtoD.efM22().bIs16(),
|
|
"efM22 not 16 in GreSetViewportOrg" );
|
|
|
|
if (!dcox.pdc->bValidPtlCurrent())
|
|
{
|
|
ASSERTGDI(dcox.pdc->bValidPtfxCurrent(), "Both CPs invalid?");
|
|
|
|
EXFORMOBJ exoDtoW(dcox, DEVICE_TO_WORLD);
|
|
|
|
if (exoDtoW.bValid())
|
|
exoDtoW.bXform(&dcox.ptfxCurrent(), &dcox.ptlCurrent(), 1);
|
|
|
|
dcox.pdc->vValidatePtlCurrent();
|
|
}
|
|
|
|
// After the transform, the device space CP will be invalid:
|
|
|
|
dcox.pdc->vInvalidatePtfxCurrent();
|
|
|
|
dcox.pdc->flSet_flXform( DEVICE_TO_WORLD_INVALID | PAGE_XLATE_CHANGED);
|
|
//xoWtoD.vSetTranslations( efDx, efDy );
|
|
|
|
//
|
|
// save in DC for USER. Caution: these valuse must be restored before app
|
|
// uses DC again
|
|
//
|
|
|
|
dcox.pdc->lWindowOrgX(x);
|
|
dcox.pdc->lWindowOrgY(y);
|
|
dcox.pdc->SetWindowOrgAndMirror(x);
|
|
|
|
xoWtoD.vInit(dcox, DEVICE_TO_WORLD);
|
|
|
|
return( TRUE );
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiConvertMetafileRect:
|
|
*
|
|
* Transform a RECT from inclusive-exclusive to inclusive-inclusive for
|
|
* a rectangle recorded in a metafile.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* hdc - current device context
|
|
* rect - rtectangle to convert
|
|
*
|
|
* Return Value:
|
|
*
|
|
* MRI_OK,MRI_NULLBOX,MRI_ERROR
|
|
*
|
|
* History:
|
|
*
|
|
* 9-Apr-1996 -by- Mark Enstrom [marke]
|
|
*
|
|
\**************************************************************************/
|
|
|
|
LONG APIENTRY
|
|
NtGdiConvertMetafileRect(
|
|
HDC hdc,
|
|
PRECTL prect
|
|
)
|
|
{
|
|
LONG lResult = MRI_ERROR;
|
|
RECTL rclMeta;
|
|
|
|
//
|
|
// copy in rect structure
|
|
//
|
|
|
|
__try
|
|
{
|
|
rclMeta = ProbeAndReadStructure(prect,RECTL);
|
|
lResult = MRI_OK;
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(22);
|
|
}
|
|
|
|
if (lResult == MRI_OK)
|
|
{
|
|
//
|
|
// attempt to lock DC
|
|
//
|
|
|
|
DCOBJ dco(hdc);
|
|
|
|
if (dco.bValid())
|
|
{
|
|
ERECTFX rectFX;
|
|
BOOL bResult;
|
|
|
|
//
|
|
// DC must be in compatible mode
|
|
//
|
|
|
|
ASSERTGDI(dco.pdc->iGraphicsMode() == GM_COMPATIBLE,
|
|
"NtGdiConvertMetafileRect: Map Mode is not GM_COMPATIBLE");
|
|
|
|
//
|
|
// transform rectangle points to device FX
|
|
//
|
|
|
|
{
|
|
EXFORMOBJ xo(dco,XFORM_WORLD_TO_DEVICE);
|
|
|
|
bResult = xo.bXform((PPOINTL)&rclMeta,(PPOINTFIX)&rectFX,2);
|
|
}
|
|
|
|
if (bResult)
|
|
{
|
|
//
|
|
// order device point rectangle
|
|
//
|
|
|
|
rectFX.vOrder();
|
|
|
|
//
|
|
// adjust lower and right points for exclusive to inclusive
|
|
//
|
|
|
|
rectFX.xRight -= 16;
|
|
rectFX.yBottom -= 16;
|
|
|
|
//
|
|
// check for empty rectFX
|
|
//
|
|
|
|
if ((rectFX.xRight < rectFX.xLeft) ||
|
|
(rectFX.yBottom < rectFX.yTop))
|
|
{
|
|
lResult = MRI_NULLBOX;
|
|
}
|
|
|
|
//
|
|
// convert back to logical space
|
|
//
|
|
|
|
EXFORMOBJ xoDev(dco,XFORM_DEVICE_TO_WORLD);
|
|
|
|
bResult = xoDev.bXform((PPOINTFIX)&rectFX,(PPOINTL)&rclMeta,2);
|
|
|
|
//
|
|
// Write results to caller's buffer
|
|
//
|
|
|
|
if (bResult)
|
|
{
|
|
__try
|
|
{
|
|
ProbeAndWriteStructure(prect,rclMeta,RECT);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNINGX(8);
|
|
lResult = MRI_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lResult = MRI_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lResult = MRI_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lResult = MRI_ERROR;
|
|
}
|
|
}
|
|
|
|
if (lResult == MRI_ERROR)
|
|
{
|
|
SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return(lResult);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
*
|
|
* History:
|
|
* 02-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreTransformPoints(
|
|
HDC hdc,
|
|
PPOINT pptIn,
|
|
PPOINT pptOut,
|
|
int c,
|
|
int iMode
|
|
)
|
|
{
|
|
XFORMPRINT(1,"GreTransformPoints, iMode = %ld\n",iMode);
|
|
|
|
BOOL bResult = FALSE;
|
|
|
|
DCOBJ dco(hdc); // lock the dc object
|
|
|
|
if (dco.bValid()) // check if lock is valid
|
|
{
|
|
if (c <= 0) // check if there are points to convert
|
|
{
|
|
bResult = TRUE;
|
|
}
|
|
else
|
|
{
|
|
EXFORMOBJ xo(dco, (iMode == XFP_DPTOLP) ? XFORM_DEVICE_TO_WORLD : XFORM_WORLD_TO_DEVICE);
|
|
|
|
if (xo.bValid())
|
|
{
|
|
switch (iMode)
|
|
{
|
|
case XFP_DPTOLP:
|
|
case XFP_LPTODP:
|
|
bResult = xo.bXform((PPOINTL)pptIn, (PPOINTL)pptOut, c);
|
|
break;
|
|
|
|
case XFP_LPTODPFX:
|
|
bResult = xo.bXform((PPOINTL)pptIn, (PPOINTFIX)pptOut, c);
|
|
break;
|
|
|
|
default:
|
|
WARNING("Invalid mode passed to GreTranformPoints\n");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return(bResult);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreDPtoLP(hdc,ppt,nCount)
|
|
*
|
|
* Convert the given device points into logical points.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreDPtoLP(
|
|
HDC hdc,
|
|
LPPOINT ppt,
|
|
int nCount)
|
|
{
|
|
return(GreTransformPoints(hdc,ppt,ppt,nCount,XFP_DPTOLP));
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreLPtoDP(hdc,ppt,nCount)
|
|
*
|
|
* Convert the given logical points into device points.
|
|
*
|
|
* History:
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY GreLPtoDP(
|
|
HDC hdc,
|
|
LPPOINT ppt,
|
|
int nCount)
|
|
{
|
|
return(GreTransformPoints(hdc,ppt,ppt,nCount,XFP_LPTODP));
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* bWorldMatrixInRange(pmx)
|
|
*
|
|
* See if the coefficients of the world transform matrix are within
|
|
* our minimum and maximum range.
|
|
*
|
|
* History:
|
|
* 27-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL bWorldMatrixInRange(PMATRIX pmx)
|
|
{
|
|
|
|
BOOL bRet;
|
|
|
|
#if defined(_AMD64_) || defined(_IA64_) || defined(BUILD_WOW6432)
|
|
/*
|
|
EFLOAT ef = pmx->efM11;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
|
|
ef = pmx->efM12;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
|
|
ef = pmx->efM21;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
|
|
ef = pmx->efM22;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
|
|
ef = pmx->efDx;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
|
|
ef = pmx->efDy;
|
|
ef.vAbs();
|
|
if ((ef < (FLOAT)MIN_WORLD_XFORM) || (ef > (FLOAT)MIN_WORLD_XFORM))
|
|
return(FALSE);
|
|
*/
|
|
|
|
bRet = TRUE;
|
|
|
|
#else
|
|
|
|
|
|
bRet =
|
|
((pmx->efM11.bExpLessThan(MAX_WORLD_XFORM_EXP)) &&
|
|
(pmx->efM12.bExpLessThan(MAX_WORLD_XFORM_EXP)) &&
|
|
(pmx->efM21.bExpLessThan(MAX_WORLD_XFORM_EXP)) &&
|
|
(pmx->efM22.bExpLessThan(MAX_WORLD_XFORM_EXP)) &&
|
|
(pmx->efDx.bExpLessThan(MAX_WORLD_XFORM_EXP)) &&
|
|
(pmx->efDy.bExpLessThan(MAX_WORLD_XFORM_EXP)))
|
|
;
|
|
|
|
#endif
|
|
|
|
if (bRet)
|
|
{
|
|
// at this point bRet == TRUE. We have to figure out the cases
|
|
// when the determinant is zero and set bRet to FALSE;
|
|
|
|
// We do what we can to avoid multiplications in common cases
|
|
// when figuring out if this is a singular trasform
|
|
|
|
if (pmx->efM12.bIsZero() && pmx->efM21.bIsZero())
|
|
{
|
|
if (pmx->efM11.bIsZero() || pmx->efM22.bIsZero())
|
|
bRet = FALSE;
|
|
}
|
|
else if (pmx->efM11.bIsZero() && pmx->efM22.bIsZero())
|
|
{
|
|
if (pmx->efM12.bIsZero() || pmx->efM21.bIsZero())
|
|
bRet = FALSE;
|
|
}
|
|
else // general case, have to do multiplications
|
|
{
|
|
EFLOAT ef = pmx->efM11;
|
|
ef *= pmx->efM22;
|
|
|
|
EFLOAT ef1 = pmx->efM12;
|
|
ef1 *= pmx->efM21;
|
|
|
|
ef -= ef1; // determinant.
|
|
|
|
if (ef.bIsZero())
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetDeviceWidth(hdc)
|
|
*
|
|
* Get the device surface width of the specified dc.
|
|
*
|
|
* History:
|
|
* 26-Jan-1998 -by- Mohamed Hassanin [mhamid]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
LONG APIENTRY
|
|
GreGetDeviceWidth(HDC hdc)
|
|
{
|
|
DCOBJ dco(hdc);
|
|
|
|
if (dco.bValid() != FALSE)
|
|
{
|
|
return (dco.pdc->GetDeviceWidth());
|
|
}
|
|
else
|
|
{
|
|
WARNING("Invalid DC passed to GreGetDeviceWidth\n");
|
|
}
|
|
|
|
return (GDI_ERROR);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreMirrorWindowOrg(hdc)
|
|
*
|
|
* Mirror the Window X Org. By calling MirrorWindowOrg
|
|
*
|
|
* History:
|
|
* 26-Jan-1998 -by- Mohamed Hassanin [mhamid]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
BOOL APIENTRY
|
|
GreMirrorWindowOrg(HDC hdc)
|
|
{
|
|
DCOBJ dco(hdc);
|
|
|
|
if (dco.bValid() != FALSE)
|
|
{
|
|
dco.pdc->MirrorWindowOrg();
|
|
return (TRUE);
|
|
}
|
|
|
|
return (FALSE);
|
|
}
|
|
/******************************Public*Routine******************************\
|
|
* GreGetLayout
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 12-Sep-1991 11:29 -by- Mohamed Hassanin [MHamid]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
DWORD APIENTRY
|
|
GreGetLayout(HDC hdc)
|
|
{
|
|
DWORD dwRet = GDI_ERROR;
|
|
|
|
DCOBJ dco(hdc);
|
|
|
|
if (dco.bValid() != FALSE)
|
|
{
|
|
dwRet = dco.pdc->dwLayout();
|
|
}
|
|
|
|
return(dwRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreSetLayout
|
|
*
|
|
*
|
|
* History:
|
|
* Fri 12-Sep-1991 11:29 -by- Mohamed Hassanin [MHamid]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
DWORD APIENTRY
|
|
GreSetLayout
|
|
( HDC hdc,
|
|
LONG wox,
|
|
DWORD dwLayout)
|
|
{
|
|
DCOBJ dco( hdc );
|
|
if( !dco.bValid() )
|
|
{
|
|
WARNING("Xform update invalid hdc\n");
|
|
return(GDI_ERROR);
|
|
}
|
|
return dco.pdc->dwSetLayout(wox, dwLayout);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreXformUpdate
|
|
*
|
|
* Updates the server's copy of the WtoD transform, transform related flags,
|
|
* and viewport and window extents.
|
|
*
|
|
* History:
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
BOOL GreXformUpdate
|
|
( HDC hdc,
|
|
FLONG flXform,
|
|
LONG wex,
|
|
LONG wey,
|
|
LONG vex,
|
|
LONG vey,
|
|
LONG mapMode,
|
|
PVOID pvMatrix
|
|
)
|
|
{
|
|
DCOBJ dco( hdc );
|
|
|
|
if( !dco.bValid() )
|
|
{
|
|
WARNING("Xform update invalid hdc\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
// Copy window and viewport extents
|
|
dco.pdc->vSet_szlWindowExt( wex, wey );
|
|
dco.pdc->vSet_szlViewportExt( vex, vey );
|
|
dco.pdc->ulMapMode( mapMode );
|
|
|
|
// Save current position
|
|
|
|
ASSERTGDI(dco.bValid(), "DC not valid");
|
|
|
|
if (!dco.pdc->bValidPtlCurrent())
|
|
{
|
|
ASSERTGDI(dco.pdc->bValidPtfxCurrent(), "Both CPs invalid?");
|
|
|
|
EXFORMOBJ exoDtoW(dco, DEVICE_TO_WORLD);
|
|
|
|
if (exoDtoW.bValid())
|
|
exoDtoW.bXform(&dco.ptfxCurrent(), &dco.ptlCurrent(), 1);
|
|
|
|
dco.pdc->vValidatePtlCurrent();
|
|
}
|
|
|
|
// Set the flags
|
|
|
|
dco.pdc->flResetflXform( flXform );
|
|
dco.pdc->flSet_flXform( DEVICE_TO_WORLD_INVALID );
|
|
|
|
// Set the new world transform
|
|
|
|
RtlCopyMemory( (PVOID) &dco.pdc->mxWorldToDevice(), pvMatrix, sizeof( MATRIX ));
|
|
RtlCopyMemory( (PVOID) &dco.pdc->mxUserWorldToDevice(), pvMatrix, sizeof( MATRIX ));
|
|
|
|
// After the transform, the device space CP will be invalid:
|
|
|
|
dco.pdc->vInvalidatePtfxCurrent();
|
|
|
|
if( flXform & INVALIDATE_ATTRIBUTES )
|
|
{
|
|
EXFORMOBJ exo(dco, WORLD_TO_DEVICE);
|
|
|
|
dco.pdc->vRealizeLineAttrs(exo);
|
|
dco.pdc->vXformChange(TRUE);
|
|
}
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
/******************************Member*Function*****************************\
|
|
* vConvertXformToMatrix
|
|
*
|
|
* Convert a xform structure into a matrix struct.
|
|
*
|
|
* History:
|
|
* 27-Mar-1991 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID vConvertXformToMatrix(CONST XFORML *pxf, PMATRIX pmx)
|
|
{
|
|
pmx->efM11 = pxf->eM11; // overloading operator = which covert
|
|
pmx->efM12 = pxf->eM12; // IEEE float to our internal EFLOAT
|
|
pmx->efM21 = pxf->eM21;
|
|
pmx->efM22 = pxf->eM22;
|
|
pmx->efDx = pxf->eDx;
|
|
pmx->efDy = pxf->eDy;
|
|
#if DBG
|
|
if (!pmx->efDx.bEfToL(pmx->fxDx))
|
|
WARNING("vConvertXformToMatrix:translation dx overflowed\n");
|
|
if (!pmx->efDy.bEfToL(pmx->fxDy))
|
|
WARNING("vConvertXformToMatrix:translation dy overflowed\n");
|
|
#else
|
|
pmx->efDx.bEfToL(pmx->fxDx);
|
|
pmx->efDy.bEfToL(pmx->fxDy);
|
|
#endif
|
|
pmx->flAccel = XFORM_FORMAT_LTOL;
|
|
|
|
if ((pmx->efDx == pmx->efDy) && pmx->efDy.bIsZero())
|
|
pmx->flAccel |= XFORM_NO_TRANSLATION;
|
|
|
|
if (pmx->efM12.bIsZero() && pmx->efM21.bIsZero())
|
|
{
|
|
pmx->flAccel |= XFORM_SCALE;
|
|
if (pmx->efM11.bIs1() && pmx->efM22.bIs1())
|
|
pmx->flAccel |= XFORM_UNITY;
|
|
}
|
|
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* vMakeIso()
|
|
*
|
|
* Shrink viewport extents in one direction to match the aspect ratio of
|
|
* the window.
|
|
*
|
|
* History:
|
|
*
|
|
* 05-Dec-1994 -by- Eric Kutter [erick]
|
|
* Moved back to the server
|
|
*
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Modified for client side use.
|
|
*
|
|
* 09-Nov-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID DC::vMakeIso()
|
|
{
|
|
LONG lVpExt;
|
|
EFLOAT efRes, efTemp, efTemp1;
|
|
|
|
// Calculate the pixel aspect ratio efRes = ASPECTY / ASPECTX.
|
|
|
|
if(lVirtualDevicePixelCx() != 0)
|
|
{
|
|
//
|
|
// if lVirtualDeviceCx/Cy are set, use these, they are in micrometers
|
|
// Otherwise use their millimeters counter part
|
|
//
|
|
if ((lVirtualDeviceCx()) != 0 && (lVirtualDeviceCy() != 0))
|
|
{
|
|
efTemp = lVirtualDevicePixelCx();
|
|
efTemp1 = lVirtualDeviceCy();
|
|
|
|
LONG lTemp = EngMulDiv(lVirtualDevicePixelCy(), lVirtualDeviceCx(), lVirtualDevicePixelCx());
|
|
efRes = lTemp;
|
|
efRes /= efTemp1;
|
|
}
|
|
else
|
|
{
|
|
efRes = lVirtualDevicePixelCy() * lVirtualDeviceMmCx();
|
|
efTemp = lVirtualDevicePixelCx();
|
|
efTemp1 = lVirtualDeviceMmCy();
|
|
|
|
efRes /= efTemp;
|
|
efRes /= efTemp1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PDEVOBJ po(hdev());
|
|
ASSERTGDI(po.bValid(), "Invalid PDEV\n");
|
|
|
|
efRes = (LONG)po.ulLogPixelsY();
|
|
efTemp = (LONG)po.ulLogPixelsX();
|
|
efRes /= efTemp;
|
|
}
|
|
|
|
// Our goal is to make the following formula true
|
|
// VpExt.cy / VpExt.cx = (WdExt.cy / WdExt.cx) * (ASPECTY / ASPECTX)
|
|
|
|
// Let's calculate VpExt.cy assuming VpExt.cx is the limiting factor.
|
|
// VpExt.cy = (WdExt.cy * VpExt.cx) / WdExt.cx * efRes
|
|
|
|
EFLOATEXT efVpExt = lWindowExtCy();
|
|
efTemp = lViewportExtCx();
|
|
efTemp1 = lWindowExtCx();
|
|
efVpExt *= efTemp;
|
|
efVpExt /= efTemp1;
|
|
efVpExt *= efRes;
|
|
efVpExt.bEfToL(lVpExt); // convert efloat to long
|
|
|
|
lVpExt = ABS(lVpExt);
|
|
|
|
// Shrink y if the |original VpExt.cy| > the |calculated VpExt.cy|
|
|
// The original signs of the extents are preserved.
|
|
|
|
if (lViewportExtCy() > 0)
|
|
{
|
|
if (lViewportExtCy() >= lVpExt)
|
|
{
|
|
lViewportExtCy(lVpExt);
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (-lViewportExtCy() >= lVpExt)
|
|
{
|
|
lViewportExtCy(-lVpExt);
|
|
return;
|
|
}
|
|
}
|
|
|
|
// We know VpExt.cy is the real limiting factor. Let's calculate the correct
|
|
// VpExt.cx.
|
|
// VpExt.cx = (WdExt.cx * VpExt.cy) / WdExt.cy / Res
|
|
|
|
efVpExt = lWindowExtCx();
|
|
efTemp = lViewportExtCy();
|
|
efTemp1 = lWindowExtCy();
|
|
efVpExt *= efTemp;
|
|
efVpExt /= efTemp1;
|
|
efVpExt /= efRes;
|
|
efVpExt.bEfToL(lVpExt);
|
|
|
|
lVpExt = ABS(lVpExt);
|
|
|
|
if(lViewportExtCx() > 0 )
|
|
lViewportExtCx(lVpExt);
|
|
else
|
|
lViewportExtCx(-lVpExt);
|
|
|
|
}
|
|
|
|
|
|
/**************************************************************************\
|
|
* NtGdiScaleViewportExtEx()
|
|
*
|
|
* History:
|
|
* 07-Jun-1995 -by- Andre Vachon [andreva]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
NtGdiScaleViewportExtEx(
|
|
HDC hdc,
|
|
int xNum,
|
|
int xDenom,
|
|
int yNum,
|
|
int yDenom,
|
|
LPSIZE pszOut
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
DCOBJ dcox(hdc);
|
|
|
|
if (dcox.bValid())
|
|
{
|
|
BOOL bNoExcept = TRUE;
|
|
|
|
//
|
|
// NOTE: NT 3.51 compatibility.
|
|
// Even if the API failed (returned FALSE), the viewport was returned
|
|
// properly - stay compatible with this.
|
|
//
|
|
|
|
if (pszOut)
|
|
{
|
|
__try
|
|
{
|
|
ProbeForWrite(pszOut,sizeof(SIZE), sizeof(DWORD));
|
|
*pszOut = dcox.pdc->szlViewportExt();
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
// SetLastError(GetExceptionCode());
|
|
|
|
bNoExcept = FALSE;
|
|
}
|
|
}
|
|
|
|
if (bNoExcept == TRUE)
|
|
{
|
|
// can't change extent if fixed scale
|
|
|
|
if (dcox.ulMapMode() <= MM_MAX_FIXEDSCALE)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LONG lx, ly;
|
|
if ((xDenom != 0) &&
|
|
(yDenom != 0) &&
|
|
((lx = (dcox.pdc->lViewportExtCx() * xNum) / xDenom) != 0) &&
|
|
((ly = (dcox.pdc->lViewportExtCy() * yNum) / yDenom) != 0))
|
|
{
|
|
dcox.pdc->lViewportExtCx(lx);
|
|
dcox.pdc->lViewportExtCy(ly);
|
|
dcox.pdc->MirrorWindowOrg();
|
|
dcox.pdc->vPageExtentsChanged();
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreScaleWindowExtEx()
|
|
*
|
|
* History:
|
|
* 02-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL GreScaleWindowExtEx(
|
|
HDC hdc,
|
|
int xNum,
|
|
int xDenom,
|
|
int yNum,
|
|
int yDenom,
|
|
PSIZE psizl)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
DCOBJ dcox(hdc); // lock the dc object
|
|
|
|
if (dcox.bValid()) // check if lock is valid
|
|
{
|
|
if (psizl != (LPSIZE)NULL)
|
|
{
|
|
*psizl = dcox.pdc->szlWindowExt(); // fetch old extent
|
|
if (MIRRORED_DC(dcox.pdc))
|
|
psizl->cx = -psizl->cx;
|
|
}
|
|
|
|
// can't change extent if fixed scale
|
|
|
|
if (dcox.ulMapMode() <= MM_MAX_FIXEDSCALE)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
else
|
|
{
|
|
LONG lx, ly;
|
|
if ((xDenom != 0) &&
|
|
(yDenom != 0) &&
|
|
((lx = (dcox.pdc->lWindowExtCx() * xNum) / xDenom) != 0) &&
|
|
((ly = (dcox.pdc->lWindowExtCy() * yNum) / yDenom) != 0))
|
|
{
|
|
dcox.pdc->lWindowExtCx(lx);
|
|
dcox.pdc->lWindowExtCy(ly);
|
|
dcox.pdc->MirrorWindowOrg();
|
|
dcox.pdc->vPageExtentsChanged();
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* vComputePageXform
|
|
*
|
|
* Compute the page to device scaling factors.
|
|
*
|
|
* History:
|
|
* 05-Dec-1994 -by- Eric Kutter [erick]
|
|
* Moved back to the server
|
|
*
|
|
*
|
|
* 15-Dec-1992 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID DC::vComputePageXform()
|
|
{
|
|
EFLOAT ef;
|
|
EFLOATEXT efTemp;
|
|
|
|
ef = LTOFX(lViewportExtCx());
|
|
efTemp = lWindowExtCx();
|
|
ef /= efTemp;
|
|
efM11PtoD(ef);
|
|
|
|
ef = LTOFX(lViewportExtCy());
|
|
efTemp = lWindowExtCy();
|
|
ef /= efTemp;
|
|
efM22PtoD(ef);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* int EngMulDiv
|
|
* I am surprised that there is no system service routine to do this.
|
|
* anyway I am just fixing the old routine
|
|
*
|
|
* History:
|
|
* 15-Dec-1995 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int EngMulDiv(
|
|
int a,
|
|
int b,
|
|
int c)
|
|
{
|
|
LONGLONG ll;
|
|
int iSign = 1;
|
|
|
|
if (a < 0)
|
|
{
|
|
iSign = -iSign;
|
|
a = -a;
|
|
}
|
|
if (b < 0)
|
|
{
|
|
iSign = -iSign;
|
|
b = -b;
|
|
}
|
|
|
|
if (c != 0)
|
|
{
|
|
if (c < 0)
|
|
{
|
|
iSign = -iSign;
|
|
c = -c;
|
|
}
|
|
|
|
ll = (LONGLONG)a;
|
|
ll *= b;
|
|
ll += (c/2); // used to add (c+1)/2 which is wrong
|
|
ll /= c;
|
|
|
|
// at this point ll is guaranteed to be > 0. Thus we will do
|
|
// unsigned compare in the next step which generates two less instructions
|
|
// on x86 [bodind]
|
|
|
|
if ((ULONGLONG)ll > (ULONG)INT_MAX) // check for overflow:
|
|
{
|
|
if (iSign > 0)
|
|
return INT_MAX;
|
|
else
|
|
return INT_MIN;
|
|
}
|
|
else
|
|
{
|
|
if (iSign > 0)
|
|
return ((int)ll);
|
|
else
|
|
return (-(int)ll);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ASSERTGDI(c, "EngMulDiv - c == 0\n");
|
|
ASSERTGDI(a | b, "EngMulDiv - a|b == 0\n");
|
|
|
|
if (iSign > 0)
|
|
return INT_MAX;
|
|
else
|
|
return INT_MIN;
|
|
}
|
|
}
|
|
/******************************Public*Routine******************************\
|
|
* dwSetLayout
|
|
*
|
|
* Mirror the dc, by offsetting the window origin. If wox == -1, then the
|
|
* window origin becomes mirrored by the DC window width as follows :
|
|
* -((Device_Surface_Width * WindowExtX) / ViewportExtX) + LogicalWindowOrgX
|
|
*
|
|
* Otherwise mirroring is done by the specified wox amount :
|
|
* (wox - Current Window X-Origin)
|
|
*
|
|
* The function also changes windowExt.cx to be -1 so that positive x will
|
|
* go from right to left.
|
|
*
|
|
* History:
|
|
* 09-Dec-1997 -by- Mohammed Abdel-Hamid [mhamid]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
DWORD DC::dwSetLayout(LONG wox, DWORD dwDefLayout)
|
|
{
|
|
|
|
POINTL ptWOrg, ptVOrg;
|
|
SIZEL SzWExt, SzVExt;
|
|
DWORD dwOldLayout;
|
|
|
|
dwOldLayout = dwLayout();
|
|
dwLayout(dwDefLayout);
|
|
if ((dwOldLayout & LAYOUT_ORIENTATIONMASK) == (dwDefLayout & LAYOUT_ORIENTATIONMASK)) {
|
|
return dwOldLayout;
|
|
}
|
|
|
|
vGet_szlWindowExt(&SzWExt);
|
|
vGet_ptlViewportOrg(&ptVOrg);
|
|
|
|
if (dwDefLayout & LAYOUT_RTL) {
|
|
//Set the rtl layout
|
|
ulMapMode(MM_ANISOTROPIC);
|
|
ASSERTGDI((SzWExt.cx > 0), "GreSetLayout WExt.cx < 0 Check it");
|
|
} else {
|
|
ASSERTGDI((SzWExt.cx < 0), "GreSetLayout WExt.cx > 0 Check it");
|
|
}
|
|
|
|
SzWExt.cx = -SzWExt.cx;
|
|
vSet_szlWindowExt(&SzWExt);
|
|
|
|
ptVOrg.x = -ptVOrg.x;
|
|
vSet_ptlViewportOrg(&ptVOrg);
|
|
|
|
if (wox == -1) {
|
|
MirrorWindowOrg();
|
|
} else {
|
|
vGet_ptlWindowOrg(&ptWOrg);
|
|
ptWOrg.x = wox - ptWOrg.x;
|
|
vSet_ptlWindowOrg(&ptWOrg);
|
|
}
|
|
|
|
//
|
|
// TA_CENTER equals 6 (0110 Bin) and TA_RIGHT equals 2 (0010 Binary) numerically.
|
|
// so be careful not to do 'flTextAlign() & TA_CENTER'
|
|
// since this will succeed for RIGHT aligned DCs
|
|
// and as a result, the TA_RIGHT bit won't get cleared. [samera]
|
|
//
|
|
if ((flTextAlign()&TA_CENTER) != TA_CENTER) {
|
|
flTextAlign(flTextAlign() ^ (TA_RIGHT));
|
|
}
|
|
if (bClockwise()) {
|
|
vClearClockwise();
|
|
} else {
|
|
vSetClockwise();
|
|
}
|
|
vPageExtentsChanged();
|
|
return dwOldLayout;
|
|
}
|
|
|
|
EFLOAT ef16 = {EFLOAT_16};
|
|
|
|
/******************************Public*Routine******************************\
|
|
* DC::iSetMapMode()
|
|
*
|
|
* History:
|
|
* 07-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
int DC::iSetMapMode(
|
|
int iMode)
|
|
{
|
|
int iOldMode;
|
|
DWORD dwOldLayout = 0;
|
|
|
|
// If the new map mode is not MM_ANISOTROPIC
|
|
// And the DC in a mirrored mode
|
|
// Then Turn off the mirroring and turn it on back after
|
|
// Setting the new mode.
|
|
|
|
if (iMode != MM_ANISOTROPIC) {
|
|
dwOldLayout = dwLayout();
|
|
if (dwOldLayout & LAYOUT_ORIENTATIONMASK) {
|
|
dwSetLayout(-1 , 0);
|
|
}
|
|
}
|
|
|
|
// If set to the old map mode, don't bother setting it again except
|
|
// with MM_ISOTROPIC in which the extents might have been changed.
|
|
|
|
iOldMode = ulMapMode();
|
|
|
|
if ((iMode != iOldMode) || (iMode == MM_ISOTROPIC))
|
|
{
|
|
if (iMode == MM_TEXT)
|
|
{
|
|
lWindowExtCx(1);
|
|
lWindowExtCy(1);
|
|
lViewportExtCx(1);
|
|
lViewportExtCy(1);
|
|
ulMapMode(iMode);
|
|
|
|
// We don't want to recalculate M11 and M22 in vUpdateWtoDXform().
|
|
// Set them correctly here so we can just recalculate translations
|
|
// in vUpdateWtoDXform().
|
|
|
|
efM11PtoD(ef16);
|
|
efM22PtoD(ef16);
|
|
mxWorldToDevice().efM11 = ef16;
|
|
mxWorldToDevice().efM22 = ef16;
|
|
mxWorldToDevice().flAccel = XFORM_FORMAT_LTOFX | XFORM_UNITY | XFORM_SCALE;
|
|
RtlCopyMemory(
|
|
(PVOID) &mxUserWorldToDevice(),
|
|
(PVOID) &mxWorldToDevice(),
|
|
sizeof( MATRIX ));
|
|
|
|
vSetFlagsMM_TEXT();
|
|
}
|
|
else if (iMode == MM_ANISOTROPIC)
|
|
{
|
|
ulMapMode(iMode);
|
|
vSetFlagsMM_ISO_OR_ANISO();
|
|
}
|
|
else if ((iMode < MM_MIN) || (iMode > MM_MAX))
|
|
{
|
|
return(0);
|
|
}
|
|
else if (lVirtualDevicePixelCx() == 0)
|
|
{
|
|
PDEVOBJ po(hdev());
|
|
ASSERTGDI(po.bValid(), "Invalid PDEV\n");
|
|
|
|
// Protect against dynamic mode changes while we compute values
|
|
// using ulHorzSize and ulVertSize:
|
|
|
|
DEVLOCKOBJ dlo(po);
|
|
|
|
// Get the size of the surface
|
|
|
|
lViewportExtCx(po.GdiInfo()->ulHorzRes);
|
|
lViewportExtCy(-(LONG)po.GdiInfo()->ulVertRes);
|
|
|
|
// Get the size of the device
|
|
|
|
switch (iMode)
|
|
{
|
|
case MM_LOMETRIC:
|
|
//
|
|
// n um. * (1 mm. / 1000 um.) * (10 LoMetric units/1 mm.) = y LoMet
|
|
//
|
|
lWindowExtCx((po.GdiInfo()->ulHorzSize + 50)/100);
|
|
lWindowExtCy((po.GdiInfo()->ulVertSize + 50)/100);
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_HIMETRIC:
|
|
//
|
|
// n um. * (1 mm. / 1000 um.) * (100 HiMetric units/1 mm.) = y HiMet
|
|
//
|
|
lWindowExtCx((po.GdiInfo()->ulHorzSize + 5)/10);
|
|
lWindowExtCy((po.GdiInfo()->ulVertSize + 5)/10);
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_LOENGLISH:
|
|
//
|
|
// n um. * (1 in. / 25400 um.) * (100 LoEng units/1 in.) = y LoEng
|
|
//
|
|
lWindowExtCx((po.GdiInfo()->ulHorzSize + 127)/254);
|
|
lWindowExtCy((po.GdiInfo()->ulVertSize + 127)/254);
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_HIENGLISH:
|
|
//
|
|
// n um. * (1 in. / 25400 um.) * (1000 HiEng units/1 in.) = m HiEng
|
|
//
|
|
lWindowExtCx(EngMulDiv(po.GdiInfo()->ulHorzSize, 10, 254));
|
|
lWindowExtCy(EngMulDiv(po.GdiInfo()->ulVertSize, 10, 254));
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_TWIPS:
|
|
//
|
|
// n um. * (1 in. / 25400 um.) * (1440 Twips/1 in.) = m Twips
|
|
//
|
|
lWindowExtCx(EngMulDiv(po.GdiInfo()->ulHorzSize, 144, 2540));
|
|
lWindowExtCy(EngMulDiv(po.GdiInfo()->ulVertSize, 144, 2540));
|
|
|
|
// If it's cached earlier, use it.
|
|
|
|
#if defined(_AMD64_) || defined(_IA64_) || defined(BUILD_WOW6432)
|
|
if (efM11_TWIPS().e == (FLOAT)0)
|
|
#else
|
|
if (efM11_TWIPS().i.lMant == 0)
|
|
#endif
|
|
{
|
|
vComputePageXform();
|
|
efM11_TWIPS(efM11PtoD());
|
|
efM22_TWIPS(efM22PtoD());
|
|
}
|
|
ulMapMode(MM_TWIPS);
|
|
|
|
// We don't want to recalculate M11 and M22 in vUpdateWtoDXform().
|
|
// Set them correctly here so we can just recalculate translations
|
|
// in vUpdateWtoDXform().
|
|
|
|
efM11PtoD(efM11_TWIPS());
|
|
efM22PtoD(efM22_TWIPS());
|
|
mxWorldToDevice().efM11 = efM11_TWIPS();
|
|
mxWorldToDevice().efM22 = efM22_TWIPS();
|
|
mxWorldToDevice().flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE;
|
|
RtlCopyMemory(
|
|
(PVOID) &mxUserWorldToDevice(),
|
|
(PVOID) &mxWorldToDevice(),
|
|
sizeof( MATRIX ));
|
|
|
|
vSetFlagsMM_FIXED_CACHED();
|
|
goto JUST_RETURN;
|
|
//
|
|
// we need to pass thru mirroring code if
|
|
// it is enabled so the followingis commented for
|
|
// the above line
|
|
// return(iOldMode);
|
|
//
|
|
|
|
case MM_ISOTROPIC:
|
|
lWindowExtCx((po.GdiInfo()->ulHorzSize + 50)/100);
|
|
lWindowExtCy((po.GdiInfo()->ulVertSize + 50)/100);
|
|
vSetFlagsMM_ISO_OR_ANISO();
|
|
break;
|
|
|
|
default:
|
|
return(0);
|
|
}
|
|
|
|
ulMapMode(iMode);
|
|
vPageExtentsChanged();
|
|
}
|
|
else
|
|
{
|
|
// Get the size of the virtual surface
|
|
|
|
lViewportExtCx(lVirtualDevicePixelCx());
|
|
lViewportExtCy(-lVirtualDevicePixelCy());
|
|
|
|
// Get the size of the virtual device
|
|
|
|
switch (iMode)
|
|
{
|
|
case MM_LOMETRIC:
|
|
//
|
|
// n mm. * (10 LoMetric units/1 mm.) = y LoMet
|
|
//
|
|
lWindowExtCx(10 * lVirtualDeviceMmCx());
|
|
lWindowExtCy(10 * lVirtualDeviceMmCy());
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_HIMETRIC:
|
|
//
|
|
// n mm. * (100 HiMetric units/1 mm.) = y HiMet
|
|
//
|
|
lWindowExtCx(100 * lVirtualDeviceMmCx());
|
|
lWindowExtCy(100 * lVirtualDeviceMmCy());
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_LOENGLISH:
|
|
//
|
|
// n mm. * (10 in./254 mm.) * (100 LoEng/1 in.) = y LoEng
|
|
//
|
|
lWindowExtCx(EngMulDiv(lVirtualDeviceMmCx(),1000, 254));
|
|
lWindowExtCy(EngMulDiv(lVirtualDeviceMmCy(),1000, 254));
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_HIENGLISH:
|
|
//
|
|
// n mm. * (10 in./254 mm.) * (1000 LoEng/1 in.) = y LoEng
|
|
//
|
|
lWindowExtCx(EngMulDiv(lVirtualDeviceMmCx(),10000, 254));
|
|
lWindowExtCy(EngMulDiv(lVirtualDeviceMmCy(),10000, 254));
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_TWIPS:
|
|
//
|
|
// n mm. * (10 in./254 mm.) * (1440 Twips/1 in.) = y Twips
|
|
//
|
|
lWindowExtCx(EngMulDiv(lVirtualDeviceMmCx(),14400, 254));
|
|
lWindowExtCy(EngMulDiv(lVirtualDeviceMmCy(),14400, 254));
|
|
vSetFlagsMM_FIXED();
|
|
break;
|
|
|
|
case MM_ISOTROPIC:
|
|
//
|
|
// n mm. * (10 LoMetric units/1 mm.) = y LoMet
|
|
//
|
|
lWindowExtCx(10 * lVirtualDeviceMmCx());
|
|
lWindowExtCy(10 * lVirtualDeviceMmCy());
|
|
vSetFlagsMM_ISO_OR_ANISO();
|
|
break;
|
|
|
|
default:
|
|
return(0);
|
|
}
|
|
|
|
ulMapMode(iMode);
|
|
vPageExtentsChanged();
|
|
|
|
}
|
|
JUST_RETURN:
|
|
// If turned the mirroring off then turn it on back.
|
|
if (dwOldLayout & LAYOUT_ORIENTATIONMASK) {
|
|
//And then set it again.
|
|
dwSetLayout(-1 , dwOldLayout);
|
|
}
|
|
}
|
|
|
|
return(iOldMode);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiSetVirtualResolution()
|
|
*
|
|
* Set the virtual resolution of the specified dc.
|
|
* The virtual resolution is used to compute transform matrix only.
|
|
* If the virtual units are all zeros, the default physical units are used.
|
|
* Otherwise, non of the units can be zero.
|
|
*
|
|
* Currently used by metafile component only.
|
|
*
|
|
* History:
|
|
*
|
|
* 05-Dec-1994 -by- Eric Kutter [erick]
|
|
* Moved back to the server
|
|
*
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Modified for client side use.
|
|
*
|
|
* Tue Aug 27 13:04:11 1991 -by- Hock San Lee [hockl]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL APIENTRY NtGdiSetVirtualResolution(
|
|
HDC hdc,
|
|
int cxVirtualDevicePixel, // Width of the virtual device in pels
|
|
int cyVirtualDevicePixel, // Height of the virtual device in pels
|
|
int cxVirtualDeviceMm, // Width of the virtual device in millimeters
|
|
int cyVirtualDeviceMm) // Height of the virtual device in millimeters
|
|
{
|
|
XFORMPRINT(1,"GreSetVirtualResolution\n",0);
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
// The units must be all zeros or all non-zeros.
|
|
|
|
if ((cxVirtualDevicePixel != 0 && cyVirtualDevicePixel != 0 &&
|
|
cxVirtualDeviceMm != 0 && cyVirtualDeviceMm != 0)
|
|
||
|
|
(cxVirtualDevicePixel == 0 && cyVirtualDevicePixel == 0 &&
|
|
cxVirtualDeviceMm == 0 && cyVirtualDeviceMm == 0))
|
|
{
|
|
// now lock down the DC
|
|
|
|
DCOBJ dcox(hdc); // lock the dc object
|
|
|
|
if (dcox.bValid()) // check if lock is valid
|
|
{
|
|
|
|
dcox.pdc->lVirtualDevicePixelCx(cxVirtualDevicePixel);
|
|
dcox.pdc->lVirtualDevicePixelCy(cyVirtualDevicePixel);
|
|
|
|
dcox.pdc->lVirtualDeviceMmCx(cxVirtualDeviceMm);
|
|
dcox.pdc->lVirtualDeviceMmCy(cyVirtualDeviceMm);
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiSetSizeDevice()
|
|
*
|
|
* This is to compensate insufficient precision in SetVirtualResolution
|
|
*
|
|
* Modified for client side use.
|
|
*
|
|
* 5/17/99 -by- Lingyun Wang [lingyunw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
BOOL APIENTRY NtGdiSetSizeDevice(
|
|
HDC hdc,
|
|
int cxVirtualDevice, // Width of the virtual device in micrometers
|
|
int cyVirtualDevice) // Height of the virtual device in micrometers
|
|
{
|
|
BOOL bRet = FALSE;
|
|
|
|
// The units must be all zeros or all non-zeros.
|
|
|
|
if ((cxVirtualDevice != 0) && (cyVirtualDevice != 0))
|
|
{
|
|
// now lock down the DC
|
|
|
|
DCOBJ dcox(hdc); // lock the dc object
|
|
|
|
if (dcox.bValid()) // check if lock is valid
|
|
{
|
|
|
|
dcox.pdc->lVirtualDeviceCx(cxVirtualDevice);
|
|
dcox.pdc->lVirtualDeviceCy(cyVirtualDevice);
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreGetTransform()
|
|
*
|
|
* History:
|
|
* 05-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL GreGetTransform(
|
|
HDC hdc,
|
|
DWORD iXform,
|
|
XFORML *pxf)
|
|
{
|
|
XFORMPRINT(1,"GreGetTransform - iXform = %ld\n",iXform);
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
// now lock down the DC
|
|
|
|
DCOBJ dcox(hdc);
|
|
|
|
if (dcox.bValid())
|
|
{
|
|
|
|
EXFORMOBJ xo(dcox,iXform);
|
|
MATRIX mx;
|
|
|
|
if (!xo.bValid() && (iXform == XFORM_PAGE_TO_DEVICE))
|
|
{
|
|
xo.vInitPageToDevice(dcox,&mx);
|
|
}
|
|
|
|
if (xo.bValid())
|
|
{
|
|
xo.vGetCoefficient(pxf);
|
|
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XformUpdate
|
|
*
|
|
* Sends update transform information to the server.
|
|
*
|
|
* History:
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID EXFORMOBJ::vInit(
|
|
XDCOBJ& dco,
|
|
ULONG iXform)
|
|
{
|
|
XFORMPRINT(1,"EXFORMOBJ::vInit - iXform = %lx\n",iXform);
|
|
|
|
if (dco.pdc->bDirtyXform())
|
|
{
|
|
// Save current position
|
|
|
|
if (!dco.pdc->bValidPtlCurrent())
|
|
{
|
|
ASSERTGDI(dco.pdc->bValidPtfxCurrent(), "Both CPs invalid?");
|
|
|
|
EXFORMOBJ exoDtoW(dco.pdc->mxDeviceToWorld());
|
|
|
|
if (exoDtoW.bValid())
|
|
exoDtoW.bXform(&dco.ptfxCurrent(), &dco.ptlCurrent(), 1);
|
|
|
|
dco.pdc->vValidatePtlCurrent();
|
|
}
|
|
|
|
// update the transforms
|
|
|
|
dco.pdc->vUpdateWtoDXform();
|
|
|
|
// After the transform, the device space CP will be invalid:
|
|
|
|
dco.pdc->vInvalidatePtfxCurrent();
|
|
|
|
if( dco.pdc->flXform() & INVALIDATE_ATTRIBUTES)
|
|
{
|
|
|
|
EXFORMOBJ exoWtoD(dco.pdc->mxWorldToDevice());
|
|
|
|
dco.pdc->vRealizeLineAttrs(exoWtoD);
|
|
dco.pdc->vXformChange(TRUE);
|
|
dco.pdc->flClr_flXform(INVALIDATE_ATTRIBUTES);
|
|
}
|
|
|
|
dco.pdc->flSet_flXform(DEVICE_TO_WORLD_INVALID);
|
|
}
|
|
|
|
switch (iXform)
|
|
{
|
|
case XFORM_WORLD_TO_DEVICE:
|
|
pmx = &dco.pdc->mxWorldToDevice();
|
|
XFORMPRINT(2,"EXFORM::vInit - WtoD, pmx = %p\n",pmx);
|
|
break;
|
|
|
|
case XFORM_DEVICE_TO_WORLD:
|
|
pmx = &dco.pdc->mxDeviceToWorld();
|
|
|
|
if (dco.pdc->flXform() & DEVICE_TO_WORLD_INVALID)
|
|
{
|
|
if (bInverse(dco.pdc->mxWorldToDevice()))
|
|
{
|
|
dco.pdc->flClr_flXform(DEVICE_TO_WORLD_INVALID);
|
|
RtlCopyMemory(
|
|
(PVOID)&dco.pdc->mxUserDeviceToWorld(),
|
|
(PVOID)pmx,
|
|
sizeof( MATRIX )
|
|
);
|
|
|
|
}
|
|
else
|
|
{
|
|
pmx = (PMATRIX)NULL;
|
|
}
|
|
XFORMPRINT(2,"EXFORM::vInit - DtoW was dirty, pmx = %p\n",pmx);
|
|
}
|
|
break;
|
|
|
|
case XFORM_WORLD_TO_PAGE:
|
|
XFORMPRINT(2,"EXFORM::vInit - WtoP, pmx = %p\n",pmx);
|
|
pmx = &dco.pdc->mxWorldToPage();
|
|
break;
|
|
|
|
default:
|
|
XFORMPRINT(2,"EXFORM::vInit - NULL",pmx);
|
|
pmx = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* EXFORMOBJ::vInitPageToDevice()
|
|
*
|
|
* History:
|
|
* 05-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID EXFORMOBJ::vInitPageToDevice(
|
|
XDCOBJ& dco,
|
|
PMATRIX pmx_)
|
|
{
|
|
pmx = pmx_;
|
|
|
|
pmx->efM11 = dco.pdc->efM11PtoD();
|
|
pmx->efM12.vSetToZero();
|
|
pmx->efM21.vSetToZero();
|
|
pmx->efM22 = dco.pdc->efM22PtoD();
|
|
pmx->efDx = dco.pdc->efDxPtoD();
|
|
pmx->efDy = dco.pdc->efDyPtoD();
|
|
pmx->efDx.bEfToL(pmx->fxDx);
|
|
pmx->efDy.bEfToL(pmx->fxDy);
|
|
|
|
vComputeWtoDAccelFlags();
|
|
}
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* vUpdateWtoDXform
|
|
*
|
|
* Update the world to device transform.
|
|
*
|
|
* History:
|
|
*
|
|
* 15-Dec-1992 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
VOID DC::vUpdateWtoDXform()
|
|
{
|
|
PMATRIX pmx = &mxWorldToDevice();
|
|
|
|
if (bDirtyXlateOrExt())
|
|
{
|
|
if (bPageExtentsChanged())
|
|
{
|
|
// Recalculate the scaling factors for the page to device xform.
|
|
|
|
// M11 = ViewportExt.cx / WindowExt.cx
|
|
// M22 = ViewportExt.cy / WindowExt.cy
|
|
|
|
if (ulMapMode() == MM_ISOTROPIC)
|
|
vMakeIso();
|
|
|
|
if ((lWindowExtCx() == lViewportExtCx()) &&
|
|
(lWindowExtCy() == lViewportExtCy()))
|
|
{
|
|
efM11PtoD(ef16);
|
|
efM22PtoD(ef16);
|
|
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_UNITY | XFORM_SCALE;
|
|
|
|
flSet_flXform(PAGE_TO_DEVICE_SCALE_IDENTITY);
|
|
}
|
|
else
|
|
{
|
|
EFLOATEXT ef1;
|
|
EFLOATEXT ef2;
|
|
ef1 = LTOFX(lViewportExtCx());
|
|
ef2 = lWindowExtCx();
|
|
ef1 /= ef2;
|
|
efM11PtoD(ef1);
|
|
|
|
ef1 = LTOFX(lViewportExtCy());
|
|
ef2 = lWindowExtCy();
|
|
ef1 /= ef2;
|
|
efM22PtoD(ef1);
|
|
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE;
|
|
flClr_flXform(PAGE_TO_DEVICE_SCALE_IDENTITY | PAGE_TO_DEVICE_IDENTITY);
|
|
}
|
|
|
|
if (efM11PtoD().bIsNegative())
|
|
flSet_flXform(PTOD_EFM11_NEGATIVE);
|
|
else
|
|
flClr_flXform(PTOD_EFM11_NEGATIVE);
|
|
|
|
if (efM22PtoD().bIsNegative())
|
|
flSet_flXform(PTOD_EFM22_NEGATIVE);
|
|
else
|
|
flClr_flXform(PTOD_EFM22_NEGATIVE);
|
|
}
|
|
|
|
// Recalculate the translations for the page to device xform.
|
|
|
|
// Dx = ViewportOrg.x - (ViewportExt.cx / WindowExt.cx) * WindowOrg.x
|
|
// (ViewportExt.cx / WindowExt.cx) = efM11
|
|
|
|
// Dy = ViewportOrg.y - (ViewportExt.cy / WindowExt.cy) * WindowOrg.cy
|
|
// (ViewportExt.cy / WindowExt.cy) = efM22
|
|
|
|
if ((lWindowOrgX() == 0) &&
|
|
(lWindowOrgY() == 0))
|
|
{
|
|
if ((lViewportOrgX() == 0) &&
|
|
(lViewportOrgY() == 0))
|
|
{
|
|
EFLOAT efZ;
|
|
efZ.vSetToZero();
|
|
|
|
efDxPtoD(efZ);
|
|
efDyPtoD(efZ);
|
|
pmx->fxDx = 0;
|
|
pmx->fxDy = 0;
|
|
pmx->flAccel |= XFORM_NO_TRANSLATION;
|
|
|
|
if (bPageToDeviceScaleIdentity())
|
|
flSet_flXform(PAGE_TO_DEVICE_IDENTITY);
|
|
}
|
|
else
|
|
{
|
|
efDxPtoD(LTOFX(lViewportOrgX()));
|
|
efDyPtoD(LTOFX(lViewportOrgY()));
|
|
|
|
pmx->fxDx = LTOFX(lViewportOrgX());
|
|
pmx->fxDy = LTOFX(lViewportOrgY());
|
|
|
|
pmx->flAccel &= ~XFORM_NO_TRANSLATION;
|
|
flClr_flXform(PAGE_TO_DEVICE_IDENTITY);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
flClr_flXform(PAGE_TO_DEVICE_IDENTITY);
|
|
pmx->flAccel &= ~XFORM_NO_TRANSLATION;
|
|
if (bPageToDeviceScaleIdentity())
|
|
{
|
|
efDxPtoD(LTOFX(-lWindowOrgX()));
|
|
efDyPtoD(LTOFX(-lWindowOrgY()));
|
|
|
|
if ((lViewportOrgX() != 0) ||
|
|
(lViewportOrgY() != 0))
|
|
{
|
|
goto ADD_VIEWPORT_ORG;
|
|
}
|
|
|
|
pmx->fxDx = LTOFX(-lWindowOrgX());
|
|
pmx->fxDy = LTOFX(-lWindowOrgY());
|
|
}
|
|
else
|
|
{
|
|
{
|
|
EFLOATEXT ef;
|
|
ef = -lWindowOrgX();
|
|
ef *= efrM11PtoD();
|
|
efDxPtoD(ef);
|
|
|
|
ef = -lWindowOrgY();
|
|
ef *= efrM22PtoD();
|
|
efDyPtoD(ef);
|
|
}
|
|
|
|
if ((lViewportOrgX()!= 0) ||
|
|
(lViewportOrgY() != 0))
|
|
{
|
|
ADD_VIEWPORT_ORG:
|
|
|
|
EFLOATEXT efXVO(LTOFX(lViewportOrgX()));
|
|
efXVO += efrDxPtoD();
|
|
efDxPtoD(efXVO);
|
|
|
|
EFLOATEXT efYVO(LTOFX(lViewportOrgY()));
|
|
efYVO += efrDyPtoD();
|
|
efDyPtoD(efYVO);
|
|
}
|
|
|
|
efDxPtoD().bEfToL(pmx->fxDx);
|
|
efDyPtoD().bEfToL(pmx->fxDy);
|
|
}
|
|
}
|
|
|
|
if (bWorldToPageIdentity())
|
|
{
|
|
// Copy the PAGE_TO_DEVICE xform to WORLD_TO_DEVICE.
|
|
// pmx->fxDx, fxDy and flAccel has been set earlier in this routine.
|
|
|
|
pmx->efM11 = efM11PtoD();
|
|
pmx->efM22 = efM22PtoD();
|
|
pmx->efM12.vSetToZero();
|
|
pmx->efM21.vSetToZero();
|
|
pmx->efDx = efDxPtoD();
|
|
pmx->efDy = efDyPtoD();
|
|
|
|
if (bPageToDeviceIdentity())
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE | XFORM_UNITY |
|
|
XFORM_NO_TRANSLATION;
|
|
else if (bPageToDeviceScaleIdentity())
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE | XFORM_UNITY;
|
|
else
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE;
|
|
|
|
flClr_flXform(PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED |
|
|
WORLD_XFORM_CHANGED);
|
|
|
|
|
|
RtlCopyMemory( (PVOID) &mxUserWorldToDevice(), pmx, sizeof( MATRIX ));
|
|
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (bWorldToPageIdentity())
|
|
{
|
|
// World transform has changed to identity.
|
|
|
|
pmx->efM11 = efM11PtoD();
|
|
pmx->efM22 = efM22PtoD();
|
|
pmx->efM12.vSetToZero();
|
|
pmx->efM21.vSetToZero();
|
|
pmx->efDx = efDxPtoD();
|
|
pmx->efDy = efDyPtoD();
|
|
|
|
efDxPtoD().bEfToL(pmx->fxDx);
|
|
efDyPtoD().bEfToL(pmx->fxDy);
|
|
|
|
if (bPageToDeviceIdentity())
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE | XFORM_UNITY |
|
|
XFORM_NO_TRANSLATION;
|
|
else if (bPageToDeviceScaleIdentity())
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE | XFORM_UNITY;
|
|
else
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE;
|
|
|
|
flClr_flXform(PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED |
|
|
WORLD_XFORM_CHANGED);
|
|
|
|
RtlCopyMemory( (PVOID) &mxUserWorldToDevice(), pmx, sizeof( MATRIX ));
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Multiply the world to page and page to device xform together.
|
|
|
|
PMATRIX pmxWtoP = &mxWorldToPage();
|
|
|
|
if (bPageToDeviceScaleIdentity())
|
|
{
|
|
RtlCopyMemory(pmx, pmxWtoP, offsetof(MATRIX, flAccel));
|
|
pmx->efM11.vTimes16();
|
|
pmx->efM12.vTimes16();
|
|
pmx->efM21.vTimes16();
|
|
pmx->efM22.vTimes16();
|
|
pmx->efDx.vTimes16();
|
|
pmx->efDy.vTimes16();
|
|
}
|
|
else
|
|
{
|
|
pmx->efM11.eqMul(pmxWtoP->efM11,efM11PtoD());
|
|
pmx->efM21.eqMul(pmxWtoP->efM21,efM11PtoD());
|
|
pmx->efM12.eqMul(pmxWtoP->efM12,efM22PtoD());
|
|
pmx->efM22.eqMul(pmxWtoP->efM22,efM22PtoD());
|
|
|
|
pmx->efDx.eqMul(pmxWtoP->efDx,efM11PtoD());
|
|
pmx->efDy.eqMul(pmxWtoP->efDy,efM22PtoD());
|
|
}
|
|
|
|
pmx->efDx += efrDxPtoD();
|
|
pmx->efDx.bEfToL(pmx->fxDx);
|
|
|
|
pmx->efDy += efrDyPtoD();
|
|
pmx->efDy.bEfToL(pmx->fxDy);
|
|
|
|
if (pmx->efM12.bIsZero() && pmx->efM21.bIsZero())
|
|
{
|
|
if (pmx->efM11.bIs16() && pmx->efM22.bIs16())
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE | XFORM_UNITY;
|
|
else
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX | XFORM_SCALE;
|
|
}
|
|
else
|
|
{
|
|
pmx->flAccel = XFORM_FORMAT_LTOFX;
|
|
}
|
|
|
|
if ((pmx->fxDx == 0) && (pmx->fxDy == 0))
|
|
pmx->flAccel |= XFORM_NO_TRANSLATION;
|
|
|
|
flClr_flXform(PAGE_XLATE_CHANGED | PAGE_EXTENTS_CHANGED |
|
|
WORLD_XFORM_CHANGED);
|
|
|
|
RtlCopyMemory((PVOID)&mxUserWorldToDevice(),pmx,sizeof(MATRIX));
|
|
|
|
}
|
|
|
|
|
|
/******************************Private*Routine*****************************\
|
|
* bWordXformIdentity
|
|
*
|
|
* See is a world transform matrix is identity.
|
|
*
|
|
* History:
|
|
*
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Modified for client side use.
|
|
*
|
|
* 26-Dec-1990 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL bWorldXformIdentity(CONST XFORML *pxf)
|
|
{
|
|
return((pxf->eM11 == IEEE_1_0F) && (pxf->eM12 == IEEE_0_0F) &&
|
|
(pxf->eM21 == IEEE_0_0F) && (pxf->eM22 == IEEE_1_0F) &&
|
|
(pxf->eDx == IEEE_0_0F) && (pxf->eDy == IEEE_0_0F));
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiModifyWorldTransform()
|
|
*
|
|
* History:
|
|
* 01-Nov-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiModifyWorldTransform(
|
|
HDC hdc,
|
|
LPXFORM pxf,
|
|
DWORD iXform
|
|
)
|
|
{
|
|
XFORMPRINT(1,"GreModifyWorldTransform - iXform = %ld\n",iXform);
|
|
|
|
ASSERTGDI(sizeof(XFORM) == sizeof(XFORML),"sizeof(XFORM) != sizeof(XFORML)\n");
|
|
|
|
BOOL bRet = FALSE;
|
|
|
|
DCOBJ dcox(hdc);
|
|
|
|
if (dcox.bValid())
|
|
{
|
|
XFORML xf;
|
|
|
|
if (pxf)
|
|
{
|
|
bRet = ProbeAndConvertXFORM((XFORML *)pxf, &xf);
|
|
}
|
|
else
|
|
{
|
|
// must be identity to allow pxf == NULL
|
|
|
|
bRet = (iXform == MWT_IDENTITY);
|
|
}
|
|
|
|
if (bRet)
|
|
{
|
|
bRet = dcox.bModifyWorldTransform(&xf,iXform);
|
|
}
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* XDCOBJ::bModifyWorldTransform()
|
|
*
|
|
* History:
|
|
* 07-Dec-1994 -by- Eric Kutter [erick]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL XDCOBJ::bModifyWorldTransform(
|
|
CONST XFORML *pxf,
|
|
ULONG iMode)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
MATRIX mx;
|
|
|
|
switch (iMode)
|
|
{
|
|
case MWT_SET:
|
|
if (!bWorldXformIdentity(pxf))
|
|
{
|
|
vConvertXformToMatrix(pxf, &mx);
|
|
|
|
if (bWorldMatrixInRange(&mx)) // check if the new world xform is
|
|
{ // within the min, max range.
|
|
RtlCopyMemory(&pdc->mxWorldToPage(), &mx, offsetof(MATRIX, flAccel));
|
|
RtlCopyMemory(&pdc->mxUserWorldToPage(), &mx, offsetof(MATRIX, flAccel));
|
|
pdc->vClrWorldXformIdentity();
|
|
bRet = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
//MWT_IDENTITY must follow MWT_SET. This will fall through if it is identity
|
|
|
|
case MWT_IDENTITY:
|
|
if (!pdc->bWorldToPageIdentity())
|
|
{
|
|
RtlCopyMemory(&pdc->mxWorldToPage(), &gmxIdentity_LToL, offsetof(MATRIX, flAccel));
|
|
RtlCopyMemory(&pdc->mxUserWorldToPage(), &gmxIdentity_LToL, offsetof(MATRIX, flAccel));
|
|
pdc->vSetWorldXformIdentity();
|
|
}
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
case MWT_LEFTMULTIPLY:
|
|
case MWT_RIGHTMULTIPLY:
|
|
vConvertXformToMatrix(pxf,&mx);
|
|
|
|
if (!pdc->bWorldToPageIdentity())
|
|
{
|
|
EXFORMOBJ xoWtoP(*this,XFORM_WORLD_TO_PAGE);
|
|
|
|
if (!xoWtoP.bMultToWorld(&mx, iMode))
|
|
break;
|
|
}
|
|
|
|
if (!bWorldMatrixInRange(&mx)) // check if the new world xform is
|
|
break; // within the min, max range.
|
|
|
|
RtlCopyMemory( &pdc->mxWorldToPage(), &mx, offsetof(MATRIX, flAccel));
|
|
RtlCopyMemory( &pdc->mxUserWorldToPage(), &mx, offsetof(MATRIX, flAccel));
|
|
|
|
// Check if the resultant matrix is identity.
|
|
|
|
if (memcmp(&mx, &gmxIdentity_LToL, offsetof(MATRIX, flAccel)))
|
|
{
|
|
pdc->vClrWorldXformIdentity();
|
|
}
|
|
else
|
|
{
|
|
pdc->vSetWorldXformIdentity();
|
|
}
|
|
bRet = TRUE;
|
|
break;
|
|
|
|
default:
|
|
WARNING("invalid mode passed to GreModifyWorldTransform\n");
|
|
break;
|
|
}
|
|
|
|
return(bRet);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* GreCombineTransform
|
|
*
|
|
* Concatenate two transforms together by (*pxfSrc1) x (*pxfSrc2).
|
|
*
|
|
* History:
|
|
*
|
|
* 6-Aug-1992 -by- Gerrit van Wingerden [gerritv]
|
|
* Modified for client side use.
|
|
*
|
|
* 24-Jan-1992 -by- Wendy Wu [wendywu]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
BOOL GreCombineTransform(
|
|
XFORML *pxfDst,
|
|
XFORML *pxfSrc1,
|
|
XFORML *pxfSrc2)
|
|
{
|
|
MATRIX mx1,mx2,mxDst;
|
|
|
|
vConvertXformToMatrix(pxfSrc1, &mx1);
|
|
vConvertXformToMatrix(pxfSrc2, &mx2);
|
|
|
|
EXFORMOBJ xoDst(mxDst);
|
|
|
|
if (!xoDst.bMultiply(&mx1, &mx2))
|
|
return(FALSE);
|
|
|
|
xoDst.flAccel(XFORM_FORMAT_LTOL);
|
|
|
|
xoDst.vGetCoefficient(pxfDst);
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* NtGdiUpdateTransform
|
|
*
|
|
* This routine flushes the current transform
|
|
*
|
|
* History:
|
|
* 7/2/98 -by- Lingyun Wang [lingyunw]
|
|
\**************************************************************************/
|
|
|
|
BOOL NtGdiUpdateTransform(HDC hdc)
|
|
{
|
|
BOOL bRet = TRUE;
|
|
|
|
// update the transforms
|
|
XDCOBJ dco(hdc);
|
|
|
|
if (dco.bValid())
|
|
{
|
|
dco.pdc->vUpdateWtoDXform();
|
|
|
|
dco.vUnlock();
|
|
}
|
|
else
|
|
{
|
|
bRet = FALSE;
|
|
}
|
|
|
|
return (bRet);
|
|
|
|
}
|
|
|
|
|