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.

457 lines
12 KiB

  1. /*****************************************************************************
  2. *
  3. * paths - 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. /***************************************************************************
  13. * BeginPath - Win32 to Win16 Metafile Converter Entry Point
  14. **************************************************************************/
  15. BOOL WINAPI DoBeginPath
  16. (
  17. PLOCALDC pLocalDC
  18. )
  19. {
  20. BOOL b ;
  21. // Set the global flag telling all all the geometric
  22. // rendering routines that we are accumulating drawing orders
  23. // for the path.
  24. pLocalDC->flags |= RECORDING_PATH ;
  25. // Tell the helper DC we are begining the path accumulation.
  26. b = BeginPath(pLocalDC->hdcHelper) ;
  27. ASSERTGDI((b == TRUE), "MF3216: DoBeginPath, BeginPath failed\n") ;
  28. return (b) ;
  29. }
  30. /***************************************************************************
  31. * EndPath - Win32 to Win16 Metafile Converter Entry Point
  32. **************************************************************************/
  33. BOOL WINAPI DoEndPath
  34. (
  35. PLOCALDC pLocalDC
  36. )
  37. {
  38. BOOL b ;
  39. // Reset the global flag, turning off the path accumulation.
  40. pLocalDC->flags &= ~RECORDING_PATH ;
  41. b = EndPath(pLocalDC->hdcHelper) ;
  42. ASSERTGDI((b == TRUE), "MF3216: DoEndPath, EndPath failed\n") ;
  43. return (b) ;
  44. }
  45. /***************************************************************************
  46. * WidenPath - Win32 to Win16 Metafile Converter Entry Point
  47. **************************************************************************/
  48. BOOL WINAPI DoWidenPath
  49. (
  50. PLOCALDC pLocalDC
  51. )
  52. {
  53. BOOL b ;
  54. b = WidenPath(pLocalDC->hdcHelper) ;
  55. ASSERTGDI((b == TRUE), "MF3216: DoWidenPath, WidenPath failed\n") ;
  56. return (b) ;
  57. }
  58. /***************************************************************************
  59. * SelectClipPath - Win32 to Win16 Metafile Converter Entry Point
  60. *
  61. * History:
  62. * Tue Apr 07 17:05:37 1992 -by- Hock San Lee [hockl]
  63. * Wrote it.
  64. **************************************************************************/
  65. BOOL WINAPI DoSelectClipPath(PLOCALDC pLocalDC, INT iMode)
  66. {
  67. // If there is no initial clip region and we are going to operate
  68. // on the initial clip region, we have to
  69. // create one. Otherwise, GDI will create some random default
  70. // clipping region for us!
  71. if ((iMode == RGN_DIFF || iMode == RGN_XOR || iMode == RGN_OR)
  72. && bNoDCRgn(pLocalDC, DCRGN_CLIP))
  73. {
  74. BOOL bRet;
  75. HRGN hrgnDefault;
  76. if (!(hrgnDefault = CreateRectRgn((int) (SHORT) MINSHORT,
  77. (int) (SHORT) MINSHORT,
  78. (int) (SHORT) MAXSHORT,
  79. (int) (SHORT) MAXSHORT)))
  80. {
  81. ASSERTGDI(FALSE, "MF3216: CreateRectRgn failed");
  82. return(FALSE);
  83. }
  84. bRet = (ExtSelectClipRgn(pLocalDC->hdcHelper, hrgnDefault, RGN_COPY)
  85. != ERROR);
  86. ASSERTGDI(bRet, "MF3216: ExtSelectClipRgn failed");
  87. if (!DeleteObject(hrgnDefault))
  88. ASSERTGDI(FALSE, "MF3216: DeleteObject failed");
  89. if (!bRet)
  90. return(FALSE);
  91. }
  92. // Do it to the helper DC.
  93. if (!SelectClipPath(pLocalDC->hdcHelper, iMode))
  94. return(FALSE);
  95. // Dump the clip region data.
  96. return(bDumpDCClipping(pLocalDC));
  97. }
  98. /***************************************************************************
  99. * FlattenPath - Win32 to Win16 Metafile Converter Entry Point
  100. **************************************************************************/
  101. BOOL WINAPI DoFlattenPath
  102. (
  103. PLOCALDC pLocalDC
  104. )
  105. {
  106. BOOL b ;
  107. b = FlattenPath(pLocalDC->hdcHelper) ;
  108. ASSERTGDI((b == TRUE), "MF3216: DoFlattenPath, FlattenPath failed\n") ;
  109. return (b) ;
  110. }
  111. /***************************************************************************
  112. * AbortPath - Win32 to Win16 Metafile Converter Entry Point
  113. **************************************************************************/
  114. BOOL WINAPI DoAbortPath
  115. (
  116. PLOCALDC pLocalDC
  117. )
  118. {
  119. BOOL b ;
  120. // Reset the global flag, turning off the path accumulation.
  121. pLocalDC->flags &= ~RECORDING_PATH ;
  122. b = AbortPath(pLocalDC->hdcHelper) ;
  123. ASSERTGDI((b == TRUE), "MF3216: DoAbortPath, AbortPath failed\n") ;
  124. return (b) ;
  125. }
  126. /***************************************************************************
  127. * CloseFigure - Win32 to Win16 Metafile Converter Entry Point
  128. **************************************************************************/
  129. BOOL WINAPI DoCloseFigure
  130. (
  131. PLOCALDC pLocalDC
  132. )
  133. {
  134. BOOL b ;
  135. b = CloseFigure(pLocalDC->hdcHelper) ;
  136. ASSERTGDI((b == TRUE), "MF3216: DoCloseFigure, CloseFigure failed\n") ;
  137. return (b) ;
  138. }
  139. /***************************************************************************
  140. * DoRenderPath - Common code for StrokePath, FillPath and StrokeAndFillPath.
  141. **************************************************************************/
  142. // Macro for copy a point in the path data.
  143. #define MOVE_A_POINT(iDst, pjTypeDst, pptDst, iSrc, pjTypeSrc, pptSrc) \
  144. { \
  145. pjTypeDst[iDst] = pjTypeSrc[iSrc]; \
  146. pptDst[iDst] = pptSrc[iSrc]; \
  147. }
  148. BOOL WINAPI DoRenderPath(PLOCALDC pLocalDC, INT mrType)
  149. {
  150. BOOL b;
  151. PBYTE pb = (PBYTE) NULL;
  152. PBYTE pbNew = (PBYTE) NULL;
  153. LPPOINT ppt, pptNew;
  154. LPBYTE pjType, pjTypeNew;
  155. PDWORD pPolyCount;
  156. INT cpt, cptNew, cPolyCount;
  157. INT i, j, jStart;
  158. LONG lhpn32;
  159. b = FALSE; // assume failure
  160. // Flatten the path, to convert all the beziers into polylines.
  161. if (!FlattenPath(pLocalDC->hdcHelper))
  162. {
  163. RIP("MF3216: DoRendarPath, FlattenPath failed\n");
  164. goto exit_DoRenderPath;
  165. }
  166. // Get the path data.
  167. // First get a count of the number of points.
  168. cpt = GetPath(pLocalDC->hdcHelper, (LPPOINT) NULL, (LPBYTE) NULL, 0);
  169. if (cpt == -1)
  170. {
  171. RIP("MF3216: DoRendarPath, GetPath failed\n");
  172. goto exit_DoRenderPath;
  173. }
  174. // Check for empty path.
  175. if (cpt == 0)
  176. {
  177. b = TRUE;
  178. goto exit_DoRenderPath;
  179. }
  180. // Allocate memory for the path data.
  181. if (!(pb = (PBYTE) LocalAlloc
  182. (
  183. LMEM_FIXED,
  184. cpt * (sizeof(POINT) + sizeof(BYTE))
  185. )
  186. )
  187. )
  188. {
  189. RIP("MF3216: DoRendarPath, LocalAlloc failed\n");
  190. goto exit_DoRenderPath;
  191. }
  192. // Order of assignment is important for dword alignment.
  193. ppt = (LPPOINT) pb;
  194. pjType = (LPBYTE) (ppt + cpt);
  195. // Finally, get the path data.
  196. if (GetPath(pLocalDC->hdcHelper, ppt, pjType, cpt) != cpt)
  197. {
  198. RIP("MF3216: DoRendarPath, GetPath failed\n");
  199. goto exit_DoRenderPath;
  200. }
  201. // The path data is in record-time world coordinates. They are the
  202. // coordinates we will use in the PolyPoly rendering functions below.
  203. //
  204. // Since we have flattened the path, the path data should only contain
  205. // the following types:
  206. //
  207. // PT_MOVETO
  208. // PT_LINETO
  209. // (PT_LINETO | PT_CLOSEFIGURE)
  210. //
  211. // To simplify, we will close the figure explicitly by inserting points
  212. // and removing the (PT_LINETO | PT_CLOSEFIGURE) type from the path data.
  213. // At the same time, we will create the PolyPoly structure to prepare for
  214. // the PolyPolygon or PolyPolyline call.
  215. //
  216. // Note that there cannot be more than one half (PT_LINETO | PT_CLOSEFIGURE)
  217. // points since they are followed by the PT_MOVETO points (except for the
  218. // last point). In addition, the first point must be a PT_MOVETO.
  219. //
  220. // We will also remove the empty figure, i.e. consecutive PT_MOVETO, from
  221. // the new path data in the process.
  222. // First, allocate memory for the new path data.
  223. cptNew = cpt + cpt / 2;
  224. if (!(pbNew = (PBYTE) LocalAlloc
  225. (
  226. LMEM_FIXED,
  227. cptNew * (sizeof(POINT) + sizeof(DWORD) + sizeof(BYTE))
  228. )
  229. )
  230. )
  231. {
  232. RIP("MF3216: DoRendarPath, LocalAlloc failed\n");
  233. goto exit_DoRenderPath;
  234. }
  235. // Order of assignment is important for dword alignment.
  236. pptNew = (LPPOINT) pbNew;
  237. pPolyCount = (PDWORD) (pptNew + cptNew);
  238. pjTypeNew = (LPBYTE) (pPolyCount + cptNew);
  239. // Close the path explicitly.
  240. i = 0;
  241. j = 0;
  242. cPolyCount = 0; // number of entries in PolyCount array
  243. while (i < cpt)
  244. {
  245. ASSERTGDI(pjType[i] == PT_MOVETO, "MF3216: DoRenderPath, bad pjType[]");
  246. // Copy everything upto the next closefigure or moveto.
  247. jStart = j;
  248. // copy the moveto
  249. MOVE_A_POINT(j, pjTypeNew, pptNew, i, pjType, ppt);
  250. i++; j++;
  251. if (i >= cpt) // stop if the last point is a moveto
  252. {
  253. j--; // don't include the last moveto
  254. break;
  255. }
  256. while (i < cpt)
  257. {
  258. MOVE_A_POINT(j, pjTypeNew, pptNew, i, pjType, ppt);
  259. i++; j++;
  260. // look for closefigure and moveto
  261. if (pjTypeNew[j - 1] != PT_LINETO)
  262. break;
  263. }
  264. if (pjTypeNew[j - 1] == PT_MOVETO)
  265. {
  266. i--; j--; // restart the next figure from moveto
  267. if (j - jStart == 1) // don't include consecutive moveto's
  268. j = jStart; // ignore the first moveto
  269. else
  270. pPolyCount[cPolyCount++] = j - jStart; // add one poly
  271. }
  272. else if (pjTypeNew[j - 1] == PT_LINETO)
  273. { // we have reached the end of path data
  274. pPolyCount[cPolyCount++] = j - jStart; // add one poly
  275. break;
  276. }
  277. else if (pjTypeNew[j - 1] == (PT_LINETO | PT_CLOSEFIGURE))
  278. {
  279. pjTypeNew[j - 1] = PT_LINETO;
  280. // Insert a PT_LINETO to close the figure.
  281. pjTypeNew[j] = PT_LINETO;
  282. pptNew[j] = pptNew[jStart];
  283. j++;
  284. pPolyCount[cPolyCount++] = j - jStart; // add one poly
  285. }
  286. else
  287. {
  288. ASSERTGDI(FALSE, "MF3216: DoRenderPath, unknown pjType[]");
  289. }
  290. } // while
  291. ASSERTGDI(j <= cptNew && cPolyCount <= cptNew,
  292. "MF3216: DoRenderPath, path data overrun");
  293. cptNew = j;
  294. // Check for empty path.
  295. if (cptNew == 0)
  296. {
  297. b = TRUE;
  298. goto exit_DoRenderPath;
  299. }
  300. // Now we have a path data that consists of only PT_MOVETO and PT_LINETO.
  301. // Furthermore, there is no "empty" figure, i.e. consecutive PT_MOVETO, in
  302. // the path. We can finally render the picture with PolyPolyline or
  303. // PolyPolygon.
  304. if (mrType == EMR_STROKEPATH)
  305. {
  306. // Do StrokePath.
  307. b = DoPolyPolyline(pLocalDC, (PPOINTL) pptNew, (PDWORD) pPolyCount,
  308. (DWORD) cPolyCount);
  309. }
  310. else
  311. {
  312. // Do FillPath and StrokeAndFillPath.
  313. // If we are doing fill only, we need to select in a NULL pen.
  314. if (mrType == EMR_FILLPATH)
  315. {
  316. lhpn32 = pLocalDC->lhpn32; // remember the previous pen
  317. if (!DoSelectObject(pLocalDC, ENHMETA_STOCK_OBJECT | NULL_PEN))
  318. {
  319. ASSERTGDI(FALSE, "MF3216: DoRenderPath, DoSelectObject failed");
  320. goto exit_DoRenderPath;
  321. }
  322. }
  323. // Do the PolyPolygon.
  324. b = DoPolyPolygon(pLocalDC, (PPOINTL) pptNew, (PDWORD) pPolyCount,
  325. (DWORD) cptNew, (DWORD) cPolyCount);
  326. // Restore the previous pen.
  327. if (mrType == EMR_FILLPATH)
  328. if (!DoSelectObject(pLocalDC, lhpn32))
  329. ASSERTGDI(FALSE, "MF3216: DoRenderPath, DoSelectObject failed");
  330. }
  331. exit_DoRenderPath:
  332. // Since this call affects the path state and current position in the helper
  333. // DC, we need to update the helper DC.
  334. switch(mrType)
  335. {
  336. case EMR_STROKEPATH:
  337. if (!StrokePath(pLocalDC->hdcHelper))
  338. ASSERTGDI(FALSE, "MF3216: DoRenderPath, StrokePath failed");
  339. break;
  340. case EMR_FILLPATH:
  341. if (!FillPath(pLocalDC->hdcHelper))
  342. ASSERTGDI(FALSE, "MF3216: DoRenderPath, FillPath failed");
  343. break;
  344. case EMR_STROKEANDFILLPATH:
  345. if (!StrokeAndFillPath(pLocalDC->hdcHelper))
  346. ASSERTGDI(FALSE, "MF3216: DoRenderPath, StrokeAndFillPath failed");
  347. break;
  348. default:
  349. ASSERTGDI(FALSE, "MF3216: DoRenderPath, unknown mrType");
  350. break;
  351. }
  352. if (pbNew)
  353. if (LocalFree((HANDLE) pbNew))
  354. RIP("MF3216: DoRendarPath, LocalFree failed\n");
  355. if (pb)
  356. if (LocalFree((HANDLE) pb))
  357. RIP("MF3216: DoRendarPath, LocalFree failed\n");
  358. return(b);
  359. }