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

  1. /******************************Module*Header*******************************\
  2. * Module Name: xformobj.hxx *
  3. * *
  4. * User objects for transforms. *
  5. * *
  6. * Created: 13-Sep-1990 14:45:27 *
  7. * Author: Wendy Wu [wendywu] *
  8. * *
  9. * Copyright (c) 1990-1999 Microsoft Corporation *
  10. \**************************************************************************/
  11. // These constants are used in the XFORMOBJ constructor.
  12. #define COORD_METAFILE 1
  13. #define COORD_WORLD 2
  14. #define COORD_PAGE 3
  15. #define COORD_DEVICE 4
  16. #define WORLD_TO_DEVICE ((COORD_WORLD << 8) + COORD_DEVICE)
  17. #define DEVICE_TO_WORLD ((COORD_DEVICE << 8) + COORD_WORLD)
  18. // The exponents of all the coefficients for the various transforms must be
  19. // within the following ranges:
  20. //
  21. // Metafile --
  22. // |--> -47 <= e <= 48
  23. // World --
  24. // |--> -47 <= e <= 48
  25. // Page --
  26. // |--> -31 <= e <= 31
  27. // Device --
  28. //
  29. // This will guarantee us a METAFILE_TO_DEVICE transform with
  30. //
  31. // -126 <= exponents <= 127
  32. //
  33. // for all the coefficients. The ranges are set so that transform coefficients
  34. // can fit nicely in the IEEE single precision floating point format which has
  35. // 8-bit exponent field that can hold values from -126 to 127. Note that when
  36. // the transforms have reached the limits the calculations of inverse transforms
  37. // might cause overflow.
  38. // The max and min values for metafile and world transforms.
  39. #define MAX_METAFILE_XFORM_EXP 52
  40. #define MIN_METAFILE_XFORM_EXP -43
  41. #define MAX_WORLD_XFORM_EXP MAX_METAFILE_XFORM_EXP
  42. #define MIN_WORLD_XFORM_EXP MIN_METAFILE_XFORM_EXP
  43. #define MAX_METAFILE_XFORM 1024*1024*1024*1024*1024*4 // 2^52
  44. #define MIN_METAFILE_XFORM 1/(1024*1024*1024*1024*8) // 2^(-43)
  45. #define MAX_WORLD_XFORM MAX_METAFILE_XFORM
  46. #define MIN_WORLD_XFORM MIN_METAFILE_XFORM
  47. // flag values for matrix.flAccel
  48. #define XFORM_SCALE 1 // off-diagonal are 0
  49. #define XFORM_UNITY 2 // diagonal are 1s, off-diagonal are 0
  50. // will be set only if XFORM_SCALE is set
  51. #define XFORM_Y_NEG 4 // M22 is negative. Will be set only if
  52. // XFORM_SCALE|XFORM_UNITY are set
  53. #define XFORM_FORMAT_LTOFX 8 // transform from LONG to FIX format
  54. #define XFORM_FORMAT_FXTOL 16 // transform from FIX to LONG format
  55. #define XFORM_FORMAT_LTOL 32 // transform from LONG to LONG format
  56. #define XFORM_NO_TRANSLATION 64 // no translations
  57. // These constants are used in the XFORMOBJ constructor.
  58. #define IDENTITY 1
  59. #define DONT_COMPUTE_FLAGS 0
  60. #define COMPUTE_FLAGS 1
  61. #define XFORM_FORMAT (XFORM_FORMAT_LTOFX|XFORM_FORMAT_FXTOL|XFORM_FORMAT_LTOL)
  62. #define BLTOFXOK(x) (((x) < 0x07FFFFFF) && ((x) > -0x07FFFFFF))
  63. extern "C" {
  64. BOOL bCvtPts(PMATRIX pmx, PPOINTL pSrc, PPOINTL pDest, SIZE_T cPts);
  65. BOOL bCvtPts1(PMATRIX pmx, PPOINTL pptl, SIZE_T cPts);
  66. BOOL bCvtVts(PMATRIX pmx, PVECTORL pSrc, PVECTORL pDest, SIZE_T cPts);
  67. BOOL bCvtVts_FlToFl(PMATRIX pmx, PVECTORFL pSrc, PVECTORFL pDest, SIZE_T cPts);
  68. };
  69. extern MATRIX gmxIdentity_LToFx;
  70. extern MATRIX gmxIdentity_LToL;
  71. extern MATRIX gmxIdentity_FxToL;
  72. VOID vConvertXformToMatrix(CONST XFORML *pxf, PMATRIX pmx);
  73. #if DBG
  74. extern int giXformLevel;
  75. #define XFORMPRINT(l,s,a) {if (giXformLevel >= l) DbgPrint(s,a);}
  76. #else
  77. #define XFORMPRINT(l,s,a)
  78. #endif
  79. /******************************Class***************************************\
  80. * class EXFORMOBJ *
  81. * *
  82. * User object that lets clients interact with transforms. *
  83. * *
  84. * History: *
  85. * 12-Nov-1990 -by- Wendy Wu [wendywu] *
  86. * Wrote it. *
  87. \**************************************************************************/
  88. class EXFORMOBJ
  89. {
  90. public:
  91. MATRIX *pmx; // pointer to the matrix
  92. ULONG ulMode;
  93. BOOL bMirrored;
  94. public:
  95. // Constructor
  96. EXFORMOBJ() { pmx = (PMATRIX)NULL;
  97. bMirrored = FALSE;
  98. }
  99. // Constructor - Make the given matrix a transform.
  100. EXFORMOBJ(MATRIX& mx) { pmx = &mx;
  101. bMirrored = FALSE;
  102. }
  103. // Initialize the the xform
  104. VOID vInit(MATRIX *pmx_, FLONG fl = DONT_COMPUTE_FLAGS)
  105. {
  106. pmx = pmx_;
  107. if (fl & COMPUTE_FLAGS) // compute accelerator flags
  108. {
  109. vComputeAccelFlags(fl & XFORM_FORMAT);
  110. }
  111. else if (fl & XFORM_FORMAT)
  112. {
  113. pmx->flAccel = fl;
  114. }
  115. }
  116. // Constructor - Make a transform object given the pointer to the matrix.
  117. EXFORMOBJ(MATRIX *pmx_, FLONG fl)
  118. {
  119. pmx = pmx_;
  120. bMirrored = FALSE;
  121. if (fl & COMPUTE_FLAGS) // compute accelerator flags
  122. {
  123. vComputeAccelFlags(fl & XFORM_FORMAT);
  124. }
  125. else if (fl & XFORM_FORMAT)
  126. {
  127. pmx->flAccel = fl;
  128. }
  129. }
  130. // Constructor - Get a transform matrix based on the request type. The only
  131. // legitimate type for now is IDENTITY.
  132. EXFORMOBJ(ULONG iXform, ULONG iFormat = XFORM_FORMAT_LTOFX);
  133. #ifdef _DCOBJ_
  134. // Constructor - Get a transform from a DC.
  135. EXFORMOBJ(XDCOBJ& dco, ULONG iXform) {vQuickInit(dco,iXform);}
  136. VOID vQuickInit(XDCOBJ& dco, ULONG iXform)
  137. {
  138. ulMode = (ULONG)dco.pdc->iGraphicsMode();
  139. bMirrored = MIRRORED_DC(dco.pdc);
  140. if (!dco.pdc->bDirtyXform() && (iXform == WORLD_TO_DEVICE))
  141. {
  142. pmx = &dco.pdc->mxWorldToDevice();
  143. }
  144. else
  145. {
  146. vInit(dco,iXform);
  147. }
  148. }
  149. VOID vInit(XDCOBJ &dco, ULONG iXform);
  150. VOID vInitPageToDevice(XDCOBJ &dco, PMATRIX pmx_);
  151. #endif
  152. // vComputeWtoDAccelFlags - Compute accelerator flags for the world
  153. // to device xform.
  154. VOID vComputeWtoDAccelFlags()
  155. {
  156. pmx->flAccel = XFORM_FORMAT_LTOFX; // clear the flag
  157. // set translation flag
  158. if ((pmx->fxDx == 0) && (pmx->fxDy == 0))
  159. pmx->flAccel |= XFORM_NO_TRANSLATION;
  160. if (pmx->efM12.bIsZero() && pmx->efM21.bIsZero())
  161. {
  162. // off diagonal elements are zeros
  163. pmx->flAccel |= XFORM_SCALE;
  164. if (pmx->efM11.bIs16() && pmx->efM22.bIs16())
  165. pmx->flAccel |= XFORM_UNITY;
  166. }
  167. }
  168. // Destructor - Don't need to free anything.
  169. ~EXFORMOBJ() {}
  170. // bValid - Validator.
  171. BOOL bValid() { return(pmx != (PMATRIX)NULL); }
  172. // vComputeAccelFlags - Compute accelerator flags for a given transform matrix.
  173. VOID vComputeAccelFlags(FLONG flFormat = XFORM_FORMAT_LTOFX);
  174. // efM11 - Get/set coefficients of the given matrix.
  175. EFLOAT& efM11() {return(pmx->efM11);}
  176. EFLOAT& efM22() {return(pmx->efM22);}
  177. EFLOAT& efM12() {return(pmx->efM12);}
  178. EFLOAT& efM21() {return(pmx->efM21);}
  179. FIX fxDx() {return(pmx->fxDx);}
  180. FIX fxDy() {return(pmx->fxDy);}
  181. VOID vSetElementsLToL (
  182. EFLOAT ef11,
  183. EFLOAT ef12,
  184. EFLOAT ef21,
  185. EFLOAT ef22
  186. )
  187. {
  188. pmx->efM11 = ef11;
  189. pmx->efM12 = ef12;
  190. pmx->efM21 = ef21;
  191. pmx->efM22 = ef22;
  192. }
  193. VOID vSetElementsLToFx (
  194. FLOATL l_e11,
  195. FLOATL l_e12,
  196. FLOATL l_e21,
  197. FLOATL l_e22
  198. )
  199. {
  200. pmx->efM11 = l_e11;
  201. pmx->efM12 = l_e12;
  202. pmx->efM21 = l_e21;
  203. pmx->efM22 = l_e22;
  204. // Elements in a transform of LTOFX format must be scaled by 16.
  205. pmx->efM11.vTimes16();
  206. pmx->efM12.vTimes16();
  207. pmx->efM21.vTimes16();
  208. pmx->efM22.vTimes16();
  209. }
  210. // flAccel - Get the accelerator flag of a given matrix.
  211. FLONG flAccel() { return(pmx->flAccel); }
  212. FLONG flAccel(FLONG fl) { return(pmx->flAccel = fl); }
  213. // bEqual - See if two transforms are identical.
  214. BOOL bEqual(EXFORMOBJ& xo);
  215. // bEqualExceptTranslations - See if two transforms are identical in M11, M12,
  216. // M21, and M22.
  217. BOOL bEqualExceptTranslations(PMATRIX pmx_);
  218. BOOL bEqualExceptTranslations(EXFORMOBJ& xo)
  219. {
  220. return(bEqualExceptTranslations(xo.pmx));
  221. }
  222. // bScale -- See if a the off-diangonal elements of a transform are 0.
  223. BOOL bScale() { return(pmx->flAccel & XFORM_SCALE); }
  224. // bRotation -- See if there is rotation.
  225. BOOL bRotation() { return(!bScale()); }
  226. // bRotationOrMirroring -- See if there is a rotation or mirroring (negative
  227. // diagonal element(s) with 0 off-diagonal elements)
  228. BOOL bRotationOrMirroring() { return (bRotation() ||
  229. (
  230. !bMirrored &&
  231. ((pmx->efM11.bIsNegative()) || (pmx->efM22.bIsNegative()))
  232. )); }
  233. // bNoTranslation -- See if a transform has translation components.
  234. BOOL bNoTranslation() { return(pmx->flAccel & XFORM_NO_TRANSLATION); }
  235. // bIdentity - See if a given transform is an identity transform.
  236. BOOL bIdentity()
  237. {
  238. return((pmx->flAccel &
  239. (XFORM_SCALE | XFORM_UNITY | XFORM_NO_TRANSLATION)) ==
  240. (XFORM_SCALE | XFORM_UNITY | XFORM_NO_TRANSLATION));
  241. }
  242. // bTranslationsOnly - no rotations and scaling, translations may possibly
  243. // be zero
  244. BOOL bTranslationsOnly () { return (pmx->flAccel & XFORM_UNITY); }
  245. // bConformal -- Does the transform preserve angles?
  246. // looks at the 2 X 2 transform only
  247. BOOL bConformal()
  248. {
  249. EFLOAT ef;
  250. ef = pmx->efM21;
  251. ef.vNegate();
  252. return (pmx->efM11 == pmx->efM22 && pmx->efM12 == ef);
  253. }
  254. // bXform - Apply the transform to various objects. Return FALSE on
  255. // overflow.
  256. // Transform a list of points.
  257. BOOL bXform(PPOINTL pptlSrc,PPOINTL pptlDst,SIZE_T cPts);
  258. BOOL bXform(PPOINTL pSrc, PPOINTFIX pDest, SIZE_T cPts);
  259. BOOL bXform(PPOINTFIX pSrc, PPOINTL pDest, SIZE_T cPts);
  260. BOOL bXformRound(PPOINTL pSrc, PPOINTFIX pDest, SIZE_T cPts);
  261. // Transform a list of points in place.
  262. BOOL bXform(PPOINTL pptl, SIZE_T cPts)
  263. {
  264. return(bIdentity() || bCvtPts1(pmx, pptl, cPts));
  265. }
  266. BOOL bXform(EPOINTL& eptl)
  267. {
  268. return(bXform((PPOINTL) &eptl, 1));
  269. }
  270. BOOL bXform(ERECTL& ercl)
  271. {
  272. BOOL bRet;
  273. bRet = bXform((PPOINTL) &ercl, 2);
  274. // If it a mirrored DC then shift the rect one pixel to the right
  275. // This will give the effect of including the right edge of the rect and exclude the left edge.
  276. if (bMirrored) {
  277. ++ercl.left;
  278. ++ercl.right;
  279. }
  280. return (bRet);
  281. }
  282. // Transform a list of vectors.
  283. BOOL bXform(PVECTORFL pvtflSrc, PVECTORFL pvtflDst,SIZE_T cVts);
  284. BOOL bXform(PVECTORL pSrc, PVECTORFX pDest, SIZE_T cVts);
  285. BOOL bXform(PVECTORL pSrc, PVECTORL pDest, SIZE_T cVts);
  286. BOOL bXform(PVECTORFX pSrc, PVECTORL pDest, SIZE_T cVts);
  287. BOOL bXformRound(PVECTORL pSrc, PVECTORFX pDest, SIZE_T cVts);
  288. // Transform a list of vectors in place.
  289. BOOL bXform(PVECTORFL pvtfl, SIZE_T cVts)
  290. {
  291. BOOL bReturn = TRUE;
  292. if (!bTranslationsOnly())
  293. bReturn = bXform(pvtfl, pvtfl, cVts);
  294. return(bReturn);
  295. }
  296. BOOL bXform(EVECTORFL& evtfl)
  297. {
  298. return(bXform((PVECTORFL) &evtfl, 1));
  299. }
  300. BOOL bXform(EVECTORL& evtl)
  301. {
  302. BOOL bReturn = TRUE;
  303. if (!bTranslationsOnly())
  304. bReturn = bXform((PVECTORL)&evtl, (PVECTORL)&evtl, 1);
  305. return(bReturn);
  306. }
  307. // bMultiply - Multiply two XFORMs together and store the result in the
  308. // XFORMOBJ.
  309. BOOL bMultiply(PMATRIX pmxLeft, PMATRIX pmxRight,
  310. FLONG fl = DONT_COMPUTE_FLAGS);
  311. BOOL bMultiply(EXFORMOBJ& exoLeft, EXFORMOBJ& exoRight,
  312. FLONG fl = DONT_COMPUTE_FLAGS)
  313. {
  314. return(bMultiply(exoLeft.pmx, exoRight.pmx, fl));
  315. }
  316. // bMultToWorld - Multiply the world transform with a given matrix. The
  317. // result is stored in the passed in matrix. This is so
  318. // that the resultant matrix can be range-checked later on
  319. // before the WORLD_TO_PAGE xform is changed.
  320. // The order of the multiplication is based on imode.
  321. // If imode == MWT_LEFTMULTIPLY, the given matrix is applied
  322. // to the left of the multiplication. It's applied to the
  323. // right otherwise.
  324. BOOL bMultToWorld(MATRIX *pmx_, ULONG imode)
  325. {
  326. MATRIX mx = *pmx_;
  327. EXFORMOBJ xo(pmx_, DONT_COMPUTE_FLAGS);
  328. if (imode == MWT_LEFTMULTIPLY)
  329. return(xo.bMultiply(&mx, pmx));
  330. else
  331. return(xo.bMultiply(pmx, &mx));
  332. }
  333. // vRemoveTranslation - Remove the translation coefficients from a matrix.
  334. VOID vRemoveTranslation();
  335. // vGetCoefficient - Get the coefficients of a transform matrix. This is
  336. // used to convert our internal matrix structure into
  337. // the GDI/DDI transform format.
  338. VOID vGetCoefficient(PFLOATOBJ_XFORM pxf);
  339. // vGetCoefficient - Get the coefficients of a transform matrix. This is
  340. // used to convert our internal matrix structure into
  341. // the GDI/DDI transform format.
  342. VOID vGetCoefficient(XFORML *pxf);
  343. // vGetCoefficient - Get the coefficients of a transform matrix. This is
  344. // used to convert our internal matrix structure into
  345. // the IFI transform format.
  346. VOID vGetCoefficient(PFD_XFORM pxf);
  347. // vSetScaling - Set the scaling factors for a given matrix.
  348. VOID vSetScaling(EFLOAT efM11, EFLOAT efM22,
  349. FLONG fl = DONT_COMPUTE_FLAGS)
  350. {
  351. ASSERTGDI(pmx->efM12.bIsZero(), "vSetScaling error: M12 not zero");
  352. ASSERTGDI(pmx->efM21.bIsZero(), "vSetScaling error: M21 not zero");
  353. pmx->efM11 = efM11;
  354. pmx->efM22 = efM22;
  355. if (fl & COMPUTE_FLAGS)
  356. vComputeAccelFlags(fl & XFORM_FORMAT);
  357. }
  358. // vSetTranslations - Set the translations for a given matrix.
  359. VOID vSetTranslations(EFLOAT efDx, EFLOAT efDy)
  360. {
  361. FIX fxDx, fxDy;
  362. pmx->efDx = efDx;
  363. pmx->efDy = efDy;
  364. #if DBG
  365. if (!efDx.bEfToL(fxDx))
  366. WARNING("vSetTranslations:dx overflowed\n");
  367. if (!efDy.bEfToL(fxDy))
  368. WARNING("vSetTranslations:dy overflowed\n");
  369. #else
  370. efDx.bEfToL(fxDx);
  371. efDy.bEfToL(fxDy);
  372. #endif
  373. pmx->fxDx = fxDx;
  374. pmx->fxDy = fxDy;
  375. if ((fxDx == 0) && (fxDy == 0))
  376. pmx->flAccel |= XFORM_NO_TRANSLATION;
  377. else
  378. pmx->flAccel &= ~(XFORM_NO_TRANSLATION);
  379. }
  380. // vSet - Set the coefficients for a given matrix.
  381. // This is used to set WorldToPage transform.
  382. VOID vSet(MATRIX *pmx_, FLONG fl = DONT_COMPUTE_FLAGS)
  383. {
  384. *pmx = *pmx_;
  385. if (fl & COMPUTE_FLAGS)
  386. vComputeAccelFlags(fl & XFORM_FORMAT);
  387. }
  388. // vCopy -- Copy a transform obj to another.
  389. VOID vCopy(EXFORMOBJ& xoSrc);
  390. // vOrder -- Order a rectangle based on the PAGE_TO_DEVICE transform.
  391. // The rectangle will be well ordered after the PAGE_TO_DEVICE
  392. // transform is applied.
  393. VOID vOrder(RECTL &rcl);
  394. // bInverse -- Calculate the inverse of a passed in xform/matrix and store
  395. // the result in the XFORMOBJ. The source and destination
  396. // matrices CANNOT be the same one.
  397. BOOL bInverse(MATRIX& mxSrc);
  398. BOOL bInverse(EXFORMOBJ& xo) { return(bInverse(*(xo.pmx))); }
  399. // bComputeUnits -- Calculates a simplified transform for vectors parallel
  400. // to the given angle.
  401. BOOL bComputeUnits(LONG lAngle,POINTFL *ppte,EFLOAT *pefWD,EFLOAT *pefDW);
  402. // fxFastX -- Does a quick scaling transform on x.
  403. FIX fxFastX(LONG ll) {return((FIX) lCvt(pmx->efM11,ll) + pmx->fxDx);}
  404. // fxFastY -- Does a quick scaling transform on y.
  405. FIX fxFastY(LONG ll) {return((FIX) lCvt(pmx->efM22,ll) + pmx->fxDy);}
  406. };
  407. typedef EXFORMOBJ *PEXFORMOBJ;