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.

1793 lines
50 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * MetaFile.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Metafile definitions
  12. *
  13. * Created:
  14. *
  15. * 4/14/1999 DCurtis
  16. *
  17. \**************************************************************************/
  18. #ifndef _METAFILE_HPP
  19. #define _METAFILE_HPP
  20. #define EMFPLUS_SIGNATURE 0x2B464D45
  21. #define EMFPLUS_DUAL 0x4C415544 // EMF+ with down-level GDI records
  22. #define EMFPLUS_ONLY 0x594C4E4F // EMF+ only -- no down-level
  23. /* The following are defined in Object.hpp:
  24. #define EMFPLUS_VERSION
  25. #define EMFPLUS_MAJORVERSION_BITS
  26. #define EMFPLUS_MINORVERSION_BITS
  27. */
  28. // Constants for MFCOMMENT Escape
  29. #define MFCOMMENT_IDENTIFIER 0x43464D57
  30. #define MFCOMMENT_ENHANCED_METAFILE 1
  31. // When serializing an object, we need to leave room for the record header
  32. // and possibly a dependent object id. Also, an image can be part of a
  33. // texture brush, so leave room for the texture brush data.
  34. // Subtract 480 for good measure.
  35. #define GDIP_MAX_OBJECT_SIZE (GDIP_MAX_COMMENT_SIZE - 480)
  36. #define GDIP_METAFILE_BUFFERSIZE 2048
  37. #define GDIP_MAX_OBJECTS 64 // max num cached objects
  38. #define GDIP_SAVE_STACK_SIZE 16 // for save/restores
  39. #define GDIP_LIST_NIL 0xFFFFFFFF
  40. #define GDIP_OBJECTID_NONE GDIP_LIST_NIL // no object present
  41. #define GDIP_REAL_SIZE 4
  42. #define GDIP_RECTF_SIZE (4 * GDIP_REAL_SIZE)
  43. #define GDIP_POINTF_SIZE (2 * GDIP_REAL_SIZE)
  44. #define GDIP_MATRIX_SIZE (6 * GDIP_REAL_SIZE)
  45. // Set in Flags in EMF+ record header
  46. // Flags Used in Object Records
  47. #define GDIP_EPRFLAGS_CONTINUEOBJECT 0x8000 // more data for previous object
  48. #define GDIP_EPRFLAGS_OBJECTTYPE 0x7F00
  49. // Used in Object records and "Fill..." and "Draw..." and many other records
  50. #define GDIP_EPRFLAGS_METAOBJECTID 0x00FF
  51. #define GDIP_BACKUP_OBJECTID 255 // the object is a "backup object"
  52. // Used in "Fill..." records
  53. #define GDIP_EPRFLAGS_SOLIDCOLOR 0x8000
  54. // Used in "Fill..." and "Draw..." records
  55. #define GDIP_EPRFLAGS_COMPRESSED 0x4000 // point data is compressed
  56. // Used in some "Fill..." records
  57. #define GDIP_EPRFLAGS_WINDINGFILL 0x2000
  58. // Used in DrawLines record
  59. #define GDIP_EPRFLAGS_CLOSED 0x2000
  60. // Used in matrix operations
  61. #define GDIP_EPRFLAGS_APPEND 0x2000
  62. // Used in SetAntiAliasMode record
  63. #define GDIP_EPRFLAGS_ANTIALIAS 0x0001
  64. // Used in SetTextRenderingHint record
  65. #define GDIP_EPRFLAGS_TEXTRENDERINGHINT 0x00FF
  66. // Used in SetTextContrast record (1000~2200)
  67. #define GDIP_EPRFLAGS_CONTRAST 0x0FFF
  68. // Used in EndOfFile record
  69. #define GDIP_EPRFLAGS_DIDGETDC 0x2000
  70. // Used in BeginContainer and SetPageTransform records
  71. #define GDIP_EPRFLAGS_PAGEUNIT 0x00FF // can't be mixed with Ids
  72. // Used in SetInterpolationMode record
  73. #define GDIP_EPRFLAGS_INTERPOLATIONMODE 0x00FF
  74. // Used in SetPixelOffsetMode record
  75. #define GDIP_EPRFLAGS_PIXELOFFSETMODE 0x00FF
  76. // Used in SetCompositingMode record
  77. #define GDIP_EPRFLAGS_COMPOSITINGMODE 0x00FF
  78. // Used in SetCompositingQuality record
  79. #define GDIP_EPRFLAGS_COMPOSITINGQUALITY 0x00FF
  80. // Used in SetClipRect, SetClipPath, and SetClipRegion records
  81. #define GDIP_EPRFLAGS_COMBINEMODE 0x0F00
  82. // Used in SetClipPath record
  83. #define GDIP_EPRFLAGS_ISDEVICEPATH 0x2000
  84. // Used in Header record
  85. #define GDIP_EPRFLAGS_EMFPLUSDUAL 0x0001
  86. inline ObjectType
  87. GetObjectType(
  88. INT flags
  89. )
  90. {
  91. return static_cast<ObjectType>((flags & GDIP_EPRFLAGS_OBJECTTYPE) >> 8);
  92. }
  93. inline GpFillMode
  94. GetFillMode(
  95. INT flags
  96. )
  97. {
  98. return ((flags & GDIP_EPRFLAGS_WINDINGFILL) == 0) ?
  99. FillModeAlternate : FillModeWinding;
  100. }
  101. inline BOOL
  102. IsClosed(
  103. INT flags
  104. )
  105. {
  106. return ((flags & GDIP_EPRFLAGS_CLOSED) != 0);
  107. }
  108. inline BOOL
  109. DidGetDC(
  110. INT flags
  111. )
  112. {
  113. return ((flags & GDIP_EPRFLAGS_DIDGETDC) != 0);
  114. }
  115. inline GpMatrixOrder
  116. GetMatrixOrder(
  117. INT flags
  118. )
  119. {
  120. return ((flags & GDIP_EPRFLAGS_APPEND) == 0) ? MatrixOrderPrepend : MatrixOrderAppend;
  121. }
  122. inline BOOL
  123. GetAntiAliasMode(
  124. INT flags
  125. )
  126. {
  127. return ((flags & GDIP_EPRFLAGS_ANTIALIAS) != 0);
  128. }
  129. inline TextRenderingHint
  130. GetTextRenderingHint(
  131. INT flags
  132. )
  133. {
  134. return static_cast<TextRenderingHint>
  135. (flags & GDIP_EPRFLAGS_TEXTRENDERINGHINT);
  136. }
  137. inline UINT
  138. GetTextContrast(
  139. INT flags
  140. )
  141. {
  142. return static_cast<UINT>
  143. (flags & GDIP_EPRFLAGS_CONTRAST);
  144. }
  145. inline InterpolationMode
  146. GetInterpolationMode(
  147. INT flags
  148. )
  149. {
  150. return static_cast<InterpolationMode>
  151. (flags & GDIP_EPRFLAGS_INTERPOLATIONMODE);
  152. }
  153. inline PixelOffsetMode
  154. GetPixelOffsetMode(
  155. INT flags
  156. )
  157. {
  158. return static_cast<PixelOffsetMode>
  159. (flags & GDIP_EPRFLAGS_PIXELOFFSETMODE);
  160. }
  161. inline GpCompositingMode
  162. GetCompositingMode(
  163. INT flags
  164. )
  165. {
  166. return static_cast<GpCompositingMode>
  167. (flags & GDIP_EPRFLAGS_COMPOSITINGMODE);
  168. }
  169. inline GpCompositingQuality
  170. GetCompositingQuality(
  171. INT flags
  172. )
  173. {
  174. return static_cast<GpCompositingQuality>
  175. (flags & GDIP_EPRFLAGS_COMPOSITINGQUALITY);
  176. }
  177. inline UINT
  178. GetMetaObjectId(
  179. INT flags
  180. )
  181. {
  182. return flags & GDIP_EPRFLAGS_METAOBJECTID;
  183. }
  184. inline GpPageUnit
  185. GetPageUnit(
  186. INT flags
  187. )
  188. {
  189. return static_cast<GpPageUnit>(flags & GDIP_EPRFLAGS_PAGEUNIT);
  190. }
  191. inline CombineMode
  192. GetCombineMode(
  193. INT flags
  194. )
  195. {
  196. return static_cast<CombineMode>((flags & GDIP_EPRFLAGS_COMBINEMODE) >> 8);
  197. }
  198. inline BOOL
  199. GetIsDevicePath(
  200. INT flags
  201. )
  202. {
  203. return ((flags & GDIP_EPRFLAGS_ISDEVICEPATH) != 0);
  204. }
  205. inline BOOL
  206. GetIsEmfPlusDual(
  207. INT flags
  208. )
  209. {
  210. return ((flags & GDIP_EPRFLAGS_EMFPLUSDUAL) != 0);
  211. }
  212. class MetafileRecorder;
  213. class MetafilePlayer;
  214. class EmfPlusRecord
  215. {
  216. public:
  217. INT16 Type;
  218. UINT16 Flags; // This has to be unsigned or the code breaks!
  219. UINT32 Size; // Record size in bytes (including size field)
  220. UINT32 DataSize; // Record size in bytes, excluding header size.
  221. };
  222. class EmfPlusContinueObjectRecord : public EmfPlusRecord
  223. {
  224. public:
  225. UINT32 TotalObjectSize;
  226. };
  227. class EmfPlusRecordPlay
  228. {
  229. public:
  230. VOID Play(
  231. MetafilePlayer * player,
  232. EmfPlusRecordType recordType,
  233. UINT flags,
  234. UINT dataSize
  235. ) const
  236. {
  237. return;
  238. }
  239. };
  240. class EmfPlusHeaderRecord : public EmfPlusRecordPlay
  241. {
  242. public:
  243. INT32 Version; // Version of the file
  244. INT32 EmfPlusFlags; // flags (display and non-dual)
  245. INT32 LogicalDpiX; // DpiX of referenceHdc
  246. INT32 LogicalDpiY; // DpiY of referenceHdc
  247. EmfPlusHeaderRecord() { /* no initialization */ }
  248. EmfPlusHeaderRecord(INT emfPlusFlags, INT logicalDpiX, INT logicalDpiY)
  249. {
  250. Version = EMFPLUS_VERSION;
  251. EmfPlusFlags = emfPlusFlags;
  252. LogicalDpiX = logicalDpiX;
  253. LogicalDpiY = logicalDpiY;
  254. }
  255. };
  256. #ifdef GDIP_RECORD_DEVICEBOUNDS
  257. class EmfPlusBoundsRecord : public EmfPlusRecordPlay
  258. {
  259. public:
  260. GpRectF DeviceBounds;
  261. };
  262. #else
  263. #define EmfPlusBoundsRecord EmfPlusRecordPlay
  264. #endif
  265. // When recording, we convert REAL data to INT16 data if we can without
  266. // losing precision.
  267. typedef struct
  268. {
  269. INT16 X;
  270. INT16 Y;
  271. } GpPoint16;
  272. typedef struct
  273. {
  274. INT16 X;
  275. INT16 Y;
  276. INT16 Width;
  277. INT16 Height;
  278. } GpRect16;
  279. inline BOOL
  280. EmfHeaderIsValid(
  281. ENHMETAHEADER3 & emfHeader
  282. )
  283. {
  284. return ((emfHeader.iType == EMR_HEADER) &&
  285. (emfHeader.dSignature == ENHMETA_SIGNATURE) &&
  286. (emfHeader.nSize >= sizeof(ENHMETAHEADER3)) &&
  287. (emfHeader.nHandles > 0) &&
  288. (emfHeader.nRecords >= 2) && // must have at least header and EOF record
  289. ((emfHeader.nBytes & 3) == 0) &&
  290. (emfHeader.szlDevice.cx > 0) &&
  291. (emfHeader.szlDevice.cy > 0) &&
  292. (emfHeader.szlMillimeters.cx > 0) &&
  293. (emfHeader.szlMillimeters.cy > 0));
  294. }
  295. GpStatus
  296. GetMetafileHeader(
  297. HMETAFILE hWmf,
  298. const WmfPlaceableFileHeader * wmfPlaceableFileHeader,
  299. MetafileHeader & header
  300. );
  301. GpStatus
  302. GetMetafileHeader(
  303. HENHMETAFILE hEmf,
  304. MetafileHeader & header,
  305. BOOL * isCorrupted = NULL
  306. );
  307. GpStatus
  308. GetMetafileHeader(
  309. IStream * stream,
  310. MetafileHeader & header,
  311. BOOL tryWmfOnly = FALSE
  312. );
  313. GpStatus
  314. GetMetafileHeader(
  315. const WCHAR * filename,
  316. MetafileHeader & header
  317. );
  318. ///////////////////////////////////////////////////////////////////////////
  319. // Stream helper methods
  320. IStream *
  321. CreateStreamOnFile(
  322. const OLECHAR * pwcsName,
  323. UINT access = GENERIC_WRITE // GENERIC_READ and/or GENERIC_WRITE
  324. );
  325. inline INT
  326. HResultSuccess(
  327. HRESULT hResult
  328. )
  329. {
  330. return (!FAILED(hResult)) ? 1 : 0;
  331. }
  332. inline INT
  333. GetStreamPosition(
  334. IStream * stream,
  335. LONGLONG & position
  336. )
  337. {
  338. HRESULT hResult;
  339. ULARGE_INTEGER curPosition;
  340. LARGE_INTEGER zeroOffset;
  341. zeroOffset.QuadPart = 0;
  342. hResult = stream->Seek(zeroOffset, STREAM_SEEK_CUR, &curPosition);
  343. position = curPosition.QuadPart;
  344. return HResultSuccess(hResult);
  345. }
  346. inline INT
  347. SeekFromHere(
  348. IStream * stream,
  349. const LONGLONG & offsetFromHere
  350. )
  351. {
  352. HRESULT hResult;
  353. LARGE_INTEGER offset;
  354. offset.QuadPart = offsetFromHere;
  355. hResult = stream->Seek(offset, STREAM_SEEK_CUR, NULL);
  356. return HResultSuccess(hResult);
  357. }
  358. inline INT
  359. SeekFromStart(
  360. IStream * stream,
  361. const LONGLONG & offsetFromStart
  362. )
  363. {
  364. HRESULT hResult;
  365. LARGE_INTEGER offset;
  366. offset.QuadPart = offsetFromStart;
  367. hResult = stream->Seek(offset, STREAM_SEEK_SET, NULL);
  368. return HResultSuccess(hResult);
  369. }
  370. inline INT
  371. CopyStream(
  372. IStream * srcStream,
  373. IStream * destStream,
  374. const LONGLONG & bytesToCopy
  375. )
  376. {
  377. HRESULT hResult;
  378. ULARGE_INTEGER numBytes;
  379. ULARGE_INTEGER bytesWritten;
  380. ASSERT (bytesToCopy > 0);
  381. numBytes.QuadPart = bytesToCopy;
  382. hResult = srcStream->CopyTo(destStream, numBytes, NULL, &bytesWritten);
  383. return ((!FAILED(hResult)) &&
  384. (bytesWritten.QuadPart == numBytes.QuadPart)) ? 1 : 0;
  385. }
  386. ///////////////////////////////////////////////////////////////////////////
  387. // Read methods to read values from a stream
  388. inline INT
  389. ReadInt16(
  390. IStream * stream,
  391. INT16 * value
  392. )
  393. {
  394. ASSERT(sizeof(INT16) == 2);
  395. HRESULT hResult;
  396. hResult = stream->Read(value, sizeof(INT16), NULL);
  397. return HResultSuccess(hResult);
  398. }
  399. inline INT
  400. ReadInt32(
  401. IStream * stream,
  402. INT32 * value
  403. )
  404. {
  405. ASSERT(sizeof(INT32) == 4);
  406. HRESULT hResult;
  407. hResult = stream->Read(value, sizeof(INT32), NULL);
  408. return HResultSuccess(hResult);
  409. }
  410. inline INT
  411. ReadInt32(
  412. IStream * stream,
  413. UINT32 * value
  414. )
  415. {
  416. ASSERT(sizeof(UINT32) == 4);
  417. HRESULT hResult;
  418. hResult = stream->Read(value, sizeof(UINT32), NULL);
  419. return HResultSuccess(hResult);
  420. }
  421. inline INT
  422. ReadReal(
  423. IStream * stream,
  424. REAL * value
  425. )
  426. {
  427. ASSERT(sizeof(REAL) == 4);
  428. HRESULT hResult;
  429. hResult = stream->Read(value, sizeof(REAL), NULL);
  430. return HResultSuccess(hResult);
  431. }
  432. inline INT
  433. ReadRect(
  434. IStream * stream,
  435. GpRectF * value
  436. )
  437. {
  438. ASSERT(sizeof(GpRectF) == GDIP_RECTF_SIZE);
  439. HRESULT hResult;
  440. hResult = stream->Read(value, sizeof(GpRectF), NULL);
  441. return HResultSuccess(hResult);
  442. }
  443. inline INT
  444. ReadMatrix(
  445. IStream * stream,
  446. GpMatrix * value
  447. )
  448. {
  449. ASSERT(sizeof(REAL) == GDIP_REAL_SIZE);
  450. REAL matrix[6];
  451. HRESULT hResult;
  452. hResult = stream->Read(matrix, GDIP_MATRIX_SIZE, NULL);
  453. value->SetMatrix(matrix);
  454. return HResultSuccess(hResult);
  455. }
  456. inline INT
  457. ReadBytes(
  458. IStream * stream,
  459. VOID * bytes,
  460. INT count
  461. )
  462. {
  463. ASSERT(sizeof(BYTE) == 1);
  464. HRESULT hResult;
  465. hResult = stream->Read(bytes, count, NULL);
  466. return HResultSuccess(hResult);
  467. }
  468. inline INT
  469. ReadPoints(
  470. IStream * stream,
  471. GpPointF * points,
  472. INT count
  473. )
  474. {
  475. ASSERT(sizeof(GpPointF) == GDIP_POINTF_SIZE);
  476. HRESULT hResult;
  477. hResult = stream->Read(points, sizeof(GpPointF) * count, NULL);
  478. return HResultSuccess(hResult);
  479. }
  480. ///////////////////////////////////////////////////////////////////////////
  481. // Write methods to write values to a stream
  482. inline INT
  483. WriteByte(
  484. IStream * stream,
  485. BYTE value
  486. )
  487. {
  488. ASSERT(sizeof(value) == 1);
  489. HRESULT hResult;
  490. hResult = stream->Write(&value, sizeof(value), NULL);
  491. return HResultSuccess(hResult);
  492. }
  493. inline INT
  494. WriteInt16(
  495. IStream * stream,
  496. INT16 value
  497. )
  498. {
  499. ASSERT(sizeof(value) == 2);
  500. HRESULT hResult;
  501. hResult = stream->Write(&value, sizeof(value), NULL);
  502. return HResultSuccess(hResult);
  503. }
  504. inline INT
  505. WriteInt32(
  506. IStream * stream,
  507. INT32 value
  508. )
  509. {
  510. ASSERT(sizeof(value) == 4);
  511. HRESULT hResult;
  512. hResult = stream->Write(&value, sizeof(value), NULL);
  513. return HResultSuccess(hResult);
  514. }
  515. inline INT
  516. WriteReal(
  517. IStream * stream,
  518. REAL value
  519. )
  520. {
  521. ASSERT(sizeof(value) == GDIP_REAL_SIZE);
  522. HRESULT hResult;
  523. hResult = stream->Write(&value, sizeof(value), NULL);
  524. return HResultSuccess(hResult);
  525. }
  526. inline INT
  527. WriteColor64(
  528. IStream * stream,
  529. const ARGB64 & value
  530. )
  531. {
  532. ASSERT(sizeof(value) == 8);
  533. HRESULT hResult;
  534. hResult = stream->Write(&value, sizeof(value), NULL);
  535. return HResultSuccess(hResult);
  536. }
  537. inline INT
  538. WriteRect(
  539. IStream * stream,
  540. const GpRectF & value
  541. )
  542. {
  543. ASSERT(sizeof(value) == GDIP_RECTF_SIZE);
  544. HRESULT hResult;
  545. hResult = stream->Write(&value, sizeof(value), NULL);
  546. return HResultSuccess(hResult);
  547. }
  548. inline INT
  549. WriteMatrix(
  550. IStream * stream,
  551. const GpMatrix & value
  552. )
  553. {
  554. ASSERT(sizeof(REAL) == GDIP_REAL_SIZE);
  555. REAL matrix[6];
  556. value.GetMatrix(matrix);
  557. HRESULT hResult;
  558. hResult = stream->Write(matrix, GDIP_MATRIX_SIZE, NULL);
  559. return HResultSuccess(hResult);
  560. }
  561. inline INT
  562. WriteBytes(
  563. IStream * stream,
  564. const VOID * bytes,
  565. INT count // number of bytes
  566. )
  567. {
  568. ASSERT(sizeof(BYTE) == 1);
  569. HRESULT hResult;
  570. hResult = stream->Write(bytes, count, NULL);
  571. return HResultSuccess(hResult);
  572. }
  573. inline INT
  574. WritePoints(
  575. IStream * stream,
  576. const GpPointF * points,
  577. INT count
  578. )
  579. {
  580. ASSERT(sizeof(GpPointF) == GDIP_POINTF_SIZE);
  581. HRESULT hResult;
  582. hResult = stream->Write(points, sizeof(GpPointF) * count, NULL);
  583. return HResultSuccess(hResult);
  584. }
  585. inline INT
  586. WriteRects(
  587. IStream * stream,
  588. const GpRectF * rects,
  589. INT count
  590. )
  591. {
  592. ASSERT(sizeof(GpRectF) == GDIP_RECTF_SIZE);
  593. HRESULT hResult;
  594. hResult = stream->Write(rects, sizeof(GpRectF) * count, NULL);
  595. return HResultSuccess(hResult);
  596. }
  597. GpPointF *
  598. GetPointsForPlayback(
  599. const BYTE * pointData,
  600. UINT pointDataSize,
  601. INT count,
  602. INT flags,
  603. UINT bufferSize,
  604. BYTE * buffer,
  605. BYTE * & allocedBuffer
  606. );
  607. GpRectF *
  608. GetRectsForPlayback(
  609. BYTE * rectData,
  610. UINT rectDataSize,
  611. INT count,
  612. INT flags,
  613. UINT bufferSize,
  614. BYTE * buffer,
  615. BYTE * & allocedBuffer
  616. );
  617. #define GDIP_POINTDATA_BUFFERSIZE 64 // Number of points for the PointBuffer
  618. class MetafilePointData
  619. {
  620. public:
  621. MetafilePointData(const GpPointF * points, INT count);
  622. ~MetafilePointData() { delete [] AllocedPoints; }
  623. INT WriteData(IStream * stream) const { return WriteBytes(stream, PointData, PointDataSize); }
  624. BYTE * GetData() const { return PointData; }
  625. INT GetDataSize() const { return PointDataSize; }
  626. INT GetFlags() const { return Flags; }
  627. protected:
  628. /**************************************************************************\
  629. *
  630. * Function Description:
  631. *
  632. * Determine if a GpPointF is equal to a GpPoint16 (within the tolerance).
  633. *
  634. * Arguments:
  635. *
  636. * [IN] point16 - the 16-bit integer point
  637. * [IN] point - the REAL point
  638. *
  639. * Return Value:
  640. *
  641. * BOOL - whether or not the points are equal
  642. *
  643. * Created:
  644. *
  645. * 6/15/1999 DCurtis
  646. *
  647. \**************************************************************************/
  648. BOOL
  649. IsPoint16Equal(
  650. const GpPoint16 * point16,
  651. const GpPointF * point
  652. )
  653. {
  654. REAL dx = point->X - (REAL)(point16->X);
  655. REAL dy = point->Y - (REAL)(point16->Y);
  656. return ((dx > -REAL_TOLERANCE) && (dx < REAL_TOLERANCE) &&
  657. (dy > -REAL_TOLERANCE) && (dy < REAL_TOLERANCE));
  658. }
  659. protected:
  660. GpPoint16 PointBuffer[GDIP_POINTDATA_BUFFERSIZE];
  661. BYTE * PointData;
  662. GpPoint16 * AllocedPoints;
  663. INT PointDataSize;
  664. INT Flags;
  665. };
  666. #define GDIP_RECTDATA_BUFFERSIZE 16 // Number of rects for the RectBuffer
  667. class MetafileRectData
  668. {
  669. public:
  670. MetafileRectData(const GpRectF * rects, INT count);
  671. ~MetafileRectData() { delete [] AllocedRects; }
  672. INT WriteData(IStream * stream) const { return WriteBytes(stream, RectData, RectDataSize); }
  673. BYTE * GetData() const { return RectData; }
  674. INT GetDataSize() const { return RectDataSize; }
  675. INT GetFlags() const { return Flags; }
  676. protected:
  677. /**************************************************************************\
  678. *
  679. * Function Description:
  680. *
  681. * Determine if a GpRectF is equal to a GpRect16 (within the toleranc).
  682. *
  683. * Arguments:
  684. *
  685. * [IN] rect16 - the 16-bit integer rect
  686. * [IN] rect - the REAL rect
  687. *
  688. * Return Value:
  689. *
  690. * BOOL - whether or not the rects are equal
  691. *
  692. * Created:
  693. *
  694. * 6/15/1999 DCurtis
  695. *
  696. \**************************************************************************/
  697. BOOL
  698. IsRect16Equal(
  699. const GpRect16 * rect16,
  700. const GpRectF * rect
  701. )
  702. {
  703. REAL dx = rect->X - static_cast<REAL>(rect16->X);
  704. REAL dy = rect->Y - static_cast<REAL>(rect16->Y);
  705. REAL dw = rect->Width - static_cast<REAL>(rect16->Width);
  706. REAL dh = rect->Height - static_cast<REAL>(rect16->Height);
  707. return ((dx > -REAL_TOLERANCE) && (dx < REAL_TOLERANCE) &&
  708. (dy > -REAL_TOLERANCE) && (dy < REAL_TOLERANCE) &&
  709. (dw > -REAL_TOLERANCE) && (dw < REAL_TOLERANCE) &&
  710. (dh > -REAL_TOLERANCE) && (dh < REAL_TOLERANCE));
  711. }
  712. protected:
  713. GpRect16 RectBuffer[GDIP_RECTDATA_BUFFERSIZE];
  714. BYTE * RectData;
  715. GpRect16 * AllocedRects;
  716. INT RectDataSize;
  717. INT Flags;
  718. };
  719. class IMetafileRecord
  720. {
  721. public:
  722. virtual ~IMetafileRecord() {}
  723. virtual VOID GetMetafileBounds(GpRect & metafileBounds) const = 0;
  724. // Record methods to be called only from API classes
  725. // This is for backward compatiblity. If we are using a new object
  726. // (such as a new kind of brush), then we can record a backup object
  727. // for down-level apps to use when they see a new object that they
  728. // don't know how to deal with.
  729. virtual GpStatus
  730. RecordBackupObject(
  731. const GpObject * object
  732. ) = 0;
  733. virtual GpStatus
  734. RecordClear(
  735. const GpRectF * deviceBounds,
  736. GpColor color
  737. ) = 0;
  738. virtual GpStatus
  739. RecordFillRects(
  740. const GpRectF * deviceBounds,
  741. GpBrush * brush,
  742. const GpRectF * rects,
  743. INT count
  744. ) = 0;
  745. virtual GpStatus
  746. RecordDrawRects(
  747. const GpRectF * deviceBounds,
  748. GpPen * pen,
  749. const GpRectF * rects,
  750. INT count
  751. ) = 0;
  752. virtual GpStatus
  753. RecordFillPolygon(
  754. const GpRectF * deviceBounds,
  755. GpBrush* brush,
  756. const GpPointF * points,
  757. INT count,
  758. GpFillMode fillMode
  759. ) = 0;
  760. virtual GpStatus
  761. RecordDrawLines(
  762. const GpRectF * deviceBounds,
  763. GpPen * pen,
  764. const GpPointF * points,
  765. INT count,
  766. BOOL closed
  767. ) = 0;
  768. virtual GpStatus
  769. RecordFillEllipse(
  770. const GpRectF * deviceBounds,
  771. GpBrush * brush,
  772. const GpRectF & rect
  773. ) = 0;
  774. virtual GpStatus
  775. RecordDrawEllipse(
  776. const GpRectF * deviceBounds,
  777. GpPen * pen,
  778. const GpRectF & rect
  779. ) = 0;
  780. virtual GpStatus
  781. RecordFillPie(
  782. const GpRectF * deviceBounds,
  783. GpBrush * brush,
  784. const GpRectF & rect,
  785. REAL startAngle,
  786. REAL sweepAngle
  787. ) = 0;
  788. virtual GpStatus
  789. RecordDrawPie(
  790. const GpRectF * deviceBounds,
  791. GpPen * pen,
  792. const GpRectF & rect,
  793. REAL startAngle,
  794. REAL sweepAngle
  795. ) = 0;
  796. virtual GpStatus
  797. RecordDrawArc(
  798. const GpRectF * deviceBounds,
  799. GpPen * pen,
  800. const GpRectF & rect,
  801. REAL startAngle,
  802. REAL sweepAngle
  803. ) = 0;
  804. virtual GpStatus
  805. RecordFillRegion(
  806. const GpRectF * deviceBounds,
  807. GpBrush * brush,
  808. GpRegion * region
  809. ) = 0;
  810. virtual GpStatus
  811. RecordFillPath(
  812. const GpRectF * deviceBounds,
  813. const GpBrush * brush,
  814. GpPath * path
  815. ) = 0;
  816. virtual GpStatus
  817. RecordDrawPath(
  818. const GpRectF * deviceBounds,
  819. GpPen * pen,
  820. GpPath * path
  821. ) = 0;
  822. virtual GpStatus
  823. RecordFillClosedCurve(
  824. const GpRectF * deviceBounds,
  825. GpBrush * brush,
  826. const GpPointF * points,
  827. INT count,
  828. REAL tension,
  829. GpFillMode fillMode
  830. ) = 0;
  831. virtual GpStatus
  832. RecordDrawClosedCurve(
  833. const GpRectF * deviceBounds,
  834. GpPen * pen,
  835. const GpPointF * points,
  836. INT count,
  837. REAL tension
  838. ) = 0;
  839. virtual GpStatus
  840. RecordDrawCurve(
  841. const GpRectF * deviceBounds,
  842. GpPen * pen,
  843. const GpPointF * points,
  844. INT count,
  845. REAL tension,
  846. INT offset,
  847. INT numberOfSegments
  848. ) = 0;
  849. virtual GpStatus
  850. RecordDrawBeziers(
  851. const GpRectF * deviceBounds,
  852. GpPen * pen,
  853. const GpPointF * points,
  854. INT count
  855. ) = 0;
  856. virtual GpStatus
  857. RecordDrawImage(
  858. const GpRectF * deviceBounds,
  859. const GpImage * image,
  860. const GpRectF & destRect,
  861. const GpRectF & srcRect,
  862. GpPageUnit srcUnit,
  863. const GpImageAttributes * imageAttributes
  864. ) = 0;
  865. virtual GpStatus
  866. RecordDrawImage(
  867. const GpRectF * deviceBounds,
  868. const GpImage * image,
  869. const GpPointF * destPoints,
  870. INT count,
  871. const GpRectF & srcRect,
  872. GpPageUnit srcUnit,
  873. const GpImageAttributes * imageAttributes
  874. ) = 0;
  875. virtual GpStatus
  876. RecordDrawString(
  877. const GpRectF * deviceBounds,
  878. const WCHAR *string,
  879. INT length,
  880. const GpFont *font,
  881. const RectF *layoutRect,
  882. const GpStringFormat *format,
  883. const GpBrush *brush
  884. ) = 0;
  885. virtual GpStatus
  886. RecordDrawDriverString(
  887. const GpRectF *deviceBounds,
  888. const UINT16 *text,
  889. INT glyphCount,
  890. const GpFont *font,
  891. const GpBrush *brush,
  892. const PointF *positions,
  893. INT flags,
  894. const GpMatrix *matrix
  895. ) = 0;
  896. virtual GpStatus
  897. RecordSave(
  898. INT gstate
  899. ) = 0;
  900. virtual GpStatus
  901. RecordRestore(
  902. INT gstate
  903. ) = 0;
  904. virtual GpStatus
  905. RecordBeginContainer(
  906. const GpRectF & destRect,
  907. const GpRectF & srcRect,
  908. GpPageUnit srcUnit,
  909. INT containerState
  910. ) = 0;
  911. virtual GpStatus
  912. RecordBeginContainer(
  913. INT containerState
  914. ) = 0;
  915. virtual GpStatus
  916. RecordEndContainer(
  917. INT containerState
  918. ) = 0;
  919. virtual GpStatus
  920. RecordSetWorldTransform(
  921. const GpMatrix & matrix
  922. ) = 0;
  923. virtual GpStatus
  924. RecordResetWorldTransform() = 0;
  925. virtual GpStatus
  926. RecordMultiplyWorldTransform(
  927. const GpMatrix & matrix,
  928. GpMatrixOrder order
  929. ) = 0;
  930. virtual GpStatus
  931. RecordTranslateWorldTransform(
  932. REAL dx,
  933. REAL dy,
  934. GpMatrixOrder order
  935. ) = 0;
  936. virtual GpStatus
  937. RecordScaleWorldTransform(
  938. REAL sx,
  939. REAL sy,
  940. GpMatrixOrder order
  941. ) = 0;
  942. virtual GpStatus
  943. RecordRotateWorldTransform(
  944. REAL angle,
  945. GpMatrixOrder order
  946. ) = 0;
  947. virtual GpStatus
  948. RecordSetPageTransform(
  949. GpPageUnit unit,
  950. REAL scale
  951. ) = 0;
  952. virtual GpStatus
  953. RecordResetClip() = 0;
  954. virtual GpStatus
  955. RecordSetClip(
  956. const GpRectF & rect,
  957. CombineMode combineMode
  958. ) = 0;
  959. virtual GpStatus
  960. RecordSetClip(
  961. GpRegion * region,
  962. CombineMode combineMode
  963. ) = 0;
  964. virtual GpStatus
  965. RecordSetClip(
  966. GpPath * path,
  967. CombineMode combineMode,
  968. BOOL isDevicePath
  969. ) = 0;
  970. virtual GpStatus
  971. RecordOffsetClip(
  972. REAL dx,
  973. REAL dy
  974. ) = 0;
  975. virtual GpStatus
  976. RecordGetDC() = 0;
  977. virtual GpStatus
  978. RecordSetAntiAliasMode(
  979. BOOL newMode
  980. ) = 0;
  981. virtual GpStatus
  982. RecordSetTextRenderingHint(
  983. TextRenderingHint newMode
  984. ) = 0;
  985. virtual GpStatus
  986. RecordSetTextContrast(
  987. UINT gammaValue
  988. ) = 0;
  989. virtual GpStatus
  990. RecordSetInterpolationMode(
  991. InterpolationMode newMode
  992. ) = 0;
  993. virtual GpStatus
  994. RecordSetPixelOffsetMode(
  995. PixelOffsetMode newMode
  996. ) = 0;
  997. virtual GpStatus
  998. RecordSetCompositingMode(
  999. GpCompositingMode newMode
  1000. ) = 0;
  1001. virtual GpStatus
  1002. RecordSetCompositingQuality(
  1003. GpCompositingQuality newQuality
  1004. ) = 0;
  1005. virtual GpStatus
  1006. RecordSetRenderingOrigin(
  1007. INT x,
  1008. INT y
  1009. ) = 0;
  1010. virtual GpStatus
  1011. RecordComment(
  1012. UINT sizeData,
  1013. const BYTE * data
  1014. ) = 0;
  1015. virtual VOID EndRecording() = 0;
  1016. };
  1017. class GpMetafile : public GpImage
  1018. {
  1019. friend class GpGraphics; // so graphics can call Play
  1020. friend class MetafileRecorder; // to write Header when recording
  1021. friend class MetafilePlayer;
  1022. friend class GpObject; // for empty constructor
  1023. public:
  1024. // Constructors for playback only
  1025. GpMetafile(HMETAFILE hWmf,
  1026. const WmfPlaceableFileHeader * wmfPlaceableFileHeader,
  1027. BOOL deleteWmf);
  1028. GpMetafile(HENHMETAFILE hEmf, BOOL deleteEmf);
  1029. GpMetafile(const WCHAR* filename,
  1030. const WmfPlaceableFileHeader * wmfPlaceableFileHeader = NULL);
  1031. GpMetafile(IStream* stream); // this requires an extra copy
  1032. // Constructors for recording followed (optionally) by playback
  1033. GpMetafile(
  1034. HDC referenceHdc,
  1035. EmfType type = EmfTypeEmfPlusDual,
  1036. const GpRectF * frameRect = NULL,
  1037. MetafileFrameUnit frameUnit = MetafileFrameUnitGdi,
  1038. const WCHAR * description = NULL
  1039. );
  1040. GpMetafile(
  1041. const WCHAR* fileName,
  1042. HDC referenceHdc,
  1043. EmfType type = EmfTypeEmfPlusDual,
  1044. const GpRectF * frameRect = NULL,
  1045. MetafileFrameUnit frameUnit = MetafileFrameUnitGdi,
  1046. const WCHAR * description = NULL
  1047. );
  1048. GpMetafile( // this requires an extra copy
  1049. IStream* stream,
  1050. HDC referenceHdc,
  1051. EmfType type = EmfTypeEmfPlusDual,
  1052. const GpRectF * frameRect = NULL,
  1053. MetafileFrameUnit frameUnit = MetafileFrameUnitGdi,
  1054. const WCHAR * description = NULL
  1055. );
  1056. // Make a copy of the image object
  1057. virtual GpImage* Clone() const;
  1058. virtual GpImage* CloneColorAdjusted(
  1059. GpRecolor * recolor,
  1060. ColorAdjustType adjustType = ColorAdjustTypeDefault
  1061. ) const;
  1062. // Dispose of the image object
  1063. virtual VOID Dispose();
  1064. // Derive a graphics context to draw into the GpImage object
  1065. virtual GpGraphics* GetGraphicsContext();
  1066. // When deleting the metafile, we have to lock the graphics, so
  1067. // no one can use the graphics while the metafile is being deleted --
  1068. // so we need a private method to get the graphics just for that purpose.
  1069. // Also, when setting the down-level rasterization limit, we have to
  1070. // make sure the graphics is locked as well as the metafile, so we
  1071. // use this method for that too.
  1072. GpGraphics* PrivateAPIForGettingMetafileGraphicsContext() const
  1073. {
  1074. // If they haven't requested the graphics, then we don't need
  1075. // to worry about locking it.
  1076. return (RequestedMetaGraphics) ? MetaGraphics : NULL;
  1077. }
  1078. // Check if the GpImage object is valid
  1079. virtual BOOL IsValid() const
  1080. {
  1081. // If the metafile came from a different version of GDI+, its tag
  1082. // will not match, and it won't be considered valid.
  1083. return ((State >= RecordingMetafileState) &&
  1084. (State <= PlayingMetafileState) &&
  1085. GpImage::IsValid());
  1086. }
  1087. virtual BOOL IsCorrupted() const
  1088. {
  1089. return (State == CorruptedMetafileState);
  1090. }
  1091. VOID
  1092. GetHeader(
  1093. MetafileHeader & header
  1094. ) const
  1095. {
  1096. ASSERT(IsValid());
  1097. header = Header;
  1098. }
  1099. // Is this an EMF or EMF+ file?
  1100. BOOL IsEmfOrEmfPlus() const { return Header.IsEmfOrEmfPlus(); }
  1101. GpStatus GetHemf(HENHMETAFILE * hEmf) const;
  1102. GpStatus PlayRecord(
  1103. EmfPlusRecordType recordType,
  1104. UINT flags,
  1105. UINT dataSize,
  1106. const BYTE * data
  1107. ) const;
  1108. VOID SetThreadId(DWORD threadId) const { ThreadId = threadId; }
  1109. DWORD GetThreadId() const { return ThreadId; }
  1110. // Create a bitmap and play the metafile into it.
  1111. GpBitmap *
  1112. GetBitmap(
  1113. INT width = 0, // 0 means figure use default size
  1114. INT height = 0,
  1115. const GpImageAttributes * imageAttributes = NULL
  1116. );
  1117. ////////////////////////////////////////////////////////////
  1118. // GpObject virtual methods
  1119. ////////////////////////////////////////////////////////////
  1120. virtual UINT GetDataSize() const;
  1121. virtual GpStatus GetData(IStream * stream) const;
  1122. virtual GpStatus SetData(const BYTE * dataBuffer, UINT size);
  1123. virtual GpStatus ColorAdjust(
  1124. GpRecolor * recolor,
  1125. ColorAdjustType adjustType
  1126. );
  1127. ////////////////////////////////////////////////////////////
  1128. // GpImage virtual methods
  1129. ////////////////////////////////////////////////////////////
  1130. // Get metafile resolution
  1131. virtual GpStatus
  1132. GetResolution(
  1133. REAL* xdpi,
  1134. REAL* ydpi
  1135. ) const
  1136. {
  1137. ASSERT(IsValid());
  1138. *xdpi = Header.GetDpiX();
  1139. *ydpi = Header.GetDpiY();
  1140. return Ok;
  1141. }
  1142. // Get metafile physical dimension in 0.01mm units
  1143. virtual GpStatus
  1144. GetPhysicalDimension(
  1145. REAL* width,
  1146. REAL* height
  1147. ) const
  1148. {
  1149. ASSERT(IsValid());
  1150. const MetafileHeader * header = &Header;
  1151. if (header->IsEmfOrEmfPlus())
  1152. {
  1153. // Don't forget to add one Device Unit
  1154. *width = (REAL)(header->EmfHeader.rclFrame.right -
  1155. header->EmfHeader.rclFrame.left) +
  1156. 2540.0f / (header->GetDpiX());
  1157. *height = (REAL)(header->EmfHeader.rclFrame.bottom -
  1158. header->EmfHeader.rclFrame.top) +
  1159. 2540.0f / (header->GetDpiY());
  1160. }
  1161. else
  1162. {
  1163. *width = ((REAL)(header->Width) / (header->GetDpiX())) * 2540.0f;
  1164. *height = ((REAL)(header->Height) / (header->GetDpiY())) * 2540.0f;
  1165. }
  1166. return Ok;
  1167. }
  1168. // Get metafile bounding rectangle in pixels
  1169. virtual GpStatus
  1170. GetBounds(
  1171. GpRectF* rect,
  1172. GpPageUnit* unit
  1173. ) const
  1174. {
  1175. ASSERT(IsValid());
  1176. const MetafileHeader * header = &Header;
  1177. #if 0
  1178. if (header->IsEmfOrEmfPlus())
  1179. {
  1180. rect->X = (REAL)(header->EmfHeader.rclFrame.left) / 2540.0f;
  1181. rect->Y = (REAL)(header->EmfHeader.rclFrame.top) / 2540.0f;
  1182. rect->Width = (REAL)(header->EmfHeader.rclFrame.right -
  1183. header->EmfHeader.rclFrame.left) / 2540.0f;
  1184. rect->Height = (REAL)(header->EmfHeader.rclFrame.bottom -
  1185. header->EmfHeader.rclFrame.top) / 2540.0f;
  1186. }
  1187. else
  1188. {
  1189. rect->X = header->X / header->GetDpiX();
  1190. rect->Width = header->Width / header->GetDpiX();
  1191. rect->Y = header->Y / header->GetDpiY();
  1192. rect->Height = header->Height / header->GetDpiY();
  1193. }
  1194. *unit = UnitInch;
  1195. #else
  1196. rect->X = (REAL)header->X;
  1197. rect->Width = (REAL)header->Width;
  1198. rect->Y = (REAL)header->Y;
  1199. rect->Height = (REAL)header->Height;
  1200. *unit = UnitPixel;
  1201. #endif
  1202. return Ok;
  1203. }
  1204. virtual GpStatus GetImageInfo(ImageInfo* imageInfo) const;
  1205. virtual GpImage* GetThumbnail(UINT thumbWidth, UINT thumbHeight,
  1206. GetThumbnailImageAbort callback, VOID *callbackData)
  1207. {
  1208. if ((thumbWidth == 0) && (thumbHeight == 0))
  1209. {
  1210. thumbWidth = thumbHeight = DEFAULT_THUMBNAIL_SIZE;
  1211. }
  1212. if ((thumbWidth > 0) && (thumbHeight > 0))
  1213. {
  1214. return this->GetBitmap(thumbWidth, thumbHeight);
  1215. }
  1216. return NULL;
  1217. }
  1218. virtual GpStatus GetPalette(ColorPalette *palette, INT size)
  1219. {
  1220. return NotImplemented; // There is no palette support for metafiles
  1221. }
  1222. virtual GpStatus SetPalette(ColorPalette *palette)
  1223. {
  1224. return NotImplemented;
  1225. }
  1226. virtual INT GetPaletteSize() { return 0; }
  1227. // Save images
  1228. // !!!TODO: save functionality?
  1229. virtual GpStatus
  1230. GetEncoderParameterListSize(
  1231. CLSID* clsidEncoder,
  1232. UINT* size
  1233. )
  1234. {
  1235. // Create a new temp bitmap to query
  1236. GpStatus status = OutOfMemory;
  1237. GpBitmap *bitmap = new GpBitmap(1, 1, PixelFormat32bppARGB);
  1238. if (bitmap != NULL)
  1239. {
  1240. if (bitmap->IsValid())
  1241. {
  1242. status = bitmap->GetEncoderParameterListSize(clsidEncoder, size);
  1243. }
  1244. bitmap->Dispose();
  1245. }
  1246. return status;
  1247. }
  1248. virtual GpStatus
  1249. GetEncoderParameterList(
  1250. CLSID* clsidEncoder,
  1251. UINT size,
  1252. EncoderParameters* pBuffer
  1253. )
  1254. {
  1255. GpStatus status = OutOfMemory;
  1256. GpBitmap *bitmap = new GpBitmap(1, 1, PixelFormat32bppARGB);
  1257. if (bitmap != NULL)
  1258. {
  1259. if (bitmap->IsValid())
  1260. {
  1261. status = bitmap->GetEncoderParameterList(clsidEncoder, size, pBuffer);
  1262. }
  1263. bitmap->Dispose();
  1264. }
  1265. return status;
  1266. }
  1267. virtual GpStatus
  1268. SaveToStream(
  1269. IStream* stream,
  1270. CLSID* clsidEncoder,
  1271. EncoderParameters* encoderParams
  1272. )
  1273. {
  1274. GpStatus status = GenericError;
  1275. GpBitmap *bitmap = GetBitmap();
  1276. if (bitmap != NULL)
  1277. {
  1278. status = bitmap->SaveToStream(stream, clsidEncoder, encoderParams);
  1279. bitmap->Dispose();
  1280. }
  1281. return status;
  1282. }
  1283. virtual GpStatus
  1284. SaveToFile(
  1285. const WCHAR* filename,
  1286. CLSID* clsidEncoder,
  1287. EncoderParameters* encoderParams
  1288. )
  1289. {
  1290. GpStatus status = GenericError;
  1291. GpBitmap *bitmap = GetBitmap();
  1292. if (bitmap != NULL)
  1293. {
  1294. status = bitmap->SaveToFile(filename, clsidEncoder, encoderParams);
  1295. bitmap->Dispose();
  1296. }
  1297. return status;
  1298. }
  1299. GpStatus
  1300. SaveAdd(
  1301. const EncoderParameters* encoderParams
  1302. )
  1303. {
  1304. return NotImplemented;
  1305. }
  1306. GpStatus
  1307. SaveAdd(
  1308. GpImage* newBits,
  1309. const EncoderParameters* encoderParams
  1310. )
  1311. {
  1312. return NotImplemented;
  1313. }
  1314. // !!!TODO: what do I do with the dimensionID?
  1315. virtual GpStatus GetFrameCount(const GUID* dimensionID, UINT* count) const
  1316. {
  1317. if (count != NULL)
  1318. {
  1319. *count = 1;
  1320. return Ok;
  1321. }
  1322. return InvalidParameter;
  1323. }
  1324. virtual GpStatus GetFrameDimensionsCount(OUT UINT* count) const
  1325. {
  1326. if (count != NULL)
  1327. {
  1328. *count = 1;
  1329. return Ok;
  1330. }
  1331. return InvalidParameter;
  1332. }
  1333. virtual GpStatus GetFrameDimensionsList(OUT GUID* dimensionIDs,
  1334. IN UINT count) const
  1335. {
  1336. // Note: the "count" has to be 1
  1337. if ((count == 1) && (dimensionIDs != NULL))
  1338. {
  1339. dimensionIDs[0] = FRAMEDIM_PAGE;
  1340. return Ok;
  1341. }
  1342. return InvalidParameter;
  1343. }
  1344. virtual GpStatus SelectActiveFrame(const GUID* dimensionID, UINT index)
  1345. {
  1346. // There is only 1 frame in a metafile, so we always succeed
  1347. return Ok;
  1348. }
  1349. virtual GpStatus RotateFlip(RotateFlipType rfType)
  1350. {
  1351. return NotImplemented;
  1352. }
  1353. virtual GpStatus GetPropertyCount(UINT* numOfProperty)
  1354. {
  1355. if (numOfProperty != NULL)
  1356. {
  1357. *numOfProperty = 0;
  1358. return Ok;
  1359. }
  1360. return InvalidParameter;
  1361. }
  1362. virtual GpStatus GetPropertyIdList(UINT numOfProperty, PROPID* list)
  1363. {
  1364. if (list != NULL)
  1365. {
  1366. return NotImplemented;
  1367. }
  1368. return InvalidParameter;
  1369. }
  1370. virtual GpStatus GetPropertyItemSize(PROPID propId, UINT* size)
  1371. {
  1372. if (size != NULL)
  1373. {
  1374. return NotImplemented;
  1375. }
  1376. return InvalidParameter;
  1377. }
  1378. virtual GpStatus GetPropertyItem(PROPID propId,UINT propSize, PropertyItem* buffer)
  1379. {
  1380. if (buffer != NULL)
  1381. {
  1382. return NotImplemented;
  1383. }
  1384. return InvalidParameter;
  1385. }
  1386. virtual GpStatus GetPropertySize(UINT* totalBufferSize, UINT* numProperties)
  1387. {
  1388. if ((totalBufferSize != NULL) && (numProperties != NULL))
  1389. {
  1390. return NotImplemented;
  1391. }
  1392. return InvalidParameter;
  1393. }
  1394. virtual GpStatus GetAllPropertyItems(UINT totalBufferSize, UINT numProperties,
  1395. PropertyItem* allItems)
  1396. {
  1397. if (allItems != NULL)
  1398. {
  1399. return NotImplemented;
  1400. }
  1401. return InvalidParameter;
  1402. }
  1403. virtual GpStatus RemovePropertyItem(PROPID propId)
  1404. {
  1405. return NotImplemented;
  1406. }
  1407. virtual GpStatus SetPropertyItem(PropertyItem* item)
  1408. {
  1409. return NotImplemented;
  1410. }
  1411. GpStatus
  1412. SetDownLevelRasterizationLimit(
  1413. UINT metafileRasterizationLimitDpi
  1414. );
  1415. GpStatus
  1416. GetDownLevelRasterizationLimit(
  1417. UINT * metafileRasterizationLimitDpi
  1418. ) const;
  1419. protected:
  1420. enum MetafileState
  1421. {
  1422. InvalidMetafileState,
  1423. CorruptedMetafileState,
  1424. RecordingMetafileState,
  1425. DoneRecordingMetafileState,
  1426. ReadyToPlayMetafileState,
  1427. PlayingMetafileState,
  1428. };
  1429. MetafileHeader Header;
  1430. mutable DWORD ThreadId; // for syncing enumeration
  1431. mutable MetafileState State;
  1432. mutable HENHMETAFILE Hemf; // for playing metafiles
  1433. WCHAR * Filename;
  1434. IStream * Stream;
  1435. GpGraphics * MetaGraphics; // for recording to metafile
  1436. mutable MetafilePlayer * Player; // for playing the metafile
  1437. INT MaxStackSize;
  1438. BOOL DeleteHemf;
  1439. BOOL RequestedMetaGraphics;
  1440. // Dummy constructors and destructors to prevent
  1441. // apps from directly using new and delete operators
  1442. // on GpImage objects.
  1443. GpMetafile() : GpImage(ImageTypeMetafile) { /* used by object factory */ InitDefaults(); }
  1444. ~GpMetafile();
  1445. VOID InitDefaults();
  1446. VOID CleanUp();
  1447. BOOL
  1448. InitForRecording(
  1449. HDC referenceHdc,
  1450. EmfType type,
  1451. const GpRectF * frameRect, // can be NULL
  1452. MetafileFrameUnit frameUnit, // if NULL frameRect, doesn't matter
  1453. const WCHAR * description // can be NULL
  1454. );
  1455. GpStatus
  1456. PrepareToPlay(
  1457. GpGraphics * g,
  1458. GpRecolor * recolor,
  1459. ColorAdjustType adjustType,
  1460. EnumerateMetafileProc enumerateCallback,
  1461. VOID * callbackData,
  1462. DrawImageAbort drawImageCallback,
  1463. VOID* drawImageCallbackData
  1464. ) const;
  1465. GpStatus
  1466. EnumerateForPlayback(
  1467. const RectF & destRect,
  1468. const RectF & srcRect,
  1469. Unit srcUnit,
  1470. GpGraphics * g,
  1471. EnumerateMetafileProc callback, // if null, just play the metafile
  1472. VOID * callbackData,
  1473. GpRecolor * recolor = NULL,
  1474. ColorAdjustType adjustType = ColorAdjustTypeDefault,
  1475. DrawImageAbort drawImageCallback = NULL,
  1476. VOID* drawImageCallbackData = NULL
  1477. ) const;
  1478. // Play is only to be called by GpGraphics::DrawImage()
  1479. GpStatus
  1480. Play(
  1481. const GpRectF& destRect,
  1482. const GpRectF& srcRect,
  1483. GpPageUnit srcUnit,
  1484. GpGraphics * graphics,
  1485. GpRecolor * recolor = NULL,
  1486. ColorAdjustType adjustType = ColorAdjustTypeDefault,
  1487. DrawImageAbort drawImageCallback = NULL,
  1488. VOID* drawImageCallbackData = NULL
  1489. ) const
  1490. {
  1491. return EnumerateForPlayback(
  1492. destRect,
  1493. srcRect,
  1494. srcUnit,
  1495. graphics,
  1496. NULL,
  1497. NULL,
  1498. recolor,
  1499. adjustType,
  1500. drawImageCallback,
  1501. drawImageCallbackData
  1502. );
  1503. }
  1504. VOID
  1505. InitWmf(
  1506. HMETAFILE hWmf,
  1507. const WmfPlaceableFileHeader * wmfPlaceableFileHeader,
  1508. BOOL deleteWmf
  1509. );
  1510. VOID
  1511. InitEmf(
  1512. HENHMETAFILE hEmf,
  1513. BOOL deleteEmf
  1514. );
  1515. VOID
  1516. InitStream(
  1517. IStream* stream,
  1518. BOOL tryWmfOnly = FALSE
  1519. );
  1520. };
  1521. HENHMETAFILE
  1522. GetEmf(
  1523. const WCHAR * fileName,
  1524. MetafileType type
  1525. );
  1526. // GillesK 05/12/2000
  1527. // Data types needed for WMF to EMF conversion.
  1528. #pragma pack(2)
  1529. typedef struct _META_ESCAPE_ENHANCED_METAFILE {
  1530. DWORD rdSize; // Size of the record in words
  1531. WORD rdFunction; // META_ESCAPE
  1532. WORD wEscape; // MFCOMMENT
  1533. WORD wCount; // Size of the following data + emf in bytes
  1534. DWORD ident; // MFCOMMENT_IDENTIFIER
  1535. DWORD iComment; // MFCOMMENT_ENHANCED_METAFILE
  1536. DWORD nVersion; // Enhanced metafile version 0x10000
  1537. WORD wChecksum; // Checksum - used by 1st record only
  1538. DWORD fFlags; // Compression etc - used by 1st record only
  1539. DWORD nCommentRecords; // Number of records making up the emf
  1540. DWORD cbCurrent; // Size of emf data in this record in bytes
  1541. DWORD cbRemainder; // Size of remainder in following records
  1542. DWORD cbEnhMetaFile; // Size of enhanced metafile in bytes
  1543. // The enhanced metafile data follows here
  1544. } META_ESCAPE_ENHANCED_METAFILE;
  1545. typedef META_ESCAPE_ENHANCED_METAFILE UNALIGNED *PMETA_ESCAPE_ENHANCED_METAFILE;
  1546. #pragma pack()
  1547. // Macro to check that it is a meta_escape embedded enhanced metafile record.
  1548. inline BOOL IsMetaEscapeEnhancedMetafile(
  1549. PMETA_ESCAPE_ENHANCED_METAFILE pmfeEnhMF
  1550. )
  1551. {
  1552. return ((pmfeEnhMF)->rdFunction == META_ESCAPE
  1553. && (pmfeEnhMF)->rdSize > sizeof(META_ESCAPE_ENHANCED_METAFILE) / 2
  1554. && (pmfeEnhMF)->wEscape == MFCOMMENT
  1555. && (pmfeEnhMF)->ident == MFCOMMENT_IDENTIFIER
  1556. && (pmfeEnhMF)->iComment == MFCOMMENT_ENHANCED_METAFILE) ;
  1557. }
  1558. // Macro to check the checksum of an EMF file
  1559. inline WORD GetWordCheckSum(UINT cbData, PWORD pwData)
  1560. {
  1561. WORD wCheckSum = 0;
  1562. UINT cwData = cbData / sizeof(WORD);
  1563. ASSERTMSG(!(cbData%sizeof(WORD)), ("GetWordCheckSum data not WORD multiple"));
  1564. ASSERTMSG(!((ULONG_PTR)pwData%sizeof(WORD)), ("GetWordCheckSum data not WORD aligned"));
  1565. while (cwData--)
  1566. wCheckSum += *pwData++;
  1567. return(wCheckSum);
  1568. }
  1569. extern "C"
  1570. UINT ConvertEmfToPlaceableWmf
  1571. ( HENHMETAFILE hemf,
  1572. UINT cbData16,
  1573. LPBYTE pData16,
  1574. INT iMapMode,
  1575. INT eFlags );
  1576. #endif // !_METAFILE_HPP