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.

741 lines
22 KiB

  1. /*****************************************************************************
  2. *
  3. * misc - 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. BOOL WINAPI GetTransform(HDC hdc,DWORD iXform,LPXFORM pxform);
  13. BOOL WINAPI DoGdiCommentMultiFormats
  14. (
  15. PLOCALDC pLocalDC,
  16. PEMRGDICOMMENT_MULTIFORMATS pemr
  17. );
  18. /***************************************************************************
  19. * ExtFloodFill - Win32 to Win16 Metafile Converter Entry Point
  20. **************************************************************************/
  21. BOOL WINAPI DoExtFloodFill
  22. (
  23. PLOCALDC pLocalDC,
  24. int x,
  25. int y,
  26. COLORREF crColor,
  27. DWORD iMode
  28. )
  29. {
  30. POINTL ptl ;
  31. BOOL b ;
  32. ptl.x = (LONG) x ;
  33. ptl.y = (LONG) y ;
  34. b = bXformRWorldToPPage(pLocalDC, &ptl, 1) ;
  35. if (b == FALSE)
  36. goto exit1 ;
  37. b = bEmitWin16ExtFloodFill(pLocalDC, LOWORD(ptl.x), LOWORD(ptl.y), crColor, LOWORD(iMode)) ;
  38. exit1:
  39. return(b) ;
  40. }
  41. /***************************************************************************
  42. * MoveToEx - Win32 to Win16 Metafile Converter Entry Point
  43. *
  44. * NOTE ON CURRENT POSITION
  45. * ------------------------
  46. * There are only three Win16 functions that use and update the
  47. * current position (CP). They are:
  48. *
  49. * MoveTo
  50. * LineTo
  51. * (Ext)TextOut with TA_UPDATECP text alignment option
  52. *
  53. * In Win32, CP is used in many more functions and has two
  54. * interpretations based on the state of the current path.
  55. * As a result, it is easier and more robust to rely on the
  56. * helper DC to keep track of the CP than doing it in the
  57. * converter. To do this, we need to do the following:
  58. *
  59. * 1. The converter will update the CP in the helper DC in all
  60. * records that modify the CP.
  61. *
  62. * 2. The converter will keep track of the CP in the converted
  63. * metafile at all time.
  64. *
  65. * 3. In LineTo and (Ext)TextOut, the metafile CP is compared to
  66. * that of the helper DC. If they are different, a MoveTo record
  67. * is emitted. This is done in bValidateMetaFileCP().
  68. *
  69. * 4. The converter should emit a MoveTo record the first time the
  70. * CP is used in the converted metafile.
  71. *
  72. * - HockL July 2, 1992
  73. **************************************************************************/
  74. BOOL WINAPI DoMoveTo
  75. (
  76. PLOCALDC pLocalDC,
  77. LONG x,
  78. LONG y
  79. )
  80. {
  81. BOOL b ;
  82. POINTL ptl ;
  83. // Whether we are recording for a path or acutally emitting
  84. // a drawing order we must pass the drawing order to the helper DC
  85. // so the helper can maintain the current positon.
  86. // If we're recording the drawing orders for a path
  87. // then just pass the drawing order to the helper DC.
  88. // Do not emit any Win16 drawing orders.
  89. b = MoveToEx(pLocalDC->hdcHelper, (INT) x, (INT) y, (LPPOINT) &ptl) ;
  90. if (pLocalDC->flags & RECORDING_PATH)
  91. return(b) ;
  92. // Update the CP in the converted metafile.
  93. b = bValidateMetaFileCP(pLocalDC, x, y) ;
  94. return(b) ;
  95. }
  96. /***************************************************************************
  97. * bValidateMetaFiloeCP - Update the current position in the converted
  98. * metafile.
  99. *
  100. * x and y are assumed to be in the record time world coordinates.
  101. *
  102. **************************************************************************/
  103. BOOL bValidateMetaFileCP(PLOCALDC pLocalDC, LONG x, LONG y)
  104. {
  105. BOOL b ;
  106. POINT pt ;
  107. // Compute the new current position in the play time page coord.
  108. pt.x = x ;
  109. pt.y = y ;
  110. if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) &pt, 1L))
  111. return(FALSE);
  112. // No need to emit the record if the converted metafile has
  113. // the same CP.
  114. if (pLocalDC->ptCP.x == pt.x && pLocalDC->ptCP.y == pt.y)
  115. return(TRUE);
  116. // Call the Win16 routine to emit the move to the metafile.
  117. b = bEmitWin16MoveTo(pLocalDC, LOWORD(pt.x), LOWORD(pt.y)) ;
  118. // Update the mf16 current position.
  119. pLocalDC->ptCP = pt ;
  120. return(b) ;
  121. }
  122. /***************************************************************************
  123. * SaveDC - Win32 to Win16 Metafile Converter Entry Point
  124. **************************************************************************/
  125. BOOL WINAPI DoSaveDC
  126. (
  127. PLOCALDC pLocalDC
  128. )
  129. {
  130. BOOL b;
  131. PLOCALDC pLocalDCNew;
  132. b = FALSE;
  133. // Save the helper DC's state first
  134. if (!SaveDC(pLocalDC->hdcHelper))
  135. {
  136. RIP("MF3216: DoSaveDC, SaveDC failed\n");
  137. return(b);
  138. }
  139. // Allocate some memory for the LocalDC.
  140. pLocalDCNew = (PLOCALDC) LocalAlloc(LMEM_FIXED, sizeof(LOCALDC));
  141. if (pLocalDCNew == (PLOCALDC) NULL)
  142. {
  143. RIP("MF3216: DoSaveDC, LocalAlloc failed\n");
  144. return(b);
  145. }
  146. // Copy the data from the current LocalDC to the new one just allocated.
  147. *pLocalDCNew = *pLocalDC;
  148. // Link in the new level.
  149. pLocalDC->pLocalDCSaved = pLocalDCNew;
  150. pLocalDC->iLevel++;
  151. // Emit Win16 drawing order.
  152. b = bEmitWin16SaveDC(pLocalDC);
  153. return(b);
  154. }
  155. /***************************************************************************
  156. * RestoreDC - Win32 to Win16 Metafile Converter Entry Point
  157. **************************************************************************/
  158. BOOL WINAPI DoRestoreDC
  159. (
  160. PLOCALDC pLocalDC,
  161. int nSavedDC
  162. )
  163. {
  164. BOOL b;
  165. INT iLevel;
  166. PLOCALDC pLocalDCNext;
  167. PLOCALDC pLocalDCTmp;
  168. b = FALSE;
  169. // First check to make sure this is a relative save level.
  170. if (nSavedDC > 0)
  171. return(b);
  172. // Restore the helper DC's state first
  173. // If we can restore the helper DC, we know that it is a balanced restore.
  174. // Otherwise, we return an error.
  175. if (!RestoreDC(pLocalDC->hdcHelper, nSavedDC))
  176. return(b);
  177. // Compute an absolute level.
  178. iLevel = pLocalDC->iLevel + nSavedDC;
  179. // The helper DC should have caught bogus levels.
  180. ASSERTGDI((iLevel >= 0) && ((UINT) iLevel < pLocalDC->iLevel),
  181. "MF3216: DoRestoreDC, Bogus RestoreDC");
  182. // Restore down to the level we want.
  183. pLocalDCNext = pLocalDC->pLocalDCSaved;
  184. while ((UINT) iLevel < pLocalDCNext->iLevel)
  185. {
  186. pLocalDCTmp = pLocalDCNext;
  187. pLocalDCNext = pLocalDCNext->pLocalDCSaved;
  188. if (LocalFree(pLocalDCTmp))
  189. ASSERTGDI(FALSE, "MF3216: DoRestoreDC, LocalFree failed");
  190. }
  191. // Restore the state of our local DC to that level.
  192. // keep some of the attributes in the current DC
  193. pLocalDCNext->ulBytesEmitted = pLocalDC->ulBytesEmitted;
  194. pLocalDCNext->ulMaxRecord = pLocalDC->ulMaxRecord;
  195. pLocalDCNext->nObjectHighWaterMark = pLocalDC->nObjectHighWaterMark;
  196. pLocalDCNext->pbCurrent = pLocalDC->pbCurrent;
  197. pLocalDCNext->cW16ObjHndlSlotStatus = pLocalDC->cW16ObjHndlSlotStatus;
  198. pLocalDCNext->pW16ObjHndlSlotStatus = pLocalDC->pW16ObjHndlSlotStatus;
  199. // now restore the other attributes
  200. *pLocalDC = *pLocalDCNext;
  201. // Free the local copy of the DC.
  202. if (LocalFree(pLocalDCNext))
  203. ASSERTGDI(FALSE, "MF3216: DoRestoreDC, LocalFree failed");
  204. // Emit the record to the Win16 metafile.
  205. b = bEmitWin16RestoreDC(pLocalDC, LOWORD(nSavedDC)) ;
  206. return (b) ;
  207. }
  208. /***************************************************************************
  209. * SetRop2 - Win32 to Win16 Metafile Converter Entry Point
  210. **************************************************************************/
  211. BOOL WINAPI DoSetRop2
  212. (
  213. PLOCALDC pLocalDC,
  214. DWORD rop
  215. )
  216. {
  217. BOOL b ;
  218. // Emit the Win16 metafile drawing order.
  219. b = bEmitWin16SetROP2(pLocalDC, LOWORD(rop)) ;
  220. return(b) ;
  221. }
  222. /***************************************************************************
  223. * SetBkMode - Win32 to Win16 Metafile Converter Entry Point
  224. **************************************************************************/
  225. BOOL WINAPI DoSetBkMode
  226. (
  227. PLOCALDC pLocalDC,
  228. DWORD iBkMode
  229. )
  230. {
  231. BOOL b ;
  232. // Do it to the helper DC. It needs this in a path bracket
  233. // if a text string is drawn.
  234. SetBkMode(pLocalDC->hdcHelper, (int) iBkMode);
  235. // Emit the Win16 metafile drawing order.
  236. b = bEmitWin16SetBkMode(pLocalDC, LOWORD(iBkMode)) ;
  237. return(b) ;
  238. }
  239. /***************************************************************************
  240. * SetBkColor - Win32 to Win16 Metafile Converter Entry Point
  241. **************************************************************************/
  242. BOOL APIENTRY DoSetBkColor
  243. (
  244. PLOCALDC pLocalDC,
  245. COLORREF crColor
  246. )
  247. {
  248. BOOL b ;
  249. pLocalDC->crBkColor = crColor; // used by brushes
  250. // Emit the Win16 metafile drawing order.
  251. b = bEmitWin16SetBkColor(pLocalDC, crColor) ;
  252. return(b) ;
  253. }
  254. /***************************************************************************
  255. * GdiComment - Win32 to Win16 Metafile Converter Entry Point
  256. **************************************************************************/
  257. BOOL WINAPI DoGdiComment
  258. (
  259. PLOCALDC pLocalDC,
  260. PEMR pemr
  261. )
  262. {
  263. BOOL b;
  264. PEMRGDICOMMENT_PUBLIC pemrComment = (PEMRGDICOMMENT_PUBLIC) pemr;
  265. // If it's not a public comment, just return TRUE.
  266. if (pemrComment->emr.nSize < sizeof(EMRGDICOMMENT_PUBLIC)
  267. || pemrComment->ident != GDICOMMENT_IDENTIFIER)
  268. return(TRUE);
  269. // Handle public comments.
  270. // A public comment consists of a public comment identifier,
  271. // a comment type, plus any accompanying data.
  272. switch (pemrComment->iComment)
  273. {
  274. case GDICOMMENT_MULTIFORMATS:
  275. b = DoGdiCommentMultiFormats(pLocalDC, (PEMRGDICOMMENT_MULTIFORMATS) pemr);
  276. break;
  277. case GDICOMMENT_BEGINGROUP:
  278. case GDICOMMENT_ENDGROUP:
  279. case GDICOMMENT_WINDOWS_METAFILE:
  280. default:
  281. b = TRUE;
  282. break;
  283. }
  284. return(b) ;
  285. }
  286. BOOL WINAPI DoGdiCommentMultiFormats
  287. (
  288. PLOCALDC pLocalDC,
  289. PEMRGDICOMMENT_MULTIFORMATS pemrcmf
  290. )
  291. {
  292. DWORD i;
  293. DWORD cSizeOld;
  294. int iBase;
  295. XFORM xformNew, xformScale;
  296. POINTL aptlFrame[4];
  297. RECTL rclFrame;
  298. UINT cbwmfNew;
  299. SIZEL szlDeviceNew, szlMillimetersNew;
  300. BOOL bRet = FALSE;
  301. PBYTE pbwmfNew = (PBYTE) NULL;
  302. HDC hdcemfNew = (HDC) 0;
  303. HENHMETAFILE hemf = (HENHMETAFILE) 0;
  304. HENHMETAFILE hemfNew = (HENHMETAFILE) 0;
  305. PENHMETAHEADER pemfh;
  306. WIN16LOGBRUSH Win16LogBrush;
  307. PMETARECORD pmr;
  308. #if DBG
  309. int iSWO = 0;
  310. int iSWE = 0;
  311. #endif
  312. // We will convert the enhanced metafile format only.
  313. // Find the enhanced metafile data.
  314. for (i = 0; i < pemrcmf->nFormats; i++)
  315. {
  316. if (pemrcmf->aemrformat[i].dSignature == ENHMETA_SIGNATURE
  317. && pemrcmf->aemrformat[i].nVersion <= META_FORMAT_ENHANCED)
  318. break;
  319. }
  320. // If we cannot find a recognized format, return failure.
  321. if (i >= pemrcmf->nFormats)
  322. {
  323. PUTS("MF3216: DoGdiCommentMultiFormats - no recognized format found\n");
  324. goto dgcmf_exit;
  325. }
  326. // Get the embedded enhanced metafile.
  327. hemf = SetEnhMetaFileBits((UINT) pemrcmf->aemrformat[i].cbData,
  328. &((PBYTE) &pemrcmf->ident)[pemrcmf->aemrformat[i].offData]);
  329. if (!hemf)
  330. goto dgcmf_exit;
  331. // Now the fun begins - we have to convert the enhanced metafile to
  332. // Windows metafile.
  333. // Since the multiformats record takes a logical rectangle, we have to
  334. // set up a proper transform for the enhanced metafile. We do it by
  335. // creating a new enhanced metafile and playing the embedded metafile
  336. // into the new metafile with the proper transform setup.
  337. // In addition, the new metafile may have a different resolution than the
  338. // metafile. We need to take this into account when setting up
  339. // the transform.
  340. // Get the world to device transform for the logical rectangle.
  341. if (!GetTransform(pLocalDC->hdcHelper, XFORM_WORLD_TO_DEVICE, &xformNew))
  342. goto dgcmf_exit;
  343. // Compute the device scales.
  344. szlDeviceNew.cx = GetDeviceCaps(pLocalDC->hdcRef, HORZRES);
  345. szlDeviceNew.cy = GetDeviceCaps(pLocalDC->hdcRef, VERTRES);
  346. szlMillimetersNew.cx = GetDeviceCaps(pLocalDC->hdcRef, HORZSIZE);
  347. szlMillimetersNew.cy = GetDeviceCaps(pLocalDC->hdcRef, VERTSIZE);
  348. pemfh = (PENHMETAHEADER) pLocalDC->pMf32Bits;
  349. xformScale.eM11 = ((FLOAT) szlDeviceNew.cx / (FLOAT) szlMillimetersNew.cx)
  350. / ((FLOAT) pemfh->szlDevice.cx / (FLOAT) pemfh->szlMillimeters.cx);
  351. xformScale.eM12 = 0.0f;
  352. xformScale.eM21 = 0.0f;
  353. xformScale.eM22 = ((FLOAT) szlDeviceNew.cy / (FLOAT) szlMillimetersNew.cy)
  354. / ((FLOAT) pemfh->szlDevice.cy / (FLOAT) pemfh->szlMillimeters.cy);
  355. xformScale.eDx = 0.0f;
  356. xformScale.eDy = 0.0f;
  357. // Compute the resulting transform to apply to the new metafile.
  358. if (!CombineTransform(&xformNew, &xformNew, &xformScale))
  359. goto dgcmf_exit;
  360. // Create the new enhanced metafile.
  361. // Compute the new metafile frame.
  362. aptlFrame[0].x = pemrcmf->rclOutput.left;
  363. aptlFrame[0].y = pemrcmf->rclOutput.top;
  364. aptlFrame[1].x = pemrcmf->rclOutput.right;
  365. aptlFrame[1].y = pemrcmf->rclOutput.top;
  366. aptlFrame[2].x = pemrcmf->rclOutput.right;
  367. aptlFrame[2].y = pemrcmf->rclOutput.bottom;
  368. aptlFrame[3].x = pemrcmf->rclOutput.left;
  369. aptlFrame[3].y = pemrcmf->rclOutput.bottom;
  370. if (!bXformWorkhorse(aptlFrame, 4, &xformNew))
  371. goto dgcmf_exit;
  372. rclFrame.left = MulDiv(100 * MIN4(aptlFrame[0].x, aptlFrame[1].x,
  373. aptlFrame[2].x, aptlFrame[3].x),
  374. szlMillimetersNew.cx,
  375. szlDeviceNew.cx);
  376. rclFrame.right = MulDiv(100 * MAX4(aptlFrame[0].x, aptlFrame[1].x,
  377. aptlFrame[2].x, aptlFrame[3].x),
  378. szlMillimetersNew.cx,
  379. szlDeviceNew.cx);
  380. rclFrame.top = MulDiv(100 * MIN4(aptlFrame[0].y, aptlFrame[1].y,
  381. aptlFrame[2].y, aptlFrame[3].y),
  382. szlMillimetersNew.cy,
  383. szlDeviceNew.cy);
  384. rclFrame.bottom = MulDiv(100 * MAX4(aptlFrame[0].y, aptlFrame[1].y,
  385. aptlFrame[2].y, aptlFrame[3].y),
  386. szlMillimetersNew.cy,
  387. szlDeviceNew.cy);
  388. hdcemfNew = CreateEnhMetaFile(pLocalDC->hdcRef, (LPCSTR) NULL,
  389. (CONST RECT *) &rclFrame, (LPCSTR) NULL);
  390. if (!hdcemfNew)
  391. goto dgcmf_exit;
  392. if (!SetGraphicsMode(hdcemfNew, GM_ADVANCED))
  393. goto dgcmf_exit;
  394. // Set up the transform in the new metafile.
  395. if (!SetWorldTransform(hdcemfNew, &xformNew))
  396. goto dgcmf_exit;
  397. // Play the embedded metafile into the new metafile.
  398. // This call ensures balanced level etc.
  399. (void) PlayEnhMetaFile(hdcemfNew, hemf, (LPRECT) &pemrcmf->rclOutput);
  400. // Close the new metafile.
  401. hemfNew = CloseEnhMetaFile(hdcemfNew);
  402. hdcemfNew = (HDC) 0; // used by clean up code below
  403. // Convert the new enhanced metafile to windows metafile.
  404. if (!(cbwmfNew = GetWinMetaFileBits(hemfNew, 0, (LPBYTE) NULL,
  405. MM_ANISOTROPIC, pLocalDC->hdcRef)))
  406. goto dgcmf_exit;
  407. if (!(pbwmfNew = (PBYTE) LocalAlloc(LMEM_FIXED, cbwmfNew)))
  408. goto dgcmf_exit;
  409. if (cbwmfNew != GetWinMetaFileBits(hemfNew, cbwmfNew, pbwmfNew,
  410. MM_ANISOTROPIC, pLocalDC->hdcRef))
  411. goto dgcmf_exit;
  412. // We now have the converted windows metafile. We need to include it into
  413. // our current data stream. There are a few things to be aware of:
  414. //
  415. // 1. Expand the object handle slot table. The converted metafile may
  416. // contain some undeleted objects. These objects are likely
  417. // the "stock" objects in the converter. As a result, we need to
  418. // expand the slot table by the number of object handles in the
  419. // converted metafile.
  420. // 2. The object index must be changed to the current object index.
  421. // We are going to do this by the lazy method, i.e. we will elevate
  422. // the current object index base to one higher than the current max
  423. // object index in the current data stream. This is because Windows uses
  424. // some an insane scheme for object index and this is the cheapest
  425. // method. We elevate the object index base by filling up the empty
  426. // indexes with dummy objects that are freed when we are done.
  427. // 3. Remove the now useless comments.
  428. // 4. Skip header and eof.
  429. // 5. Set up the transform to place the embedded metafile into the data
  430. // stream. We know that the metafile bits returned by the converter
  431. // contains only a SetWindowOrg and a SetWindowExt record.
  432. // By implementation, we can simply remove both the SetWindowOrg and
  433. // SetWindowExt records from the data stream. The window origin and
  434. // extents have been set up when we begin converting this enhanced
  435. // metafile.
  436. // Expand the object handle slot table.
  437. if (((PMETAHEADER) pbwmfNew)->mtNoObjects)
  438. {
  439. PW16OBJHNDLSLOTSTATUS pW16ObjHndlSlotStatusTmp;
  440. cSizeOld = (DWORD) pLocalDC->cW16ObjHndlSlotStatus;
  441. if (cSizeOld + ((PMETAHEADER)pbwmfNew)->mtNoObjects > (UINT) (WORD) MAXWORD)
  442. goto dgcmf_exit; // w16 handle index is only 16-bit
  443. pLocalDC->cW16ObjHndlSlotStatus += ((PMETAHEADER)pbwmfNew)->mtNoObjects;
  444. i = pLocalDC->cW16ObjHndlSlotStatus * sizeof(W16OBJHNDLSLOTSTATUS);
  445. pW16ObjHndlSlotStatusTmp = (PW16OBJHNDLSLOTSTATUS)
  446. LocalReAlloc(pLocalDC->pW16ObjHndlSlotStatus, i, LMEM_MOVEABLE);
  447. if (pW16ObjHndlSlotStatusTmp == NULL)
  448. {
  449. pLocalDC->cW16ObjHndlSlotStatus -= ((PMETAHEADER)pbwmfNew)->mtNoObjects;
  450. goto dgcmf_exit;
  451. }
  452. pLocalDC->pW16ObjHndlSlotStatus = pW16ObjHndlSlotStatusTmp;
  453. for (i = cSizeOld; i < pLocalDC->cW16ObjHndlSlotStatus; i++)
  454. {
  455. pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT;
  456. pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
  457. }
  458. }
  459. // Find the new base for the object index.
  460. for (iBase = pLocalDC->cW16ObjHndlSlotStatus - 1; iBase >= 0; iBase--)
  461. {
  462. if (pLocalDC->pW16ObjHndlSlotStatus[iBase].use != OPEN_AVAILABLE_SLOT)
  463. break;
  464. }
  465. iBase++;
  466. // Fill up the object index table with dummy objects.
  467. Win16LogBrush.lbStyle = BS_SOLID;
  468. Win16LogBrush.lbColor = 0;
  469. Win16LogBrush.lbHatch = 0;
  470. for (i = 0; i < (DWORD) iBase; i++)
  471. {
  472. if (pLocalDC->pW16ObjHndlSlotStatus[i].use == OPEN_AVAILABLE_SLOT)
  473. {
  474. if (!bEmitWin16CreateBrushIndirect(pLocalDC, &Win16LogBrush))
  475. goto dgcmf_exit;
  476. pLocalDC->pW16ObjHndlSlotStatus[i].use = REALIZED_DUMMY;
  477. }
  478. }
  479. // Update the high water mark.
  480. if (iBase + ((PMETAHEADER) pbwmfNew)->mtNoObjects - 1 > pLocalDC->nObjectHighWaterMark)
  481. pLocalDC->nObjectHighWaterMark = iBase + ((PMETAHEADER) pbwmfNew)->mtNoObjects - 1;
  482. // Save DC states.
  483. if (!bEmitWin16SaveDC(pLocalDC))
  484. goto dgcmf_exit;
  485. // Enumerate the records and fix them up as necessary.
  486. for (pmr = (PMETARECORD) (pbwmfNew + sizeof(METAHEADER));
  487. pmr->rdFunction != 0;
  488. pmr = (PMETARECORD) ((PWORD) pmr + pmr->rdSize))
  489. {
  490. switch (pmr->rdFunction)
  491. {
  492. case META_SETWINDOWORG:
  493. ASSERTGDI(++iSWO <= 1,
  494. "MF3216: DoGdiCommentMultiFormats - unexpected SWO record\n");
  495. break;
  496. case META_SETWINDOWEXT:
  497. ASSERTGDI(++iSWE <= 1,
  498. "MF3216: DoGdiCommentMultiFormats - unexpected SWE record\n");
  499. break;
  500. case META_ESCAPE:
  501. if (!IS_META_ESCAPE_ENHANCED_METAFILE((PMETA_ESCAPE_ENHANCED_METAFILE) pmr))
  502. goto default_alt;
  503. break;
  504. case META_RESTOREDC:
  505. ASSERTGDI((int)(SHORT)pmr->rdParm[0] < 0,
  506. "MF3216: DoGdiCommentMultiFormats - bogus RestoreDC record\n");
  507. goto default_alt;
  508. case META_SELECTCLIPREGION:
  509. if (pmr->rdParm[0] != 0) // allow for default clipping!
  510. {
  511. pmr->rdParm[0] += (WORD)iBase;
  512. pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = REALIZED_OBJECT;
  513. }
  514. goto default_alt;
  515. case META_FRAMEREGION:
  516. case META_FILLREGION:
  517. pmr->rdParm[1] += (WORD)iBase;
  518. pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[1]].use = REALIZED_OBJECT;
  519. // fall through
  520. case META_PAINTREGION:
  521. case META_INVERTREGION:
  522. case META_DELETEOBJECT:
  523. case META_SELECTPALETTE:
  524. case META_SELECTOBJECT:
  525. pmr->rdParm[0] += (WORD)iBase;
  526. if (pmr->rdFunction != META_DELETEOBJECT)
  527. pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = REALIZED_OBJECT;
  528. else
  529. pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = OPEN_AVAILABLE_SLOT;
  530. // fall through
  531. default:
  532. default_alt:
  533. if (!bEmit(pLocalDC, (PVOID) pmr, pmr->rdSize * sizeof(WORD)))
  534. goto dgcmf_exit;
  535. vUpdateMaxRecord(pLocalDC, pmr);
  536. break;
  537. }
  538. }
  539. // Restore DC states.
  540. if (!bEmitWin16RestoreDC(pLocalDC, (WORD) -1))
  541. goto dgcmf_exit;
  542. // Remove the dummy objects from the handle table.
  543. for (i = 0; i < (DWORD) iBase; i++)
  544. {
  545. if (pLocalDC->pW16ObjHndlSlotStatus[i].use == REALIZED_DUMMY)
  546. {
  547. if (!bEmitWin16DeleteObject(pLocalDC, (WORD) i))
  548. goto dgcmf_exit;
  549. pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT;
  550. }
  551. }
  552. // Shrink the object handle slot table.
  553. if (((PMETAHEADER) pbwmfNew)->mtNoObjects)
  554. {
  555. DWORD cUndel = 0; // number of objects not deleted
  556. DWORD iUndelMax = iBase - 1; // the max undeleted object index
  557. for (i = iBase; i < pLocalDC->cW16ObjHndlSlotStatus; i++)
  558. {
  559. if (pLocalDC->pW16ObjHndlSlotStatus[i].use != OPEN_AVAILABLE_SLOT)
  560. {
  561. cUndel++;
  562. iUndelMax = i;
  563. }
  564. }
  565. pLocalDC->cW16ObjHndlSlotStatus = max(cSizeOld + cUndel, iUndelMax + 1);
  566. }
  567. // Everything is golden.
  568. bRet = TRUE;
  569. dgcmf_exit:
  570. if (pbwmfNew)
  571. if (LocalFree(pbwmfNew))
  572. ASSERTGDI(FALSE, "MF3216: DoGdiCommentMultiFormats - LocalFree failed\n");
  573. if (hemf)
  574. DeleteEnhMetaFile(hemf);
  575. if (hdcemfNew)
  576. hemfNew = CloseEnhMetaFile(hdcemfNew); // hemfNew will be deleted next
  577. if (hemfNew)
  578. DeleteEnhMetaFile(hemfNew);
  579. return(bRet);
  580. }
  581. /***************************************************************************
  582. * EOF - Win32 to Win16 Metafile Converter Entry Point
  583. **************************************************************************/
  584. BOOL APIENTRY DoEOF
  585. (
  586. PLOCALDC pLocalDC
  587. )
  588. {
  589. BOOL b ;
  590. b = bEmitWin16EOF(pLocalDC) ;
  591. return(b) ;
  592. }