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.

754 lines
24 KiB

  1. /*************************************************************************\
  2. * Module Name: mfdc.hxx
  3. *
  4. * This file contains the definition for metafile DC and MF classes.
  5. *
  6. * Created: 12-June-1991 13:46:00
  7. * Author: Hock San Lee [hockl]
  8. *
  9. * Copyright (c) 1991-1999 Microsoft Corporation
  10. \*************************************************************************/
  11. #define MDC_IDENTIFIER 0x0043444D /* 'MDC' */
  12. #define MF_IDENTIFIER 0x0000464D /* 'MF' */
  13. // Function prototypes
  14. extern "C" {
  15. BOOL WINAPI GetTransform(HDC hdc,DWORD iXform,LPXFORM pxform);
  16. BOOL WINAPI SetVirtualResolution(HDC hdc, int cxDevice, int cyDevice,
  17. int cxMillimeters, int cyMillimeters);
  18. UINT WINAPI GetBoundsRectAlt(HDC, LPRECT, UINT);
  19. UINT WINAPI SetBoundsRectAlt(HDC, LPRECT, UINT);
  20. BOOL bMetaResetDC(HDC hdc);
  21. BOOL bInternalPlayEMF(HDC hdc, HENHMETAFILE hemf, ENHMFENUMPROC pfn, LPVOID pv, CONST RECTL *prcl);
  22. BOOL bIsPoly16(PPOINTL pptl, DWORD cptl);
  23. int APIENTRY GetRandomRgn(HDC hdc,HRGN hrgn,int iNum);
  24. BOOL APIENTRY GetRandomRgnBounds(HDC hdc,PRECTL prcl,INT iType);
  25. }
  26. extern RECTL rclInfinity; // METAFILE.CXX
  27. extern RECTL rclNull; // METAFILE.CXX
  28. #include "emfspool.hxx"
  29. /*********************************Class************************************\
  30. * class METALINK
  31. *
  32. * Define a link for metafile friends.
  33. *
  34. * A metafile link begins with the metalink field of the LHE entry of an
  35. * object. If there is no link, this field is zero. Otherwise, it begins
  36. * with a 16-bit metafile object-link, whose first element points to the
  37. * begining of the METALINK link list.
  38. *
  39. * The 16-bit metafile object-link should be created as necessary when the
  40. * first METALINK is created. It should be removed as necessary when the
  41. * last METALINK is removed.
  42. *
  43. * We assume that the imhe object index cannot be zero. Otherwise, bValid()
  44. * will not work.
  45. *
  46. * History:
  47. * Wed Jul 31 21:09:28 1991 -by- Hock San Lee [hockl]
  48. * Wrote it.
  49. \**************************************************************************/
  50. class METALINK
  51. {
  52. public:
  53. USHORT imhe; // MHE index of object of next friend.
  54. USHORT ihdc; // Local index of metafile DC of next friend.
  55. public:
  56. // Constructor -- This one is to allow METALINKs inside other classes.
  57. METALINK() {}
  58. // Constructor -- Fills the METALINK.
  59. METALINK(USHORT imhe_, USHORT ihdc_)
  60. {
  61. imhe = imhe_;
  62. ihdc = ihdc_;
  63. }
  64. METALINK(PMETALINK16 pmetalink16)
  65. {
  66. if (*(PULONG_PTR) this = (ULONG_PTR)pmetalink16)
  67. *(PULONG_PTR) this = pmetalink16->metalink;
  68. }
  69. // Destructor -- Does nothing.
  70. ~METALINK() {}
  71. // Initializer -- Initialize the METALINK.
  72. VOID vInit(USHORT imhe_, USHORT ihdc_)
  73. {
  74. imhe = imhe_;
  75. ihdc = ihdc_;
  76. }
  77. VOID vInit(ULONG metalink);
  78. // moved to mfdc.cxx temporarily to work around a compiler bug
  79. // {
  80. // imhe = ((METALINK *) &metalink)->imhe;
  81. // ihdc = ((METALINK *) &metalink)->ihdc;
  82. // }
  83. //
  84. VOID vInit(PMETALINK16 pmetalink16)
  85. {
  86. if (*(PULONG_PTR) this = (ULONG_PTR)pmetalink16)
  87. *(PULONG_PTR) this = pmetalink16->metalink;
  88. }
  89. // operator ULONG -- Return the long equivalent value.
  90. operator ULONG() { return(*(PULONG) this); }
  91. // bValid -- Is this a valid metalink?
  92. // imhe object index cannot be zero.
  93. BOOL bValid()
  94. {
  95. ASSERTGDI(*(PULONG) this == 0L || imhe != 0,
  96. "METALINK::bValid: Invalid metalink");
  97. return(*(PULONG) this != 0L);
  98. }
  99. // bEqual -- does this metalink refer to imhe and hdc?
  100. BOOL bEqual(USHORT imhe_, USHORT ihdc_)
  101. {
  102. return(imhe == imhe_ && ihdc == ihdc_);
  103. }
  104. // vNext -- Update *this to the next metalink.
  105. VOID vNext();
  106. // pmetalinkNext -- Return the pointer to the next metalink.
  107. METALINK * pmetalinkNext();
  108. };
  109. typedef METALINK *PMETALINK;
  110. /*********************************Class************************************\
  111. * class MHE
  112. *
  113. * Define a Metafile Handle Entry. Our Metafile Handle Table is an array
  114. * of these. The MHT is used to keep track of object handles at record time.
  115. *
  116. * Note that the first entry (index zero) is reserved. See METALINK comment.
  117. *
  118. * History:
  119. * Wed Jul 31 21:09:28 1991 -by- Hock San Lee [hockl]
  120. * Wrote it.
  121. \**************************************************************************/
  122. class MHE
  123. {
  124. public:
  125. HANDLE lhObject; // Handle to the GDI object.
  126. METALINK metalink; // Links to the next "metafile friend".
  127. // Also links the free list.
  128. };
  129. typedef MHE *PMHE;
  130. // Metafile Handle Table size
  131. #define MHT_HANDLE_SIZE 1024
  132. #define MHT_MAX_HANDLE_SIZE ((unsigned) 0xFFFF) // ENHMETAHEADER.nHandles is a USHORT.
  133. // Metafile palette initial size and increment
  134. #define MF_PALETTE_SIZE 256
  135. // Metafile memory buffer size
  136. #define MF_BUFSIZE_INIT (16*1024)
  137. #define MF_BUFSIZE_INC (16*1024)
  138. // Metafile DC flags
  139. #define MDC_DISKFILE 0x0001 // Disk or memory metafile.
  140. #define MDC_FATALERROR 0x0002 // Fatal error in recording.
  141. #define MDC_DELAYCOMMIT 0x0004 // Delay commit for bounds record.
  142. #define MDC_CHECKSUM 0x0008 // checksum needed
  143. #define MDC_METABOUNDSDIRTY 0x0020 // Current meta region bounds is dirty.
  144. #define MDC_CLIPBOUNDSDIRTY 0x0040 // Current clip region bounds is dirty.
  145. #define MDC_EMFSPOOL 0x0080 // For EMF spooling (record)
  146. /*********************************Class************************************\
  147. * class MDC
  148. *
  149. * Metafile DC structure.
  150. *
  151. * There is no constructor or destructor for this object. We do the
  152. * initialization in pmdcAllocMDC and cleanup in vFreeMDC.
  153. *
  154. * History:
  155. * Wed Jul 17 17:10:28 1991 -by- Hock San Lee [hockl]
  156. * Wrote it.
  157. \**************************************************************************/
  158. class MDC
  159. {
  160. friend MDC * pmdcAllocMDC(HDC hdcRef, LPCWSTR pwszFilename, LPCWSTR pwszDescription, HANDLE hEMFSpool);
  161. friend VOID vFreeMDC(MDC *pmdc);
  162. friend HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc);
  163. friend ULONG imheAllocMHE(HDC hdc, HANDLE lhObject);
  164. friend VOID vFreeMHE(HDC hdc, ULONG imhe);
  165. friend BOOL MF_SelectAnyObject(HDC hdc,HANDLE h,DWORD mrType); // we really don't need this
  166. friend BOOL MF_DeleteObject(HANDLE h); // we really don't need this
  167. friend BOOL MF_SetPaletteEntries(HPALETTE hpal, UINT iStart, UINT cEntries,
  168. CONST PALETTEENTRY *pPalEntries); // we really don't need this
  169. friend BOOL MF_ResizePalette(HPALETTE hpal,UINT c); // we really don't need this
  170. friend BOOL MF_RealizePalette(HPALETTE hpal); // we really don't need this
  171. friend HDC CreateEnhMetaFileW(HDC, LPCWSTR, CONST RECT *, LPCWSTR);
  172. friend BOOL AssociateEnhMetaFile(HDC);
  173. friend HENHMETAFILE UnassociateEnhMetaFile(HDC, BOOL);
  174. friend HENHMETAFILE SetWinMetaFileBits(UINT, CONST BYTE *, HDC, CONST METAFILEPICT *);
  175. friend BOOL MF_GdiComment(HDC, UINT, CONST BYTE *);
  176. #ifdef GL_METAFILE
  177. friend BOOL GdiAddGlsRecord(HDC, DWORD, BYTE *, LPRECTL);
  178. friend BOOL MF_SetPixelFormat(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
  179. #endif
  180. friend class METALINK;
  181. private:
  182. ULONG ident; // Identifier 'MDC'
  183. HANDLE hFile; // Handle to the disk metafile.
  184. HANDLE hData; // content depends on whether we're EMF spooling
  185. ULONG nMem; // Size of the memory buffer.
  186. ULONG iMem; // Current memory index pointer.
  187. ULONG fl; // Flags.
  188. ENHMETAHEADER mrmf; // MRMETAFILE record.
  189. ULONG cmhe; // Size of the metafile handle table.
  190. ULONG imheFree; // Identifies a free MHE index.
  191. PMHE pmhe; // Metafile handle table.
  192. ULONG cPalEntries; // Size of metafile palette.
  193. ULONG iPalEntries; // Index to next free metafile palette entry.
  194. PPALETTEENTRY pPalEntries; // Metafile palette.
  195. ERECTL erclMetaBounds;// Meta region bounds.
  196. ERECTL erclClipBounds;// Clip region bounds.
  197. FLOAT eXFontScale; // X and Y scales from Page units to .01mm units
  198. FLOAT eYFontScale; // in font transform.
  199. WCHAR wszPathname[MAX_PATH+1];
  200. // Full pathname of the disk metafile.
  201. LIST_ENTRY leAttachedColorProfile; // List of attached ICC profile filename
  202. public:
  203. HDC hdcRef; // Info DC associated with metafile
  204. HDC hdcSrc; // src DC for Blt routines
  205. public:
  206. // pvNewRecord -- Allocate a metafile record from memory buffer.
  207. // Also set the size field in the metafile record. If a fatal error
  208. // has occurred, do not allocate new record.
  209. void * pvNewRecord(DWORD nSize); // MFDC.CXX
  210. // vUpdateNHandles -- Update number of handles in the metafile header record.
  211. VOID vUpdateNHandles(ULONG imhe)
  212. {
  213. ASSERTGDI(imhe < (ULONG) MHT_MAX_HANDLE_SIZE && HIWORD(imhe) == 0,
  214. "MDC::vUpdateNHandles: Handle index too big");
  215. if (mrmf.nHandles < (WORD) (imhe + 1))
  216. mrmf.nHandles = (WORD) (imhe + 1); // imhe is zero based.
  217. }
  218. // vAddToMetaFilePalette -- Add new palette entries to the metafile palette.
  219. VOID vAddToMetaFilePalette(UINT cEntries, PPALETTEENTRY pPalEntriesNew);
  220. // bIsDiskFile -- Is this a disk or memory metafile?
  221. BOOL bIsDiskFile() { return(fl & MDC_DISKFILE); }
  222. // bFatalError -- Have we encountered a fatal error?
  223. BOOL bFatalError() { return(fl & MDC_FATALERROR); }
  224. // bIsEMFSpool -- Are we doing EMF spooling?
  225. BOOL bIsEMFSpool() { return (fl & MDC_EMFSPOOL); }
  226. // SaveFontCommentOffset - Remember where the font data comment is
  227. BOOL SaveFontCommentOffset(ULONG ulID, ULONG offset)
  228. {
  229. ASSERTGDI(bIsEMFSpool(), "SaveFontCommentOffset: not EMF spooling\n");
  230. return ((EMFSpoolData *) hData)->AddFontExtRecord(ulID, offset+iMem);
  231. }
  232. //
  233. // GetPtr()
  234. // Get a pointer to emf data of the give size at the given offset. When
  235. // caller is done with the pointer they must call ReleasePtr(). Only one
  236. // pointer can be outstanding at a time (calling GetPtr on a second pointer
  237. // without first releasing the first pointer will fail returning NULL).
  238. //
  239. PVOID GetPtr(UINT32 inOffset, UINT32 inSize)
  240. {
  241. if(bIsEMFSpool())
  242. {
  243. return (PBYTE) ((EMFSpoolData *) hData)->GetPtr(inOffset, inSize);
  244. }
  245. else
  246. {
  247. return (PBYTE) hData + inOffset;
  248. }
  249. }
  250. //
  251. // ReleasePtr()
  252. // Callers of GetPtr and GetNextRecordPtr must call ReleasePtr when they
  253. // are done using the pointer.
  254. //
  255. VOID ReleasePtr(PVOID inPtr)
  256. {
  257. if(bIsEMFSpool())
  258. {
  259. ((EMFSpoolData *) hData)->ReleasePtr(inPtr);
  260. }
  261. }
  262. //
  263. // GetNextRecordPtr -- Return a pointer to the start of next EMF record
  264. // Caller must call ReleasePtr() when they are done using the pointer
  265. //
  266. PVOID GetNextRecordPtr(UINT32 inSize)
  267. {
  268. if(bIsEMFSpool())
  269. {
  270. return (PBYTE) ((EMFSpoolData *) hData)->GetPtr(iMem, inSize);
  271. }
  272. else
  273. {
  274. return (PBYTE) hData + iMem;
  275. }
  276. }
  277. // CompleteEMFData -- Finish recording EMF data (during EMF spooling)
  278. HENHMETAFILE CompleteEMFData(BOOL bKeepEMF)
  279. {
  280. ASSERTGDI(bIsEMFSpool(), "CompleteEMFData: called not during EMF spooling\n");
  281. PENHMETAHEADER pEMFHeader;
  282. UINT64 qwOffset;
  283. HANDLE hFile;
  284. if(((EMFSpoolData *) hData)->CompleteEMFData(bKeepEMF ? iMem : 0, &hFile, &qwOffset))
  285. {
  286. return SetEnhMetaFileBitsAlt(NULL, hData, hFile, qwOffset);
  287. }
  288. else
  289. {
  290. return NULL;
  291. }
  292. }
  293. // Reallocate memory for EMF data buffer
  294. BOOL ReallocMem(ULONG newsize);
  295. // bFlush -- Flush the filled memory buffer to disk.
  296. BOOL bFlush(); // MFDC.CXX
  297. // Get and set scales for font xform.
  298. FLOAT exFontScale() { return(eXFontScale); }
  299. FLOAT eyFontScale() { return(eYFontScale); }
  300. FLOAT exFontScale(FLOAT e) { return(eXFontScale = e); }
  301. FLOAT eyFontScale(FLOAT e) { return(eYFontScale = e); }
  302. // Get the device sizes of the reference device.
  303. LONG cxMillimeters() { return(mrmf.szlMillimeters.cx); }
  304. LONG cyMillimeters() { return(mrmf.szlMillimeters.cy); }
  305. LONG cxDevice() { return(mrmf.szlDevice.cx); }
  306. LONG cyDevice() { return(mrmf.szlDevice.cy); }
  307. // vMarkClipBoundsDirty -- Mark the current clip region bounds as dirty.
  308. VOID vMarkClipBoundsDirty() { fl |= MDC_CLIPBOUNDSDIRTY; }
  309. // vMarkMetaBoundsDirty -- Mark the current meta region bounds as dirty.
  310. VOID vMarkMetaBoundsDirty() { fl |= MDC_METABOUNDSDIRTY; }
  311. // perclMetaBoundsGet -- Get the current meta region bounds.
  312. PERECTL perclMetaBoundsGet()
  313. {
  314. if (fl & MDC_METABOUNDSDIRTY)
  315. {
  316. // Update the meta region bounds
  317. if (!GetRandomRgnBounds(hdcRef, &erclMetaBounds, 2))
  318. {
  319. erclMetaBounds = rclNull;
  320. }
  321. fl &= ~MDC_METABOUNDSDIRTY;
  322. }
  323. return(&erclMetaBounds);
  324. }
  325. // perclClipBoundsGet -- Get the current clip region bounds.
  326. PERECTL perclClipBoundsGet()
  327. {
  328. if (fl & MDC_CLIPBOUNDSDIRTY)
  329. {
  330. // Update the clip region bounds
  331. if (!GetRandomRgnBounds(hdcRef, &erclClipBounds, 1))
  332. {
  333. erclMetaBounds = rclNull;
  334. }
  335. fl &= ~MDC_CLIPBOUNDSDIRTY;
  336. }
  337. return(&erclClipBounds);
  338. }
  339. // vSetMetaBounds -- Update both meta and clip bounds.
  340. // The new meta bounds is the intersection of the meta and clip bounds.
  341. // The new clip bounds is the default, i.e. infinite bounds.
  342. VOID vSetMetaBounds()
  343. {
  344. *perclMetaBoundsGet() *= *perclClipBoundsGet();
  345. erclClipBounds = rclInfinity;
  346. }
  347. // vFlushBounds -- Flush the bounds to the metafile header record.
  348. // See also MDC::pvNewRecord.
  349. VOID vFlushBounds()
  350. {
  351. ERECTL ercl; // Inclusive-inclusive bounds in device units
  352. // Accumulate bounds if not empty.
  353. if (GetBoundsRectAlt(hdcRef, (LPRECT) &ercl, (UINT) (DCB_RESET | DCB_WINDOWMGR))
  354. == DCB_SET)
  355. {
  356. // Need to intersect bounds with current clipping region first
  357. ercl *= *perclMetaBoundsGet();
  358. ercl *= *perclClipBoundsGet();
  359. // Check that the clipped bounds is not empty.
  360. if ((ercl.left < ercl.right) && (ercl.top < ercl.bottom))
  361. {
  362. // Make it inclusive-inclusive.
  363. ercl.right--;
  364. ercl.bottom--;
  365. // Accumulate bounds to the metafile header.
  366. *((PERECTL) &mrmf.rclBounds) += ercl;
  367. }
  368. }
  369. }
  370. // vDelayCommit -- Delay commitment of a bound record to the next pvNewRecord.
  371. VOID vDelayCommit()
  372. {
  373. ASSERTGDI(!(fl & MDC_DELAYCOMMIT),"MDC::vDelayCommit: Already delayed");
  374. fl |= MDC_DELAYCOMMIT;
  375. }
  376. // vCommit -- Commit a metafile record to metafile.
  377. VOID vCommit(ENHMETARECORD &mr)
  378. {
  379. PUTS("MDC::vCommit(mr)\n");
  380. ASSERTGDI(mr.iType >= EMR_MIN && mr.iType <= EMR_MAX,
  381. "MDC::vCommit: Bad record type");
  382. ASSERTGDI(mr.nSize % 4 == 0,
  383. "MDC::vCommit: Record not DWORD aligned");
  384. ASSERTGDI(!(fl & MDC_FATALERROR),
  385. "MDC::vCommit: Fatal error has occurred");
  386. iMem += mr.nSize;
  387. mrmf.nBytes += mr.nSize;
  388. mrmf.nRecords++;
  389. }
  390. // bCommit -- Commit a metafile record with palette entries to metafile.
  391. // It also updates the metafile palette.
  392. BOOL bCommit(ENHMETARECORD &mr, UINT cEntries, PPALETTEENTRY pPalEntriesNew)
  393. {
  394. PUTS("MDC::bCommit(mr,cEntries,pPalEntriesNew)\n");
  395. // Allocate memory for the metafile palette if not done yet.
  396. if (!pPalEntries)
  397. {
  398. if (!(pPalEntries = (PPALETTEENTRY) LocalAlloc(LMEM_FIXED,
  399. MF_PALETTE_SIZE * sizeof(PALETTEENTRY))))
  400. return(FALSE);
  401. cPalEntries = MF_PALETTE_SIZE;
  402. iPalEntries = 0;
  403. }
  404. // Allocate more palette entries if needed.
  405. if (iPalEntries + cEntries > cPalEntries)
  406. {
  407. PPALETTEENTRY pPalEntries1;
  408. cPalEntries +=
  409. MF_PALETTE_SIZE + cEntries / MF_PALETTE_SIZE * MF_PALETTE_SIZE;
  410. if (!(pPalEntries1 = (PPALETTEENTRY) LocalReAlloc
  411. (
  412. (HLOCAL)pPalEntries,
  413. (UINT) cPalEntries * sizeof(PALETTEENTRY),
  414. LMEM_MOVEABLE
  415. )
  416. )
  417. )
  418. {
  419. cPalEntries -=
  420. MF_PALETTE_SIZE + cEntries / MF_PALETTE_SIZE * MF_PALETTE_SIZE;
  421. ERROR_ASSERT(FALSE, "LocalReAlloc failed");
  422. return(FALSE);
  423. }
  424. pPalEntries = pPalEntries1;
  425. }
  426. // Add to the metafile palette.
  427. vAddToMetaFilePalette(cEntries, pPalEntriesNew);
  428. ASSERTGDI(iPalEntries <= cPalEntries, "MDC::bCommit: palette error");
  429. // Commit it.
  430. vCommit(mr);
  431. return(TRUE);
  432. }
  433. // Embeded ICC profile list control
  434. //
  435. VOID vInitColorProfileList(VOID)
  436. {
  437. InitializeListHead(&leAttachedColorProfile);
  438. }
  439. VOID vFreeColorProfileList(VOID)
  440. {
  441. IcmFreeMetafileList(&leAttachedColorProfile);
  442. }
  443. VOID vInsertColorProfile(PWSZ Name)
  444. {
  445. IcmInsertMetafileList(&leAttachedColorProfile,Name);
  446. }
  447. BOOL bExistColorProfile(PWSZ Name)
  448. {
  449. return (IcmCheckMetafileList(&leAttachedColorProfile,Name));
  450. }
  451. };
  452. typedef MDC *PMDC;
  453. // Metafile MF flags
  454. #define MF_DISKFILE 0x0001 // Disk or memory metafile.
  455. #define MF_FOUNDBAD 0x8000 // Found bad records in metafile.
  456. /*********************************Class************************************\
  457. * class MF
  458. *
  459. * Metafile MF structure.
  460. *
  461. * There is no constructor or destructor for this object. We do the
  462. * initialization in pmfAllocMF and cleanup in vFreeMF.
  463. *
  464. * History:
  465. * Wed Jul 17 17:10:28 1991 -by- Hock San Lee [hockl]
  466. * Wrote it.
  467. \**************************************************************************/
  468. class MF
  469. {
  470. friend MF * pmfAllocMF(ULONG fl, CONST UNALIGNED DWORD *pb, LPCWSTR pwszFilename, HANDLE hFile, UINT64 fileOffset, HANDLE hExtra);
  471. friend VOID vFreeMF(MF *pmf);
  472. friend VOID vFreeMFAlt(MF *pmf, BOOL bAllocBuffer);
  473. friend BOOL bInternalPlayEMF(HDC hdc, HENHMETAFILE hemf, ENHMFENUMPROC pfn, LPVOID pv, CONST RECTL *prcl);
  474. friend HENHMETAFILE APIENTRY CopyEnhMetaFileW(HENHMETAFILE, LPCWSTR);
  475. friend UINT APIENTRY GetEnhMetaFileBits( HENHMETAFILE, UINT, LPBYTE);
  476. friend UINT APIENTRY GetWinMetaFileBits( HENHMETAFILE, UINT, LPBYTE, INT, HDC);
  477. friend HENHMETAFILE APIENTRY SetEnhMetaFileBitsAlt(HLOCAL, HANDLE, HANDLE, UINT64 qwFileOffset);
  478. friend UINT APIENTRY GetEnhMetaFilePaletteEntries( HENHMETAFILE, UINT, LPPALETTEENTRY);
  479. friend UINT APIENTRY GetEnhMetaFileHeader( HENHMETAFILE, UINT, LPENHMETAHEADER);
  480. friend UINT InternalGetEnhMetaFileDescription( HENHMETAFILE, UINT, LPSTR, BOOL);
  481. friend HANDLE GdiConvertEnhMetaFile(HENHMETAFILE);
  482. private:
  483. ULONG ident; // Identifier 'MF'
  484. HANDLE hFile; // Handle to the disk metafile.
  485. HANDLE hFileMap; // Handle to the disk file mapping object.
  486. public:
  487. PVOID pvFileMapping; // Pointer to file mapping
  488. PVOID pvLocalCopy; // Local copy of meta file
  489. EMFContainer emfc;
  490. EMFSpoolData *pEMFSpool; // handle to extra EMF spool information
  491. private:
  492. ULONG iMem; // Current memory index pointer.
  493. ERECTL erclClipBox; // Incl-incl clip box in source device units.
  494. WCHAR wszPathname[MAX_PATH+1];
  495. // Full pathname of the disk metafile.
  496. public:
  497. ULONG fl; // Flags.
  498. PHANDLETABLE pht; // Pointer to the object handle table.
  499. BOOL bBeginGroup; // Is begin group comment emitted?
  500. // Init to FALSE before play or enum.
  501. ULONG cLevel; // Saved level. Init to 1 before play or enum.
  502. XFORM xformBase; // Base playback transform for target.
  503. // This happens to be the same as cliprgn xform.
  504. HDC hdcXform; // Virtual DC for use in transform computation.
  505. public:
  506. // bIsDiskFile -- Is this a disk or memory metafile?
  507. BOOL bIsDiskFile() { return(fl & MF_DISKFILE); }
  508. // bIsEMFSpool -- During EMF spooling?
  509. BOOL bIsEMFSpool() { return (pEMFSpool != NULL); }
  510. // bSetTransform -- Set up the transform in the target DC.
  511. BOOL bSetTransform(HDC hdc)
  512. {
  513. XFORM xformMF;
  514. // Get the new metafile transform from the virtual DC.
  515. GetTransform(hdcXform, XFORM_WORLD_TO_DEVICE, &xformMF);
  516. // Set up new transform in the target DC.
  517. if (!CombineTransform(&xformMF, &xformMF, &xformBase))
  518. return(FALSE);
  519. else
  520. return(SetWorldTransform(hdc, &xformMF));
  521. }
  522. BOOL bValidBoundedSize(PVOID p, DWORD dwSize)
  523. {
  524. // If hFile is valid check file extents
  525. if (hFile != INVALID_HANDLE_VALUE)
  526. {
  527. UINT64 fileSize;
  528. if (!GetFileSizeEx(hFile,(PLARGE_INTEGER)&fileSize))
  529. {
  530. fl |= MF_FOUNDBAD;
  531. EMFVALFAIL(("GetFileSizeEx(%p) failed\n", hFile));
  532. return(FALSE);
  533. }
  534. if ((UINT64)dwSize > fileSize)
  535. {
  536. fl |= MF_FOUNDBAD;
  537. EMFVALFAIL(("Record size (%d) larger than file size (%d)!\n", dwSize, (UINT32)fileSize));
  538. return(FALSE);
  539. }
  540. }
  541. else // else check against emfContainer.dwHdrSize
  542. {
  543. if (dwSize > emfc.GetdwHdrSize())
  544. {
  545. fl |= MF_FOUNDBAD;
  546. EMFVALFAIL(("Record size (%d) larger than dwHdrSize (%d)!\n", dwSize, emfc.GetdwHdrSize()));
  547. return(FALSE);
  548. }
  549. }
  550. // Check arithmetic overflow
  551. if ((PBYTE)p + dwSize < (PBYTE)p)
  552. {
  553. fl |= MF_FOUNDBAD;
  554. EMFVALFAIL(("Pointer Bounds (%p+%p) failed due to arithmetic overflow!\n", p, dwSize));
  555. return(FALSE);
  556. }
  557. #if 0
  558. // Dont do this now: It appears some MetaRecords can be hand generated
  559. // on the fly and sending them into emfc.bBounded will fail and we
  560. // will break a bunch of components like GDI+/Office200/Corel etc.
  561. // Now check pointer bounds with emfc.
  562. if (!emfc.bBounded((PBYTE)p, dwSize))
  563. {
  564. fl |= MF_FOUNDBAD;
  565. EMFVALFAIL(("Pointer Bounds (%p+%p) failed!\n", p, dwSize));
  566. return(FALSE);
  567. }
  568. #endif
  569. return (TRUE);
  570. }
  571. // bClipped -- Returns TRUE if erclBounds does not intersect the clip box,
  572. // otherwise FALSE. Both rectangles are assumed to be incl-incl
  573. // in source device units. The clip box must not be empty.
  574. //
  575. // If erclBounds is empty, we will return FALSE to force playback of the
  576. // record. The reason is that at record (or embed) time, the scale transform
  577. // at the time may cause the bounds to be empty due to rounding error. At
  578. // playback time, this bounds may not be empty anymore.
  579. BOOL bClipped(ERECTL &erclBounds)
  580. {
  581. if (erclBounds.bEmpty())
  582. return(FALSE);
  583. else
  584. return(erclClipBox.bNoIntersect(erclBounds));
  585. }
  586. };
  587. typedef MF *PMF;
  588. // pmfAllocMF flags
  589. #define ALLOCMF_TRANSFER_BUFFER 0x1
  590. #define hmfCreate(pmf) hCreateClientObjLink((PVOID)pmf,LO_METAFILE_TYPE)
  591. #define bDeleteHmf(hmf) bDeleteClientObjLink((HANDLE)hmf)
  592. #define GET_PMF(hmf) ((PMF)pvClientObjGet((HANDLE)hmf,LO_METAFILE_TYPE))
  593. PMDC pmdcGetFromHdc(HDC hdc);