Leaked source code of windows server 2003
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.
 
 
 
 
 
 

543 lines
17 KiB

/******************************Module*Header*******************************\
* Module Name: xformobj.hxx *
* *
* User objects for transforms. *
* *
* Created: 13-Sep-1990 14:45:27 *
* Author: Wendy Wu [wendywu] *
* *
* Copyright (c) 1990-1999 Microsoft Corporation *
\**************************************************************************/
// These constants are used in the XFORMOBJ constructor.
#define COORD_METAFILE 1
#define COORD_WORLD 2
#define COORD_PAGE 3
#define COORD_DEVICE 4
#define WORLD_TO_DEVICE ((COORD_WORLD << 8) + COORD_DEVICE)
#define DEVICE_TO_WORLD ((COORD_DEVICE << 8) + COORD_WORLD)
// The exponents of all the coefficients for the various transforms must be
// within the following ranges:
//
// Metafile --
// |--> -47 <= e <= 48
// World --
// |--> -47 <= e <= 48
// Page --
// |--> -31 <= e <= 31
// Device --
//
// This will guarantee us a METAFILE_TO_DEVICE transform with
//
// -126 <= exponents <= 127
//
// for all the coefficients. The ranges are set so that transform coefficients
// can fit nicely in the IEEE single precision floating point format which has
// 8-bit exponent field that can hold values from -126 to 127. Note that when
// the transforms have reached the limits the calculations of inverse transforms
// might cause overflow.
// The max and min values for metafile and world transforms.
#define MAX_METAFILE_XFORM_EXP 52
#define MIN_METAFILE_XFORM_EXP -43
#define MAX_WORLD_XFORM_EXP MAX_METAFILE_XFORM_EXP
#define MIN_WORLD_XFORM_EXP MIN_METAFILE_XFORM_EXP
#define MAX_METAFILE_XFORM 1024*1024*1024*1024*1024*4 // 2^52
#define MIN_METAFILE_XFORM 1/(1024*1024*1024*1024*8) // 2^(-43)
#define MAX_WORLD_XFORM MAX_METAFILE_XFORM
#define MIN_WORLD_XFORM MIN_METAFILE_XFORM
// flag values for matrix.flAccel
#define XFORM_SCALE 1 // off-diagonal are 0
#define XFORM_UNITY 2 // diagonal are 1s, off-diagonal are 0
// will be set only if XFORM_SCALE is set
#define XFORM_Y_NEG 4 // M22 is negative. Will be set only if
// XFORM_SCALE|XFORM_UNITY are set
#define XFORM_FORMAT_LTOFX 8 // transform from LONG to FIX format
#define XFORM_FORMAT_FXTOL 16 // transform from FIX to LONG format
#define XFORM_FORMAT_LTOL 32 // transform from LONG to LONG format
#define XFORM_NO_TRANSLATION 64 // no translations
// These constants are used in the XFORMOBJ constructor.
#define IDENTITY 1
#define DONT_COMPUTE_FLAGS 0
#define COMPUTE_FLAGS 1
#define XFORM_FORMAT (XFORM_FORMAT_LTOFX|XFORM_FORMAT_FXTOL|XFORM_FORMAT_LTOL)
#define BLTOFXOK(x) (((x) < 0x07FFFFFF) && ((x) > -0x07FFFFFF))
extern "C" {
BOOL bCvtPts(PMATRIX pmx, PPOINTL pSrc, PPOINTL pDest, SIZE_T cPts);
BOOL bCvtPts1(PMATRIX pmx, PPOINTL pptl, SIZE_T cPts);
BOOL bCvtVts(PMATRIX pmx, PVECTORL pSrc, PVECTORL pDest, SIZE_T cPts);
BOOL bCvtVts_FlToFl(PMATRIX pmx, PVECTORFL pSrc, PVECTORFL pDest, SIZE_T cPts);
};
extern MATRIX gmxIdentity_LToFx;
extern MATRIX gmxIdentity_LToL;
extern MATRIX gmxIdentity_FxToL;
VOID vConvertXformToMatrix(CONST XFORML *pxf, PMATRIX pmx);
#if DBG
extern int giXformLevel;
#define XFORMPRINT(l,s,a) {if (giXformLevel >= l) DbgPrint(s,a);}
#else
#define XFORMPRINT(l,s,a)
#endif
/******************************Class***************************************\
* class EXFORMOBJ *
* *
* User object that lets clients interact with transforms. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
class EXFORMOBJ
{
public:
MATRIX *pmx; // pointer to the matrix
ULONG ulMode;
BOOL bMirrored;
public:
// Constructor
EXFORMOBJ() { pmx = (PMATRIX)NULL;
bMirrored = FALSE;
}
// Constructor - Make the given matrix a transform.
EXFORMOBJ(MATRIX& mx) { pmx = &mx;
bMirrored = FALSE;
}
// Initialize the the xform
VOID vInit(MATRIX *pmx_, FLONG fl = DONT_COMPUTE_FLAGS)
{
pmx = pmx_;
if (fl & COMPUTE_FLAGS) // compute accelerator flags
{
vComputeAccelFlags(fl & XFORM_FORMAT);
}
else if (fl & XFORM_FORMAT)
{
pmx->flAccel = fl;
}
}
// Constructor - Make a transform object given the pointer to the matrix.
EXFORMOBJ(MATRIX *pmx_, FLONG fl)
{
pmx = pmx_;
bMirrored = FALSE;
if (fl & COMPUTE_FLAGS) // compute accelerator flags
{
vComputeAccelFlags(fl & XFORM_FORMAT);
}
else if (fl & XFORM_FORMAT)
{
pmx->flAccel = fl;
}
}
// Constructor - Get a transform matrix based on the request type. The only
// legitimate type for now is IDENTITY.
EXFORMOBJ(ULONG iXform, ULONG iFormat = XFORM_FORMAT_LTOFX);
#ifdef _DCOBJ_
// Constructor - Get a transform from a DC.
EXFORMOBJ(XDCOBJ& dco, ULONG iXform) {vQuickInit(dco,iXform);}
VOID vQuickInit(XDCOBJ& dco, ULONG iXform)
{
ulMode = (ULONG)dco.pdc->iGraphicsMode();
bMirrored = MIRRORED_DC(dco.pdc);
if (!dco.pdc->bDirtyXform() && (iXform == WORLD_TO_DEVICE))
{
pmx = &dco.pdc->mxWorldToDevice();
}
else
{
vInit(dco,iXform);
}
}
VOID vInit(XDCOBJ &dco, ULONG iXform);
VOID vInitPageToDevice(XDCOBJ &dco, PMATRIX pmx_);
#endif
// vComputeWtoDAccelFlags - Compute accelerator flags for the world
// to device xform.
VOID vComputeWtoDAccelFlags()
{
pmx->flAccel = XFORM_FORMAT_LTOFX; // clear the flag
// set translation flag
if ((pmx->fxDx == 0) && (pmx->fxDy == 0))
pmx->flAccel |= XFORM_NO_TRANSLATION;
if (pmx->efM12.bIsZero() && pmx->efM21.bIsZero())
{
// off diagonal elements are zeros
pmx->flAccel |= XFORM_SCALE;
if (pmx->efM11.bIs16() && pmx->efM22.bIs16())
pmx->flAccel |= XFORM_UNITY;
}
}
// Destructor - Don't need to free anything.
~EXFORMOBJ() {}
// bValid - Validator.
BOOL bValid() { return(pmx != (PMATRIX)NULL); }
// vComputeAccelFlags - Compute accelerator flags for a given transform matrix.
VOID vComputeAccelFlags(FLONG flFormat = XFORM_FORMAT_LTOFX);
// efM11 - Get/set coefficients of the given matrix.
EFLOAT& efM11() {return(pmx->efM11);}
EFLOAT& efM22() {return(pmx->efM22);}
EFLOAT& efM12() {return(pmx->efM12);}
EFLOAT& efM21() {return(pmx->efM21);}
FIX fxDx() {return(pmx->fxDx);}
FIX fxDy() {return(pmx->fxDy);}
VOID vSetElementsLToL (
EFLOAT ef11,
EFLOAT ef12,
EFLOAT ef21,
EFLOAT ef22
)
{
pmx->efM11 = ef11;
pmx->efM12 = ef12;
pmx->efM21 = ef21;
pmx->efM22 = ef22;
}
VOID vSetElementsLToFx (
FLOATL l_e11,
FLOATL l_e12,
FLOATL l_e21,
FLOATL l_e22
)
{
pmx->efM11 = l_e11;
pmx->efM12 = l_e12;
pmx->efM21 = l_e21;
pmx->efM22 = l_e22;
// Elements in a transform of LTOFX format must be scaled by 16.
pmx->efM11.vTimes16();
pmx->efM12.vTimes16();
pmx->efM21.vTimes16();
pmx->efM22.vTimes16();
}
// flAccel - Get the accelerator flag of a given matrix.
FLONG flAccel() { return(pmx->flAccel); }
FLONG flAccel(FLONG fl) { return(pmx->flAccel = fl); }
// bEqual - See if two transforms are identical.
BOOL bEqual(EXFORMOBJ& xo);
// bEqualExceptTranslations - See if two transforms are identical in M11, M12,
// M21, and M22.
BOOL bEqualExceptTranslations(PMATRIX pmx_);
BOOL bEqualExceptTranslations(EXFORMOBJ& xo)
{
return(bEqualExceptTranslations(xo.pmx));
}
// bScale -- See if a the off-diangonal elements of a transform are 0.
BOOL bScale() { return(pmx->flAccel & XFORM_SCALE); }
// bRotation -- See if there is rotation.
BOOL bRotation() { return(!bScale()); }
// bRotationOrMirroring -- See if there is a rotation or mirroring (negative
// diagonal element(s) with 0 off-diagonal elements)
BOOL bRotationOrMirroring() { return (bRotation() ||
(
!bMirrored &&
((pmx->efM11.bIsNegative()) || (pmx->efM22.bIsNegative()))
)); }
// bNoTranslation -- See if a transform has translation components.
BOOL bNoTranslation() { return(pmx->flAccel & XFORM_NO_TRANSLATION); }
// bIdentity - See if a given transform is an identity transform.
BOOL bIdentity()
{
return((pmx->flAccel &
(XFORM_SCALE | XFORM_UNITY | XFORM_NO_TRANSLATION)) ==
(XFORM_SCALE | XFORM_UNITY | XFORM_NO_TRANSLATION));
}
// bTranslationsOnly - no rotations and scaling, translations may possibly
// be zero
BOOL bTranslationsOnly () { return (pmx->flAccel & XFORM_UNITY); }
// bConformal -- Does the transform preserve angles?
// looks at the 2 X 2 transform only
BOOL bConformal()
{
EFLOAT ef;
ef = pmx->efM21;
ef.vNegate();
return (pmx->efM11 == pmx->efM22 && pmx->efM12 == ef);
}
// bXform - Apply the transform to various objects. Return FALSE on
// overflow.
// Transform a list of points.
BOOL bXform(PPOINTL pptlSrc,PPOINTL pptlDst,SIZE_T cPts);
BOOL bXform(PPOINTL pSrc, PPOINTFIX pDest, SIZE_T cPts);
BOOL bXform(PPOINTFIX pSrc, PPOINTL pDest, SIZE_T cPts);
BOOL bXformRound(PPOINTL pSrc, PPOINTFIX pDest, SIZE_T cPts);
// Transform a list of points in place.
BOOL bXform(PPOINTL pptl, SIZE_T cPts)
{
return(bIdentity() || bCvtPts1(pmx, pptl, cPts));
}
BOOL bXform(EPOINTL& eptl)
{
return(bXform((PPOINTL) &eptl, 1));
}
BOOL bXform(ERECTL& ercl)
{
BOOL bRet;
bRet = bXform((PPOINTL) &ercl, 2);
// If it a mirrored DC then shift the rect one pixel to the right
// This will give the effect of including the right edge of the rect and exclude the left edge.
if (bMirrored) {
++ercl.left;
++ercl.right;
}
return (bRet);
}
// Transform a list of vectors.
BOOL bXform(PVECTORFL pvtflSrc, PVECTORFL pvtflDst,SIZE_T cVts);
BOOL bXform(PVECTORL pSrc, PVECTORFX pDest, SIZE_T cVts);
BOOL bXform(PVECTORL pSrc, PVECTORL pDest, SIZE_T cVts);
BOOL bXform(PVECTORFX pSrc, PVECTORL pDest, SIZE_T cVts);
BOOL bXformRound(PVECTORL pSrc, PVECTORFX pDest, SIZE_T cVts);
// Transform a list of vectors in place.
BOOL bXform(PVECTORFL pvtfl, SIZE_T cVts)
{
BOOL bReturn = TRUE;
if (!bTranslationsOnly())
bReturn = bXform(pvtfl, pvtfl, cVts);
return(bReturn);
}
BOOL bXform(EVECTORFL& evtfl)
{
return(bXform((PVECTORFL) &evtfl, 1));
}
BOOL bXform(EVECTORL& evtl)
{
BOOL bReturn = TRUE;
if (!bTranslationsOnly())
bReturn = bXform((PVECTORL)&evtl, (PVECTORL)&evtl, 1);
return(bReturn);
}
// bMultiply - Multiply two XFORMs together and store the result in the
// XFORMOBJ.
BOOL bMultiply(PMATRIX pmxLeft, PMATRIX pmxRight,
FLONG fl = DONT_COMPUTE_FLAGS);
BOOL bMultiply(EXFORMOBJ& exoLeft, EXFORMOBJ& exoRight,
FLONG fl = DONT_COMPUTE_FLAGS)
{
return(bMultiply(exoLeft.pmx, exoRight.pmx, fl));
}
// bMultToWorld - Multiply the world transform with a given matrix. The
// result is stored in the passed in matrix. This is so
// that the resultant matrix can be range-checked later on
// before the WORLD_TO_PAGE xform is changed.
// The order of the multiplication is based on imode.
// If imode == MWT_LEFTMULTIPLY, the given matrix is applied
// to the left of the multiplication. It's applied to the
// right otherwise.
BOOL bMultToWorld(MATRIX *pmx_, ULONG imode)
{
MATRIX mx = *pmx_;
EXFORMOBJ xo(pmx_, DONT_COMPUTE_FLAGS);
if (imode == MWT_LEFTMULTIPLY)
return(xo.bMultiply(&mx, pmx));
else
return(xo.bMultiply(pmx, &mx));
}
// vRemoveTranslation - Remove the translation coefficients from a matrix.
VOID vRemoveTranslation();
// vGetCoefficient - Get the coefficients of a transform matrix. This is
// used to convert our internal matrix structure into
// the GDI/DDI transform format.
VOID vGetCoefficient(PFLOATOBJ_XFORM pxf);
// vGetCoefficient - Get the coefficients of a transform matrix. This is
// used to convert our internal matrix structure into
// the GDI/DDI transform format.
VOID vGetCoefficient(XFORML *pxf);
// vGetCoefficient - Get the coefficients of a transform matrix. This is
// used to convert our internal matrix structure into
// the IFI transform format.
VOID vGetCoefficient(PFD_XFORM pxf);
// vSetScaling - Set the scaling factors for a given matrix.
VOID vSetScaling(EFLOAT efM11, EFLOAT efM22,
FLONG fl = DONT_COMPUTE_FLAGS)
{
ASSERTGDI(pmx->efM12.bIsZero(), "vSetScaling error: M12 not zero");
ASSERTGDI(pmx->efM21.bIsZero(), "vSetScaling error: M21 not zero");
pmx->efM11 = efM11;
pmx->efM22 = efM22;
if (fl & COMPUTE_FLAGS)
vComputeAccelFlags(fl & XFORM_FORMAT);
}
// vSetTranslations - Set the translations for a given matrix.
VOID vSetTranslations(EFLOAT efDx, EFLOAT efDy)
{
FIX fxDx, fxDy;
pmx->efDx = efDx;
pmx->efDy = efDy;
#if DBG
if (!efDx.bEfToL(fxDx))
WARNING("vSetTranslations:dx overflowed\n");
if (!efDy.bEfToL(fxDy))
WARNING("vSetTranslations:dy overflowed\n");
#else
efDx.bEfToL(fxDx);
efDy.bEfToL(fxDy);
#endif
pmx->fxDx = fxDx;
pmx->fxDy = fxDy;
if ((fxDx == 0) && (fxDy == 0))
pmx->flAccel |= XFORM_NO_TRANSLATION;
else
pmx->flAccel &= ~(XFORM_NO_TRANSLATION);
}
// vSet - Set the coefficients for a given matrix.
// This is used to set WorldToPage transform.
VOID vSet(MATRIX *pmx_, FLONG fl = DONT_COMPUTE_FLAGS)
{
*pmx = *pmx_;
if (fl & COMPUTE_FLAGS)
vComputeAccelFlags(fl & XFORM_FORMAT);
}
// vCopy -- Copy a transform obj to another.
VOID vCopy(EXFORMOBJ& xoSrc);
// vOrder -- Order a rectangle based on the PAGE_TO_DEVICE transform.
// The rectangle will be well ordered after the PAGE_TO_DEVICE
// transform is applied.
VOID vOrder(RECTL &rcl);
// bInverse -- Calculate the inverse of a passed in xform/matrix and store
// the result in the XFORMOBJ. The source and destination
// matrices CANNOT be the same one.
BOOL bInverse(MATRIX& mxSrc);
BOOL bInverse(EXFORMOBJ& xo) { return(bInverse(*(xo.pmx))); }
// bComputeUnits -- Calculates a simplified transform for vectors parallel
// to the given angle.
BOOL bComputeUnits(LONG lAngle,POINTFL *ppte,EFLOAT *pefWD,EFLOAT *pefDW);
// fxFastX -- Does a quick scaling transform on x.
FIX fxFastX(LONG ll) {return((FIX) lCvt(pmx->efM11,ll) + pmx->fxDx);}
// fxFastY -- Does a quick scaling transform on y.
FIX fxFastY(LONG ll) {return((FIX) lCvt(pmx->efM22,ll) + pmx->fxDy);}
};
typedef EXFORMOBJ *PEXFORMOBJ;