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.
 
 
 
 
 
 

1258 lines
45 KiB

/******************************Module*Header*******************************\
* Module Name: xformobj.cxx *
* *
* Xform object non-inline methods. *
* *
* Created: 12-Nov-1990 16:54:37 *
* Author: Wendy Wu [wendywu] *
* *
* Copyright (c) 1990-1999 Microsoft Corporation *
\**************************************************************************/
#include "precomp.hxx"
extern "C" {
void __cdecl _fltused(void) {} // just so that we link clean...
};
#if defined(_AMD64_) || defined(_IA64_) || defined(BUILD_WOW6432)
#define vSetTo1Over16(ef) (ef.e = EFLOAT_1Over16)
#else
#define vSetTo1Over16(ef) (ef.i.lMant = 0x040000000, ef.i.lExp = -2)
#endif
/******************************Data*Structure******************************\
* matrixIdentity *
* *
* Defines the identity transform matrices in different formats. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
MATRIX gmxIdentity_LToFx =
{
EFLOAT_16, // efM11
EFLOAT_0, // efM12
EFLOAT_0, // efM21
EFLOAT_16, // efM22
EFLOAT_0, // efDx
EFLOAT_0, // efDy
0, // fxDx
0, // fxDy
XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION|XFORM_FORMAT_LTOFX
};
MATRIX gmxIdentity_LToL =
{
EFLOAT_1, // efM11
EFLOAT_0, // efM12
EFLOAT_0, // efM21
EFLOAT_1, // efM22
EFLOAT_0, // efDx
EFLOAT_0, // efDy
0, // fxDx
0, // fxDy
XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION|XFORM_FORMAT_LTOL
};
MATRIX gmxIdentity_FxToL =
{
EFLOAT_1Over16, // efM11
EFLOAT_0, // efM12
EFLOAT_0, // efM21
EFLOAT_1Over16, // efM22
EFLOAT_0, // efDx
EFLOAT_0, // efDy
0, // fxDx
0, // fxDy
XFORM_SCALE|XFORM_UNITY|XFORM_NO_TRANSLATION|XFORM_FORMAT_FXTOL
};
/******************************Member*Function*****************************\
* EXFORMOBJ::EXFORMOBJ *
* *
* Get a transform matrix based on the request type. The only legitimate *
* type for now is IDENTITY. *
* *
* History: *
* 27-Mar-1991 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
EXFORMOBJ::EXFORMOBJ(ULONG iXform, ULONG iFormat)
{
ASSERTGDI((iXform == IDENTITY),"XFORMOBJ:invalid iXform\n");
bMirrored = FALSE;
if (iFormat == XFORM_FORMAT_LTOFX)
pmx = &gmxIdentity_LToFx;
else if (iFormat == XFORM_FORMAT_FXTOL)
pmx = &gmxIdentity_FxToL;
else
pmx = &gmxIdentity_LToL;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bEqual(EXFORMOBJ& xo) *
* *
* See if two transforms are identical. Matrices of different formats are *
* considered different even though the coefficients are same. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bEqual(EXFORMOBJ& xo)
{
if (pmx == xo.pmx)
return(TRUE); // point to the same matrix
// compare each and every element of the matrices as the structures may
// be padded.
return ((pmx->efM11 == xo.pmx->efM11) && (pmx->efM12 == xo.pmx->efM12) &&
(pmx->efM21 == xo.pmx->efM21) && (pmx->efM22 == xo.pmx->efM22) &&
(pmx->efDx == xo.pmx->efDx) && (pmx->efDy == xo.pmx->efDy));
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bEqualExceptTranslations *
* *
* See if two transforms are identical other than the translations elements.*
* Matrices of different formats are considered different even though the *
* coefficients are same. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bEqualExceptTranslations(PMATRIX pmx_)
{
if (pmx == pmx_)
return(TRUE); // point to the same matrix
// compare each and every element of the matrices as the structures may
// be padded.
return ((pmx->efM11 == pmx_->efM11) && (pmx->efM12 == pmx_->efM12) &&
(pmx->efM21 == pmx_->efM21) && (pmx->efM22 == pmx_->efM22));
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of POINTL to a list of POINTL. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PPOINTL pptlSrc,
PPOINTL pptlDst,
SIZE_T cPts)
{
ASSERTGDI(cPts > 0, "Can take only positive count");
ASSERTGDI( (((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOFX) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_FXTOL) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOL)),
"EXFORMOBJ::bXformPtlToPtl: wrong xform format\n");
// copy the source to the dest, This way we can use bCvtPts1 which is more efficient
if (pptlSrc != pptlDst)
{
RtlCopyMemory(pptlDst, pptlSrc, cPts*sizeof(POINTL));
}
// Straight copy if identity transform.
if (bIdentity())
{
return(TRUE);
}
BOOL bReturn = bCvtPts1(pmx, pptlDst, cPts);
if (!bReturn)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return(bReturn);
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of POINTL to a list of POINTFIX. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PPOINTL pptlSrc,
PPOINTFIX pptfxDst,
SIZE_T cPts)
{
ASSERTGDI(cPts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_LTOFX),
"EXFORMOBJ::bXformPtlToPtfx: wrong xform format\n");
// Convert a list of POINTL to a list of POINTFIX if identity transform.
if (bIdentity())
{
PPOINTL pptlSrcEnd = pptlSrc + cPts;
for ( ; pptlSrc < pptlSrcEnd; pptlSrc++, pptfxDst++)
{
pptfxDst->x = LTOFX(pptlSrc->x);
pptfxDst->y = LTOFX(pptlSrc->y);
}
return(TRUE);
}
BOOL bRet = bCvtPts(pmx, pptlSrc, (PPOINTL)pptfxDst, cPts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXformRound *
* *
* Transform a list of POINTL to a list of POINTFIX. Round the resulting *
* points to the nearest integers for Win31 compatibility. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXformRound(
PPOINTL pptlSrc,
PPOINTFIX pptfxDst,
SIZE_T cPts)
{
ASSERTGDI(cPts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_LTOFX),
"EXFORMOBJ::bXformPtlToPtfx: wrong xform format\n");
// Convert a list of POINTL to a list of POINTFIX if identity transform.
if (bIdentity())
{
PPOINTL pptlSrcEnd = pptlSrc + cPts;
for ( ; pptlSrc < pptlSrcEnd; pptlSrc++, pptfxDst++)
{
pptfxDst->x = LTOFX(pptlSrc->x);
pptfxDst->y = LTOFX(pptlSrc->y);
}
return(TRUE);
}
BOOL bRet = bCvtPts(pmx, pptlSrc, (PPOINTL)pptfxDst, cPts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
if (ulMode != GM_ADVANCED)
{
PPOINTFIX pptfxDstEnd = pptfxDst + cPts;
for ( ; pptfxDst < pptfxDstEnd; pptfxDst++)
{
pptfxDst->x = (pptfxDst->x + FIX_HALF) & 0xFFFFFFF0;
pptfxDst->y = (pptfxDst->y + FIX_HALF) & 0xFFFFFFF0;
}
}
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of POINTFIX to a list of POINTL. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PPOINTFIX pptfxSrc,
PPOINTL pptlDst,
SIZE_T cPts)
{
ASSERTGDI(cPts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_FXTOL),
"EXFORMOBJ::bXformPtfxToPtl: wrong xform format\n");
// Convert a list of POINTFIX to a list of POINTL if identity transform.
if (bIdentity())
{
PPOINTFIX pptfxSrcEnd = pptfxSrc + cPts;
for ( ; pptfxSrc < pptfxSrcEnd; pptfxSrc++, pptlDst++)
{
pptlDst->x = FXTOLROUND(pptfxSrc->x);
pptlDst->y = FXTOLROUND(pptfxSrc->y);
}
return(TRUE); // never overflows
}
BOOL bRet = bCvtPts(pmx, (PPOINTL)pptfxSrc, pptlDst, cPts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return bRet;
}
/******************************Member*Function*****************************\
* BOOL EXFORMOBJ::bXform
*
* Given a list of vectors (pptflSrc) and number of points in the list (cVts)
* transform the vectors and store into another list (pptflDst).
*
* History:
* 28-Jan-1992 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PVECTORFL pvtflSrc,
PVECTORFL pvtflDst,
SIZE_T cVts)
{
ASSERTGDI(cVts > 0, "Can take only positive count");
// check for quick exit, if the transform consists of translations
// only, there is nothing to do:
if (bTranslationsOnly())
{
if (pvtflDst != pvtflSrc) // if not transforming in place
{
RtlCopyMemory(pvtflDst, pvtflSrc, cVts*sizeof(VECTORFL));
}
return(TRUE);
}
BOOL bRet;
if (pmx->flAccel & XFORM_FORMAT_LTOL)
{
bRet = bCvtVts_FlToFl(pmx, pvtflSrc, pvtflDst, cVts);
}
else if (pmx->flAccel & XFORM_FORMAT_LTOFX)
{
pmx->efM11.vDivBy16();
pmx->efM12.vDivBy16();
pmx->efM21.vDivBy16();
pmx->efM22.vDivBy16();
bRet = bCvtVts_FlToFl(pmx, pvtflSrc, pvtflDst, cVts);
pmx->efM11.vTimes16();
pmx->efM12.vTimes16();
pmx->efM21.vTimes16();
pmx->efM22.vTimes16();
}
else
{
pmx->efM11.vTimes16();
pmx->efM12.vTimes16();
pmx->efM21.vTimes16();
pmx->efM22.vTimes16();
bRet = bCvtVts_FlToFl(pmx, pvtflSrc, pvtflDst, cVts);
pmx->efM11.vDivBy16();
pmx->efM12.vDivBy16();
pmx->efM21.vDivBy16();
pmx->efM22.vDivBy16();
}
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of VECTORL to a list of VECTORL. *
* *
* History: *
* 28-Jan-1992 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PVECTORL pvtlSrc,
PVECTORL pvtlDst,
SIZE_T cVts)
{
ASSERTGDI(cVts > 0, "Can take only positive count");
// Straight copy if identity transform.
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_LTOFX),
"EXFORMOBJ::bXformVtlToVtl: wrong xform format\n");
if (bTranslationsOnly())
{
if (pvtlDst != pvtlSrc)
{
RtlCopyMemory(pvtlDst, pvtlSrc, cVts*sizeof(VECTORL));
return(TRUE);
}
}
pmx->efM11.vDivBy16();
pmx->efM12.vDivBy16();
pmx->efM21.vDivBy16();
pmx->efM22.vDivBy16();
BOOL bReturn = bCvtVts(pmx, pvtlSrc, pvtlDst, cVts);
pmx->efM11.vTimes16();
pmx->efM12.vTimes16();
pmx->efM21.vTimes16();
pmx->efM22.vTimes16();
if (!bReturn)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return(bReturn);
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of VECTORL to a list of VECTORFX. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PVECTORL pvtlSrc,
PVECTORFX pvtfxDst,
SIZE_T cVts)
{
ASSERTGDI(cVts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_LTOFX),
"XFORMOBJ::bXformVtlToVtfx: wrong xform format\n");
// Convert a list of VECTORL to a list of VECTORFX if identity transform.
if (bTranslationsOnly())
{
PVECTORL pvtlSrcEnd = pvtlSrc + cVts;
for ( ; pvtlSrc < pvtlSrcEnd; pvtlSrc++, pvtfxDst++)
{
if (BLTOFXOK(pvtlSrc->x) && BLTOFXOK(pvtlSrc->y))
{
pvtfxDst->x = LTOFX(pvtlSrc->x);
pvtfxDst->y = LTOFX(pvtlSrc->y);
}
else
{
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return(FALSE);
}
}
return(TRUE);
}
BOOL bRet = bCvtVts(pmx, pvtlSrc, (PVECTORL)pvtfxDst, cVts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXformRound *
* *
* Transform a list of VECTORL to a list of VECTORFIX. Round the resulting *
* vectors to the nearest integers for Win31 compatibility. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXformRound(
PVECTORL pvtlSrc,
PVECTORFX pvtfxDst,
SIZE_T cVts)
{
ASSERTGDI(cVts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_LTOFX),
"XFORMOBJ::bXformVtlToVtfx: wrong xform format\n");
// Convert a list of VECTORL to a list of VECTORFX if identity transform.
if (bTranslationsOnly())
{
PVECTORL pvtlSrcEnd = pvtlSrc + cVts;
for ( ; pvtlSrc < pvtlSrcEnd; pvtlSrc++, pvtfxDst++)
{
if (BLTOFXOK(pvtlSrc->x) && BLTOFXOK(pvtlSrc->y))
{
pvtfxDst->x = LTOFX(pvtlSrc->x);
pvtfxDst->y = LTOFX(pvtlSrc->y);
}
else
{
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return(FALSE);
}
}
return(TRUE);
}
BOOL bRet = bCvtVts(pmx, pvtlSrc, (PVECTORL)pvtfxDst, cVts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
if (ulMode != GM_ADVANCED)
{
PVECTORFX pvtfxDstEnd = pvtfxDst + cVts;
for ( ; pvtfxDst < pvtfxDstEnd; pvtfxDst++)
{
pvtfxDst->x = (pvtfxDst->x + FIX_HALF) & 0xFFFFFFF0;
pvtfxDst->y = (pvtfxDst->y + FIX_HALF) & 0xFFFFFFF0;
}
}
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bXform *
* *
* Transform a list of VECTORFX to a list of VECTORL. *
* *
* History: *
* 06-Feb-1992 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bXform(
PVECTORFX pvtfxSrc,
PVECTORL pvtlDst,
SIZE_T cVts)
{
ASSERTGDI(cVts > 0, "Can take only positive count");
ASSERTGDI((pmx->flAccel & XFORM_FORMAT_FXTOL),
"EXFORMOBJ::bXformVtfxToVtl: wrong xform format\n");
// Convert a list of VECTORFX to a list of VECTORL if identity transform.
if (bTranslationsOnly())
{
PVECTORFX pvtfxSrcEnd = pvtfxSrc + cVts;
for ( ; pvtfxSrc < pvtfxSrcEnd; pvtfxSrc++, pvtlDst++)
{
pvtlDst->x = FXTOL(pvtfxSrc->x);
pvtlDst->y = FXTOL(pvtfxSrc->y);
}
return(TRUE);
}
BOOL bRet = bCvtVts(pmx, (PVECTORL)pvtfxSrc, pvtlDst, cVts);
if (!bRet)
SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
return bRet;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vComputeAccelFlags *
* *
* Set the accelerator flags for a given matrix. *
* *
* History: *
* 06-Dec-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
VOID EXFORMOBJ::vComputeAccelFlags(FLONG flFormat)
{
pmx->flAccel = flFormat; // 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;
switch(flFormat)
{
case XFORM_FORMAT_LTOFX:
if (pmx->efM11.bIs16() && pmx->efM22.bIs16())
pmx->flAccel |= XFORM_UNITY;
break;
case XFORM_FORMAT_LTOL:
if (pmx->efM11.bIs1() && pmx->efM22.bIs1())
pmx->flAccel |= XFORM_UNITY;
break;
default:
if (pmx->efM11.bIs1Over16() && pmx->efM22.bIs1Over16())
pmx->flAccel |= XFORM_UNITY;
break;
}
}
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vCopy(EXFORMOBJ& xo) *
* *
* Copy the coefficient values of a transform to another. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
VOID EXFORMOBJ::vCopy(EXFORMOBJ& xo)
{
RtlCopyMemory(pmx, xo.pmx, sizeof(MATRIX));
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vRemoveTranslation() *
* *
* Remove the translation coefficients of a transform. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
VOID EXFORMOBJ::vRemoveTranslation()
{
pmx->fxDx = 0;
pmx->fxDy = 0;
pmx->efDx.vSetToZero();
pmx->efDy.vSetToZero();
pmx->flAccel |= XFORM_NO_TRANSLATION;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vGetCoefficient() *
* *
* Get the coefficient of a transform matrix. This is used to convert *
* our internal matrix structure into the GDI/DDI transform format. *
* *
* History: *
* 12-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
VOID EXFORMOBJ::vGetCoefficient(XFORML *pxf)
{
// The coefficients have already been range-checked before they are set
// in the DC. So it's just a matter of converting them back to
// IEEE FLOAT. They can't possibly overflow.
// For i386, lEfToF() calls off to the assembly routine to do the EFLOAT
// to FLOAT conversion and put the result in eax, we want the C compiler
// to do direct copy to the destination here(no fstp), so some casting
// is necessary. Note the return type of lEfToF() is LONG. We do the
// same thing for MIPS so the code here can be shared.
ASSERTGDI( (((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOFX) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_FXTOL) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOL)),
"EXFORMOBJ::vGetCoefficient: wrong xform format\n");
if (pmx->flAccel & XFORM_FORMAT_LTOFX)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vDivBy16();
mxTmp.efM12.vDivBy16();
mxTmp.efM21.vDivBy16();
mxTmp.efM22.vDivBy16();
mxTmp.efDx.vDivBy16();
mxTmp.efDy.vDivBy16();
*(LONG *)&pxf->eM11 = mxTmp.efM11.lEfToF();
*(LONG *)&pxf->eM12 = mxTmp.efM12.lEfToF();
*(LONG *)&pxf->eM21 = mxTmp.efM21.lEfToF();
*(LONG *)&pxf->eM22 = mxTmp.efM22.lEfToF();
*(LONG *)&pxf->eDx = mxTmp.efDx.lEfToF();
*(LONG *)&pxf->eDy = mxTmp.efDy.lEfToF();
}
else if (pmx->flAccel & XFORM_FORMAT_FXTOL)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vTimes16();
mxTmp.efM12.vTimes16();
mxTmp.efM21.vTimes16();
mxTmp.efM22.vTimes16();
*(LONG *)&pxf->eM11 = mxTmp.efM11.lEfToF();
*(LONG *)&pxf->eM12 = mxTmp.efM12.lEfToF();
*(LONG *)&pxf->eM21 = mxTmp.efM21.lEfToF();
*(LONG *)&pxf->eM22 = mxTmp.efM22.lEfToF();
*(LONG *)&pxf->eDx = mxTmp.efDx.lEfToF();
*(LONG *)&pxf->eDy = mxTmp.efDy.lEfToF();
}
else
{
*(LONG *)&pxf->eM11 = pmx->efM11.lEfToF();
*(LONG *)&pxf->eM12 = pmx->efM12.lEfToF();
*(LONG *)&pxf->eM21 = pmx->efM21.lEfToF();
*(LONG *)&pxf->eM22 = pmx->efM22.lEfToF();
*(LONG *)&pxf->eDx = pmx->efDx.lEfToF();
*(LONG *)&pxf->eDy = pmx->efDy.lEfToF();
}
return;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vGetCoefficient() *
* *
* Get the coefficient of a transform matrix. This is to convert EFLOAT's *
* into FLOATOBJs which are now the same. *
* *
* History: *
* 13-Mar-1995 -by- Eric Kutter [erick]
* Wrote it. *
\**************************************************************************/
VOID EXFORMOBJ::vGetCoefficient(PFLOATOBJ_XFORM pxf)
{
// The coefficients have already been range-checked before they are set
// in the DC. So it's just a matter of converting them back to
// IEEE FLOAT. They can't possibly overflow.
// For i386, lEfToF() calls off to the assembly routine to do the EFLOAT
// to FLOAT conversion and put the result in eax, we want the C compiler
// to do direct copy to the destination here(no fstp), so some casting
// is necessary. Note the return type of lEfToF() is LONG. We do the
// same thing for MIPS so the code here can be shared.
ASSERTGDI( (((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOFX) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_FXTOL) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOL)),
"EXFORMOBJ::vGetCoefficient: wrong xform format\n");
if (pmx->flAccel & XFORM_FORMAT_LTOFX)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vDivBy16();
mxTmp.efM12.vDivBy16();
mxTmp.efM21.vDivBy16();
mxTmp.efM22.vDivBy16();
mxTmp.efDx.vDivBy16();
mxTmp.efDy.vDivBy16();
*(EFLOAT *)&pxf->eM11 = mxTmp.efM11;
*(EFLOAT *)&pxf->eM12 = mxTmp.efM12;
*(EFLOAT *)&pxf->eM21 = mxTmp.efM21;
*(EFLOAT *)&pxf->eM22 = mxTmp.efM22;
*(EFLOAT *)&pxf->eDx = mxTmp.efDx;
*(EFLOAT *)&pxf->eDy = mxTmp.efDy;
}
else if (pmx->flAccel & XFORM_FORMAT_FXTOL)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vTimes16();
mxTmp.efM12.vTimes16();
mxTmp.efM21.vTimes16();
mxTmp.efM22.vTimes16();
*(EFLOAT *)&pxf->eM11 = mxTmp.efM11;
*(EFLOAT *)&pxf->eM12 = mxTmp.efM12;
*(EFLOAT *)&pxf->eM21 = mxTmp.efM21;
*(EFLOAT *)&pxf->eM22 = mxTmp.efM22;
*(EFLOAT *)&pxf->eDx = mxTmp.efDx;
*(EFLOAT *)&pxf->eDy = mxTmp.efDy;
}
else
{
*(EFLOAT *)&pxf->eM11 = pmx->efM11;
*(EFLOAT *)&pxf->eM12 = pmx->efM12;
*(EFLOAT *)&pxf->eM21 = pmx->efM21;
*(EFLOAT *)&pxf->eM22 = pmx->efM22;
*(EFLOAT *)&pxf->eDx = pmx->efDx;
*(EFLOAT *)&pxf->eDy = pmx->efDy;
}
return;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vGetCoefficient()
*
* Get the coefficient of a transform matrix. This is used to convert
* our internal matrix structure into the IFI transform format.
*
* History:
* 04-Feb-1992 -by- Gilman Wong [gilmanw]
* Adapted from vGetCoefficient.
\**************************************************************************/
VOID EXFORMOBJ::vGetCoefficient(PFD_XFORM pfd_xf)
{
// The coefficients have already been range-checked before they are set
// in the DC. So it's just a matter of converting them back to
// IEEE FLOAT. They can't possibly overflow.
// For i386, lEfToF() calls off to the assembly routine to do the EFLOAT
// to FLOAT conversion and put the result in eax, we want the C compiler
// to do direct copy to the destination here(no fstp), so some casting
// is necessary. Note the return type of lEfToF() is LONG. We do the
// same thing for MIPS so the code here can be shared.
ASSERTGDI( (((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOFX) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_FXTOL) ||
((pmx->flAccel & XFORM_FORMAT) == XFORM_FORMAT_LTOL)),
"EXFORMOBJ::vGetCoefficient: wrong xform format\n");
if (pmx->flAccel & XFORM_FORMAT_LTOFX)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vDivBy16();
mxTmp.efM12.vDivBy16();
mxTmp.efM21.vDivBy16();
mxTmp.efM22.vDivBy16();
*(LONG *)&pfd_xf->eXX = mxTmp.efM11.lEfToF();
*(LONG *)&pfd_xf->eXY = mxTmp.efM12.lEfToF();
*(LONG *)&pfd_xf->eYX = mxTmp.efM21.lEfToF();
*(LONG *)&pfd_xf->eYY = mxTmp.efM22.lEfToF();
}
else if (pmx->flAccel & XFORM_FORMAT_FXTOL)
{
MATRIX mxTmp;
mxTmp = *pmx;
mxTmp.efM11.vTimes16();
mxTmp.efM12.vTimes16();
mxTmp.efM21.vTimes16();
mxTmp.efM22.vTimes16();
*(LONG *)&pfd_xf->eXX = mxTmp.efM11.lEfToF();
*(LONG *)&pfd_xf->eXY = mxTmp.efM12.lEfToF();
*(LONG *)&pfd_xf->eYX = mxTmp.efM21.lEfToF();
*(LONG *)&pfd_xf->eYY = mxTmp.efM22.lEfToF();
}
else
{
*(LONG *)&pfd_xf->eXX = pmx->efM11.lEfToF();
*(LONG *)&pfd_xf->eXY = pmx->efM12.lEfToF();
*(LONG *)&pfd_xf->eYX = pmx->efM21.lEfToF();
*(LONG *)&pfd_xf->eYY = pmx->efM22.lEfToF();
}
return;
}
/******************************Member*Function*****************************\
* EXFORMOBJ::vOrder(RECTL &rcl)
*
* Order a rectangle based on the given transform. The rectangle will be
* well ordered after the transform is applied. Note that the off-diagonal
* elements of the transform MUST be zero's. ie. only scaling is allowed.
*
* History:
* 18-Dec-1990 -by- Wendy Wu [wendywu]
* Wrote it.
\**************************************************************************/
VOID EXFORMOBJ::vOrder(RECTL &rcl)
{
LONG lTmp;
ASSERTGDI(bScale(), "vOrder error: not scaling transform");
if ((pmx->efM11.bIsNegative() && (rcl.left < rcl.right)) ||
(!pmx->efM11.bIsNegative() && (rcl.left > rcl.right)))
{
SWAPL(rcl.left, rcl.right, lTmp);
}
if ((pmx->efM22.bIsNegative() && (rcl.top < rcl.bottom)) ||
(!pmx->efM22.bIsNegative() && (rcl.top > rcl.bottom)))
{
SWAPL(rcl.top, rcl.bottom, lTmp);
}
}
/******************************Member*Function*****************************\
* bMultiply(PMATRIX pmxLeft, PMATRIX pmxRight) *
* *
* Multiply two matrices together. Put the results in the XFORMOBJ. *
* The target matrix CANNOT be the same as either of the two src matrices. *
* *
* History: *
* Fri 20-Mar-1992 13:54:28 -by- Charles Whitmer [chuckwh] *
* Rewrote with new EFLOAT math operations. We should never do any *
* operations like efA=efB*efC+efD! They generate intensely bad code. *
* *
* 19-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bMultiply(PMATRIX pmxLeft, PMATRIX pmxRight, FLONG fl)
{
MATRIX *pmxTemp = pmx;
ASSERTGDI((pmx != pmxLeft), "bMultiply error: pmx == pmxLeft\n");
ASSERTGDI((pmx != pmxRight), "bMultiply error: pmx == pmxRight\n");
EFLOAT efA,efB;
if (pmxLeft->efM12.bIsZero() && pmxLeft->efM21.bIsZero() &&
pmxRight->efM12.bIsZero() && pmxRight->efM21.bIsZero())
{
pmxTemp->efM11.eqMul(pmxLeft->efM11,pmxRight->efM11);
pmxTemp->efM22.eqMul(pmxLeft->efM22,pmxRight->efM22);
pmxTemp->efM12.vSetToZero();
pmxTemp->efM21.vSetToZero();
}
else
{
// calculate the first row of the results
efA.eqMul(pmxLeft->efM11,pmxRight->efM11);
efB.eqMul(pmxLeft->efM12,pmxRight->efM21);
pmxTemp->efM11.eqAdd(efA,efB);
efA.eqMul(pmxLeft->efM11,pmxRight->efM12);
efB.eqMul(pmxLeft->efM12,pmxRight->efM22);
pmxTemp->efM12.eqAdd(efA,efB);
// calculate the second row of the results
efA.eqMul(pmxLeft->efM21,pmxRight->efM11);
efB.eqMul(pmxLeft->efM22,pmxRight->efM21);
pmxTemp->efM21.eqAdd(efA,efB);
efA.eqMul(pmxLeft->efM21,pmxRight->efM12);
efB.eqMul(pmxLeft->efM22,pmxRight->efM22);
pmxTemp->efM22.eqAdd(efA,efB);
}
// calculate the translation
if (pmxLeft->efDx.bIsZero() && pmxLeft->efDy.bIsZero())
{
pmxTemp->efDx = pmxRight->efDx;
pmxTemp->efDy = pmxRight->efDy;
pmxTemp->fxDx = pmxRight->fxDx;
pmxTemp->fxDy = pmxRight->fxDy;
}
else
{
efA.eqMul(pmxLeft->efDx,pmxRight->efM11);
efB.eqMul(pmxLeft->efDy,pmxRight->efM21);
efB.eqAdd(efB,pmxRight->efDx);
pmxTemp->efDx.eqAdd(efA,efB);
efA.eqMul(pmxLeft->efDx,pmxRight->efM12);
efB.eqMul(pmxLeft->efDy,pmxRight->efM22);
efB.eqAdd(efB,pmxRight->efDy);
pmxTemp->efDy.eqAdd(efA,efB);
if (!pmxTemp->efDx.bEfToL(pmxTemp->fxDx))
return(FALSE);
if (!pmxTemp->efDy.bEfToL(pmxTemp->fxDy))
return(FALSE);
}
if (fl & COMPUTE_FLAGS)
vComputeAccelFlags(fl & XFORM_FORMAT);
return(TRUE);
}
/******************************Member*Function*****************************\
* EXFORMOBJ::bInverse(MATRIX& mxSrc) *
* *
* Calculate the inverse of a given matrix. *
* *
* The inverse is calculated as follows: *
* *
* If x' = D + xM then x = (-DM') + x'M' where M'M = 1. *
* *
* M'11 = M22/det, M'12 = -M12/det, M'21 = -M21/det, M'22 = M11/det, *
* where det = M11*M22 - M12*M21 *
* *
* History: *
* Fri 20-Mar-1992 13:54:28 -by- Charles Whitmer [chuckwh] *
* Rewrote with new EFLOAT math operations. We should never do any *
* operations like efA=efB*efC+efD! They generate intensely bad code. *
* *
* 19-Nov-1990 -by- Wendy Wu [wendywu] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bInverse(MATRIX& mxSrc)
{
MATRIX *pmxTemp = pmx;
ASSERTGDI((&mxSrc != pmx), "bInverse src, dest same matrix\n");
ASSERTGDI((mxSrc.flAccel & XFORM_FORMAT_LTOFX), "bInverse: wrong xform format\n");
// The accelerators of the destination matrix always equal to the
// accelerators of the source matrix.
pmxTemp->flAccel = (mxSrc.flAccel & ~XFORM_FORMAT_LTOFX) | XFORM_FORMAT_FXTOL;
if (mxSrc.flAccel & XFORM_UNITY)
{
vSetTo1Over16(pmxTemp->efM11);
vSetTo1Over16(pmxTemp->efM22);
pmxTemp->efM12.vSetToZero();
pmxTemp->efM21.vSetToZero();
pmxTemp->efDx = mxSrc.efDx;
pmxTemp->efDy = mxSrc.efDy;
pmxTemp->efDx.vNegate();
pmxTemp->efDy.vNegate();
pmxTemp->efDx.vDivBy16();
pmxTemp->efDy.vDivBy16();
pmxTemp->fxDx = -FXTOL(mxSrc.fxDx);
pmxTemp->fxDy = -FXTOL(mxSrc.fxDy);
return(TRUE);
}
// calculate the determinant
EFLOAT efDet;
EFLOAT efA,efB;
efA.eqMul(mxSrc.efM11,mxSrc.efM22);
efB.eqMul(mxSrc.efM12,mxSrc.efM21);
efDet.eqSub(efA,efB);
// if determinant = 0, return false
if (efDet.bIsZero())
return(FALSE);
if (mxSrc.flAccel & XFORM_SCALE)
{
pmxTemp->efM12.vSetToZero();
pmxTemp->efM21.vSetToZero();
}
else
{
pmxTemp->efM12.eqDiv(mxSrc.efM12,efDet);
pmxTemp->efM12.vNegate();
pmxTemp->efM21.eqDiv(mxSrc.efM21,efDet);
pmxTemp->efM21.vNegate();
}
pmxTemp->efM11.eqDiv(mxSrc.efM22,efDet);
pmxTemp->efM22.eqDiv(mxSrc.efM11,efDet);
// calculate the offset
if (mxSrc.flAccel & XFORM_NO_TRANSLATION)
{
pmxTemp->efDx.vSetToZero();
pmxTemp->efDy.vSetToZero();
pmxTemp->fxDx = 0;
pmxTemp->fxDy = 0;
return(TRUE);
}
if (mxSrc.flAccel & XFORM_SCALE)
{
pmxTemp->efDx.eqMul(mxSrc.efDx,pmxTemp->efM11);
pmxTemp->efDy.eqMul(mxSrc.efDy,pmxTemp->efM22);
}
else
{
efA.eqMul(mxSrc.efDx,pmxTemp->efM11);
efB.eqMul(mxSrc.efDy,pmxTemp->efM21);
pmxTemp->efDx.eqAdd(efA,efB);
efA.eqMul(mxSrc.efDx,pmxTemp->efM12);
efB.eqMul(mxSrc.efDy,pmxTemp->efM22);
pmxTemp->efDy.eqAdd(efA,efB);
}
pmxTemp->efDx.vNegate();
pmxTemp->efDy.vNegate();
// Return FALSE if translations can't fit in LONG type.
if (!pmxTemp->efDx.bEfToL(pmxTemp->fxDx))
return(FALSE);
if (!pmxTemp->efDy.bEfToL(pmxTemp->fxDy))
return(FALSE);
return(TRUE);
}
/******************************Public*Routine******************************\
* bComputeUnits (lAngle,ppte,pefWD,pefDW) *
* *
* Given an angle in 1/10ths of a degree in logical coordinates, we *
* transform a vector at that angle into device coordinates. We normalize *
* the result into a unit vector and a scaling. *
* *
* Knowing the unit vector and scaling allows us to quickly calculate the *
* transform of any vector parallel to the angle. *
* *
* Sun 15-Mar-1992 05:26:57 -by- Charles Whitmer [chuckwh] *
* Wrote it. *
\**************************************************************************/
BOOL EXFORMOBJ::bComputeUnits
(
LONG lAngle, // Angle in tenths of a degree.
POINTFL *ppte, // Unit vector in Device Coordinates.
EFLOAT *pefWD, // World to Device multiplier.
EFLOAT *pefDW // (Optional) Device to World multiplier.
)
{
EVECTORFL vt;
EFLOAT efA;
EFLOAT efB;
BOOL bNegate = FALSE;
// Get rid of negative angles. (Modulo is unreliable on negatives.)
if (lAngle < 0)
{
lAngle = -lAngle;
bNegate = TRUE;
}
// Handle simple cases separately for greater accuracy.
if (bScale() && (lAngle % 900 == 0))
{
lAngle /= 900;
if (lAngle & 1)
{
vt.x = (LONG) 0;
vt.y = (LONG) 1;
efA = efM22();
}
else
{
vt.x = (LONG) 1;
vt.y = (LONG) 0;
efA = efM11();
}
if (efA.bIsZero())
return(FALSE);
if (lAngle & 2)
efA.vNegate();
if (efA.bIsNegative())
{
vt.x.vNegate();
vt.y.vNegate();
efA.vNegate();
}
}
else
{
// Get the angle.
EFLOATEXT efAngle = lAngle;
efAngle /= (LONG) 10;
// Make a unit vector at that angle.
vt.x = efCos(efAngle);
vt.y = efSin(efAngle);
// Transform it to device coordinates.
if (!bXform(vt))
return(FALSE);
// Determine its length.
efA.eqLength(*(POINTFL *) &vt);
if (efA.bIsZero())
return(FALSE);
// Make a unit vector.
vt.x /= efA;
vt.y /= efA;
efA.vTimes16();
}
// Copy the results out.
if (bNegate)
vt.y.vNegate();
*ppte = vt;
*pefWD = efA;
if (pefDW != (EFLOAT *) NULL)
{
// Calculate the inverse.
efB = (LONG) 1;
efB /= efA;
*pefDW = efB;
}
return(TRUE);
}