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
16 KiB

  1. /***************************************************************************\
  2. *
  3. * File: Matrix.cpp
  4. *
  5. * Description:
  6. * Matrix.cpp implements common Matrix and Vector operations.
  7. *
  8. *
  9. * History:
  10. * 3/25/2000: JStall: Created
  11. *
  12. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  13. *
  14. \***************************************************************************/
  15. #include "stdafx.h"
  16. #include "Base.h"
  17. #include "Matrix.h"
  18. #include "Rect.h"
  19. /***************************************************************************\
  20. *****************************************************************************
  21. *
  22. * class Vector3
  23. *
  24. *****************************************************************************
  25. \***************************************************************************/
  26. #if DBG
  27. //------------------------------------------------------------------------------
  28. void
  29. Vector3::Dump() const
  30. {
  31. Trace(" | %6.2f, %6.2f, %6.2f |\n", m_rgfl[0], m_rgfl[1], m_rgfl[2]);
  32. }
  33. #endif // DBG
  34. /***************************************************************************\
  35. *****************************************************************************
  36. *
  37. * class Matrix3
  38. *
  39. *****************************************************************************
  40. \***************************************************************************/
  41. /*
  42. //
  43. // Standard multiplication of A by the current Matrix. This can be used
  44. // as a template to be optimized for different cases.
  45. //
  46. Vector3 rgvT0 = m_rgv[0];
  47. Vector3 rgvT1 = m_rgv[1];
  48. Vector3 rgvT2 = m_rgv[2];
  49. m_rgv[0].Set(A[0][0] * rgvT0[0] + A[0][1] * rgvT1[0] + A[0][2] * rgvT2[0],
  50. A[0][0] * rgvT0[1] + A[0][1] * rgvT1[1] + A[0][2] * rgvT2[1],
  51. A[0][0] * rgvT0[2] + A[0][1] * rgvT1[2] + A[0][2] * rgvT2[2]);
  52. m_rgv[1].Set(A[1][0] * rgvT0[0] + A[1][1] * rgvT1[0] + A[1][2] * rgvT2[0],
  53. A[1][0] * rgvT0[1] + A[1][1] * rgvT1[1] + A[1][2] * rgvT2[1],
  54. A[1][0] * rgvT0[2] + A[1][1] * rgvT1[2] + A[1][2] * rgvT2[2]);
  55. m_rgv[2].Set(A[2][0] * rgvT0[0] + A[2][1] * rgvT1[0] + A[2][2] * rgvT2[0],
  56. A[2][0] * rgvT0[1] + A[2][1] * rgvT1[1] + A[2][2] * rgvT2[1],
  57. A[2][0] * rgvT0[2] + A[2][1] * rgvT1[2] + A[2][2] * rgvT2[2]);
  58. */
  59. /***************************************************************************\
  60. *
  61. * Matrix3::ApplyLeft
  62. *
  63. * ApplyLeft() left-multiples the given GDI matrix to the current matrix and
  64. * stores the result in the current matrix.
  65. *
  66. * mCurrent = pxfLeft * mCurrent
  67. *
  68. \***************************************************************************/
  69. void
  70. Matrix3::ApplyLeft(
  71. IN const XFORM * pxfLeft) // GDI matrix to left-multiply
  72. {
  73. const XFORM * pxf = pxfLeft;
  74. Vector3 rgvT0 = m_rgv[0];
  75. Vector3 rgvT1 = m_rgv[1];
  76. Vector3 rgvT2 = m_rgv[2];
  77. m_rgv[0].Set(pxf->eM11 * rgvT0[0] + pxf->eM12 * rgvT1[0],
  78. pxf->eM11 * rgvT0[1] + pxf->eM12 * rgvT1[1],
  79. pxf->eM11 * rgvT0[2] + pxf->eM12 * rgvT1[2]);
  80. m_rgv[1].Set(pxf->eM21 * rgvT0[0] + pxf->eM22 * rgvT1[0],
  81. pxf->eM21 * rgvT0[1] + pxf->eM22 * rgvT1[1],
  82. pxf->eM21 * rgvT0[2] + pxf->eM22 * rgvT1[2]);
  83. m_rgv[2].Set(pxf->eDx * rgvT0[0] + pxf->eDy * rgvT1[0] + rgvT2[0],
  84. pxf->eDx * rgvT0[1] + pxf->eDy * rgvT1[1] + rgvT2[1],
  85. pxf->eDx * rgvT0[2] + pxf->eDy * rgvT1[2] + rgvT2[2]);
  86. m_fIdentity = FALSE;
  87. m_fOnlyTranslate = FALSE;
  88. }
  89. /***************************************************************************\
  90. *
  91. * Matrix3::ApplyLeft
  92. *
  93. * ApplyLeft() left-multiples the given matrix to the current matrix and
  94. * stores the result in the current matrix.
  95. *
  96. * mCurrent = mLeft * mCurrent
  97. *
  98. \***************************************************************************/
  99. void
  100. Matrix3::ApplyLeft(
  101. IN const Matrix3 & mLeft) // Matrix to left-multiply
  102. {
  103. if (mLeft.m_fIdentity) {
  104. return;
  105. }
  106. if (m_fOnlyTranslate && mLeft.m_fOnlyTranslate) {
  107. m_rgv[2].Set(0, m_rgv[2][0] + mLeft.m_rgv[2][0]);
  108. m_rgv[2].Set(1, m_rgv[2][1] + mLeft.m_rgv[2][1]);
  109. m_fIdentity = FALSE;
  110. return;
  111. }
  112. const Vector3 & A0 = mLeft.m_rgv[0];
  113. const Vector3 & A1 = mLeft.m_rgv[1];
  114. const Vector3 & A2 = mLeft.m_rgv[2];
  115. Vector3 B0 = m_rgv[0];
  116. Vector3 B1 = m_rgv[1];
  117. Vector3 B2 = m_rgv[2];
  118. m_rgv[0].Set(A0[0] * B0[0] + A0[1] * B1[0] + A0[2] * B2[0],
  119. A0[0] * B0[1] + A0[1] * B1[1] + A0[2] * B2[1],
  120. A0[0] * B0[2] + A0[1] * B1[2] + A0[2] * B2[2]);
  121. m_rgv[1].Set(A1[0] * B0[0] + A1[1] * B1[0] + A1[2] * B2[0],
  122. A1[0] * B0[1] + A1[1] * B1[1] + A1[2] * B2[1],
  123. A1[0] * B0[2] + A1[1] * B1[2] + A1[2] * B2[2]);
  124. m_rgv[2].Set(A2[0] * B0[0] + A2[1] * B1[0] + A2[2] * B2[0],
  125. A2[0] * B0[1] + A2[1] * B1[1] + A2[2] * B2[1],
  126. A2[0] * B0[2] + A2[1] * B1[2] + A2[2] * B2[2]);
  127. m_fIdentity = FALSE;
  128. m_fOnlyTranslate = FALSE;
  129. }
  130. /***************************************************************************\
  131. *
  132. * Matrix3::ApplyRight
  133. *
  134. * ApplyRight() right-multiples the given matrix to the current matrix and
  135. * stores the result in the current matrix.
  136. *
  137. * mCurrent = mCurrent * mRight
  138. *
  139. \***************************************************************************/
  140. void
  141. Matrix3::ApplyRight(
  142. IN const Matrix3 & mRight) // Matrix to right-multiply
  143. {
  144. if (mRight.m_fIdentity) {
  145. return;
  146. }
  147. if (m_fOnlyTranslate && mRight.m_fOnlyTranslate) {
  148. m_rgv[2].Set(0, m_rgv[2][0] + mRight.m_rgv[2][0]);
  149. m_rgv[2].Set(1, m_rgv[2][1] + mRight.m_rgv[2][1]);
  150. m_fIdentity = FALSE;
  151. return;
  152. }
  153. Vector3 A0 = m_rgv[0];
  154. Vector3 A1 = m_rgv[1];
  155. Vector3 A2 = m_rgv[2];
  156. const Vector3 & B0 = mRight.m_rgv[0];
  157. const Vector3 & B1 = mRight.m_rgv[1];
  158. const Vector3 & B2 = mRight.m_rgv[2];
  159. m_rgv[0].Set(A0[0] * B0[0] + A0[1] * B1[0] + A0[2] * B2[0],
  160. A0[0] * B0[1] + A0[1] * B1[1] + A0[2] * B2[1],
  161. A0[0] * B0[2] + A0[1] * B1[2] + A0[2] * B2[2]);
  162. m_rgv[1].Set(A1[0] * B0[0] + A1[1] * B1[0] + A1[2] * B2[0],
  163. A1[0] * B0[1] + A1[1] * B1[1] + A1[2] * B2[1],
  164. A1[0] * B0[2] + A1[1] * B1[2] + A1[2] * B2[2]);
  165. m_rgv[2].Set(A2[0] * B0[0] + A2[1] * B1[0] + A2[2] * B2[0],
  166. A2[0] * B0[1] + A2[1] * B1[1] + A2[2] * B2[1],
  167. A2[0] * B0[2] + A2[1] * B1[2] + A2[2] * B2[2]);
  168. m_fIdentity = FALSE;
  169. m_fOnlyTranslate = FALSE;
  170. }
  171. /***************************************************************************\
  172. *
  173. * Matrix3::ApplyRight
  174. *
  175. * ApplyRight() right-multiples the given matrix to the current matrix and
  176. * stores the result in the current matrix.
  177. *
  178. \***************************************************************************/
  179. void
  180. Matrix3::Get(
  181. OUT XFORM * pxf // GDI matrix to receive information
  182. ) const
  183. {
  184. pxf->eM11 = m_rgv[0][0];
  185. pxf->eM12 = m_rgv[0][1];
  186. pxf->eM21 = m_rgv[1][0];
  187. pxf->eM22 = m_rgv[1][1];
  188. pxf->eDx = m_rgv[2][0];
  189. pxf->eDy = m_rgv[2][1];
  190. }
  191. /***************************************************************************\
  192. *
  193. * Matrix3::Execute
  194. *
  195. * Execute() applies to given matrix on the collection of points,
  196. * transforming each appropriately.
  197. *
  198. \***************************************************************************/
  199. void
  200. Matrix3::Execute(
  201. IN OUT POINT * rgpt, // Points to apply matrix on
  202. IN int cPoints) const // Number of points
  203. {
  204. if (m_fIdentity) {
  205. return;
  206. }
  207. POINT ptT, ptN;
  208. POINT * pptCur = rgpt;
  209. if (m_fOnlyTranslate) {
  210. //
  211. // Only have translated so far, so can just offset the points without
  212. // going through an entire transformation.
  213. //
  214. while (cPoints-- > 0) {
  215. ptT = *pptCur;
  216. ptN.x = ptT.x + (int) m_rgv[2][0];
  217. ptN.y = ptT.y + (int) m_rgv[2][1];
  218. *pptCur++ = ptN;
  219. }
  220. } else {
  221. while (cPoints-- > 0) {
  222. ptT = *pptCur;
  223. ptN.x = (int) (ptT.x * m_rgv[0][0] + ptT.y * m_rgv[1][0] + m_rgv[2][0] + 0.5f);
  224. ptN.y = (int) (ptT.x * m_rgv[0][1] + ptT.y * m_rgv[1][1] + m_rgv[2][1] + 0.5f);
  225. *pptCur++ = ptN;
  226. }
  227. }
  228. }
  229. /***************************************************************************\
  230. *
  231. * Matrix3::ComputeBounds
  232. *
  233. * ComputeBounds() computes the bounding box that will contain the given
  234. * transformed rectangle.
  235. *
  236. \***************************************************************************/
  237. void
  238. Matrix3::ComputeBounds(
  239. OUT RECT * prcBounds, // The bound of the transformation
  240. IN const RECT * prcLogical, // The logical rectangle to transform
  241. IN EHintBounds hb // Hinting for border pixels
  242. ) const
  243. {
  244. if (m_fIdentity) {
  245. AssertMsg(InlineIsRectNormalized(prcLogical), "Ensure normalized rect");
  246. *prcBounds = *prcLogical;
  247. return;
  248. }
  249. if (m_fOnlyTranslate) {
  250. //
  251. // Only have translated, so the bounding
  252. //
  253. AssertMsg(InlineIsRectNormalized(prcLogical), "Ensure normalized rect");
  254. *prcBounds = *prcLogical;
  255. InlineOffsetRect(prcBounds, (int) m_rgv[2][0], (int) m_rgv[2][1]);
  256. return;
  257. }
  258. POINT rgpt[4];
  259. rgpt[0].x = prcLogical->left;
  260. rgpt[0].y = prcLogical->top;
  261. rgpt[1].x = prcLogical->right;
  262. rgpt[1].y = prcLogical->top;
  263. rgpt[2].x = prcLogical->right;
  264. rgpt[2].y = prcLogical->bottom;
  265. rgpt[3].x = prcLogical->left;
  266. rgpt[3].y = prcLogical->bottom;
  267. Execute(rgpt, _countof(rgpt));
  268. prcBounds->left = min(min(rgpt[0].x, rgpt[1].x), min(rgpt[2].x, rgpt[3].x));
  269. prcBounds->top = min(min(rgpt[0].y, rgpt[1].y), min(rgpt[2].y, rgpt[3].y));
  270. prcBounds->right = max(max(rgpt[0].x, rgpt[1].x), max(rgpt[2].x, rgpt[3].x));
  271. prcBounds->bottom = max(max(rgpt[0].y, rgpt[1].y), max(rgpt[2].y, rgpt[3].y));
  272. if (hb == hbOutside) {
  273. //
  274. // Just converted from int to float back to int, so we may have rounding
  275. // errors. To compensate, need to inflate the given rectangle so that
  276. // it overlaps these errors.
  277. //
  278. InlineInflateRect(prcBounds, 1, 1);
  279. }
  280. }
  281. /***************************************************************************\
  282. *
  283. * Matrix3::ComputeRgn
  284. *
  285. * ComputeRgn() builds a region for the quadrilateral generated by applying
  286. * this matrix to the given rectangle.
  287. *
  288. \***************************************************************************/
  289. int
  290. Matrix3::ComputeRgn(
  291. IN HRGN hrgnDest,
  292. IN const RECT * prcLogical,
  293. IN SIZE sizeOffsetPxl
  294. ) const
  295. {
  296. AssertMsg(hrgnDest != NULL, "Must specify a valid (real) region");
  297. if (m_fIdentity || m_fOnlyTranslate){
  298. AssertMsg(InlineIsRectNormalized(prcLogical), "Ensure normalized rect");
  299. RECT rcBounds = *prcLogical;
  300. InlineOffsetRect(&rcBounds,
  301. ((int) m_rgv[2][0]) + sizeOffsetPxl.cx,
  302. ((int) m_rgv[2][1]) + sizeOffsetPxl.cy);
  303. BOOL fSuccess = SetRectRgn(hrgnDest, rcBounds.left, rcBounds.top, rcBounds.right, rcBounds.bottom);
  304. return fSuccess ? SIMPLEREGION : ERROR;
  305. }
  306. POINT rgpt[4];
  307. rgpt[0].x = prcLogical->left;
  308. rgpt[0].y = prcLogical->top;
  309. rgpt[1].x = prcLogical->right;
  310. rgpt[1].y = prcLogical->top;
  311. rgpt[2].x = prcLogical->right;
  312. rgpt[2].y = prcLogical->bottom;
  313. rgpt[3].x = prcLogical->left;
  314. rgpt[3].y = prcLogical->bottom;
  315. Execute(rgpt, _countof(rgpt));
  316. HRGN hrgnTemp = CreatePolygonRgn(rgpt, _countof(rgpt), WINDING);
  317. if (hrgnTemp == NULL) {
  318. return ERROR;
  319. }
  320. int nResult;
  321. nResult = OffsetRgn(hrgnTemp, sizeOffsetPxl.cx, sizeOffsetPxl.cy);
  322. AssertMsg((nResult == SIMPLEREGION) || (nResult == COMPLEXREGION),
  323. "Just successfully created region should be either simple or complex");
  324. nResult = CombineRgn(hrgnDest, hrgnTemp, NULL, RGN_COPY);
  325. DeleteObject(hrgnTemp);
  326. return nResult;
  327. }
  328. /***************************************************************************\
  329. *
  330. * Matrix3::SetIdentity
  331. *
  332. * SetIdentity() resets the matrix to the identity matrix.
  333. *
  334. \***************************************************************************/
  335. void
  336. Matrix3::SetIdentity()
  337. {
  338. m_rgv[0].Set(1.0f, 0.0f, 0.0f);
  339. m_rgv[1].Set(0.0f, 1.0f, 0.0f);
  340. m_rgv[2].Set(0.0f, 0.0f, 1.0f);
  341. m_fIdentity = TRUE;
  342. m_fOnlyTranslate = TRUE;
  343. }
  344. /***************************************************************************\
  345. *
  346. * Matrix3::Rotate
  347. *
  348. * Rotate() rotates the matrix by the specified angle. The specific
  349. * orientation of clockwise or counterclockwise depends on how the matrix
  350. * is being applied. For MM_TEXT, this is clockwise.
  351. *
  352. \***************************************************************************/
  353. void
  354. Matrix3::Rotate(
  355. IN float flRotationRad) // Rotation angle in radians
  356. {
  357. float flCos = (float) cos(flRotationRad);
  358. float flSin = (float) sin(flRotationRad);
  359. float flSinN = - flSin;
  360. Vector3 rgvT0 = m_rgv[0];
  361. Vector3 rgvT1 = m_rgv[1];
  362. Vector3 rgvT2 = m_rgv[2];
  363. m_rgv[0].Set(flCos * rgvT0[0] + flSin * rgvT1[0],
  364. flCos * rgvT0[1] + flSin * rgvT1[1],
  365. flCos * rgvT0[2] + flSin * rgvT1[2]);
  366. m_rgv[1].Set(flSinN * rgvT0[0] + flCos * rgvT1[0],
  367. flSinN * rgvT0[1] + flCos * rgvT1[1],
  368. flSinN * rgvT0[2] + flCos * rgvT1[2]);
  369. m_fIdentity = FALSE;
  370. m_fOnlyTranslate = FALSE;
  371. }
  372. /***************************************************************************\
  373. *
  374. * Matrix3::Translate
  375. *
  376. * Translate() offsets the matrix.
  377. *
  378. \***************************************************************************/
  379. void
  380. Matrix3::Translate(
  381. IN float flOffsetX, // Horizontal offset
  382. IN float flOffsetY) // Vertical offset
  383. {
  384. if (m_fOnlyTranslate) {
  385. AssertMsg(fabs(m_rgv[2][2] - 1.0f) < 0.00001f, "Should still be 1.0f");
  386. m_rgv[2].Set(m_rgv[2][0] + flOffsetX,
  387. m_rgv[2][1] + flOffsetY,
  388. 1.0f);
  389. m_fIdentity = FALSE;
  390. return;
  391. }
  392. Vector3 rgvT0 = m_rgv[0];
  393. Vector3 rgvT1 = m_rgv[1];
  394. Vector3 rgvT2 = m_rgv[2];
  395. m_rgv[2].Set(flOffsetX * rgvT0[0] + flOffsetY * rgvT1[0] + rgvT2[0],
  396. flOffsetX * rgvT0[1] + flOffsetY * rgvT1[1] + rgvT2[1],
  397. flOffsetX * rgvT0[2] + flOffsetY * rgvT1[2] + rgvT2[2]);
  398. m_fIdentity = FALSE;
  399. }
  400. /***************************************************************************\
  401. *
  402. * Matrix3::Scale
  403. *
  404. * Scale() scales the matrix.
  405. *
  406. \***************************************************************************/
  407. void
  408. Matrix3::Scale(
  409. IN float flScaleX, // Horizontal scaling
  410. IN float flScaleY) // Vertical scaling
  411. {
  412. Vector3 rgvT0 = m_rgv[0];
  413. Vector3 rgvT1 = m_rgv[1];
  414. Vector3 rgvT2 = m_rgv[2];
  415. m_rgv[0].Set(flScaleX * rgvT0[0],
  416. flScaleX * rgvT0[1],
  417. flScaleX * rgvT0[2]);
  418. m_rgv[1].Set(flScaleY * rgvT1[0],
  419. flScaleY * rgvT1[1],
  420. flScaleY * rgvT1[2]);
  421. m_fIdentity = FALSE;
  422. m_fOnlyTranslate = FALSE;
  423. }
  424. #if DBG
  425. //------------------------------------------------------------------------------
  426. void
  427. Matrix3::Dump() const
  428. {
  429. m_rgv[0].Dump();
  430. m_rgv[1].Dump();
  431. m_rgv[2].Dump();
  432. }
  433. #endif // DBG