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.

616 lines
18 KiB

  1. /*****************************************************************************
  2. *
  3. * conics - Entry points for Win32 to Win 16 converter
  4. *
  5. * Date: 7/1/91
  6. * Author: Jeffrey Newman (c-jeffn)
  7. *
  8. * Copyright 1991 Microsoft Corp
  9. *****************************************************************************/
  10. #include "precomp.h"
  11. #pragma hdrstop
  12. FLOAT eRadsPerDegree = (FLOAT) (ePI / (FLOAT) 180.0) ;
  13. BOOL bFindRadialEllipseIntersection(PLOCALDC pLocalDC,
  14. INT x1, INT y1, INT x2, INT y2,
  15. INT x3, INT y3, INT x4, INT y4,
  16. PPOINT pptStart, PPOINT pptEnd) ;
  17. BOOL bIncIncToIncExcXform (PLOCALDC pLocalDC, PRECTL prcl) ;
  18. VOID vDoArcReflection(PLOCALDC pLocalDC, PPOINTL pptl) ;
  19. /***************************************************************************
  20. * DoSetArcDirection - Win32 to Win16 Metafile Converter Entry Point
  21. **************************************************************************/
  22. BOOL WINAPI DoSetArcDirection(PLOCALDC pLocalDC, INT iArcDirection)
  23. {
  24. pLocalDC->iArcDirection = iArcDirection ;
  25. return(SetArcDirection(pLocalDC->hdcHelper, iArcDirection) != 0);
  26. }
  27. /***************************************************************************
  28. * AngleArc - Win32 to Win16 Metafile Converter Entry Point
  29. **************************************************************************/
  30. BOOL WINAPI DoAngleArc
  31. (
  32. PLOCALDC pLocalDC,
  33. int x,
  34. int y,
  35. DWORD ulRadius,
  36. FLOAT eStartAngle,
  37. FLOAT eSweepAngle
  38. )
  39. {
  40. BOOL b ;
  41. POINTL aptl[4] ;
  42. FLOAT eEndAngle;
  43. INT iArcDirection;
  44. // If we're recording the drawing orders for a path
  45. // then just pass the drawing order to the helper DC.
  46. // Do not emit any Win16 drawing orders.
  47. if (pLocalDC->flags & RECORDING_PATH)
  48. {
  49. b = AngleArc(pLocalDC->hdcHelper, x, y, ulRadius, eStartAngle, eSweepAngle) ;
  50. ASSERTGDI(b, "MF3216: DoAngleArc, in path render failed\n") ;
  51. return(b) ;
  52. }
  53. // Do the transformations.
  54. // And emit the Win16 drawing orders.
  55. if (pLocalDC->flags & STRANGE_XFORM
  56. || eSweepAngle > 360.0f // more than one revolution
  57. || eSweepAngle < -360.0f
  58. )
  59. {
  60. b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
  61. x, y, 0, 0, 0, 0, 0, 0,
  62. ulRadius, eStartAngle, eSweepAngle, EMR_ANGLEARC);
  63. return(b);
  64. }
  65. // Calculate the ARC bounding box.
  66. aptl[0].x = x - ulRadius ;
  67. aptl[0].y = y - ulRadius ;
  68. aptl[1].x = x + ulRadius ;
  69. aptl[1].y = y + ulRadius ;
  70. // Calculate the begin and end points for ARC from the
  71. // eStartAngle and eSweepAngle.
  72. aptl[2].x = x + (LONG) ((double) (ulRadius) * cos(eStartAngle * eRadsPerDegree) + 0.5f) ;
  73. aptl[2].y = y - (LONG) ((double) (ulRadius) * sin(eStartAngle * eRadsPerDegree) + 0.5f) ;
  74. eEndAngle = eStartAngle + eSweepAngle ;
  75. aptl[3].x = x + (LONG) ((double) (ulRadius) * cos(eEndAngle * eRadsPerDegree) + 0.5f) ;
  76. aptl[3].y = y - (LONG) ((double) (ulRadius) * sin(eEndAngle * eRadsPerDegree) + 0.5f) ;
  77. // If the endpoints are identical, we cannot represent the AngleArc as
  78. // an ArcTo. Use path to render it instead.
  79. if (aptl[2].x == aptl[3].x && aptl[2].y == aptl[3].y)
  80. {
  81. b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
  82. x, y, 0, 0, 0, 0, 0, 0,
  83. ulRadius, eStartAngle, eSweepAngle, EMR_ANGLEARC);
  84. return(b);
  85. }
  86. // At this point we have the same parameters that would apply to
  87. // a standard ArcTo. However, we still need to determine the arc
  88. // direction to apply. If the sweep angle is positive, it is counter-
  89. // clockwise. If the sweep angle is negative, it is clockwise.
  90. // Save the current arc direction.
  91. iArcDirection = pLocalDC->iArcDirection;
  92. // Prepare the arc direction for the ArcTo.
  93. (void) DoSetArcDirection
  94. (pLocalDC, eSweepAngle < 0.0f ? AD_CLOCKWISE : AD_COUNTERCLOCKWISE);
  95. // Do the ArcTo.
  96. b = DoArcTo(pLocalDC, aptl[0].x, aptl[0].y, aptl[1].x, aptl[1].y,
  97. aptl[2].x, aptl[2].y, aptl[3].x, aptl[3].y) ;
  98. // Restore the current arc direction.
  99. (void) DoSetArcDirection(pLocalDC, iArcDirection);
  100. return (b) ;
  101. }
  102. /***************************************************************************
  103. * Arc - Win32 to Win16 Metafile Converter Entry Point
  104. **************************************************************************/
  105. BOOL WINAPI DoArc
  106. (
  107. PLOCALDC pLocalDC,
  108. int x1,
  109. int y1,
  110. int x2,
  111. int y2,
  112. int x3,
  113. int y3,
  114. int x4,
  115. int y4
  116. )
  117. {
  118. BOOL b ;
  119. b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_ARC) ;
  120. return(b) ;
  121. }
  122. /***************************************************************************
  123. * ArcTo - Win32 to Win16 Metafile Converter Entry Point
  124. **************************************************************************/
  125. BOOL WINAPI DoArcTo
  126. (
  127. PLOCALDC pLocalDC,
  128. int x1,
  129. int y1,
  130. int x2,
  131. int y2,
  132. int x3,
  133. int y3,
  134. int x4,
  135. int y4
  136. )
  137. {
  138. BOOL b ;
  139. POINT ptStart,
  140. ptEnd ;
  141. // If we're recording the drawing orders for a path
  142. // then just pass the drawing order to the helper DC.
  143. // Do not emit any Win16 drawing orders.
  144. if (pLocalDC->flags & RECORDING_PATH)
  145. {
  146. b = ArcTo(pLocalDC->hdcHelper, x1, y1, x2, y2, x3, y3, x4, y4) ;
  147. return(b) ;
  148. }
  149. b = bFindRadialEllipseIntersection(pLocalDC,
  150. x1, y1, x2, y2,
  151. x3, y3, x4, y4,
  152. &ptStart, &ptEnd) ;
  153. if (b == FALSE)
  154. return(b) ;
  155. b = DoLineTo(pLocalDC, ptStart.x, ptStart.y) ;
  156. if (b == FALSE)
  157. return(b) ;
  158. b = DoArc(pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4) ;
  159. if (b == FALSE)
  160. return(b) ;
  161. b = DoMoveTo(pLocalDC, ptEnd.x, ptEnd.y) ;
  162. return(b) ;
  163. }
  164. /***************************************************************************
  165. * Chord - Win32 to Win16 Metafile Converter Entry Point
  166. **************************************************************************/
  167. BOOL WINAPI DoChord
  168. (
  169. PLOCALDC pLocalDC,
  170. int x1,
  171. int y1,
  172. int x2,
  173. int y2,
  174. int x3,
  175. int y3,
  176. int x4,
  177. int y4
  178. )
  179. {
  180. BOOL b ;
  181. b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_CHORD) ;
  182. return(b) ;
  183. }
  184. /***************************************************************************
  185. * Ellipse - Win32 to Win16 Metafile Converter Entry Point
  186. **************************************************************************/
  187. BOOL WINAPI DoEllipse
  188. (
  189. PLOCALDC pLocalDC,
  190. int x1,
  191. int y1,
  192. int x2,
  193. int y2
  194. )
  195. {
  196. BOOL b ;
  197. b = bConicCommon (pLocalDC, x1, y1, x2, y2, 0, 0, 0, 0, EMR_ELLIPSE) ;
  198. return(b) ;
  199. }
  200. /***************************************************************************
  201. * Pie - Win32 to Win16 Metafile Converter Entry Point
  202. **************************************************************************/
  203. BOOL WINAPI DoPie
  204. (
  205. PLOCALDC pLocalDC,
  206. int x1,
  207. int y1,
  208. int x2,
  209. int y2,
  210. int x3,
  211. int y3,
  212. int x4,
  213. int y4
  214. )
  215. {
  216. BOOL b ;
  217. b = bConicCommon (pLocalDC, x1, y1, x2, y2, x3, y3, x4, y4, EMR_PIE) ;
  218. return(b) ;
  219. }
  220. /***************************************************************************
  221. * bConicCommon - The mother of all conic translations.
  222. * They are Arc, Chord, Pie, Ellipse, Rectangle and RoundRect.
  223. **************************************************************************/
  224. BOOL bConicCommon (PLOCALDC pLocalDC, INT x1, INT y1, INT x2, INT y2,
  225. INT x3, INT y3, INT x4, INT y4,
  226. DWORD mrType)
  227. {
  228. SHORT sx1, sx2, sx3, sx4,
  229. sy1, sy2, sy3, sy4 ;
  230. LONG nPointls ;
  231. POINTL aptl[4] ;
  232. BOOL b ;
  233. // If we're recording the drawing orders for a path
  234. // then just pass the drawing order to the helper DC.
  235. // Do not emit any Win16 drawing orders.
  236. if (pLocalDC->flags & RECORDING_PATH)
  237. {
  238. switch(mrType)
  239. {
  240. case EMR_ARC:
  241. b = Arc(pLocalDC->hdcHelper, x1, y1, x2, y2,
  242. x3, y3, x4, y4) ;
  243. break ;
  244. case EMR_CHORD:
  245. b = Chord(pLocalDC->hdcHelper, x1, y1, x2, y2,
  246. x3, y3, x4, y4) ;
  247. break ;
  248. case EMR_ELLIPSE:
  249. b = Ellipse(pLocalDC->hdcHelper, x1, y1, x2, y2) ;
  250. break ;
  251. case EMR_PIE:
  252. b = Pie(pLocalDC->hdcHelper, x1, y1, x2, y2,
  253. x3, y3, x4, y4) ;
  254. break ;
  255. case EMR_RECTANGLE:
  256. b = Rectangle(pLocalDC->hdcHelper, x1, y1, x2, y2) ;
  257. break ;
  258. case EMR_ROUNDRECT:
  259. b = RoundRect(pLocalDC->hdcHelper, x1, y1, x2, y2, x3, y3) ;
  260. break ;
  261. default:
  262. b = FALSE;
  263. RIP("MF3216: bConicCommon, bad mrType");
  264. break ;
  265. }
  266. ASSERTGDI(b, "MF3216: bConicCommon, in path render failed\n") ;
  267. return(b) ;
  268. }
  269. // Do the transformations.
  270. // And emit the Win16 drawing orders.
  271. if (pLocalDC->flags & STRANGE_XFORM)
  272. {
  273. b = bRenderCurveWithPath(pLocalDC, (LPPOINT) NULL, (PBYTE) NULL, 0,
  274. x1, y1, x2, y2, x3, y3, x4, y4, 0, 0.0f, 0.0f, mrType);
  275. return(b);
  276. }
  277. // Do the simple transform case.
  278. // Compute the number of points
  279. nPointls = (LONG) (sizeof(aptl) / sizeof(POINTL)) ;
  280. // Assign all the coordinates into an array for conversion.
  281. aptl[0].x = x1 ;
  282. aptl[0].y = y1 ;
  283. aptl[1].x = x2 ;
  284. aptl[1].y = y2 ;
  285. aptl[2].x = x3 ;
  286. aptl[2].y = y3 ;
  287. aptl[3].x = x4 ;
  288. aptl[3].y = y4 ;
  289. // Take care of the arc direction.
  290. switch (mrType)
  291. {
  292. case EMR_ARC:
  293. case EMR_CHORD:
  294. case EMR_PIE:
  295. vDoArcReflection(pLocalDC, &aptl[2]) ;
  296. break ;
  297. default:
  298. break ;
  299. }
  300. // Do the Record-time World to Play-time Page transformations.
  301. // The radial definitions need only a world to page xform,
  302. // and the ellipse definitions for roundrects only require
  303. // a magnitude transformation.
  304. if (mrType != EMR_ROUNDRECT)
  305. {
  306. b = bXformRWorldToPPage(pLocalDC, (PPOINTL) aptl, nPointls) ;
  307. if (!b)
  308. goto exit1 ;
  309. }
  310. else
  311. {
  312. /*
  313. For roundrects do a Record-time-World to Play-time-Page
  314. transform of the bounding box only. Then a magnatude only
  315. transform of the corner ellipse definitions.
  316. */
  317. b = bXformRWorldToPPage(pLocalDC, (PPOINTL) aptl, 2) ;
  318. if (!b)
  319. goto exit1 ;
  320. aptl[2].x = iMagnitudeXform(pLocalDC, aptl[2].x, CX_MAG) ;
  321. aptl[2].y = iMagnitudeXform(pLocalDC, aptl[2].y, CY_MAG) ;
  322. aptl[3].x = iMagnitudeXform(pLocalDC, aptl[3].x, CX_MAG) ;
  323. aptl[3].y = iMagnitudeXform(pLocalDC, aptl[3].y, CY_MAG) ;
  324. }
  325. // The bounding boxes for
  326. // all the conics and rectangles that are handled by this
  327. // common routine are inclusive-inclusive, and they must
  328. // be transformed to the inclusive-exclusive Win16 form.
  329. b = bIncIncToIncExcXform(pLocalDC, (PRECTL) &aptl[0]) ;
  330. if (!b)
  331. goto exit1 ;
  332. // Assign the converted coordinates variables suited to
  333. // the Win16 metafile.
  334. sx1 = LOWORD(aptl[0].x) ;
  335. sy1 = LOWORD(aptl[0].y) ;
  336. sx2 = LOWORD(aptl[1].x) ;
  337. sy2 = LOWORD(aptl[1].y) ;
  338. sx3 = LOWORD(aptl[2].x) ;
  339. sy3 = LOWORD(aptl[2].y) ;
  340. sx4 = LOWORD(aptl[3].x) ;
  341. sy4 = LOWORD(aptl[3].y) ;
  342. // Emit the Win16 drawing orders to the Win16 metafile.
  343. switch(mrType)
  344. {
  345. case EMR_ARC:
  346. b = bEmitWin16Arc(pLocalDC, sx1, sy1, sx2, sy2,
  347. sx3, sy3, sx4, sy4) ;
  348. break ;
  349. case EMR_CHORD:
  350. b = bEmitWin16Chord(pLocalDC, sx1, sy1, sx2, sy2,
  351. sx3, sy3, sx4, sy4) ;
  352. break ;
  353. case EMR_ELLIPSE:
  354. b = bEmitWin16Ellipse(pLocalDC, sx1, sy1, sx2, sy2) ;
  355. break ;
  356. case EMR_PIE:
  357. b = bEmitWin16Pie(pLocalDC, sx1, sy1, sx2, sy2,
  358. sx3, sy3, sx4, sy4) ;
  359. break ;
  360. case EMR_RECTANGLE:
  361. b = bEmitWin16Rectangle(pLocalDC, sx1, sy1, sx2, sy2) ;
  362. break ;
  363. case EMR_ROUNDRECT:
  364. b = bEmitWin16RoundRect(pLocalDC, sx1, sy1, sx2, sy2, sx3, sy3) ;
  365. break ;
  366. default:
  367. RIP("MF3216: bConicCommon, bad mrType");
  368. break ;
  369. }
  370. exit1:
  371. return (b) ;
  372. }
  373. /*****************************************************************************
  374. * vDoArcReflection - Test for an inversion in the RWorld to PPage matrix.
  375. * If one and only one is found then swap the start
  376. * and end position for the conics.
  377. *****************************************************************************/
  378. VOID vDoArcReflection(PLOCALDC pLocalDC, PPOINTL pptl)
  379. {
  380. FLOAT eM11,
  381. eM22 ;
  382. POINTL ptl ;
  383. BOOL bFlip ;
  384. // Win16 assumes the counter-clockwise arc direction in the
  385. // device coordinates. Win32 defines the arc direction in the
  386. // world coordinates.
  387. // Assume no flipping of start and end points.
  388. bFlip = FALSE ;
  389. // Account for current arc direction.
  390. if (pLocalDC->iArcDirection == AD_CLOCKWISE)
  391. bFlip = !bFlip;
  392. // If there is an inversion in the xform matrix then invert
  393. // the arc direction.
  394. eM11 = pLocalDC->xformRWorldToPPage.eM11 ;
  395. eM22 = pLocalDC->xformRWorldToPPage.eM22 ;
  396. if ( (eM11 < 0.0f && eM22 > 0.0f)
  397. ||(eM11 > 0.0f && eM22 < 0.0f)
  398. )
  399. bFlip = !bFlip;
  400. // If the REQUESTED Win16 mapmode is fixed, then invert the
  401. // arc direction.
  402. switch(pLocalDC->iMapMode)
  403. {
  404. case MM_LOMETRIC:
  405. case MM_HIMETRIC:
  406. case MM_LOENGLISH:
  407. case MM_HIENGLISH:
  408. case MM_TWIPS:
  409. bFlip = !bFlip;
  410. break ;
  411. }
  412. if (bFlip)
  413. SWAP(pptl[0], pptl[1], ptl);
  414. return ;
  415. }
  416. /*****************************************************************************
  417. * bIncIncToIncExcXform - Inclusize Inclusive To Inclusive Exclusize
  418. * transform in play time coordinate space.
  419. *****************************************************************************/
  420. BOOL bIncIncToIncExcXform (PLOCALDC pLocalDC, PRECTL prcl)
  421. {
  422. LONG l;
  423. // Convert the points from Playtime Page to Playtime Device space.
  424. if (!bXformPPageToPDev(pLocalDC, (PPOINTL) prcl, 2))
  425. return(FALSE);
  426. // Reorder the rectangle
  427. if (prcl->left > prcl->right)
  428. SWAP(prcl->left, prcl->right, l);
  429. if (prcl->top > prcl->bottom)
  430. SWAP(prcl->top, prcl->bottom, l);
  431. // Expand the right and bottom by one pixel.
  432. prcl->right++ ;
  433. prcl->bottom++ ;
  434. // Convert the points back to Playtime Page space
  435. return(bXformPDevToPPage(pLocalDC, (PPOINTL) prcl, 2));
  436. }
  437. /*****************************************************************************
  438. * bFindRadialEllipseIntersection - Calculate the intersection of a radial
  439. * and an Ellipse.
  440. *
  441. * Play the ArcTo into a path then query the path for the first and
  442. * last points on the Arc.
  443. *****************************************************************************/
  444. BOOL bFindRadialEllipseIntersection(PLOCALDC pLocalDC,
  445. INT x1, INT y1, INT x2, INT y2,
  446. INT x3, INT y3, INT x4, INT y4,
  447. LPPOINT pptStart, LPPOINT pptEnd)
  448. {
  449. BOOL b;
  450. POINT ptCP;
  451. b = FALSE; // assume failure
  452. // Save the current position in the helper DC.
  453. if (!GetCurrentPositionEx(pLocalDC->hdcHelper, &ptCP))
  454. return(FALSE);
  455. // Do an ArcTo with the same start radial line.
  456. if (!ArcTo(pLocalDC->hdcHelper, x1, y1, x2, y2, x3, y3, x3, y3))
  457. goto exit_bFindRadialEllipseIntersection;
  458. // Get the start point of the arc. It is the current position.
  459. if (!GetCurrentPositionEx(pLocalDC->hdcHelper, pptStart))
  460. goto exit_bFindRadialEllipseIntersection;
  461. // Continue with the ArcTo with the same end radial line this time.
  462. if (!ArcTo(pLocalDC->hdcHelper, x1, y1, x2, y2, x4, y4, x4, y4))
  463. goto exit_bFindRadialEllipseIntersection;
  464. // Get the end point of the arc. It is the current position.
  465. if (!GetCurrentPositionEx(pLocalDC->hdcHelper, pptEnd))
  466. goto exit_bFindRadialEllipseIntersection;
  467. // Everything is golden.
  468. b = TRUE;
  469. exit_bFindRadialEllipseIntersection:
  470. // Restore the current position in the helper DC.
  471. if (!MoveToEx(pLocalDC->hdcHelper, ptCP.x, ptCP.y, (LPPOINT) NULL))
  472. RIP("MF3216: bFindRadialEllipseIntersection, MoveToEx failed");
  473. return(b);
  474. }