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.

873 lines
22 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: pathgdi.cxx
  3. *
  4. * Contains the path APIs.
  5. *
  6. * Created: 12-Sep-1991
  7. * Author: J. Andrew Goossen [andrewgo]
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.hxx"
  12. #include "pathwide.hxx"
  13. // Default line attributes used for WidenPath:
  14. static LINEATTRS glaNominalGeometric =
  15. {
  16. LA_GEOMETRIC, // fl
  17. JOIN_ROUND, // iJoin
  18. ENDCAP_ROUND, // iEndCap
  19. {IEEE_0_0F}, // elWidth
  20. IEEE_0_0F, // eMiterLimit
  21. 0, // cstyle
  22. (FLOAT_LONG*) NULL, // pstyle
  23. {IEEE_0_0F} // elStyleState
  24. };
  25. /******************************Public*Routine******************************\
  26. * BOOL NtGdiCloseFigure(hdc)
  27. *
  28. * Closes the figure in an active path.
  29. *
  30. * History:
  31. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  32. * Wrote it.
  33. \**************************************************************************/
  34. BOOL APIENTRY NtGdiCloseFigure(HDC hdc)
  35. {
  36. BOOL bRet = FALSE;
  37. DCOBJ dco(hdc);
  38. if (!dco.bValid())
  39. {
  40. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  41. return(bRet);
  42. }
  43. if (!dco.pdc->bActive())
  44. {
  45. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  46. return(bRet);
  47. }
  48. XEPATHOBJ epath(dco);
  49. if (!epath.bValid() || !epath.bCloseFigure())
  50. {
  51. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  52. return(bRet);
  53. }
  54. bRet = TRUE;
  55. return(bRet);
  56. }
  57. /******************************Public*Routine******************************\
  58. * BOOL NtGdiAbortPath(hdc)
  59. *
  60. * Aborts a path bracket, or discards the path from a closed path bracket.
  61. *
  62. * History:
  63. * 19-Mar-1992 -by- J. Andrew Goossen [andrewgo]
  64. * Wrote it.
  65. \**************************************************************************/
  66. BOOL APIENTRY NtGdiAbortPath(HDC hdc)
  67. {
  68. BOOL bRet = FALSE;
  69. // Lock the DC.
  70. DCOBJ dco(hdc);
  71. if (!dco.bValid())
  72. {
  73. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  74. return(bRet);
  75. }
  76. // Delete the previous path if there was one:
  77. if (dco.hpath() != HPATH_INVALID)
  78. {
  79. // If we did a SaveDC, we don't actually have to delete the entire path:
  80. if (dco.pdc->bLazySave())
  81. dco.pdc->vClearLazySave();
  82. else
  83. {
  84. XEPATHOBJ epath(dco);
  85. ASSERTGDI(epath.bValid(), "Invalid DC path");
  86. epath.vDelete();
  87. }
  88. dco.pdc->vDestroy();
  89. }
  90. bRet = TRUE;
  91. return(bRet);
  92. }
  93. /******************************Public*Routine******************************\
  94. * BOOL NtGdiBeginPath(hdc)
  95. *
  96. * Starts a path bracket; subsequent drawing calls are added to the path
  97. * until GreEndPath is called. Destroys the old one if there was one.
  98. *
  99. * History:
  100. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  101. * Wrote it.
  102. \**************************************************************************/
  103. BOOL APIENTRY NtGdiBeginPath(HDC hdc)
  104. {
  105. BOOL bRet = FALSE;
  106. // Lock the DC.
  107. DCOBJ dco(hdc);
  108. if (!dco.bValid())
  109. {
  110. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  111. return(bRet);
  112. }
  113. // Delete the previous path if there was one:
  114. if (dco.hpath() != HPATH_INVALID)
  115. {
  116. // If we did a SaveDC, we don't actually have to delete the entire path:
  117. if (dco.pdc->bLazySave())
  118. dco.pdc->vClearLazySave();
  119. else
  120. {
  121. XEPATHOBJ epath(dco);
  122. ASSERTGDI(epath.bValid(), "Invalid DC path");
  123. epath.vDelete();
  124. }
  125. dco.pdc->vDestroy();
  126. }
  127. // Create a new path:
  128. PATHMEMOBJ pmo;
  129. if (!pmo.bValid())
  130. {
  131. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  132. return(bRet);
  133. }
  134. // Tell the path we're keeping it, store the handle in the DC, and
  135. // set the flag that we're now accumulating a path:
  136. pmo.vKeepIt();
  137. dco.pdc->hpath(pmo.hpath());
  138. dco.pdc->vSetActive();
  139. bRet = TRUE;
  140. return(bRet);
  141. }
  142. /******************************Public*Routine******************************\
  143. * BOOL NtGdiEndPath(hdc)
  144. *
  145. * Ends an active path bracket.
  146. *
  147. * History:
  148. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  149. * Wrote it.
  150. \**************************************************************************/
  151. BOOL APIENTRY NtGdiEndPath(HDC hdc)
  152. {
  153. BOOL bRet = FALSE;
  154. // Lock the DC.
  155. DCOBJ dco(hdc);
  156. if (!dco.bValid())
  157. {
  158. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  159. return(bRet);
  160. }
  161. if (!dco.pdc->bActive())
  162. {
  163. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  164. return(bRet);
  165. }
  166. // Mark the path handle as no longer active:
  167. dco.pdc->vClearActive();
  168. bRet = TRUE;
  169. return(bRet);
  170. }
  171. /******************************Public*Routine******************************\
  172. * BOOL NtGdiFlattenPath(hdc)
  173. *
  174. * Flattens an inactive path. Path must be inactive, by calling GreEndPath.
  175. *
  176. * History:
  177. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  178. * Wrote it.
  179. \**************************************************************************/
  180. BOOL APIENTRY NtGdiFlattenPath(HDC hdc)
  181. {
  182. BOOL bRet = FALSE;
  183. // Lock the DC.
  184. DCOBJ dco(hdc);
  185. if (!dco.bValid())
  186. {
  187. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  188. return(bRet);
  189. }
  190. if (!dco.pdc->bInactive())
  191. {
  192. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  193. return(bRet);
  194. }
  195. XEPATHOBJ epath(dco);
  196. if (!epath.bValid() || !epath.bFlatten())
  197. {
  198. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  199. return(bRet);
  200. }
  201. bRet = TRUE;
  202. return(bRet);
  203. }
  204. /******************************Public*Routine******************************\
  205. * HRGN NtGdiWidenPath(hdc, pac)
  206. *
  207. * Widens the inactive path.
  208. *
  209. * History:
  210. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  211. * Wrote it.
  212. \**************************************************************************/
  213. BOOL APIENTRY NtGdiWidenPath(HDC hdc)
  214. {
  215. BOOL bRet = FALSE;
  216. DCOBJ dco(hdc);
  217. if (!dco.bValid())
  218. {
  219. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  220. return(bRet);
  221. }
  222. if (!dco.pdc->bInactive())
  223. {
  224. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  225. return(bRet);
  226. }
  227. XEPATHOBJ epath(dco);
  228. if (!epath.bValid())
  229. {
  230. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  231. return(bRet);
  232. }
  233. EXFORMOBJ xfo(dco, WORLD_TO_DEVICE);
  234. ASSERTGDI(xfo.bValid(), "Invalid DC xform");
  235. LINEATTRS *pla = dco.plaRealize(xfo);
  236. if (!(pla->fl & LA_GEOMETRIC))
  237. {
  238. // If the pen is an extended pen, it has to be geometric to be used
  239. // for widening. If we have an old style pen and the transform says
  240. // we would normally draw it using a cosmetic pen, substitute a stock
  241. // solid geometric pen for it instead. Thus if pens created via
  242. // CreatePen are used for the widening, we won't suddenly fail the
  243. // call when the transform gets small enough.
  244. if (!((PPEN)dco.pdc->pbrushLine())->bIsOldStylePen())
  245. {
  246. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  247. return(bRet);
  248. }
  249. pla = &glaNominalGeometric;
  250. }
  251. if (!epath.bComputeWidenedBounds((XFORMOBJ *) &xfo, pla))
  252. {
  253. SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
  254. return(bRet);
  255. }
  256. if (!epath.bWiden((XFORMOBJ *) &xfo, pla))
  257. {
  258. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  259. return(bRet);
  260. }
  261. // The computed widened bounds were only a guess, so recompute based
  262. // on the widened result:
  263. epath.vReComputeBounds();
  264. bRet = TRUE;
  265. return(bRet);
  266. }
  267. /******************************Public*Routine******************************\
  268. * BOOL NtGdiSelectClipPath(hdc, iMode)
  269. *
  270. * Selects a path as the DC clip region. Destroys the path.
  271. *
  272. * History:
  273. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  274. * Wrote it.
  275. \**************************************************************************/
  276. BOOL
  277. APIENTRY
  278. NtGdiSelectClipPath(HDC hdc, int iMode)
  279. {
  280. GDITraceMultiBegin("NtGdiSelectClipPath(%X, %d)\n", (va_list)&hdc);
  281. GDITraceMultiHandle(hdc);
  282. GDITraceMulti(NtGdiSelectClipPath);
  283. GDITraceMulti(PATH);
  284. GDITraceMultiEnd();
  285. BOOL bRet = FALSE;
  286. DCOBJ dco(hdc);
  287. if (!dco.bValid() || ((iMode < RGN_MIN) || (iMode > RGN_MAX)))
  288. {
  289. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  290. return(bRet);
  291. }
  292. if (!dco.pdc->bInactive())
  293. {
  294. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  295. return(bRet);
  296. }
  297. // After this point, the path will be deleted no matter what:
  298. XEPATHOBJ epath(dco);
  299. if (!epath.bValid())
  300. {
  301. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  302. // The path has been deleted, so delete its handle from the DC too:
  303. dco.pdc->vDestroy();
  304. return(bRet);
  305. }
  306. RGNMEMOBJTMP rmo(epath, dco.pdc->jFillMode());
  307. bRet = (rmo.bValid() &&
  308. dco.pdc->iSelect(rmo.prgnGet(), iMode));
  309. // Destroy the path (the region will be destroyed automatically):
  310. epath.vDelete();
  311. dco.pdc->vDestroy();
  312. return(bRet);
  313. }
  314. /******************************Public*Routine******************************\
  315. * BOOL NtGdiFillPath(hdc, pac)
  316. *
  317. * Fills an inactive path. Destroys the path.
  318. *
  319. * History:
  320. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  321. * Wrote it.
  322. \**************************************************************************/
  323. BOOL APIENTRY NtGdiFillPath(HDC hdc)
  324. {
  325. BOOL bRet = FALSE;
  326. DCOBJ dco(hdc);
  327. if (!dco.bValid())
  328. {
  329. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  330. return(bRet);
  331. }
  332. if (!dco.pdc->bInactive())
  333. {
  334. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  335. return(bRet);
  336. }
  337. // sync the client side cached brush
  338. if (dco.pdc->ulDirty() & DC_BRUSH_DIRTY)
  339. {
  340. GreDCSelectBrush(dco.pdc, dco.pdc->hbrush());
  341. }
  342. // After this point, the path will be deleted no matter what:
  343. XEPATHOBJ epath(dco);
  344. if (!epath.bValid())
  345. {
  346. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  347. // The path has been deleted, so delete its handle from the DC too:
  348. dco.pdc->vDestroy();
  349. return(bRet);
  350. }
  351. epath.vCloseAllFigures();
  352. bRet = epath.bFill(dco);
  353. // Destroy the path:
  354. epath.vDelete();
  355. dco.pdc->vDestroy();
  356. return(bRet);
  357. }
  358. /******************************Public*Routine******************************\
  359. * HRGN NtGdiPathToRegion(hdc)
  360. *
  361. * Creates a region from the inactive path. Destroys the path.
  362. *
  363. * History:
  364. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  365. * Wrote it.
  366. \**************************************************************************/
  367. HRGN APIENTRY NtGdiPathToRegion(HDC hdc)
  368. {
  369. DCOBJ dco(hdc);
  370. HRGN hrgnRet = (HRGN) 0;
  371. if (!dco.bValid())
  372. {
  373. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  374. return(hrgnRet);
  375. }
  376. if (!dco.pdc->bInactive())
  377. {
  378. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  379. return(hrgnRet);
  380. }
  381. // After this point, the path will be deleted no matter what:
  382. XEPATHOBJ epath(dco);
  383. if (!epath.bValid())
  384. {
  385. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  386. // The path has been deleted, so delete its handle from the DC too:
  387. dco.pdc->vDestroy();
  388. return(hrgnRet);
  389. }
  390. RGNMEMOBJ rmo(epath, dco.pdc->jFillMode());
  391. if (rmo.bValid())
  392. {
  393. hrgnRet = rmo.hrgnAssociate();
  394. if (hrgnRet == NULL)
  395. {
  396. rmo.bDeleteRGNOBJ();
  397. }
  398. }
  399. else
  400. {
  401. hrgnRet = NULL;
  402. }
  403. // Destroy the path:
  404. epath.vDelete();
  405. dco.pdc->vDestroy();
  406. return(hrgnRet);
  407. }
  408. /******************************Public*Routine******************************\
  409. * HRGN NtGdiStrokeAndFillPath(hdc, pac)
  410. *
  411. * StrokeAndFill's the inactive path. Destroys it.
  412. *
  413. * History:
  414. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  415. * Wrote it.
  416. \**************************************************************************/
  417. BOOL APIENTRY NtGdiStrokeAndFillPath(HDC hdc)
  418. {
  419. BOOL bRet = FALSE;
  420. DCOBJ dco(hdc);
  421. if (!dco.bValid())
  422. {
  423. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  424. return(bRet);
  425. }
  426. if (!dco.pdc->bInactive())
  427. {
  428. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  429. return(bRet);
  430. }
  431. // sync the client side cached brush and pen
  432. SYNC_DRAWING_ATTRS(dco.pdc);
  433. // After this point, the path will be deleted no matter what:
  434. XEPATHOBJ epath(dco);
  435. if (!epath.bValid())
  436. {
  437. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  438. // The path has been deleted, so delete its handle from the DC too:
  439. dco.pdc->vDestroy();
  440. return(bRet);
  441. }
  442. EXFORMOBJ xfo(dco, WORLD_TO_DEVICE);
  443. ASSERTGDI(xfo.bValid(), "Invalid DC xform");
  444. epath.vCloseAllFigures();
  445. bRet = epath.bStrokeAndFill(dco, dco.plaRealize(xfo), &xfo);
  446. // Destroy the path:
  447. epath.vDelete();
  448. dco.pdc->vDestroy();
  449. return(bRet);
  450. }
  451. /******************************Public*Routine******************************\
  452. * HRGN NtGdiStrokePath(hdc)
  453. *
  454. * Stroke's the inactive path. Destroys it.
  455. *
  456. * History:
  457. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  458. * Wrote it.
  459. \**************************************************************************/
  460. BOOL APIENTRY NtGdiStrokePath(HDC hdc)
  461. {
  462. BOOL bRet = FALSE;
  463. DCOBJ dco(hdc);
  464. if (!dco.bValid())
  465. {
  466. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  467. return(bRet);
  468. }
  469. if (!dco.pdc->bInactive())
  470. {
  471. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  472. return(bRet);
  473. }
  474. // sync the client side cached pen
  475. if (dco.pdc->ulDirty() & DC_PEN_DIRTY)
  476. {
  477. GreDCSelectPen(dco.pdc, dco.pdc->hpen());
  478. }
  479. // After this point, the path will be deleted no matter what:
  480. XEPATHOBJ epath(dco);
  481. if (!epath.bValid())
  482. {
  483. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  484. // The path has been deleted, so delete its handle from the DC too:
  485. dco.pdc->vDestroy();
  486. return(bRet);
  487. }
  488. EXFORMOBJ xfo(dco, WORLD_TO_DEVICE);
  489. ASSERTGDI(xfo.bValid(), "Invalid DC xform");
  490. bRet = epath.bStroke(dco, dco.plaRealize(xfo), &xfo);
  491. // Destroy the path:
  492. epath.vDelete();
  493. dco.pdc->vDestroy();
  494. return(bRet);
  495. }
  496. /******************************Public*Routine******************************\
  497. * BOOL GreSetMiterLimit(hdc, eNewLimit, peOldLimit)
  498. *
  499. * Sets the DC's miter limit for wide lines. Optionally returns the old one.
  500. *
  501. * History:
  502. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  503. * Wrote it.
  504. \**************************************************************************/
  505. BOOL APIENTRY GreSetMiterLimit
  506. (
  507. HDC hdc,
  508. FLOATL l_eNewLimit,
  509. FLOATL *pl_eOldLimit
  510. )
  511. {
  512. BOOL bRet = FALSE;
  513. DCOBJ dco(hdc);
  514. if (!dco.bValid() || l_eNewLimit < IEEE_1_0F)
  515. {
  516. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  517. return(bRet);
  518. }
  519. if (pl_eOldLimit != (FLOATL *) NULL)
  520. {
  521. *pl_eOldLimit = dco.pdc->l_eMiterLimit();
  522. }
  523. dco.pdc->l_eMiterLimit(l_eNewLimit);
  524. bRet = TRUE;
  525. return(bRet);
  526. }
  527. /******************************Public*Routine******************************\
  528. * BOOL GreGetMiterLimit(hdc, peMiterLimit)
  529. *
  530. * Returns the DC's miter limit for wide lines.
  531. *
  532. * History:
  533. * 7-Apr-1992 -by- J. Andrew Goossen [andrewgo]
  534. * Wrote it.
  535. \**************************************************************************/
  536. BOOL APIENTRY GreGetMiterLimit(
  537. HDC hdc,
  538. FLOATL *pl_eMiterLimit)
  539. {
  540. BOOL bRet = FALSE;
  541. DCOBJ dco(hdc);
  542. if (!dco.bValid())
  543. {
  544. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  545. return(bRet);
  546. }
  547. *pl_eMiterLimit = dco.pdc->l_eMiterLimit();
  548. bRet = TRUE;
  549. return(bRet);
  550. }
  551. /******************************Public*Routine******************************\
  552. * NtGdiGetPath()
  553. *
  554. * Gets the path data. pcptPath will contain the number of points in the
  555. * path, even if the supplied buffer is too small.
  556. *
  557. * History:
  558. * 12-Sep-1991 -by- J. Andrew Goossen [andrewgo]
  559. * Wrote it.
  560. \**************************************************************************/
  561. int
  562. APIENTRY
  563. NtGdiGetPath(
  564. HDC hdc,
  565. LPPOINT pptlBuf,
  566. LPBYTE pjTypes,
  567. int cptBuf
  568. )
  569. {
  570. int cptPath = -1;
  571. DCOBJ dco(hdc);
  572. if (dco.bValid() && cptBuf >= 0)
  573. {
  574. if (dco.pdc->bInactive())
  575. {
  576. EXFORMOBJ exfoDtoW(dco, DEVICE_TO_WORLD);
  577. if (exfoDtoW.bValid())
  578. {
  579. //
  580. // We're not going to modify the path, so we don't have to worry
  581. // about copying it if a SaveDC is pending:
  582. //
  583. XEPATHOBJ epath(dco.hpath());
  584. ASSERTGDI(epath.bValid(), "Invalid DC path");
  585. cptPath = (int) epath.cTotalPts();
  586. //
  587. // if cptBuf == 0, this is not an error. This is a request
  588. // for the size of the path.
  589. //
  590. if (cptBuf != 0)
  591. {
  592. //
  593. // Return an error if the buffer is too small:
  594. //
  595. // Note: sizeof(BYTE) < sizeof(POINT), so the single test
  596. // suffices to check for overflow in both write
  597. // probes; also, using MAXULONG instead of
  598. // MAXIMUM_POOL_ALLOC because checking for overflow,
  599. // not allocating memory
  600. //
  601. ASSERTGDI(sizeof(BYTE) <= sizeof(POINT),
  602. "NtGdiGetPath: bad overflow check\n");
  603. if ((cptBuf >= cptPath) &&
  604. (cptBuf <= (MAXULONG/sizeof(POINT))))
  605. {
  606. PATHDATA pd;
  607. PBYTE pjEnd;
  608. BYTE jType;
  609. BOOL bMore;
  610. epath.vEnumStart();
  611. __try {
  612. ProbeForWrite(pptlBuf,
  613. cptBuf * sizeof(POINT),
  614. sizeof(DWORD));
  615. ProbeForWrite(pjTypes,
  616. cptBuf * sizeof(BYTE),
  617. sizeof(DWORD));
  618. do {
  619. bMore = epath.bEnum(&pd);
  620. // We can get a zero point record if it's an empty path:
  621. if (pd.count > 0)
  622. {
  623. // Copy points:
  624. if (!exfoDtoW.bXform(pd.pptfx,
  625. (PPOINTL) pptlBuf,
  626. (SIZE_T) pd.count))
  627. {
  628. SAVE_ERROR_CODE(ERROR_ARITHMETIC_OVERFLOW);
  629. cptPath = -1;
  630. break;
  631. }
  632. pptlBuf += pd.count;
  633. // Determine types:
  634. pjEnd = pjTypes + pd.count;
  635. // First point in a subpath is always a MoveTo:
  636. if (pd.flags & PD_BEGINSUBPATH)
  637. {
  638. *pjTypes++ = PT_MOVETO;
  639. }
  640. // Other points are LineTo's or BezierTo's:
  641. jType = (pd.flags & PD_BEZIERS)
  642. ? (BYTE) PT_BEZIERTO
  643. : (BYTE) PT_LINETO;
  644. while (pjTypes < pjEnd)
  645. {
  646. *pjTypes++ = jType;
  647. }
  648. // Set CloseFigure bit for last point in a subpath:
  649. if (pd.flags & PD_CLOSEFIGURE)
  650. {
  651. ASSERTGDI(pd.flags & PD_ENDSUBPATH, "Expected on last pd");
  652. *(pjTypes - 1) |= PT_CLOSEFIGURE;
  653. }
  654. }
  655. } while (bMore);
  656. }
  657. __except(EXCEPTION_EXECUTE_HANDLER)
  658. {
  659. // SetLastError(GetExceptionCode());
  660. cptPath = -1;
  661. }
  662. }
  663. else
  664. {
  665. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  666. cptPath = -1;
  667. }
  668. }
  669. }
  670. else
  671. {
  672. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  673. }
  674. }
  675. else
  676. {
  677. SAVE_ERROR_CODE(ERROR_CAN_NOT_COMPLETE);
  678. }
  679. }
  680. else
  681. {
  682. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  683. }
  684. return(cptPath);
  685. }