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.

2190 lines
79 KiB

  1. /****************************** Module Header ******************************\
  2. * Module Name: MfPlay16.c
  3. *
  4. * This file contains the routines for playing the GDI metafile. Most of these
  5. * routines are adopted from windows gdi code. Most of the code is from
  6. * win3.0 except for the GetEvent code which is taken from win2.1
  7. *
  8. * Created: 11-Oct-1989
  9. *
  10. * Copyright (c) 1985-1999 Microsoft Corporation
  11. *
  12. *
  13. * Public Functions:
  14. * PlayMetaFile
  15. * PlayMetaFileRecord
  16. * GetMetaFile
  17. * DeleteMetaFile
  18. * Private Functions:
  19. * GetEvent
  20. * IsDIBBlackAndWhite
  21. *
  22. * History:
  23. * 02-Jul-1991 -by- John Colleran [johnc]
  24. * Combined From Win 3.1 and WLO 1.0 sources
  25. \***************************************************************************/
  26. #include "precomp.h"
  27. #pragma hdrstop
  28. #include "mf16.h"
  29. BOOL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, UINT noObjs);
  30. BOOL CommonEnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC proc, LPARAM lpData);
  31. HANDLE CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo);
  32. WORD GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo);
  33. BOOL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo);
  34. BOOL PlayIntoAMetafile(LPMETARECORD lpMR, HDC hdcDest);
  35. #if DBG
  36. UINT curRecord; // debuging helpers
  37. UINT iBreakRecord = 0xFFFFFFFF;
  38. #endif
  39. /***************************** Public Function ****************************\
  40. * BOOL APIENTRY PlayMetaFile(hdc, hmf)
  41. * HDC hDC;
  42. * HMETAFILE hMF;
  43. *
  44. * Play a windows metafile.
  45. *
  46. * History:
  47. * 02-Jul-1991 -by- John Colleran [johnc]
  48. * Ported from Windows and WLO
  49. \***************************************************************************/
  50. BOOL APIENTRY PlayMetaFile(HDC hdc, HMETAFILE hmf)
  51. {
  52. return (CommonEnumMetaFile(hdc, hmf, (MFENUMPROC)NULL, (LPARAM)0));
  53. }
  54. /******************************** Public Function **************************\
  55. * BOOL EnumMetaFile(hmf)
  56. *
  57. * The EnumMetaFile function enumerates the GDI calls within the metafile
  58. * identified by the hMF parameter. The EnumMetaFile function retrieves each
  59. * GDI call within the metafile and passes it to the function pointed to by the
  60. * pCallbackFunc parameter. This callback function, an application-supplied
  61. * function, can process each GDI call as desired. Enumeration continues until
  62. * there are no more GDI calls or the callback function returns zero.
  63. *
  64. *
  65. * Effects:
  66. *
  67. \***************************************************************************/
  68. BOOL EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC pCallBackFunction, LPARAM pClientData)
  69. {
  70. // Make sure that the callback function is given. CommonEnumMetaFile expects
  71. // it to be given in EnumMetaFile.
  72. if (!pCallBackFunction)
  73. {
  74. GdiSetLastError(ERROR_INVALID_PARAMETER );
  75. return(FALSE);
  76. }
  77. return (CommonEnumMetaFile(hdc, hmf, pCallBackFunction, pClientData));
  78. }
  79. BOOL CommonEnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC pCallBack, LPARAM pClientData)
  80. {
  81. BOOL fStatus = FALSE; // assume it fails
  82. UINT ii;
  83. UINT noObjs;
  84. PMETAFILE16 pMF;
  85. INT oldMapMode = -1;
  86. PMETARECORD pMR = (PMETARECORD) NULL;
  87. LPHANDLETABLE pht = (LPHANDLETABLE) NULL;
  88. HFONT hLFont;
  89. HBRUSH hLBrush;
  90. HPALETTE hLPal;
  91. HPEN hLPen;
  92. HRGN hClipRgn = (HRGN)NULL;
  93. SIZE sizeOldWndExt;
  94. SIZE sizeOldVprtExt;
  95. PDC_ATTR pDcAttr;
  96. PLDC pldc;
  97. int iGraphicsModeOld;
  98. BOOL bMetaDC16 = FALSE;
  99. FLONG flPlayMetaFile = (FLONG) 0;
  100. // First validate the DC type and note whether or not we
  101. // are playing into a 16bit metafile.Null hdc is allowed
  102. // in win3.0 but disallowed in win3.1.
  103. if(LO_TYPE(hdc) == LO_METADC16_TYPE)
  104. {
  105. bMetaDC16 = TRUE;
  106. }
  107. else if ((hdc == NULL) && pCallBack)
  108. {
  109. // Actually win9x can take NULL hdc. There are some image filter
  110. // that actually pass in us NULL hdc. Only let NULL hdc thru if there is a
  111. // callback routine. [bug 102767]
  112. bMetaDC16 = TRUE;
  113. }
  114. else
  115. if((LO_TYPE(hdc) != LO_DC_TYPE ) &&
  116. (LO_TYPE(hdc) != LO_ALTDC_TYPE))
  117. {
  118. WARNING("CommonEnumMetaFile: bogus DC\n");
  119. return(FALSE);
  120. }
  121. // need a pointer to pDcAttr for DC_PLAYMETAFILE flag
  122. PSHARED_GET_VALIDATE((PVOID)pDcAttr,hdc,DC_TYPE);
  123. if(!bMetaDC16 && !pDcAttr) {
  124. WARNING("CommonEnumMetaFile: Couldn't Validate DC\n");
  125. return(FALSE);
  126. }
  127. // we still need to PLDC in the case that we are printing and there is
  128. // an abort proc
  129. pldc = GET_PLDC(hdc);
  130. PUTS("CommonEnumMetaFile\n");
  131. #if DBG
  132. curRecord = 0;
  133. #endif
  134. // Validate the 16 bit MetaFile
  135. pMF = GET_PMF16(hmf);
  136. if (pMF == NULL)
  137. {
  138. GdiSetLastError(ERROR_INVALID_HANDLE);
  139. return(FALSE);
  140. }
  141. // Allocate memory for the handle table.
  142. if ((noObjs = pMF->metaHeader.mtNoObjects) > 0)
  143. if (!(pht = (LPHANDLETABLE) LocalAlloc(
  144. LMEM_FIXED | LMEM_ZEROINIT,
  145. sizeof(HANDLE) * pMF->metaHeader.mtNoObjects
  146. + sizeof(WORD)))) // need extra word?
  147. return(FALSE);
  148. // Save the old objects so we can put them back if this is not a metafile.
  149. // Only do object save/reselect for real DC's.
  150. if( !bMetaDC16 )
  151. {
  152. hLBrush = (HBRUSH) GetDCObject(hdc, LO_BRUSH_TYPE);
  153. hLFont = (HFONT) GetDCObject(hdc, LO_FONT_TYPE);
  154. hLPal = (HPALETTE) GetDCObject(hdc, LO_PALETTE_TYPE);
  155. hLPen = (HPEN) GetDCObject(hdc, LO_PEN_TYPE);
  156. // Set a bit in the DC to indicate that we are playing the metafile.
  157. // This bit is cleared by CancelDC() to stop playing the metafile.
  158. // At the same time, remember the previous DC_PLAYMETAFILE bit.
  159. try
  160. {
  161. flPlayMetaFile = pDcAttr->ulDirty_ & DC_PLAYMETAFILE;
  162. if (flPlayMetaFile)
  163. {
  164. PUTS("CommonEnumMetaFile: DC_PLAYMETAFILE bit is set!\n");
  165. }
  166. pDcAttr->ulDirty_ |= DC_PLAYMETAFILE;
  167. }
  168. except(EXCEPTION_EXECUTE_HANDLER)
  169. {
  170. WARNING("except in SetBkMode\n");
  171. GdiSetLastError(ERROR_INVALID_PARAMETER);
  172. return(FALSE);
  173. }
  174. // Create a region in case there is a clip region to receive from GetClipRgn
  175. if (!(hClipRgn = CreateRectRgn(0,0,0,0)))
  176. goto pmf_cleanup;
  177. switch (GetClipRgn(hdc, hClipRgn))
  178. {
  179. case -1: // error
  180. ASSERTGDI(FALSE, "GetClipRgn failed");
  181. goto pmf_cleanup;
  182. case 0: // no initial clip region
  183. if (!DeleteObject(hClipRgn))
  184. ASSERTGDI(FALSE, "CommonEnumMetaFile: Detele region failed\n");
  185. hClipRgn = (HRGN) 0;
  186. break;
  187. case 1: // has initial clip region
  188. break;
  189. }
  190. // The metafile is to be played in the compatible graphics mode only.
  191. iGraphicsModeOld = GetGraphicsMode(hdc);
  192. if (iGraphicsModeOld != GM_COMPATIBLE)
  193. SetGraphicsMode(hdc, GM_COMPATIBLE);
  194. }
  195. // Are we doing an EnumMetaFile or PlayMetaFile
  196. if (pCallBack)
  197. {
  198. fStatus = TRUE; // assume success
  199. // EnumMetaFile
  200. while (pMR = (PMETARECORD) GetEvent(pMF, pMR))
  201. {
  202. if (pMR == (PMETARECORD) -1)
  203. {
  204. fStatus = FALSE;
  205. break;
  206. }
  207. if (!bMetaDC16 && !( pDcAttr->ulDirty_ & DC_PLAYMETAFILE))
  208. {
  209. WARNING("CommonEnumMetaFile: CancelDC called\n");
  210. fStatus = FALSE;
  211. break;
  212. }
  213. if (!(fStatus = (*pCallBack)(hdc, pht, (METARECORD FAR *) pMR,
  214. (int) noObjs, pClientData)))
  215. break;
  216. #if DBG
  217. curRecord++;
  218. if (curRecord == iBreakRecord)
  219. ASSERTGDI(FALSE, "CommonEnumMetaFile: iBreakRecord reached\n");
  220. #endif
  221. }
  222. }
  223. else
  224. {
  225. // PlayMetaFile
  226. fStatus = TRUE; // assume success
  227. while (pMR = (PMETARECORD) GetEvent(pMF, pMR))
  228. {
  229. if (pMR == (PMETARECORD) -1)
  230. {
  231. fStatus = FALSE;
  232. break;
  233. }
  234. if (!bMetaDC16 && !( pDcAttr->ulDirty_ & DC_PLAYMETAFILE))
  235. {
  236. WARNING("CommonEnumMetaFile: CancelDC called\n");
  237. fStatus = FALSE;
  238. break;
  239. }
  240. if (pldc && pldc->pfnAbort != NULL)
  241. {
  242. if (!(*pldc->pfnAbort)(hdc, 0))
  243. {
  244. fStatus = FALSE;
  245. break;
  246. }
  247. }
  248. // For win3.1 compatability, ignore the return value from PlayMetaFileRecord
  249. PlayMetaFileRecord(hdc, pht, pMR, noObjs);
  250. #if DBG
  251. curRecord++;
  252. if (curRecord == iBreakRecord)
  253. ASSERTGDI(FALSE, "CommonEnumMetaFile: iBreakRecord reached\n");
  254. #endif
  255. }
  256. }
  257. // if we fail restoring an object, we need to select some
  258. // default object so that we can DeleteObject any Metafile-
  259. // selected objects
  260. if( !bMetaDC16 )
  261. {
  262. if (iGraphicsModeOld != GM_COMPATIBLE)
  263. SetGraphicsMode(hdc, iGraphicsModeOld);
  264. if (!SelectObject(hdc,hLPen))
  265. SelectObject(hdc,GetStockObject(BLACK_PEN));
  266. if (!SelectObject(hdc,hLBrush))
  267. SelectObject(hdc,GetStockObject(BLACK_BRUSH));
  268. if (!SelectPalette(hdc, hLPal, FALSE))
  269. SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE);
  270. if (hLFont != (HFONT) GetDCObject(hdc, LO_FONT_TYPE))
  271. {
  272. if (!SelectObject(hdc,hLFont))
  273. {
  274. // if we cannot select the original font back in, we
  275. // select the system font. this will allow us to delete
  276. // the metafile font selected. to insure that the system
  277. // font gets selected, we reset the DC's transform to
  278. // default. after the selection, we restore this stuff
  279. //
  280. GetWindowExtEx(hdc, &sizeOldWndExt);
  281. GetViewportExtEx(hdc, &sizeOldVprtExt);
  282. oldMapMode = SetMapMode(hdc, MM_TEXT);
  283. SelectObject(hdc,GetStockObject(SYSTEM_FONT));
  284. SetMapMode(hdc,oldMapMode);
  285. SetWindowExtEx( hdc, sizeOldWndExt.cx, sizeOldWndExt.cy, NULL);
  286. SetViewportExtEx(hdc, sizeOldVprtExt.cx, sizeOldVprtExt.cy, NULL);
  287. }
  288. }
  289. if (SelectClipRgn(hdc, hClipRgn) == RGN_ERROR)
  290. SelectClipRgn(hdc, (HRGN) 0);
  291. }
  292. // Cleanup all created objects
  293. for (ii = 0; ii < noObjs; ii++)
  294. {
  295. if (pht->objectHandle[ii])
  296. if (!DeleteObject(pht->objectHandle[ii]))
  297. ERROR_ASSERT(FALSE,
  298. "CommonEnumMetaFile: DeleteObject(objectHandle) failed\n");
  299. }
  300. // if we fiddled with the map mode because we could not
  301. // restore the original font, then maybe we can restore the
  302. // font now
  303. if (oldMapMode > 0)
  304. SelectObject(hdc,hLFont);
  305. pmf_cleanup:
  306. if (pldc)
  307. {
  308. // Preserve the DC_PLAYMETAFILE bit.
  309. // If we hit a CancelDC, then we will leave the bit clear.
  310. ASSERTGDI(!(flPlayMetaFile & ~DC_PLAYMETAFILE),
  311. "CommonEnumMetaFile: bad flPlayMetaFile\n");
  312. if (!bMetaDC16 && !( pDcAttr->ulDirty_ & DC_PLAYMETAFILE) )
  313. {
  314. pDcAttr->ulDirty_ &= ~DC_PLAYMETAFILE;
  315. pDcAttr->ulDirty_ |= flPlayMetaFile; // restore the original flag
  316. }
  317. }
  318. if (hClipRgn)
  319. if (!DeleteObject(hClipRgn))
  320. ASSERTGDI(FALSE, "CommonEnumMetaFile: Delete region 2 failed\n");
  321. if (pht)
  322. if (LocalFree((HANDLE) pht))
  323. ASSERTGDI(FALSE, "CommonEnumMetaFile: LocalFree failed\n");
  324. return(fStatus);
  325. }
  326. /***************************** Internal Function **************************\
  327. * BOOL NEAR PASCAL IsDIBBlackAndWhite
  328. *
  329. * Check to see if this DIB is a black and white DIB (and should be
  330. * converted into a mono bitmap as opposed to a color bitmap).
  331. *
  332. * Returns: TRUE it is a B&W bitmap
  333. * FALSE this is for color
  334. *
  335. * Effects: ?
  336. *
  337. * Warnings: ?
  338. *
  339. * History:
  340. \***************************************************************************/
  341. BOOL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo)
  342. {
  343. LPDWORD lpRGB;
  344. PUTS("IsDIBBlackAndWhite\n");
  345. ASSERTGDI(!((ULONG_PTR) lpDIBInfo & 0x3), "IsDIBBlackAndWhite: dword alignment error\n");
  346. /* pointer color table */
  347. lpRGB = (LPDWORD)((LPBITMAPINFO)lpDIBInfo)->bmiColors;
  348. return (lpDIBInfo->biBitCount == 1
  349. && lpDIBInfo->biPlanes == 1
  350. && lpRGB[0] == (DWORD) 0
  351. && lpRGB[1] == (DWORD) 0xFFFFFF);
  352. }
  353. /***************************** Internal Function **************************\
  354. * UseStretchDIBits
  355. *
  356. * set this directly to the device using StretchDIBits.
  357. * if DIB is black&white, don't do this.
  358. *
  359. * Returns:
  360. * TRUE --- operation successful
  361. * FALSE -- decided not to use StretchDIBits
  362. *
  363. * History:
  364. \***************************************************************************/
  365. BOOL UseStretchDIB(HDC hDC, WORD magic, LPMETARECORD lpMR)
  366. {
  367. LPBITMAPINFOHEADER lpDIBInfo;
  368. INT sExtX, sExtY;
  369. INT sSrcX, sSrcY;
  370. INT DstX, DstY, DstXE, DstYE;
  371. if (magic == META_DIBBITBLT)
  372. {
  373. lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8];
  374. DstX = (INT) (SHORT) lpMR->rdParm[7];
  375. DstY = (INT) (SHORT) lpMR->rdParm[6];
  376. sSrcX = (INT) (SHORT) lpMR->rdParm[3];
  377. sSrcY = (INT) (SHORT) lpMR->rdParm[2];
  378. DstXE = sExtX = (INT) (SHORT) lpMR->rdParm[5];
  379. DstYE = sExtY = (INT) (SHORT) lpMR->rdParm[4];
  380. }
  381. else
  382. {
  383. lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10];
  384. DstX = (INT) (SHORT) lpMR->rdParm[9];
  385. DstY = (INT) (SHORT) lpMR->rdParm[8];
  386. DstXE = (INT) (SHORT) lpMR->rdParm[7];
  387. DstYE = (INT) (SHORT) lpMR->rdParm[6];
  388. sSrcX = (INT) (SHORT) lpMR->rdParm[5];
  389. sSrcY = (INT) (SHORT) lpMR->rdParm[4];
  390. sExtX = (INT) (SHORT) lpMR->rdParm[3];
  391. sExtY = (INT) (SHORT) lpMR->rdParm[2];
  392. }
  393. ASSERTGDI(!((ULONG_PTR) lpDIBInfo & 0x3), "UseStretchDIB: dword alignment error\n");
  394. /* if DIB is black&white, we don't really want to do this */
  395. if (IsDIBBlackAndWhite(lpDIBInfo))
  396. return(FALSE);
  397. // Need to flip the source y coordinates to call StretchDIBits.
  398. sSrcY = ABS(lpDIBInfo->biHeight) - sSrcY - sExtY;
  399. StretchDIBits(hDC, DstX, DstY, DstXE, DstYE,
  400. sSrcX, sSrcY, sExtX, sExtY,
  401. (LPBYTE)((LPSTR)lpDIBInfo + lpDIBInfo->biSize
  402. + GetSizeOfColorTable(lpDIBInfo)),
  403. (LPBITMAPINFO)lpDIBInfo, DIB_RGB_COLORS,
  404. (MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])));
  405. return(TRUE);
  406. }
  407. BOOL
  408. bValidExtent(PMETAFILE16 pmf16, LPMETARECORD lpMR, DWORD cbSize)
  409. {
  410. #if 0
  411. // No absolute pointer validations as the records can be copied and played back.
  412. BYTE *pB = (BYTE*)pmf16->hMem;
  413. BYTE *pE = (BYTE*)lpMR + cbSize;
  414. #endif
  415. if (pmf16->fl & MF16_DISKFILE)
  416. {
  417. UINT64 fileSize;
  418. if (!GetFileSizeEx(pmf16->hFile, (PLARGE_INTEGER)&fileSize))
  419. {
  420. EMFVALFAIL(("GetFileSize(%p) failed\n", pmf16->hFile));
  421. return(FALSE);
  422. }
  423. if (cbSize > fileSize)
  424. {
  425. EMFVALFAIL(("Record Size (%d) larger than file size (%d)!\n", cbSize, (UINT32)fileSize));
  426. return(FALSE);
  427. }
  428. }
  429. else
  430. {
  431. if (cbSize > (((PMETAHEADER)pmf16->hMem)->mtSize * sizeof(WORD)))
  432. {
  433. EMFVALFAIL(("Record Size (%d) larger than file size (%d)!\n", cbSize, (UINT32)(((PMETAHEADER)pmf16->hMem)->mtSize * sizeof(WORD))));
  434. return(FALSE);
  435. }
  436. }
  437. #if 0
  438. // No absolute pointer validations as the records can be copied and played back.
  439. if (pE < pB)
  440. {
  441. EMFVALFAIL(("End pointer(%p) is less than Begin pointer (%p). Arithmetic wrap around!\n", pE, pB));
  442. return(FALSE);
  443. }
  444. #endif
  445. return (TRUE);
  446. }
  447. /***************************** Internal Function **************************\
  448. * GetEvent
  449. *
  450. * This routine will now open a disk metafile in READ_ONLY mode. This will
  451. * allow us to play read-only metafiles or to share such file.
  452. *
  453. * To start the enumeration, the first lpMR must be NULL.
  454. * It does not enumerate the first (header) and last (terminator) records.
  455. *
  456. * Returns: Next MetaFile Record to be played
  457. * NULL if the next metafile record is the EOF record
  458. * -1 if an error occurs.
  459. *
  460. \***************************************************************************/
  461. PMETARECORD GetEvent(PMETAFILE16 pmf16, PMETARECORD lpMR)
  462. {
  463. PMETARECORD lpMRNext;
  464. PUTS("GetEvent\n");
  465. if (lpMR == (PMETARECORD) NULL)
  466. {
  467. if (!bValidExtent(pmf16, (PMETARECORD)pmf16, sizeof(METAHEADER)))
  468. {
  469. EMFVALFAIL(("GetEvent: bValidExtent(%p) (%p) (%08x) failed\n", pmf16, pmf16, sizeof(METAHEADER)));
  470. return((PMETARECORD) -1);
  471. }
  472. pmf16->iMem = sizeof(METAHEADER);
  473. }
  474. else
  475. {
  476. if (lpMR->rdSize * sizeof(WORD) < lpMR->rdSize)
  477. {
  478. EMFVALFAIL(("GetEvent: arithmetic overflow\n"));
  479. return((PMETARECORD) -1);
  480. }
  481. if (lpMR->rdSize == 0 || !bValidExtent(pmf16, lpMR, lpMR->rdSize * sizeof(WORD)))
  482. {
  483. EMFVALFAIL(("GetEvent: bValidExtent(%p) (%p) (%08x) failed\n", pmf16, lpMR, lpMR->rdSize * sizeof(WORD)));
  484. return((PMETARECORD) -1);
  485. }
  486. pmf16->iMem += (lpMR->rdSize * sizeof(WORD));
  487. }
  488. // Make sure that we don't read past the EOF. A minimal record includes
  489. // rdSize (DWORD) and rdFunction (WORD).
  490. if (pmf16->iMem > pmf16->metaHeader.mtSize * sizeof(WORD) - sizeof(DWORD) - sizeof(WORD))
  491. {
  492. VERIFYGDI(FALSE, "GetEvent: Metafile contains bad data\n");
  493. return((PMETARECORD) -1);
  494. }
  495. lpMRNext = (PMETARECORD) ((LPBYTE) pmf16->hMem + pmf16->iMem);
  496. // If we are at the end of the metafile then return NULL.
  497. if (lpMRNext->rdFunction == 0)
  498. return((PMETARECORD) NULL);
  499. return(lpMRNext);
  500. }
  501. /***************************** Internal Function **************************\
  502. * BOOL GDIENTRY PlayMetaFileRecord
  503. *
  504. * Plays a metafile record by executing the GDI function call contained
  505. * withing the metafile record
  506. *
  507. * Effects:
  508. *
  509. \***************************************************************************/
  510. //LPSTR lpZapfDingbats = "ZAPFDINGBATS";
  511. //LPSTR lpZapf_Dingbats = "ZAPF DINGBATS";
  512. //LPSTR lpSymbol = "SYMBOL";
  513. //LPSTR lpTmsRmn = "TMS RMN";
  514. //LPSTR lpHelv = "HELV";
  515. #define PITCH_MASK ( FIXED_PITCH | VARIABLE_PITCH )
  516. BOOL
  517. APIENTRY PlayMetaFileRecord(
  518. HDC hdc,
  519. LPHANDLETABLE lpHandleTable,
  520. LPMETARECORD lpMR,
  521. UINT noObjs
  522. )
  523. {
  524. BOOL fStatus = FALSE;
  525. LPMETARECORD lpMRdup = (LPMETARECORD) NULL;
  526. WORD magic;
  527. HANDLE hObject;
  528. HANDLE hOldObject;
  529. HBRUSH hBrush;
  530. HRGN hRgn;
  531. HANDLE hPal;
  532. PUTSX("PlayMetaFileRecord 0x%p\n", lpMR);
  533. magic = lpMR->rdFunction;
  534. switch (magic & 255)
  535. {
  536. case (META_BITBLT & 255):
  537. case (META_STRETCHBLT & 255):
  538. {
  539. HDC hSDC;
  540. HANDLE hBitmap;
  541. PBITMAP16 lpBitmap16;
  542. INT delta = 0;
  543. DWORD rop;
  544. WARNING("PlayMetaFileRecord: obsolete META_BITBLT/META_STRETCHBLT record\n");
  545. /* if playing into another Metafile, do direct copy */
  546. if (PlayIntoAMetafile(lpMR, hdc))
  547. {
  548. fStatus = TRUE;
  549. break;
  550. }
  551. if ((lpMR->rdSize - 3) == ((DWORD) magic >> 8))
  552. {
  553. hSDC = hdc;
  554. delta = 1;
  555. }
  556. else
  557. {
  558. LPMETARECORD lpMRtmp;
  559. // Make the bitmap bits dword aligned. To do this,
  560. // lpMR has to fall on a dword aligned even address so that
  561. // the bitmap bits (&lpMR->rdParm[8+5] or &lpMR->rdParm[10+5])
  562. // will fall on the dword aligned addresses.
  563. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  564. (UINT) lpMR->rdSize * sizeof(WORD))))
  565. break;
  566. lpMRtmp = lpMRdup;
  567. RtlCopyMemory((PBYTE) lpMRtmp,
  568. (PBYTE) lpMR,
  569. (UINT) lpMR->rdSize * sizeof(WORD));
  570. if (hSDC = CreateCompatibleDC(hdc))
  571. {
  572. if (magic == META_BITBLT)
  573. lpBitmap16 = (PBITMAP16) &lpMRtmp->rdParm[8];
  574. else
  575. lpBitmap16 = (PBITMAP16) &lpMRtmp->rdParm[10];
  576. if (hBitmap = CreateBitmap(lpBitmap16->bmWidth,
  577. lpBitmap16->bmHeight,
  578. lpBitmap16->bmPlanes,
  579. lpBitmap16->bmBitsPixel,
  580. (LPBYTE)&lpBitmap16->bmBits))
  581. hOldObject = SelectObject(hSDC, hBitmap);
  582. else
  583. goto PMFR_BitBlt_cleanup;
  584. }
  585. else
  586. break;
  587. }
  588. rop = MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]);
  589. if (magic == META_BITBLT)
  590. fStatus = BitBlt(hdc,
  591. (int) (SHORT) lpMR->rdParm[7 + delta],
  592. (int) (SHORT) lpMR->rdParm[6 + delta],
  593. (int) (SHORT) lpMR->rdParm[5 + delta],
  594. (int) (SHORT) lpMR->rdParm[4 + delta],
  595. (delta && !ISSOURCEINROP3(rop)) ? 0 : hSDC,
  596. (int) (SHORT) lpMR->rdParm[3],
  597. (int) (SHORT) lpMR->rdParm[2],
  598. rop);
  599. else
  600. fStatus = StretchBlt(hdc,
  601. (int) (SHORT) lpMR->rdParm[9 + delta],
  602. (int) (SHORT) lpMR->rdParm[8 + delta],
  603. (int) (SHORT) lpMR->rdParm[7 + delta],
  604. (int) (SHORT) lpMR->rdParm[6 + delta],
  605. (delta && !ISSOURCEINROP3(rop)) ? 0 : hSDC,
  606. (int) (SHORT) lpMR->rdParm[5],
  607. (int) (SHORT) lpMR->rdParm[4],
  608. (int) (SHORT) lpMR->rdParm[3],
  609. (int) (SHORT) lpMR->rdParm[2],
  610. rop);
  611. if (hSDC != hdc)
  612. {
  613. if (!SelectObject(hSDC, hOldObject))
  614. ASSERTGDI(FALSE, "PlayMetaFileRecord: SelectObject Bitblt Failed\n");
  615. if (!DeleteObject(hBitmap))
  616. ASSERTGDI(FALSE, "PlayMetaFileRecord: DeleteObject Bitblt Failed\n");
  617. PMFR_BitBlt_cleanup:
  618. if (!DeleteDC(hSDC))
  619. ASSERTGDI(FALSE, "PlayMetaFileRecord: DeleteDC BitBlt Failed\n");
  620. }
  621. }
  622. break;
  623. case (META_DIBBITBLT & 255):
  624. case (META_DIBSTRETCHBLT & 255):
  625. {
  626. HDC hSDC;
  627. HANDLE hBitmap;
  628. LPBITMAPINFOHEADER lpDIBInfo ;
  629. INT delta = 0;
  630. HANDLE hOldPal;
  631. /* if playing into another metafile, do direct copy */
  632. if (PlayIntoAMetafile(lpMR, hdc))
  633. {
  634. fStatus = TRUE;
  635. break;
  636. }
  637. if ((lpMR->rdSize - 3) == ((DWORD) magic >> 8))
  638. {
  639. hSDC = hdc;
  640. delta = 1;
  641. }
  642. else
  643. {
  644. LPMETARECORD lpMRtmp;
  645. // Make the bitmap info and bits dword aligned. To do this,
  646. // lpMR has to fall on a non dword aligned even address so that
  647. // the bitmap info (&lpMR->rdParm[8] or &lpMR->rdParm[10]) and
  648. // the bitmap bits will fall on the dword aligned addresses.
  649. // Note that the size of the bitmap info is always a multiple
  650. // of 4.
  651. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  652. (UINT) lpMR->rdSize * sizeof(WORD) + sizeof(WORD))))
  653. break;
  654. lpMRtmp = (LPMETARECORD) &((PWORD) lpMRdup)[1];
  655. RtlCopyMemory((PBYTE) lpMRtmp,
  656. (PBYTE) lpMR,
  657. (UINT) lpMR->rdSize * sizeof(WORD));
  658. if (UseStretchDIB(hdc, magic, lpMRtmp))
  659. {
  660. fStatus = TRUE;
  661. break;
  662. }
  663. if (hSDC = CreateCompatibleDC(hdc))
  664. {
  665. /* set up the memDC to have the same palette */
  666. hOldPal = SelectPalette(hSDC, GetCurrentObject(hdc,OBJ_PAL), TRUE);
  667. if (magic == META_DIBBITBLT)
  668. lpDIBInfo = (LPBITMAPINFOHEADER)&lpMRtmp->rdParm[8];
  669. else
  670. lpDIBInfo = (LPBITMAPINFOHEADER)&lpMRtmp->rdParm[10];
  671. /* now create the bitmap for the MemDC and fill in the bits */
  672. /* the processing for old and new format of metafiles is
  673. different here (till hBitmap is obtained) */
  674. /* new metafile version */
  675. hBitmap = CreateBitmapForDC (hdc,lpDIBInfo);
  676. if (hBitmap)
  677. hOldObject = SelectObject (hSDC, hBitmap) ;
  678. else
  679. goto PMFR_DIBBITBLT_cleanup;
  680. }
  681. else
  682. break;
  683. }
  684. if (magic == META_DIBBITBLT)
  685. fStatus = BitBlt(hdc,
  686. (int) (SHORT) lpMR->rdParm[7 + delta],
  687. (int) (SHORT) lpMR->rdParm[6 + delta],
  688. (int) (SHORT) lpMR->rdParm[5 + delta],
  689. (int) (SHORT) lpMR->rdParm[4 + delta],
  690. delta ? 0 : hSDC,
  691. (int) (SHORT) lpMR->rdParm[3],
  692. (int) (SHORT) lpMR->rdParm[2],
  693. MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
  694. else
  695. fStatus = StretchBlt(hdc,
  696. (int) (SHORT) lpMR->rdParm[9 + delta],
  697. (int) (SHORT) lpMR->rdParm[8 + delta],
  698. (int) (SHORT) lpMR->rdParm[7 + delta],
  699. (int) (SHORT) lpMR->rdParm[6 + delta],
  700. delta ? 0 : hSDC,
  701. (int) (SHORT) lpMR->rdParm[5],
  702. (int) (SHORT) lpMR->rdParm[4],
  703. (int) (SHORT) lpMR->rdParm[3],
  704. (int) (SHORT) lpMR->rdParm[2],
  705. MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
  706. if (hSDC != hdc)
  707. {
  708. /* Deselect hDC's palette from memDC */
  709. SelectPalette(hSDC, hOldPal, TRUE);
  710. if (!SelectObject(hSDC, hOldObject))
  711. ASSERTGDI(FALSE, "PlayMetaFileRecord: SelectObject DIBBitBlt Failed\n");
  712. if (!DeleteObject(hBitmap))
  713. ASSERTGDI(FALSE, "PlayMetaFileRecord: DeleteObject(hBitmap) DIBBitBlt Failed\n");
  714. PMFR_DIBBITBLT_cleanup:
  715. if (!DeleteDC(hSDC))
  716. ASSERTGDI(FALSE, "PlayMetaFileRecord DeleteDC DIBBitblt failed\n");
  717. }
  718. }
  719. break;
  720. case (META_SELECTOBJECT & 255):
  721. {
  722. if (hObject = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  723. {
  724. fStatus = SelectObject(hdc, hObject) != (HANDLE)0;
  725. // new in win3.1
  726. if (!fStatus)
  727. {
  728. switch (GetObjectType(hObject))
  729. {
  730. case OBJ_PAL:
  731. SelectObject(hdc, (HGDIOBJ) GetStockObject(DEFAULT_PALETTE));
  732. break;
  733. case OBJ_BRUSH:
  734. SelectObject(hdc, (HGDIOBJ) GetStockObject(WHITE_BRUSH));
  735. break;
  736. case OBJ_PEN:
  737. SelectObject(hdc, (HGDIOBJ) GetStockObject(BLACK_PEN));
  738. break;
  739. case OBJ_FONT:
  740. SelectObject(hdc, (HGDIOBJ) GetStockObject(DEVICE_DEFAULT_FONT));
  741. break;
  742. case OBJ_REGION:
  743. SelectClipRgn(hdc, 0);
  744. break;
  745. default:
  746. ASSERTGDI(FALSE,
  747. "PlayMetaFileRecord:SELECTOBJECT unknown object\n");
  748. break;
  749. }
  750. }
  751. }
  752. }
  753. break;
  754. case (META_CREATEPENINDIRECT & 255):
  755. {
  756. LOGPEN lp;
  757. LOGPEN32FROMLOGPEN16(&lp, (PLOGPEN16) &lpMR->rdParm[0]);
  758. if (hObject = CreatePenIndirect(&lp))
  759. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  760. }
  761. break;
  762. case (META_CREATEFONTINDIRECT & 255):
  763. {
  764. LOGFONTA lf;
  765. PLOGFONT16 plf16 = (PLOGFONT16) &lpMR->rdParm[0];
  766. CHAR achCapString[LF_FACESIZE];
  767. LOGFONT32FROMLOGFONT16(&lf, (PLOGFONT16) &lpMR->rdParm[0]);
  768. // Capitalize the string for faster compares.
  769. lstrcpynA(achCapString, lf.lfFaceName, LF_FACESIZE);
  770. CharUpperBuffA(achCapString, LF_FACESIZE);
  771. // Here we are going to implement a bunch of Win 3.1 hacks rather
  772. // than contaminate the 32-bit engine. These same hacks can be found
  773. // in WOW (in the CreateFont/CreateFontIndirect code).
  774. //
  775. // These hacks are keyed off the facename in the LOGFONTA. String
  776. // comparisons have been unrolled for maximal performance.
  777. // Win 3.1 facename-based hack. Some apps, like
  778. // Publisher, create a "Helv" font but have the lfPitchAndFamily
  779. // set to specify FIXED_PITCH. To work around this, we will patch
  780. // the pitch field for a "Helv" font to be variable.
  781. // if ( !lstrcmp(achCapString, lpHelv) )
  782. if ( ((achCapString[0] == 'H') &&
  783. (achCapString[1] == 'E') &&
  784. (achCapString[2] == 'L') &&
  785. (achCapString[3] == 'V') &&
  786. (achCapString[4] == '\0')) )
  787. {
  788. lf.lfPitchAndFamily |= ( (lf.lfPitchAndFamily & ~PITCH_MASK) | VARIABLE_PITCH );
  789. }
  790. else
  791. {
  792. // Win 3.1 hack for Legacy 2.0. When a printer does not enumerate
  793. // a "Tms Rmn" font, the app enumerates and gets the LOGFONTA for
  794. // "Script" and then create a font with the name "Tms Rmn" but with
  795. // the lfCharSet and lfPitchAndFamily taken from the LOGFONTA for
  796. // "Script". Here we will over the lfCharSet to be ANSI_CHARSET.
  797. // if ( !lstrcmp(achCapString, lpTmsRmn) )
  798. if ( ((achCapString[0] == 'T') &&
  799. (achCapString[1] == 'M') &&
  800. (achCapString[2] == 'S') &&
  801. (achCapString[3] == ' ') &&
  802. (achCapString[4] == 'R') &&
  803. (achCapString[5] == 'M') &&
  804. (achCapString[6] == 'N') &&
  805. (achCapString[7] == '\0')) )
  806. {
  807. lf.lfCharSet = ANSI_CHARSET;
  808. }
  809. else
  810. {
  811. // If the lfFaceName is "Symbol", "Zapf Dingbats", or "ZapfDingbats",
  812. // enforce lfCharSet to be SYMBOL_CHARSET. Some apps (like Excel) ask
  813. // for a "Symbol" font but have the char set set to ANSI. PowerPoint
  814. // has the same problem with "Zapf Dingbats".
  815. //if ( !lstrcmp(achCapString, lpSymbol) ||
  816. // !lstrcmp(achCapString, lpZapfDingbats) ||
  817. // !lstrcmp(achCapString, lpZapf_Dingbats) )
  818. if ( ((achCapString[0] == 'S') &&
  819. (achCapString[1] == 'Y') &&
  820. (achCapString[2] == 'M') &&
  821. (achCapString[3] == 'B') &&
  822. (achCapString[4] == 'O') &&
  823. (achCapString[5] == 'L') &&
  824. (achCapString[6] == '\0')) ||
  825. ((achCapString[0] == 'Z') &&
  826. (achCapString[1] == 'A') &&
  827. (achCapString[2] == 'P') &&
  828. (achCapString[3] == 'F') &&
  829. (achCapString[4] == 'D') &&
  830. (achCapString[5] == 'I') &&
  831. (achCapString[6] == 'N') &&
  832. (achCapString[7] == 'G') &&
  833. (achCapString[8] == 'B') &&
  834. (achCapString[9] == 'A') &&
  835. (achCapString[10] == 'T') &&
  836. (achCapString[11] == 'S') &&
  837. (achCapString[12] == '\0')) ||
  838. ((achCapString[0] == 'Z') &&
  839. (achCapString[1] == 'A') &&
  840. (achCapString[2] == 'P') &&
  841. (achCapString[3] == 'F') &&
  842. (achCapString[4] == ' ') &&
  843. (achCapString[5] == 'D') &&
  844. (achCapString[6] == 'I') &&
  845. (achCapString[7] == 'N') &&
  846. (achCapString[8] == 'G') &&
  847. (achCapString[9] == 'B') &&
  848. (achCapString[10] == 'A') &&
  849. (achCapString[11] == 'T') &&
  850. (achCapString[12] == 'S') &&
  851. (achCapString[13] == '\0')) )
  852. {
  853. lf.lfCharSet = SYMBOL_CHARSET;
  854. }
  855. }
  856. }
  857. if (hObject = CreateFontIndirectA(&lf))
  858. {
  859. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  860. }
  861. }
  862. break;
  863. case (META_CREATEPATTERNBRUSH & 255):
  864. {
  865. HANDLE hBitmap;
  866. BITMAP Bitmap;
  867. LPMETARECORD lpMRtmp;
  868. WARNING("PlayMetaFileRecord: obsolete META_CREATEPATTERNBRUSH record\n");
  869. // Make the bitmap bits dword aligned. To do this,
  870. // lpMR has to fall on a non dword aligned even address so that
  871. // the bitmap bits (bmBits) will fall on the dword aligned address.
  872. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  873. (UINT) lpMR->rdSize * sizeof(WORD) + sizeof(WORD))))
  874. break;
  875. lpMRtmp = (LPMETARECORD) &((PWORD) lpMRdup)[1];
  876. RtlCopyMemory((PBYTE) lpMRtmp,
  877. (PBYTE) lpMR,
  878. (UINT) lpMR->rdSize * sizeof(WORD));
  879. BITMAP32FROMBITMAP16(&Bitmap, (PBITMAP16) &lpMRtmp->rdParm[0]);
  880. // The magic number 18 is based on the IPBITMAP structure in win3.1
  881. Bitmap.bmBits = (PBYTE) &lpMRtmp->rdParm + sizeof(BITMAP16) + 18;
  882. if (hBitmap = CreateBitmapIndirect(&Bitmap))
  883. {
  884. if (hObject = CreatePatternBrush(hBitmap))
  885. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  886. if (!DeleteObject(hBitmap))
  887. ASSERTGDI(FALSE, "PlayMetaFileRecord: DeleteObject(hBitmap) CreatePatternBrush Failed\n");
  888. }
  889. }
  890. break;
  891. case (META_DIBCREATEPATTERNBRUSH & 255):
  892. {
  893. HDC hMemDC ;
  894. HANDLE hBitmap;
  895. LPBITMAPINFOHEADER lpDIBInfo ;
  896. LPMETARECORD lpMRtmp;
  897. // Make the bitmap info and bits dword aligned. To do this,
  898. // lpMR has to fall on a non dword aligned even address so that
  899. // the bitmap info (&lpMR->rdParm[2]) and
  900. // the bitmap bits will fall on the dword aligned addresses.
  901. // Note that the size of the bitmap info is always a multiple
  902. // of 4.
  903. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  904. (UINT) lpMR->rdSize * sizeof(WORD) + sizeof(WORD))))
  905. break;
  906. lpMRtmp = (LPMETARECORD) &((PWORD) lpMRdup)[1];
  907. RtlCopyMemory((PBYTE) lpMRtmp,
  908. (PBYTE) lpMR,
  909. (UINT) lpMR->rdSize * sizeof(WORD));
  910. if (lpMRtmp->rdParm[0] == BS_PATTERN)
  911. {
  912. /* the address of the second paramter is the address of the DIB
  913. header, extract it */
  914. lpDIBInfo = (LPBITMAPINFOHEADER) &lpMRtmp->rdParm[2];
  915. /* now create a device dependend bitmap compatible to the default
  916. screen DC - hScreenDC and extract the bits from the DIB into it.
  917. The following function does all these, and returns a HANDLE
  918. to the device dependent BItmap. */
  919. /* we will use a dummy memory DC compatible to the screen DC */
  920. hMemDC = CreateCompatibleDC((HDC)NULL);
  921. if (!hMemDC)
  922. {
  923. ERROR_ASSERT(FALSE, "PlayMetaRecord: CreateCompDC Failed\n");
  924. break;
  925. }
  926. hBitmap = CreateBitmapForDC(hMemDC,lpDIBInfo);
  927. if (hBitmap)
  928. {
  929. if (hObject = CreatePatternBrush(hBitmap))
  930. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  931. if (!DeleteObject(hBitmap))
  932. ASSERTGDI(FALSE, "PlayMetaFileRecord: DeleteObject(hBitmap) DIBCreatePatternBrush Failed\n");
  933. }
  934. /* delete the dummy memory DC for new version Metafiles*/
  935. if (!DeleteDC (hMemDC))
  936. ASSERTGDI(FALSE, "PlayMetaRecord: DeleteDC DIBCreatePatternBrush Failed\n");
  937. }
  938. /* this is a DIBPattern brush */
  939. else
  940. {
  941. if (hObject = CreateDIBPatternBrushPt((LPVOID)&lpMRtmp->rdParm[2],
  942. (DWORD) lpMRtmp->rdParm[1]))
  943. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  944. }
  945. }
  946. break;
  947. case (META_CREATEBRUSHINDIRECT & 255):
  948. {
  949. LOGBRUSH lb;
  950. LOGBRUSH32FROMLOGBRUSH16(&lb, (PLOGBRUSH16) &lpMR->rdParm[0]);
  951. if (hObject = CreateBrushIndirect(&lb))
  952. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  953. }
  954. break;
  955. case (META_POLYLINE & 255):
  956. case (META_POLYGON & 255):
  957. {
  958. PPOINTL pptl;
  959. UINT cpts = lpMR->rdParm[0];
  960. if (!(pptl = (PPOINTL) LocalAlloc
  961. (LMEM_FIXED, (UINT) cpts * sizeof(POINTL))))
  962. break;
  963. INT32FROMINT16(pptl, &lpMR->rdParm[1], cpts * 2);
  964. switch (magic)
  965. {
  966. case META_POLYGON:
  967. fStatus = Polygon(hdc, (LPPOINT) pptl, (int) cpts);
  968. break;
  969. case META_POLYLINE:
  970. fStatus = Polyline(hdc, (LPPOINT) pptl, (int) cpts);
  971. break;
  972. default:
  973. ASSERTGDI(FALSE, "Bad record type");
  974. break;
  975. }
  976. if (LocalFree(pptl))
  977. ASSERTGDI(FALSE, "PlayMetaRecord: LocalFree failed\n");
  978. }
  979. break;
  980. case (META_POLYPOLYGON & 255):
  981. {
  982. PPOINTL pptl;
  983. LPINT lpPolyCount;
  984. PBYTE pb;
  985. UINT ii;
  986. UINT cpts = 0;
  987. UINT cPoly = lpMR->rdParm[0];
  988. for (ii = 0; ii < cPoly; ii++)
  989. cpts += ((LPWORD)&lpMR->rdParm[1])[ii];
  990. if (!(pb = (PBYTE) LocalAlloc
  991. (
  992. LMEM_FIXED,
  993. cPoly * sizeof(INT) + cpts * sizeof(POINTL)
  994. )
  995. )
  996. )
  997. break;
  998. lpPolyCount = (LPINT) pb;
  999. pptl = (PPOINTL) (pb + cPoly * sizeof(INT));
  1000. for (ii = 0; ii < cPoly; ii++)
  1001. lpPolyCount[ii] = (INT) (UINT) ((LPWORD)&lpMR->rdParm[1])[ii];
  1002. INT32FROMINT16(pptl, &lpMR->rdParm[1] + cPoly, cpts * 2);
  1003. fStatus = PolyPolygon(hdc, (LPPOINT) pptl, lpPolyCount, (int) cPoly);
  1004. if (LocalFree((HANDLE) pb))
  1005. ASSERTGDI(FALSE, "PlayMetaRecord: LocalFree failed\n");
  1006. }
  1007. break;
  1008. case (META_EXTTEXTOUT & 255):
  1009. {
  1010. PSHORT lpdx16;
  1011. LPINT lpdx;
  1012. LPSTR lpch;
  1013. RECT rc;
  1014. LPRECT lprc;
  1015. lprc = (lpMR->rdParm[3] & (ETO_OPAQUE|ETO_CLIPPED))
  1016. ? (LPRECT) &lpMR->rdParm[4]
  1017. : (LPRECT) NULL;
  1018. if (lprc)
  1019. {
  1020. rc.left = ((PRECT16)lprc)->left;
  1021. rc.right = ((PRECT16)lprc)->right;
  1022. rc.top = ((PRECT16)lprc)->top;
  1023. rc.bottom = ((PRECT16)lprc)->bottom;
  1024. lprc = &rc;
  1025. }
  1026. lpch = (LPSTR)&lpMR->rdParm[4] + ((lprc) ? sizeof(RECT16) : 0);
  1027. /* dx array starts at next word boundary after char string */
  1028. lpdx16 = (PSHORT) (lpch + ((lpMR->rdParm[2] + 1) / 2 * 2));
  1029. /* check to see if there is a Dx array by seeing if
  1030. structure ends after the string itself
  1031. */
  1032. if (((DWORD)((LPWORD)lpdx16 - (LPWORD)(lpMR))) >= lpMR->rdSize)
  1033. lpdx = NULL;
  1034. else
  1035. {
  1036. lpdx = (LPINT)LocalAlloc(LMEM_FIXED, lpMR->rdParm[2]*sizeof(INT));
  1037. if (!lpdx)
  1038. {
  1039. ERROR_ASSERT(FALSE, "PlayMetaFileRecord: out of memory exttextout");
  1040. break;
  1041. }
  1042. INT32FROMINT16(lpdx, lpdx16, (UINT) lpMR->rdParm[2]);
  1043. }
  1044. // Mask off bit 0x80 that an old Excel used to add to its
  1045. // Metafiles and the GDI errors on.
  1046. fStatus = ExtTextOutA(hdc,
  1047. (int) (SHORT) lpMR->rdParm[1],
  1048. (int) (SHORT) lpMR->rdParm[0],
  1049. gbLpk ?
  1050. ((UINT) lpMR->rdParm[3]) :
  1051. ((UINT) lpMR->rdParm[3] & ~ETO_RTLREADING),
  1052. lprc,
  1053. lpch,
  1054. (UINT) lpMR->rdParm[2],
  1055. lpdx);
  1056. if (lpdx)
  1057. if (LocalFree((HANDLE)lpdx))
  1058. ASSERTGDI(FALSE, "PlayMetaRecord: LocalFree failed\n");
  1059. break;
  1060. }
  1061. case (META_TEXTOUT & 255):
  1062. fStatus = TextOutA(hdc,
  1063. (int) (SHORT) lpMR->rdParm[lpMR->rdSize-4],
  1064. (int) (SHORT) lpMR->rdParm[lpMR->rdSize-5],
  1065. (LPSTR) &lpMR->rdParm[1],
  1066. (int) (UINT) lpMR->rdParm[0]);
  1067. break;
  1068. case (META_ESCAPE & 255):
  1069. if (!(fStatus = PlayIntoAMetafile(lpMR, hdc)))
  1070. {
  1071. if ((int)(UINT)lpMR->rdParm[0] != MFCOMMENT)
  1072. {
  1073. fStatus = Escape(hdc,
  1074. (int) (UINT) lpMR->rdParm[0],
  1075. (int) (UINT) lpMR->rdParm[1],
  1076. (LPCSTR) &lpMR->rdParm[2],
  1077. (LPVOID) NULL) != 0;
  1078. }
  1079. else
  1080. {
  1081. fStatus = TRUE;
  1082. }
  1083. }
  1084. break;
  1085. case (META_FRAMEREGION & 255):
  1086. if ((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1087. && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]]))
  1088. fStatus = FrameRgn(hdc,
  1089. hRgn,
  1090. hBrush,
  1091. (int) (SHORT) lpMR->rdParm[3],
  1092. (int) (SHORT) lpMR->rdParm[2]);
  1093. break;
  1094. case (META_PAINTREGION & 255):
  1095. if (hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1096. fStatus = PaintRgn(hdc, hRgn);
  1097. break;
  1098. case (META_INVERTREGION & 255):
  1099. if (hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1100. fStatus = InvertRgn(hdc, hRgn);
  1101. break;
  1102. case (META_FILLREGION & 255):
  1103. if ((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1104. && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]]))
  1105. fStatus = FillRgn(hdc, hRgn, hBrush);
  1106. break;
  1107. /*
  1108. *** in win2, METACREATEREGION records contained an entire region object,
  1109. *** including the full header. this header changed in win3.
  1110. ***
  1111. *** to remain compatible, the region records will be saved with the
  1112. *** win2 header. here we read a win2 header with region, and actually
  1113. *** create a win3 header with same region internals
  1114. */
  1115. case (META_CREATEREGION & 255):
  1116. {
  1117. HRGN hrgn;
  1118. PSHORT pXs;
  1119. PWIN3REGION pW3Rgn = (PWIN3REGION) lpMR->rdParm;
  1120. UINT ii, jj;
  1121. UINT cscn;
  1122. PSCAN pscn;
  1123. DWORD nrcl;
  1124. PRECTL prcl;
  1125. UINT cRgnData;
  1126. PRGNDATA pRgnData;
  1127. cscn = (UINT) pW3Rgn->cScans;
  1128. // Handle the empty region.
  1129. if (!cscn)
  1130. {
  1131. hrgn = CreateRectRgn(0, 0, 0, 0);
  1132. fStatus = AddToHandleTable(lpHandleTable, hrgn, noObjs);
  1133. break;
  1134. }
  1135. // Count the number of rectangles in the region.
  1136. nrcl = 0;
  1137. pscn = pW3Rgn->aScans;
  1138. for (ii = 0; ii < cscn; ii++)
  1139. {
  1140. nrcl += pscn->scnPntCnt / 2;
  1141. pscn = (PSCAN) ((PBYTE) pscn
  1142. + sizeof(SCAN)
  1143. - 2 * sizeof(WORD)
  1144. + (int) (UINT) pscn->scnPntCnt * sizeof(WORD));
  1145. }
  1146. cRgnData = sizeof(RGNDATAHEADER) + nrcl * sizeof(RECTL);
  1147. if (!(pRgnData = (PRGNDATA) LocalAlloc(LMEM_FIXED, cRgnData)))
  1148. break;
  1149. pRgnData->rdh.dwSize = sizeof(RGNDATAHEADER);
  1150. pRgnData->rdh.iType = RDH_RECTANGLES;
  1151. pRgnData->rdh.nCount = nrcl;
  1152. pRgnData->rdh.nRgnSize = 0;
  1153. pRgnData->rdh.rcBound.left = (LONG) pW3Rgn->rcBounding.left ;
  1154. pRgnData->rdh.rcBound.top = (LONG) pW3Rgn->rcBounding.top ;
  1155. pRgnData->rdh.rcBound.right = (LONG) pW3Rgn->rcBounding.right ;
  1156. pRgnData->rdh.rcBound.bottom = (LONG) pW3Rgn->rcBounding.bottom ;
  1157. prcl = (PRECTL) pRgnData->Buffer;
  1158. pscn = pW3Rgn->aScans;
  1159. for (ii = 0; ii < cscn; ii++)
  1160. {
  1161. pXs = (PSHORT) pscn->scnPntsX;
  1162. for (jj = pscn->scnPntCnt / 2; jj; jj--)
  1163. {
  1164. prcl->left = (LONG) (*pXs++);
  1165. prcl->top = (LONG) (SHORT) pscn->scnPntTop;
  1166. prcl->right = (LONG) (*pXs++);
  1167. prcl->bottom = (LONG) (SHORT) pscn->scnPntBottom;
  1168. prcl++;
  1169. }
  1170. pscn = (PSCAN) ((PBYTE) pscn
  1171. + sizeof(SCAN)
  1172. - 2 * sizeof(WORD)
  1173. + (int) (UINT) pscn->scnPntCnt * sizeof(WORD));
  1174. }
  1175. hrgn = ExtCreateRegion((LPXFORM) NULL, cRgnData, pRgnData);
  1176. fStatus = AddToHandleTable(lpHandleTable, hrgn, noObjs);
  1177. if (LocalFree((HANDLE) pRgnData))
  1178. ASSERTGDI(FALSE, "PlayMetaRecord: LocalFree failed\n");
  1179. }
  1180. break;
  1181. case (META_DELETEOBJECT & 255):
  1182. {
  1183. HANDLE h;
  1184. if (h = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1185. {
  1186. if (!(fStatus = DeleteObject(h)))
  1187. ERROR_ASSERT(FALSE, "PlayMetaFileRecord: DeleteObject(h) Failed\n");
  1188. lpHandleTable->objectHandle[lpMR->rdParm[0]] = NULL;
  1189. }
  1190. }
  1191. break;
  1192. case (META_CREATEPALETTE & 255):
  1193. {
  1194. LPMETARECORD lpMRtmp;
  1195. // Make the logical palette dword aligned. To do this,
  1196. // lpMR has to fall on a non dword aligned even address so that
  1197. // the logical palette (&lpMR->rdParm[0]) will fall on the
  1198. // dword aligned address.
  1199. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  1200. (UINT) lpMR->rdSize * sizeof(WORD) + sizeof(WORD))))
  1201. break;
  1202. lpMRtmp = (LPMETARECORD) &((PWORD) lpMRdup)[1];
  1203. RtlCopyMemory((PBYTE) lpMRtmp,
  1204. (PBYTE) lpMR,
  1205. (UINT) lpMR->rdSize * sizeof(WORD));
  1206. if (hObject = CreatePalette((LPLOGPALETTE)&lpMRtmp->rdParm[0]))
  1207. fStatus = AddToHandleTable(lpHandleTable, hObject, noObjs);
  1208. }
  1209. break;
  1210. case (META_SELECTPALETTE & 255):
  1211. if (hPal = lpHandleTable->objectHandle[lpMR->rdParm[0]])
  1212. fStatus = SelectPalette(hdc, hPal, 0) != 0;
  1213. break;
  1214. case (META_REALIZEPALETTE & 255):
  1215. fStatus = RealizePalette(hdc) != -1;
  1216. break;
  1217. case (META_SETPALENTRIES & 255):
  1218. case (META_ANIMATEPALETTE & 255):
  1219. {
  1220. LPMETARECORD lpMRtmp;
  1221. // Make the palette entry array dword aligned. To do this,
  1222. // lpMR has to fall on a non dword aligned even address so that
  1223. // the palette entry array (&lpMR->rdParm[2]) will fall on the
  1224. // dword aligned address.
  1225. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  1226. (UINT) lpMR->rdSize * sizeof(WORD) + sizeof(WORD))))
  1227. break;
  1228. lpMRtmp = (LPMETARECORD) &((PWORD) lpMRdup)[1];
  1229. RtlCopyMemory((PBYTE) lpMRtmp,
  1230. (PBYTE) lpMR,
  1231. (UINT) lpMR->rdSize * sizeof(WORD));
  1232. // we know the palette being set is the current palette
  1233. if (magic == META_SETPALENTRIES)
  1234. fStatus = SetPaletteEntries(GetCurrentObject(hdc,OBJ_PAL),
  1235. (UINT) lpMRtmp->rdParm[0],
  1236. (UINT) lpMRtmp->rdParm[1],
  1237. (LPPALETTEENTRY)&lpMRtmp->rdParm[2]
  1238. ) != 0;
  1239. else
  1240. fStatus = AnimatePalette(GetCurrentObject(hdc,OBJ_PAL),
  1241. (UINT) lpMR->rdParm[0],
  1242. (UINT) lpMR->rdParm[1],
  1243. (LPPALETTEENTRY)&lpMR->rdParm[2]);
  1244. }
  1245. break;
  1246. case (META_RESIZEPALETTE & 255):
  1247. fStatus = ResizePalette(GetCurrentObject(hdc,OBJ_PAL),
  1248. (UINT) lpMR->rdParm[0]);
  1249. break;
  1250. case (META_SETDIBTODEV & 255):
  1251. {
  1252. LPBITMAPINFOHEADER lpBitmapInfo;
  1253. DWORD ColorSize;
  1254. LPMETARECORD lpMRtmp;
  1255. /* if playing into another metafile, do direct copy */
  1256. if (PlayIntoAMetafile(lpMR, hdc))
  1257. {
  1258. fStatus = TRUE;
  1259. break;
  1260. }
  1261. // Make the bitmap info and bits dword aligned. To do this,
  1262. // lpMR has to fall on a dword aligned address so that
  1263. // the bitmap info (&lpMR->rdParm[9]) and
  1264. // the bitmap bits will fall on the dword aligned addresses.
  1265. // Note that the size of the bitmap info is always a multiple
  1266. // of 4.
  1267. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  1268. (UINT) lpMR->rdSize * sizeof(WORD))))
  1269. break;
  1270. lpMRtmp = lpMRdup;
  1271. RtlCopyMemory((PBYTE) lpMRtmp,
  1272. (PBYTE) lpMR,
  1273. (UINT) lpMR->rdSize * sizeof(WORD));
  1274. lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMRtmp->rdParm[9]);
  1275. if (lpBitmapInfo->biBitCount == 16 || lpBitmapInfo->biBitCount == 32)
  1276. ColorSize = 3 * sizeof(DWORD);
  1277. else if (lpBitmapInfo->biClrUsed)
  1278. ColorSize = lpBitmapInfo->biClrUsed *
  1279. (DWORD)(lpMRtmp->rdParm[0] == DIB_RGB_COLORS ?
  1280. sizeof(RGBQUAD) :
  1281. sizeof(WORD));
  1282. else if (lpBitmapInfo->biBitCount == 24)
  1283. ColorSize = 0;
  1284. else
  1285. ColorSize = (DWORD)(1 << lpBitmapInfo->biBitCount) *
  1286. (DWORD)(lpMRtmp->rdParm[0] == DIB_RGB_COLORS ?
  1287. sizeof(RGBQUAD) :
  1288. sizeof(WORD));
  1289. ColorSize = (ColorSize + 3) / 4 * 4; // make sure it is aligned
  1290. ColorSize += lpBitmapInfo->biSize;
  1291. fStatus = SetDIBitsToDevice(hdc,
  1292. (int) (SHORT) lpMRtmp->rdParm[8],
  1293. (int) (SHORT) lpMRtmp->rdParm[7],
  1294. (DWORD) (int) (SHORT)lpMRtmp->rdParm[6],
  1295. (DWORD) (int) (SHORT)lpMRtmp->rdParm[5],
  1296. (int) (SHORT) lpMRtmp->rdParm[4],
  1297. (int) (SHORT) lpMRtmp->rdParm[3],
  1298. (UINT) lpMRtmp->rdParm[2],
  1299. (UINT) lpMRtmp->rdParm[1],
  1300. (PBYTE)(((PBYTE)lpBitmapInfo) + ColorSize),
  1301. (LPBITMAPINFO) lpBitmapInfo,
  1302. (DWORD) lpMRtmp->rdParm[0]
  1303. ) != 0;
  1304. }
  1305. break;
  1306. case (META_STRETCHDIB & 255):
  1307. {
  1308. LPBITMAPINFOHEADER lpBitmapInfo;
  1309. DWORD ColorSize;
  1310. LPMETARECORD lpMRtmp;
  1311. /* if playing into another metafile, do direct copy */
  1312. if (PlayIntoAMetafile(lpMR, hdc))
  1313. {
  1314. fStatus = TRUE;
  1315. break;
  1316. }
  1317. // Make the bitmap info and bits dword aligned. To do this,
  1318. // lpMR has to fall on a dword aligned address so that
  1319. // the bitmap info (&lpMR->rdParm[11]) and
  1320. // the bitmap bits will fall on the dword aligned addresses.
  1321. // Note that the size of the bitmap info is always a multiple
  1322. // of 4.
  1323. if (!(lpMRdup = (LPMETARECORD) LocalAlloc(LMEM_FIXED,
  1324. (UINT) lpMR->rdSize * sizeof(WORD))))
  1325. break;
  1326. lpMRtmp = lpMRdup;
  1327. RtlCopyMemory((PBYTE) lpMRtmp,
  1328. (PBYTE) lpMR,
  1329. (UINT) lpMR->rdSize * sizeof(WORD));
  1330. //
  1331. // rdsize is SIZEOF_METARECORDHEADER/sizeof(WORD) + cw;
  1332. // where cw is from MF16_RecordDIBits (11)
  1333. //
  1334. if (lpMR->rdSize > SIZEOF_METARECORDHEADER/sizeof(WORD) + 11)
  1335. {
  1336. lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMRtmp->rdParm[11]);
  1337. if (lpBitmapInfo->biBitCount == 16 || lpBitmapInfo->biBitCount == 32)
  1338. ColorSize = 3 * sizeof(DWORD);
  1339. else if (lpBitmapInfo->biClrUsed)
  1340. ColorSize = lpBitmapInfo->biClrUsed *
  1341. (DWORD)(lpMRtmp->rdParm[2] == DIB_RGB_COLORS ?
  1342. sizeof(RGBQUAD) :
  1343. sizeof(WORD));
  1344. else if (lpBitmapInfo->biBitCount == 24)
  1345. ColorSize = 0;
  1346. else
  1347. ColorSize = (DWORD)(1 << lpBitmapInfo->biBitCount) *
  1348. (DWORD)(lpMRtmp->rdParm[2] == DIB_RGB_COLORS ?
  1349. sizeof(RGBQUAD) :
  1350. sizeof(WORD));
  1351. ColorSize = (ColorSize + 3) / 4 * 4; // make sure it is aligned
  1352. ColorSize += lpBitmapInfo->biSize;
  1353. }
  1354. else
  1355. {
  1356. lpBitmapInfo = NULL;
  1357. }
  1358. fStatus = StretchDIBits(hdc,
  1359. (int) (SHORT) lpMRtmp->rdParm[10],
  1360. (int) (SHORT) lpMRtmp->rdParm[9],
  1361. (int) (SHORT) lpMRtmp->rdParm[8],
  1362. (int) (SHORT) lpMRtmp->rdParm[7],
  1363. (int) (SHORT) lpMRtmp->rdParm[6],
  1364. (int) (SHORT) lpMRtmp->rdParm[5],
  1365. (int) (SHORT) lpMRtmp->rdParm[4],
  1366. (int) (SHORT) lpMRtmp->rdParm[3],
  1367. lpBitmapInfo ? (LPBYTE)(((PBYTE)lpBitmapInfo) + ColorSize) : NULL,
  1368. (LPBITMAPINFO) lpBitmapInfo,
  1369. (DWORD) lpMRtmp->rdParm[2],
  1370. MAKELONG(lpMRtmp->rdParm[0], lpMRtmp->rdParm[1])
  1371. ) != ERROR;
  1372. }
  1373. break;
  1374. // Function that have new parameters on WIN32
  1375. // Or have DWORDs that stayed DWORDs; all other INTs to DWORDs
  1376. case (META_PATBLT & 255):
  1377. fStatus = PatBlt(hdc,
  1378. (int) (SHORT) lpMR->rdParm[5],
  1379. (int) (SHORT) lpMR->rdParm[4],
  1380. (int) (SHORT) lpMR->rdParm[3],
  1381. (int) (SHORT) lpMR->rdParm[2],
  1382. MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1]));
  1383. break;
  1384. case (META_MOVETO & 255):
  1385. fStatus = MoveToEx(hdc, (int)(SHORT)lpMR->rdParm[1], (int)(SHORT)lpMR->rdParm[0], NULL);
  1386. break;
  1387. case (META_RESTOREDC & 255):
  1388. fStatus = RestoreDC(hdc, (int)(SHORT)lpMR->rdParm[0]);
  1389. break;
  1390. case (META_SETBKCOLOR & 255):
  1391. fStatus = SetBkColor(hdc, *(COLORREF UNALIGNED *)lpMR->rdParm) != CLR_INVALID;
  1392. break;
  1393. case (META_SETTEXTCOLOR & 255):
  1394. fStatus = SetTextColor(hdc, *(COLORREF UNALIGNED *)lpMR->rdParm) != CLR_INVALID;
  1395. break;
  1396. case (META_SETPIXEL & 255):
  1397. fStatus = SetPixel(hdc,
  1398. (int) (SHORT) lpMR->rdParm[3],
  1399. (int) (SHORT) lpMR->rdParm[2],
  1400. *(COLORREF UNALIGNED *) lpMR->rdParm
  1401. ) != CLR_INVALID;
  1402. break;
  1403. case (META_SETMAPPERFLAGS & 255):
  1404. fStatus = SetMapperFlags(hdc, *(DWORD UNALIGNED *)lpMR->rdParm) != GDI_ERROR;
  1405. break;
  1406. case (META_FLOODFILL & 255):
  1407. fStatus = FloodFill(hdc,
  1408. (int) (SHORT) lpMR->rdParm[3],
  1409. (int) (SHORT) lpMR->rdParm[2],
  1410. *(COLORREF UNALIGNED *) lpMR->rdParm);
  1411. break;
  1412. case (META_EXTFLOODFILL & 255):
  1413. fStatus = ExtFloodFill(hdc,
  1414. (int) (SHORT) lpMR->rdParm[4],
  1415. (int) (SHORT) lpMR->rdParm[3],
  1416. *(COLORREF UNALIGNED *) &lpMR->rdParm[1],
  1417. (UINT) lpMR->rdParm[0]);
  1418. break;
  1419. case (META_SCALEWINDOWEXT & 255):
  1420. fStatus = ScaleWindowExtEx(hdc,
  1421. (int)(SHORT)lpMR->rdParm[3],
  1422. (int)(SHORT)lpMR->rdParm[2],
  1423. (int)(SHORT)lpMR->rdParm[1],
  1424. (int)(SHORT)lpMR->rdParm[0],
  1425. NULL);
  1426. break;
  1427. case (META_SCALEVIEWPORTEXT & 255):
  1428. fStatus = ScaleViewportExtEx(hdc,
  1429. (int)(SHORT)lpMR->rdParm[3],
  1430. (int)(SHORT)lpMR->rdParm[2],
  1431. (int)(SHORT)lpMR->rdParm[1],
  1432. (int)(SHORT)lpMR->rdParm[0],
  1433. NULL);
  1434. break;
  1435. case (META_SETWINDOWORG & 255):
  1436. fStatus = SetWindowOrgEx(hdc,
  1437. (int)(SHORT)lpMR->rdParm[1],
  1438. (int)(SHORT)lpMR->rdParm[0],
  1439. (LPPOINT) NULL);
  1440. break;
  1441. case (META_SETWINDOWEXT & 255):
  1442. fStatus = SetWindowExtEx(hdc,
  1443. (int)(SHORT)lpMR->rdParm[1],
  1444. (int)(SHORT)lpMR->rdParm[0],
  1445. (LPSIZE) NULL);
  1446. break;
  1447. case (META_SETVIEWPORTORG & 255):
  1448. fStatus = SetViewportOrgEx(hdc,
  1449. (int)(SHORT)lpMR->rdParm[1],
  1450. (int)(SHORT)lpMR->rdParm[0],
  1451. (LPPOINT) NULL);
  1452. break;
  1453. case (META_SETVIEWPORTEXT & 255):
  1454. fStatus = SetViewportExtEx(hdc,
  1455. (int)(SHORT)lpMR->rdParm[1],
  1456. (int)(SHORT)lpMR->rdParm[0],
  1457. (LPSIZE) NULL);
  1458. break;
  1459. case (META_OFFSETWINDOWORG & 255):
  1460. fStatus = OffsetWindowOrgEx(hdc,
  1461. (int)(SHORT)lpMR->rdParm[1],
  1462. (int)(SHORT)lpMR->rdParm[0],
  1463. (LPPOINT) NULL);
  1464. break;
  1465. case (META_OFFSETVIEWPORTORG & 255):
  1466. fStatus = OffsetViewportOrgEx(hdc,
  1467. (int)(SHORT)lpMR->rdParm[1],
  1468. (int)(SHORT)lpMR->rdParm[0],
  1469. (LPPOINT) NULL);
  1470. break;
  1471. case (META_SETTEXTCHAREXTRA & 255):
  1472. fStatus = SetTextCharacterExtra(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0x80000000;
  1473. break;
  1474. case (META_SETTEXTALIGN & 255):
  1475. fStatus = SetTextAlign(hdc, (UINT)lpMR->rdParm[0]) != GDI_ERROR;
  1476. break;
  1477. case (META_SAVEDC & 255):
  1478. fStatus = (SaveDC(hdc) != 0);
  1479. break;
  1480. case (META_SELECTCLIPREGION & 255):
  1481. // Win3.1 has never got this right except when the handle is 0.
  1482. hObject = (lpMR->rdParm[0] == 0)
  1483. ? 0
  1484. : lpHandleTable->objectHandle[lpMR->rdParm[0]];
  1485. fStatus = (SelectClipRgn(hdc, hObject) != RGN_ERROR);
  1486. break;
  1487. case (META_SETBKMODE & 255):
  1488. fStatus = (SetBkMode(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0);
  1489. break;
  1490. case (META_SETMAPMODE & 255):
  1491. fStatus = (SetMapMode(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0);
  1492. break;
  1493. case (META_SETLAYOUT & 255):
  1494. fStatus = (SetLayout(hdc, (DWORD)lpMR->rdParm[0]) != GDI_ERROR);
  1495. break;
  1496. case (META_SETPOLYFILLMODE & 255):
  1497. fStatus = (SetPolyFillMode(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0);
  1498. break;
  1499. case (META_SETROP2 & 255):
  1500. fStatus = (SetROP2(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0);
  1501. break;
  1502. case (META_SETSTRETCHBLTMODE & 255):
  1503. fStatus = (SetStretchBltMode(hdc, (int)(SHORT)lpMR->rdParm[0]) != 0);
  1504. break;
  1505. case (META_LINETO & 255):
  1506. fStatus = LineTo(hdc,
  1507. (int)(SHORT)lpMR->rdParm[1],
  1508. (int)(SHORT)lpMR->rdParm[0]);
  1509. break;
  1510. case (META_OFFSETCLIPRGN & 255):
  1511. fStatus = OffsetClipRgn(hdc,
  1512. (int)(SHORT)lpMR->rdParm[1],
  1513. (int)(SHORT)lpMR->rdParm[0]
  1514. ) != RGN_ERROR;
  1515. break;
  1516. case (META_SETTEXTJUSTIFICATION & 255):
  1517. fStatus = SetTextJustification(hdc,
  1518. (int)(SHORT)lpMR->rdParm[1],
  1519. (int)(SHORT)lpMR->rdParm[0]);
  1520. break;
  1521. case (META_ELLIPSE & 255):
  1522. fStatus = Ellipse(hdc,
  1523. (int)(SHORT)lpMR->rdParm[3],
  1524. (int)(SHORT)lpMR->rdParm[2],
  1525. (int)(SHORT)lpMR->rdParm[1],
  1526. (int)(SHORT)lpMR->rdParm[0]);
  1527. break;
  1528. case (META_RECTANGLE & 255):
  1529. fStatus = Rectangle(hdc,
  1530. (int)(SHORT)lpMR->rdParm[3],
  1531. (int)(SHORT)lpMR->rdParm[2],
  1532. (int)(SHORT)lpMR->rdParm[1],
  1533. (int)(SHORT)lpMR->rdParm[0]);
  1534. break;
  1535. case (META_EXCLUDECLIPRECT & 255):
  1536. fStatus = ExcludeClipRect(hdc,
  1537. (int)(SHORT)lpMR->rdParm[3],
  1538. (int)(SHORT)lpMR->rdParm[2],
  1539. (int)(SHORT)lpMR->rdParm[1],
  1540. (int)(SHORT)lpMR->rdParm[0]
  1541. ) != RGN_ERROR;
  1542. break;
  1543. case (META_INTERSECTCLIPRECT & 255):
  1544. fStatus = IntersectClipRect(hdc,
  1545. (int)(SHORT)lpMR->rdParm[3],
  1546. (int)(SHORT)lpMR->rdParm[2],
  1547. (int)(SHORT)lpMR->rdParm[1],
  1548. (int)(SHORT)lpMR->rdParm[0]
  1549. ) != RGN_ERROR;
  1550. break;
  1551. case (META_ROUNDRECT & 255):
  1552. fStatus = RoundRect(hdc,
  1553. (int)(SHORT)lpMR->rdParm[5],
  1554. (int)(SHORT)lpMR->rdParm[4],
  1555. (int)(SHORT)lpMR->rdParm[3],
  1556. (int)(SHORT)lpMR->rdParm[2],
  1557. (int)(SHORT)lpMR->rdParm[1],
  1558. (int)(SHORT)lpMR->rdParm[0]
  1559. );
  1560. break;
  1561. case (META_ARC & 255):
  1562. fStatus = Arc(hdc,
  1563. (int)(SHORT)lpMR->rdParm[7],
  1564. (int)(SHORT)lpMR->rdParm[6],
  1565. (int)(SHORT)lpMR->rdParm[5],
  1566. (int)(SHORT)lpMR->rdParm[4],
  1567. (int)(SHORT)lpMR->rdParm[3],
  1568. (int)(SHORT)lpMR->rdParm[2],
  1569. (int)(SHORT)lpMR->rdParm[1],
  1570. (int)(SHORT)lpMR->rdParm[0]
  1571. );
  1572. break;
  1573. case (META_CHORD & 255):
  1574. fStatus = Chord(hdc,
  1575. (int)(SHORT)lpMR->rdParm[7],
  1576. (int)(SHORT)lpMR->rdParm[6],
  1577. (int)(SHORT)lpMR->rdParm[5],
  1578. (int)(SHORT)lpMR->rdParm[4],
  1579. (int)(SHORT)lpMR->rdParm[3],
  1580. (int)(SHORT)lpMR->rdParm[2],
  1581. (int)(SHORT)lpMR->rdParm[1],
  1582. (int)(SHORT)lpMR->rdParm[0]
  1583. );
  1584. break;
  1585. case (META_PIE & 255):
  1586. fStatus = Pie(hdc,
  1587. (int)(SHORT)lpMR->rdParm[7],
  1588. (int)(SHORT)lpMR->rdParm[6],
  1589. (int)(SHORT)lpMR->rdParm[5],
  1590. (int)(SHORT)lpMR->rdParm[4],
  1591. (int)(SHORT)lpMR->rdParm[3],
  1592. (int)(SHORT)lpMR->rdParm[2],
  1593. (int)(SHORT)lpMR->rdParm[1],
  1594. (int)(SHORT)lpMR->rdParm[0]
  1595. );
  1596. break;
  1597. case (META_SETRELABS & 255):
  1598. ERROR_ASSERT(FALSE, "PlayMetaFileRecord: unsupported META_SETRELABS record\n");
  1599. fStatus = TRUE;
  1600. break;
  1601. #if 0
  1602. case (META_CREATEBITMAP & 255):
  1603. case (META_CREATEBITMAPINDIRECT & 255):
  1604. case (META_CREATEBRUSH & 255):
  1605. case (META_ABORTDOC & 255):
  1606. case (META_ENDPAGE & 255):
  1607. case (META_ENDDOC & 255):
  1608. case (META_RESETDC & 255):
  1609. case (META_STARTDOC & 255):
  1610. case (META_STARTPAGE & 255):
  1611. // not created or playbacked on Win3.1!
  1612. ASSERTGDI(FALSE, "PlayMetaFileRecord: unsupported record\n");
  1613. fStatus = TRUE;
  1614. break;
  1615. #endif // 0
  1616. case 0: // End of metafile record
  1617. fStatus = TRUE;
  1618. break;
  1619. default:
  1620. VERIFYGDI(FALSE, "PlayMetaFileRecord: unknown record\n");
  1621. #if DBG
  1622. DbgPrint("Record %lx pMFRecord %p magic %X\n", curRecord, lpMR, magic);
  1623. #endif
  1624. fStatus = TRUE;
  1625. break;
  1626. } // switch (magic & 255)
  1627. if (lpMRdup)
  1628. if (LocalFree((HANDLE) lpMRdup))
  1629. ASSERTGDI(FALSE, "LocalFree failed");
  1630. #if DBG
  1631. if (!fStatus)
  1632. {
  1633. DbgPrint("PlayMetaFileRecord Record %lx pMFRecord %p magic %X\n", curRecord, lpMR, magic);
  1634. ERROR_ASSERT(FALSE, "PlayMetaFileRecord Failing\n");
  1635. }
  1636. #endif
  1637. return(fStatus);
  1638. }
  1639. /****************************** Internal Function **************************\
  1640. * AddToHandleTable
  1641. *
  1642. * Adds an object to the metafile table of objects
  1643. *
  1644. *
  1645. \***************************************************************************/
  1646. BOOL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, UINT noObjs)
  1647. {
  1648. UINT ii;
  1649. PUTS("AddToHandleTable\n");
  1650. if (lpHandleTable == (LPHANDLETABLE) NULL)
  1651. {
  1652. ASSERTGDI(FALSE, "AddToHandleTable: lpHT is NULL\n");
  1653. return(FALSE);
  1654. }
  1655. /* linear search through table for first open slot */
  1656. for (ii = 0; ((lpHandleTable->objectHandle[ii] != NULL) && (ii < noObjs));
  1657. ++ii);
  1658. if (ii < noObjs) /* ok index */
  1659. {
  1660. lpHandleTable->objectHandle[ii] = hObject;
  1661. return (TRUE);
  1662. }
  1663. else
  1664. {
  1665. ASSERTGDI(FALSE, "AddToHandleTable: Too many objects in table\n");
  1666. return(FALSE);
  1667. }
  1668. }
  1669. BOOL IsValidMetaHeader16(PMETAHEADER pMetaHeader)
  1670. {
  1671. BOOL status;
  1672. PUTS("IsValidMetaHeader16\n");
  1673. status = (
  1674. (pMetaHeader->mtType == MEMORYMETAFILE ||
  1675. pMetaHeader->mtType == DISKMETAFILE) &&
  1676. (pMetaHeader->mtHeaderSize == (sizeof(METAHEADER)/sizeof(WORD))) &&
  1677. ((pMetaHeader->mtVersion == METAVERSION300) ||
  1678. (pMetaHeader->mtVersion ==METAVERSION100))
  1679. );
  1680. ERROR_ASSERT(status, "IsValidMetaHeader16 is failing\n");
  1681. return status;
  1682. }
  1683. /****************************** Internal Function **************************\
  1684. * CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo)
  1685. *
  1686. * This routine takes a memory device context and a DIB bitmap, creates a
  1687. * compatible bitmap for the DC and fills it with the bits from the DIB
  1688. * converting to the device dependent format). The pointer to the DIB bits
  1689. * start immediately after the color table in the INFO header.
  1690. *
  1691. * The routine returns the handle to the bitmap with the bits filled in if
  1692. * everything goes well else it returns NULL.
  1693. \***************************************************************************/
  1694. HANDLE CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo)
  1695. {
  1696. HBITMAP hBitmap ;
  1697. LPBYTE lpDIBits ;
  1698. PUTS("CreateBitmapForDC\n");
  1699. ASSERTGDI(!((ULONG_PTR) lpDIBInfo & 0x3), "CreateBitmapForDC: dword alignment error\n");
  1700. /* preserve monochrome if it started out as monochrome
  1701. ** and check for REAL Black&white monochrome as opposed
  1702. ** to a 2-color DIB
  1703. */
  1704. if (IsDIBBlackAndWhite(lpDIBInfo))
  1705. hBitmap = CreateBitmap ((WORD)lpDIBInfo->biWidth,
  1706. (WORD)lpDIBInfo->biHeight,
  1707. 1, 1, (LPBYTE) NULL);
  1708. else
  1709. /* otherwise, make a compatible bitmap */
  1710. hBitmap = CreateCompatibleBitmap (hMemDC,
  1711. (WORD)lpDIBInfo->biWidth,
  1712. (WORD)lpDIBInfo->biHeight);
  1713. if (!hBitmap)
  1714. goto CreateBitmapForDCErr ;
  1715. /* take a pointer past the header of the DIB, to the start of the color
  1716. table */
  1717. lpDIBits = (LPBYTE) lpDIBInfo + lpDIBInfo->biSize;
  1718. /* take the pointer past the color table */
  1719. lpDIBits += GetSizeOfColorTable (lpDIBInfo) ;
  1720. /* get the bits from the DIB into the Bitmap */
  1721. if (!SetDIBits (hMemDC, hBitmap, 0, (WORD)lpDIBInfo->biHeight,
  1722. lpDIBits, (LPBITMAPINFO)lpDIBInfo, DIB_RGB_COLORS))
  1723. {
  1724. if (!DeleteObject(hBitmap))
  1725. ASSERTGDI(FALSE, "CreateBitmapForDC: DeleteObject(hBitmap) Failed\n");
  1726. goto CreateBitmapForDCErr ;
  1727. }
  1728. /* return success */
  1729. return (hBitmap) ;
  1730. CreateBitmapForDCErr:
  1731. /* returm failure for function */
  1732. return (NULL);
  1733. }
  1734. /****************************** Internal Function **************************\
  1735. * GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
  1736. *
  1737. * Returns the number of bytes in the color table for the giving info header
  1738. *
  1739. \***************************************************************************/
  1740. WORD GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo)
  1741. {
  1742. PUTS("GetSizeOfColorTable\n");
  1743. ASSERTGDI(!((ULONG_PTR) lpDIBInfo & 0x3), "GetSizeOfColorTable: dword alignment error\n");
  1744. if (lpDIBInfo->biBitCount == 16 || lpDIBInfo->biBitCount == 32)
  1745. return(3 * sizeof(DWORD));
  1746. if (lpDIBInfo->biClrUsed)
  1747. return((WORD)lpDIBInfo->biClrUsed * (WORD)sizeof(RGBQUAD));
  1748. if (lpDIBInfo->biBitCount < 16)
  1749. return((1 << lpDIBInfo->biBitCount) * sizeof(RGBQUAD));
  1750. else
  1751. return(0);
  1752. }
  1753. /***************************** Public Function ****************************\
  1754. * BOOL APIENTRY DeleteMetaFile(hmf)
  1755. *
  1756. * Frees a metafile handle.
  1757. *
  1758. * Effects:
  1759. *
  1760. \***************************************************************************/
  1761. BOOL APIENTRY DeleteMetaFile(HMETAFILE hmf)
  1762. {
  1763. PMETAFILE16 pmf16;
  1764. PUTS("DeleteMetaFile\n");
  1765. pmf16 = GET_PMF16(hmf);
  1766. if (pmf16 == NULL)
  1767. {
  1768. GdiSetLastError(ERROR_INVALID_HANDLE);
  1769. return(FALSE);
  1770. }
  1771. // Free the metafile and its handle.
  1772. vFreeMF16(pmf16);
  1773. bDeleteHmf16(hmf);
  1774. return(TRUE);
  1775. }
  1776. /***************************** Public Function ****************************\
  1777. * HMETAFILE APIENTRY GetMetaFileW(pszwFilename)
  1778. *
  1779. * Returns a metafile handle for a disk based metafile.
  1780. *
  1781. * Effects:
  1782. *
  1783. * History:
  1784. * Fri May 15 14:11:22 1992 -by- Hock San Lee [hockl]
  1785. * Wrote it.
  1786. \***************************************************************************/
  1787. HMETAFILE GetMetaFileA(LPCSTR pszFileName)
  1788. {
  1789. UINT cch;
  1790. WCHAR awch[MAX_PATH];
  1791. cch = strlen(pszFileName)+1;
  1792. if (cch > MAX_PATH)
  1793. {
  1794. ERROR_ASSERT(FALSE, "GetMetaFileA filename too long");
  1795. GdiSetLastError(ERROR_FILENAME_EXCED_RANGE);
  1796. return ((HMETAFILE)0);
  1797. }
  1798. vToUnicodeN(awch, MAX_PATH, pszFileName, cch);
  1799. return (GetMetaFileW(awch));
  1800. }
  1801. HMETAFILE APIENTRY GetMetaFileW(LPCWSTR pwszFileName)
  1802. {
  1803. PMETAFILE16 pmf16;
  1804. HMETAFILE hmf;
  1805. PUTS("GetMetaFileW\n");
  1806. // Allocate and initialize a metafile.
  1807. if (!(pmf16 = pmf16AllocMF16(0, 0, (PDWORD) NULL, (LPWSTR) pwszFileName)))
  1808. return((HMETAFILE) 0);
  1809. ASSERTGDI(pmf16->metaHeader.mtType == DISKMETAFILE,
  1810. "GetMetaFileW: Bad mtType\n");
  1811. // Allocate a local handle.
  1812. hmf = hmf16Create(pmf16);
  1813. if (!hmf)
  1814. {
  1815. vFreeMF16(pmf16);
  1816. }
  1817. // Return the metafile handle.
  1818. return(hmf);
  1819. }
  1820. /***************************** Internal Function **************************\
  1821. * BOOL FAR PASCAL PlayIntoAMetafile
  1822. *
  1823. * if this record is being played into another metafile, simply record
  1824. * it into that metafile, without hassling with a real playing.
  1825. *
  1826. * Returns: TRUE if record was played (copied) into another metafile
  1827. * FALSE if destination DC was a real (non-meta) DC
  1828. *
  1829. * Effects: ?
  1830. *
  1831. * Warnings: ?
  1832. *
  1833. \***************************************************************************/
  1834. BOOL PlayIntoAMetafile(LPMETARECORD lpMR, HDC hdcDest)
  1835. {
  1836. PUTS("PlayIntoAMetafile\n");
  1837. if (LO_TYPE(hdcDest) != LO_METADC16_TYPE)
  1838. return(FALSE);
  1839. // If a metafile is retrieved with GetWinMetaFileBits, it may contain
  1840. // an embedded enhanced metafile. Do not include the enhanced metafile
  1841. // if we are playing the metafile to another metafile.
  1842. if (IS_META_ESCAPE_ENHANCED_METAFILE((PMETA_ESCAPE_ENHANCED_METAFILE) lpMR))
  1843. return(TRUE);
  1844. // the size is the same minus 3 words for the record header
  1845. return(RecordParms(hdcDest, (DWORD)lpMR->rdFunction, (DWORD)lpMR->rdSize - 3,
  1846. (LPWORD)&(lpMR->rdParm[0])));
  1847. }