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
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);
|
|
}
|