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.

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