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.

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