Source code of Windows XP (NT5)
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.

2311 lines
51 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: mf.cpp
  7. //
  8. // Contents: Implentation of hte metafile picture object
  9. //
  10. // Classes: CMfObject
  11. //
  12. // Functions: OleIsDcMeta
  13. //
  14. // History: dd-mmm-yy Author Comment
  15. // 01-Feb-95 t-ScottH added Dump method to CMfObject
  16. // added DumpCMfObject API
  17. // initialize m_pfnContinue in constructor
  18. // 25-Jan-94 alexgo first pass at converting to Cairo-style
  19. // memory allocations.
  20. // 11-Jan-93 alexgo added VDATEHEAP macros to every
  21. // function and method
  22. // 31-Dec-93 ErikGav chicago port
  23. // 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
  24. // in CallbackFuncForDraw
  25. // 07-Dec-93 ChrisWe made default params to StSetSize explicit
  26. // 07-Dec-93 alexgo merged 16bit RC9 changes
  27. // 29-Nov-93 alexgo 32bit port
  28. // 04-Jun-93 srinik support for demand loading and discarding
  29. // of caches
  30. // 13-Mar-92 srinik created
  31. //
  32. //--------------------------------------------------------------------------
  33. #include <le2int.h>
  34. #include <qd2gdi.h>
  35. #include "mf.h"
  36. #ifdef _DEBUG
  37. #include <dbgdump.h>
  38. #endif // _DEBUG
  39. #define M_HPRES() (m_hPres ? m_hPres : LoadHPRES())
  40. /*
  41. * IMPLEMENTATION of CMfObject
  42. *
  43. */
  44. //+-------------------------------------------------------------------------
  45. //
  46. // Member: CMfObject::CMfObject
  47. //
  48. // Synopsis: constructor for the metafile object
  49. //
  50. // Effects:
  51. //
  52. // Arguments: [pCacheNode] -- pointer to the cache node for this object
  53. // [dwAspect] -- drawing aspect for the object
  54. // [fConvert] -- specifies whether to convert from Mac
  55. // QuickDraw format
  56. //
  57. // Requires:
  58. //
  59. // Returns:
  60. //
  61. // Signals:
  62. //
  63. // Modifies:
  64. //
  65. // Derivation:
  66. //
  67. // Algorithm:
  68. //
  69. // History: dd-mmm-yy Author Comment
  70. // 13-Feb-95 t-ScottH initialize m_pfnContinue
  71. // 29-Nov-93 alexgo 32bit port
  72. //
  73. // Notes:
  74. //
  75. //--------------------------------------------------------------------------
  76. CMfObject::CMfObject(LPCACHENODE pCacheNode, DWORD dwAspect, BOOL fConvert)
  77. {
  78. VDATEHEAP();
  79. m_ulRefs = 1;
  80. m_hPres = NULL;
  81. m_dwSize = 0;
  82. m_dwAspect = dwAspect;
  83. m_pCacheNode = pCacheNode;
  84. m_dwContinue = 0;
  85. m_pfnContinue = NULL;
  86. m_lWidth = 0;
  87. m_lHeight = 0;
  88. m_fConvert = fConvert;
  89. m_pMetaInfo = NULL;
  90. m_pCurMdc = NULL;
  91. m_fMetaDC = FALSE;
  92. m_nRecord = 0;
  93. m_error = NOERROR;
  94. m_pColorSet = NULL;
  95. m_hPalDCOriginal = NULL;
  96. m_hPalLast = NULL;
  97. }
  98. //+-------------------------------------------------------------------------
  99. //
  100. // Member: CMfObject::~CMfObject
  101. //
  102. // Synopsis: Destroys a metafile presentation object
  103. //
  104. // Effects:
  105. //
  106. // Arguments: void
  107. //
  108. // Requires:
  109. //
  110. // Returns: void
  111. //
  112. // Signals:
  113. //
  114. // Modifies:
  115. //
  116. // Derivation:
  117. //
  118. // Algorithm:
  119. //
  120. // History: dd-mmm-yy Author Comment
  121. // 29-Nov-93 alexgo 32bit port
  122. //
  123. // Notes:
  124. //
  125. //--------------------------------------------------------------------------
  126. CMfObject::~CMfObject (void)
  127. {
  128. VDATEHEAP();
  129. CMfObject::DiscardHPRES();
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Member: CMfObject::QueryInterface
  134. //
  135. // Synopsis: returns supported interfaces
  136. //
  137. // Effects:
  138. //
  139. // Arguments: [iid] -- the requested interface ID
  140. // [ppvObj] -- where to put the interface pointer
  141. //
  142. // Requires:
  143. //
  144. // Returns: NOERROR, E_NOINTERFACE
  145. //
  146. // Signals:
  147. //
  148. // Modifies:
  149. //
  150. // Derivation: IOlePresObj
  151. //
  152. // Algorithm:
  153. //
  154. // History: dd-mmm-yy Author Comment
  155. // 29-Nov-93 alexgo 32bit port
  156. //
  157. // Notes:
  158. //
  159. //--------------------------------------------------------------------------
  160. STDMETHODIMP CMfObject::QueryInterface (REFIID iid, void FAR* FAR* ppvObj)
  161. {
  162. VDATEHEAP();
  163. if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
  164. {
  165. *ppvObj = this;
  166. AddRef();
  167. return NOERROR;
  168. }
  169. else
  170. {
  171. *ppvObj = NULL;
  172. return E_NOINTERFACE;
  173. }
  174. }
  175. //+-------------------------------------------------------------------------
  176. //
  177. // Member: CMfObject::AddRef
  178. //
  179. // Synopsis: Increments the reference count
  180. //
  181. // Effects:
  182. //
  183. // Arguments: void
  184. //
  185. // Requires:
  186. //
  187. // Returns: ULONG -- the new reference count
  188. //
  189. // Signals:
  190. //
  191. // Modifies:
  192. //
  193. // Derivation: IOlePresObj
  194. //
  195. // Algorithm:
  196. //
  197. // History: dd-mmm-yy Author Comment
  198. // 29-Nov-93 alexgo 32bit port
  199. //
  200. // Notes:
  201. //
  202. //--------------------------------------------------------------------------
  203. STDMETHODIMP_(ULONG) CMfObject::AddRef(void)
  204. {
  205. VDATEHEAP();
  206. return ++m_ulRefs;
  207. }
  208. //+-------------------------------------------------------------------------
  209. //
  210. // Member: CMfObject::Release
  211. //
  212. // Synopsis: decrements the reference count
  213. //
  214. // Effects: deletes the object once the ref count goes to zero
  215. //
  216. // Arguments: void
  217. //
  218. // Requires:
  219. //
  220. // Returns: ULONG -- the new reference count
  221. //
  222. // Signals:
  223. //
  224. // Modifies:
  225. //
  226. // Derivation: IOlePresObj
  227. //
  228. // Algorithm:
  229. //
  230. // History: dd-mmm-yy Author Comment
  231. // 29-Nov-93 alexgo 32bit port
  232. //
  233. // Notes:
  234. //
  235. //--------------------------------------------------------------------------
  236. STDMETHODIMP_(ULONG) CMfObject::Release(void)
  237. {
  238. VDATEHEAP();
  239. if (--m_ulRefs == 0) {
  240. delete this;
  241. return 0;
  242. }
  243. return m_ulRefs;
  244. }
  245. //+-------------------------------------------------------------------------
  246. //
  247. // Member: CMfObject::GetData
  248. //
  249. // Synopsis: Retrieves data in the specified format from the object
  250. //
  251. // Effects:
  252. //
  253. // Arguments: [pformatetcIn] -- the requested data format
  254. // [pmedium] -- where to put the data
  255. //
  256. // Requires:
  257. //
  258. // Returns: HRESULT
  259. //
  260. // Signals:
  261. //
  262. // Modifies:
  263. //
  264. // Derivation: IOlePresObject
  265. //
  266. // Algorithm: Does error checking and then gets a copy of the metafilepict
  267. //
  268. // History: dd-mmm-yy Author Comment
  269. // 29-Nov-93 alexgo 32bit port
  270. //
  271. // Notes:
  272. //
  273. //--------------------------------------------------------------------------
  274. STDMETHODIMP CMfObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  275. {
  276. VDATEHEAP();
  277. SCODE sc;
  278. // null out in case of error
  279. pmedium->tymed = (DWORD) TYMED_NULL;
  280. pmedium->pUnkForRelease = NULL;
  281. if (!(pformatetcIn->tymed & (DWORD) TYMED_MFPICT))
  282. {
  283. sc = DV_E_TYMED;
  284. }
  285. else if (pformatetcIn->cfFormat != CF_METAFILEPICT)
  286. {
  287. sc = DV_E_CLIPFORMAT;
  288. }
  289. else if (IsBlank())
  290. {
  291. sc = OLE_E_BLANK;
  292. }
  293. // here we actually try to get the data
  294. else if (NULL == (pmedium->hGlobal = GetHmfp()))
  295. {
  296. sc = E_OUTOFMEMORY;
  297. }
  298. else {
  299. pmedium->tymed = (DWORD) TYMED_MFPICT;
  300. return NOERROR;
  301. }
  302. return ResultFromScode(sc);
  303. }
  304. //+-------------------------------------------------------------------------
  305. //
  306. // Member: CMfObject::GetDataHere
  307. //
  308. // Synopsis: Retrieves data of the specified format into the specified
  309. // medium
  310. //
  311. // Effects:
  312. //
  313. // Arguments: [pformatetcIn] -- the requested data format
  314. // [pmedium] -- where to put the data
  315. //
  316. // Requires:
  317. //
  318. // Returns: HRESULT
  319. //
  320. // Signals:
  321. //
  322. // Modifies:
  323. //
  324. // Derivation: IOlePresObj
  325. //
  326. // Algorithm: Does error checking and then copies the metafile into a
  327. // stream.
  328. //
  329. // History: dd-mmm-yy Author Comment
  330. // 29-Nov-93 alexgo 32bit port
  331. //
  332. // Notes:
  333. //
  334. //--------------------------------------------------------------------------
  335. STDMETHODIMP CMfObject::GetDataHere
  336. (LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
  337. {
  338. VDATEHEAP();
  339. SCODE sc;
  340. if (pformatetcIn->cfFormat != CF_METAFILEPICT)
  341. {
  342. sc = DV_E_CLIPFORMAT;
  343. }
  344. else if (pmedium->tymed != (DWORD) TYMED_ISTREAM)
  345. {
  346. sc = DV_E_TYMED;
  347. }
  348. else if (pmedium->pstm == NULL)
  349. {
  350. sc = E_INVALIDARG;
  351. }
  352. else if (IsBlank())
  353. {
  354. sc = OLE_E_BLANK;
  355. }
  356. else
  357. {
  358. HANDLE hpres = M_HPRES();
  359. return UtHMFToPlaceableMFStm(&hpres, m_dwSize, m_lWidth,
  360. m_lHeight, pmedium->pstm);
  361. }
  362. return ResultFromScode(sc);
  363. }
  364. //+-------------------------------------------------------------------------
  365. //
  366. // Member: CMfObject::SetDataWDO
  367. //
  368. // Synopsis: Stores a metafile in this object
  369. //
  370. // Effects:
  371. //
  372. // Arguments: [pformatetc] -- format of the data coming in
  373. // [pmedium] -- the new metafile (data)
  374. // [fRelease] -- if true, then we'll release the [pmedium]
  375. // [pDataObj] -- unused for MF objects
  376. //
  377. // Requires:
  378. //
  379. // Returns: HRESULT
  380. //
  381. // Signals:
  382. //
  383. // Modifies:
  384. //
  385. // Derivation: IOlePresObj
  386. //
  387. // Algorithm: does error checking and then stores the new data.
  388. //
  389. // History: dd-mmm-yy Author Comment
  390. // 29-Nov-93 alexgo 32bit port
  391. //
  392. // Notes:
  393. //
  394. //--------------------------------------------------------------------------
  395. STDMETHODIMP CMfObject::SetDataWDO (LPFORMATETC pformatetc,
  396. STGMEDIUM * pmedium,
  397. BOOL fRelease,
  398. IDataObject * /* UNUSED */)
  399. {
  400. VDATEHEAP();
  401. HRESULT error;
  402. BOOL fTakeData = FALSE;
  403. if (pformatetc->cfFormat != CF_METAFILEPICT)
  404. {
  405. return ResultFromScode(DV_E_CLIPFORMAT);
  406. }
  407. if (pmedium->tymed != (DWORD) TYMED_MFPICT)
  408. {
  409. return ResultFromScode(DV_E_TYMED);
  410. }
  411. if ((pmedium->pUnkForRelease == NULL) && fRelease)
  412. {
  413. // we can take the ownership of the data
  414. fTakeData = TRUE;
  415. }
  416. // ChangeData will keep the data if fRelease is TRUE, else it copies
  417. error = ChangeData (pmedium->hGlobal, fTakeData);
  418. if (fTakeData)
  419. {
  420. pmedium->tymed = (DWORD) TYMED_NULL;
  421. }
  422. else if (fRelease)
  423. {
  424. ReleaseStgMedium(pmedium);
  425. }
  426. return error;
  427. }
  428. //+-------------------------------------------------------------------------
  429. //
  430. // Member: CMfObject::GetHmfp (internal)
  431. //
  432. // Synopsis: Gets a copy of the stored metafile presentation
  433. //
  434. // Effects:
  435. //
  436. // Arguments: void
  437. //
  438. // Requires:
  439. //
  440. // Returns: HANDLE
  441. //
  442. // Signals:
  443. //
  444. // Modifies:
  445. //
  446. // Derivation: IOlePresObj
  447. //
  448. // Algorithm:
  449. //
  450. // History: dd-mmm-yy Author Comment
  451. // 29-Nov-93 alexgo 32bit port
  452. //
  453. // Notes:
  454. //
  455. //--------------------------------------------------------------------------
  456. INTERNAL_(HANDLE) CMfObject::GetHmfp (void)
  457. {
  458. VDATEHEAP();
  459. return UtGetHMFPICT((HMETAFILE)GetCopyOfHPRES(), TRUE, m_lWidth,
  460. m_lHeight);
  461. }
  462. //+-------------------------------------------------------------------------
  463. //
  464. // Member: CMfObject::ChangeData (internal)
  465. //
  466. // Synopsis: Swaps the stored metafile presentation
  467. //
  468. // Effects:
  469. //
  470. // Arguments: [hMfp] -- the new metafile
  471. // [fDelete] -- if TRUE, then delete [hMfp]
  472. //
  473. // Requires:
  474. //
  475. // Returns: HRESULT
  476. //
  477. // Signals:
  478. //
  479. // Modifies:
  480. //
  481. // Derivation:
  482. //
  483. // Algorithm:
  484. //
  485. // History: dd-mmm-yy Author Comment
  486. // 29-Nov-93 alexgo 32bit port, fixed GlobalUnlock bug
  487. // Notes:
  488. //
  489. // If the routine fails then the object will be left with it's old data.
  490. // If fDelete is TRUE, then hMeta, and the hMF it contains will be deleted
  491. // whether the routine is successful or not.
  492. //
  493. //--------------------------------------------------------------------------
  494. INTERNAL CMfObject::ChangeData (HANDLE hMfp, BOOL fDelete)
  495. {
  496. VDATEHEAP();
  497. HANDLE hNewMF;
  498. LPMETAFILEPICT lpMetaPict;
  499. DWORD dwSize;
  500. HRESULT error = NOERROR;
  501. if ((lpMetaPict = (LPMETAFILEPICT) GlobalLock (hMfp)) == NULL)
  502. {
  503. if (fDelete)
  504. {
  505. LEVERIFY( NULL == GlobalFree (hMfp) );
  506. }
  507. return E_OUTOFMEMORY;
  508. }
  509. if (!fDelete) {
  510. if (NULL == (hNewMF = CopyMetaFile (lpMetaPict->hMF, NULL)))
  511. {
  512. return E_OUTOFMEMORY;
  513. }
  514. }
  515. else
  516. {
  517. hNewMF = lpMetaPict->hMF;
  518. }
  519. if (lpMetaPict->mm != MM_ANISOTROPIC)
  520. {
  521. error = ResultFromScode(E_UNSPEC);
  522. LEWARN( error, "Mapping mode is not anisotropic" );
  523. }
  524. else if (0 == (dwSize = MfGetSize (&hNewMF)))
  525. {
  526. error = ResultFromScode(OLE_E_BLANK);
  527. }
  528. else
  529. {
  530. if (m_hPres)
  531. {
  532. LEVERIFY( DeleteMetaFile (m_hPres) );
  533. }
  534. m_hPres = (HMETAFILE)hNewMF;
  535. m_dwSize = dwSize;
  536. m_lWidth = lpMetaPict->xExt;
  537. m_lHeight = lpMetaPict->yExt;
  538. }
  539. GlobalUnlock (hMfp);
  540. if (error != NOERROR)
  541. {
  542. LEVERIFY( DeleteMetaFile ((HMETAFILE)hNewMF) );
  543. }
  544. if (fDelete)
  545. {
  546. LEVERIFY( NULL == GlobalFree (hMfp) );
  547. }
  548. return error;
  549. }
  550. //+-------------------------------------------------------------------------
  551. //
  552. // Member: CMfObject::Draw
  553. //
  554. // Synopsis: Draws the stored presentation
  555. //
  556. // Effects:
  557. //
  558. // Arguments: [pvAspect] -- the drawing aspect
  559. // [hicTargetDev] -- the target device
  560. // [hdcDraw] -- hdc to draw into
  561. // [lprcBounds] -- bounding rectangle to draw into
  562. // [lprcWBounds] -- bounding rectangle for the metafile
  563. // [pfnContinue] -- function to call while drawing
  564. // [dwContinue] -- parameter to [pfnContinue]
  565. //
  566. // Requires:
  567. //
  568. // Returns: HRESULT
  569. //
  570. // Signals:
  571. //
  572. // Modifies:
  573. //
  574. // Derivation: IOlePresObj
  575. //
  576. // Algorithm: Sets the viewport and metafile boundaries, then plays
  577. // the metafile
  578. //
  579. // History: dd-mmm-yy Author Comment
  580. // 29-Nov-93 alexgo 32bit port
  581. //
  582. // Notes:
  583. //
  584. //--------------------------------------------------------------------------
  585. STDMETHODIMP CMfObject::Draw (void * /* UNUSED pvAspect */,
  586. HDC /* UNUSED hicTargetDev */,
  587. HDC hdcDraw,
  588. LPCRECTL lprcBounds,
  589. LPCRECTL lprcWBounds,
  590. BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
  591. ULONG_PTR dwContinue)
  592. {
  593. VDATEHEAP();
  594. m_error = NOERROR;
  595. int iRgn;
  596. int iOldDc;
  597. RECT rect;
  598. LPRECT lpRrc = (LPRECT) &rect;
  599. Assert(lprcBounds);
  600. if (!M_HPRES())
  601. {
  602. return ResultFromScode(OLE_E_BLANK);
  603. }
  604. rect.left = lprcBounds->left;
  605. rect.right = lprcBounds->right;
  606. rect.top = lprcBounds->top;
  607. rect.bottom = lprcBounds->bottom;
  608. iOldDc = SaveDC (hdcDraw);
  609. if (0 == iOldDc)
  610. {
  611. return ResultFromScode(E_OUTOFMEMORY);
  612. }
  613. m_nRecord = RECORD_COUNT;
  614. m_fMetaDC = OleIsDcMeta (hdcDraw);
  615. if (!m_fMetaDC) {
  616. iRgn = IntersectClipRect (hdcDraw, lpRrc->left, lpRrc->top,
  617. lpRrc->right, lpRrc->bottom);
  618. Assert( ERROR != iRgn );
  619. if (iRgn == NULLREGION) {
  620. goto errRtn;
  621. }
  622. if (iRgn == ERROR) {
  623. m_error = ResultFromScode(E_UNSPEC);
  624. goto errRtn;
  625. }
  626. // Because the LPToDP conversion takes the current world
  627. // transform into consideration, we must check to see
  628. // if we are in a GM_ADVANCED device context. If so,
  629. // save its state and reset to GM_COMPATIBLE while we
  630. // convert LP to DP (then restore the DC).
  631. if (GM_ADVANCED == GetGraphicsMode(hdcDraw))
  632. {
  633. HDC screendc = GetDC(NULL);
  634. RECT rect = {0, 0, 1000, 1000};
  635. HDC emfdc = CreateEnhMetaFile(screendc, NULL, &rect, NULL);
  636. PlayMetaFile( emfdc, m_hPres);
  637. HENHMETAFILE hemf = CloseEnhMetaFile(emfdc);
  638. PlayEnhMetaFile( hdcDraw, hemf, lpRrc);
  639. DeleteEnhMetaFile( hemf );
  640. goto errRtn;
  641. }
  642. else
  643. {
  644. LEVERIFY( LPtoDP (hdcDraw, (LPPOINT) lpRrc, 2) );
  645. }
  646. LEVERIFY( 0 != SetMapMode (hdcDraw, MM_ANISOTROPIC) );
  647. LEVERIFY( SetViewportOrg (hdcDraw, lpRrc->left, lpRrc->top) );
  648. LEVERIFY( SetViewportExt (hdcDraw, lpRrc->right - lpRrc->left,
  649. lpRrc->bottom - lpRrc->top) );
  650. }
  651. else
  652. {
  653. iOldDc = -1;
  654. if (!lprcWBounds)
  655. {
  656. return ResultFromScode(E_DRAW);
  657. }
  658. m_pMetaInfo = (LPMETAINFO)PrivMemAlloc(sizeof(METAINFO));
  659. if( !m_pMetaInfo )
  660. {
  661. AssertSz(m_pMetaInfo, "Memory allocation failed");
  662. m_error = ResultFromScode(E_OUTOFMEMORY);
  663. goto errRtn;
  664. }
  665. m_pCurMdc = (LPMETADC) (m_pMetaInfo);
  666. m_pMetaInfo->xwo = lprcWBounds->left;
  667. m_pMetaInfo->ywo = lprcWBounds->top;
  668. m_pMetaInfo->xwe = lprcWBounds->right;
  669. m_pMetaInfo->ywe = lprcWBounds->bottom;
  670. m_pMetaInfo->xro = lpRrc->left - lprcWBounds->left;
  671. m_pMetaInfo->yro = lpRrc->top - lprcWBounds->top;
  672. m_pCurMdc->xre = lpRrc->right - lpRrc->left;
  673. m_pCurMdc->yre = lpRrc->bottom - lpRrc->top;
  674. m_pCurMdc->xMwo = 0;
  675. m_pCurMdc->yMwo = 0;
  676. m_pCurMdc->xMwe = 0;
  677. m_pCurMdc->yMwe = 0;
  678. m_pCurMdc->pNext = NULL;
  679. }
  680. m_pfnContinue = pfnContinue;
  681. m_dwContinue = dwContinue;
  682. // m_hPalDCOriginal and m_hPalLast are used to clean up any
  683. // palettes that are selected into a DC during the metafile
  684. // enumeration.
  685. m_hPalDCOriginal = NULL;
  686. m_hPalLast = NULL;
  687. LEVERIFY( EnumMetaFile(hdcDraw, m_hPres, MfCallbackFuncForDraw,
  688. (LPARAM) this) );
  689. if (m_fMetaDC)
  690. {
  691. CleanStack();
  692. }
  693. // if m_hPalLast exists at this point, we have duped a palette
  694. // and it needs to be freed.
  695. if (m_hPalLast)
  696. {
  697. HPALETTE hPalTemp;
  698. // when calling SelectPalette on a Metafile DC, the old
  699. // palette is not returned. We need to select another
  700. // palette into the metafile DC so DeleteObject can be
  701. // called. To do this, we will use the stock palette.
  702. if (m_fMetaDC)
  703. {
  704. hPalTemp = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  705. }
  706. else
  707. {
  708. // Get the original palette selected in the DC.
  709. hPalTemp = m_hPalDCOriginal;
  710. }
  711. // hPalTemp could be NULL...
  712. if (hPalTemp)
  713. {
  714. // Should this palette be selected in the foreground?
  715. // [Probably not, this code is well-tested]
  716. SelectPalette(hdcDraw, hPalTemp, TRUE);
  717. }
  718. DeleteObject(m_hPalLast);
  719. }
  720. m_fMetaDC = FALSE;
  721. errRtn:
  722. LEVERIFY( RestoreDC (hdcDraw, iOldDc) );
  723. return m_error;
  724. }
  725. //+-------------------------------------------------------------------------
  726. //
  727. // Member: CMfObject::GetColorSet
  728. //
  729. // Synopsis: Retrieves the logical palette associated with the metafile
  730. //
  731. // Effects:
  732. //
  733. // Arguments: [pvAspect] -- the drawing aspect
  734. // [hicTargetDev] -- target device
  735. // [ppColorSet] -- where to put the logical palette pointer
  736. //
  737. // Requires:
  738. //
  739. // Returns: HRESULT
  740. //
  741. // Signals:
  742. //
  743. // Modifies:
  744. //
  745. // Derivation: IOlePresObj
  746. //
  747. // Algorithm: Plays the metafile into a new metafile. The play callback
  748. // function stores the metafile palette which is then returned.
  749. //
  750. // History: dd-mmm-yy Author Comment
  751. // 29-Nov-93 alexgo 32bit port
  752. //
  753. // Notes:
  754. //
  755. //--------------------------------------------------------------------------
  756. STDMETHODIMP CMfObject::GetColorSet (LPVOID /* UNUSED pvAspect */,
  757. HDC /* UNUSED hicTargetDev */,
  758. LPLOGPALETTE * ppColorSet)
  759. {
  760. VDATEHEAP();
  761. if (IsBlank() || !M_HPRES())
  762. {
  763. return ResultFromScode(OLE_E_BLANK);
  764. }
  765. m_pColorSet = NULL;
  766. HDC hdcMeta = CreateMetaFile(NULL);
  767. if (NULL == hdcMeta)
  768. {
  769. return ResultFromScode(E_OUTOFMEMORY);
  770. }
  771. m_error = NOERROR;
  772. LEVERIFY( EnumMetaFile(hdcMeta, m_hPres, MfCallbackFuncForGetColorSet,
  773. (LPARAM) this) );
  774. HMETAFILE hMetaFile = CloseMetaFile(hdcMeta);
  775. if( hMetaFile )
  776. {
  777. DeleteMetaFile(hMetaFile);
  778. }
  779. if( m_error != NOERROR )
  780. {
  781. return m_error;
  782. }
  783. if ((*ppColorSet = m_pColorSet) == NULL)
  784. {
  785. return ResultFromScode(S_FALSE);
  786. }
  787. return NOERROR;
  788. }
  789. //+-------------------------------------------------------------------------
  790. //
  791. // Function: MfCallBackFunForDraw
  792. //
  793. // Synopsis: callback function for drawing metafiles -- call's the caller's
  794. // draw method (via a passed in this pointer)
  795. //
  796. // Effects:
  797. //
  798. // Arguments: [hdc] -- the device context
  799. // [lpHTable] -- pointer to the MF handle table
  800. // [lpMFR] -- pointer to metafile record
  801. // [nObj] -- number of objects
  802. //
  803. // Requires:
  804. //
  805. // Returns: non-zero to continue, zero stops the drawing
  806. //
  807. // Signals:
  808. //
  809. // Modifies:
  810. //
  811. // Algorithm:
  812. //
  813. // History: dd-mmm-yy Author Comment
  814. // 29-Nov-93 alexgo 32bit port
  815. //
  816. // Notes:
  817. //
  818. //--------------------------------------------------------------------------
  819. int CALLBACK __loadds MfCallbackFuncForDraw
  820. (HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
  821. LPARAM lpobj)
  822. {
  823. VDATEHEAP();
  824. return ((CMfObject FAR*) lpobj)->CallbackFuncForDraw(hdc, lpHTable,
  825. lpMFR, nObj);
  826. }
  827. //+-------------------------------------------------------------------------
  828. //
  829. // Function: MfCallbackFuncForGetColorSet
  830. //
  831. // Synopsis: callback function for grabbing the palette from a metafile
  832. //
  833. // Effects:
  834. //
  835. // Arguments: [hdc] -- the device context
  836. // [lpHTable] -- pointer to the MF handle table
  837. // [lpMFR] -- pointer to metafile record
  838. // [nObj] -- number of objects
  839. //
  840. // Requires:
  841. //
  842. // Returns: non-zero to continue, zero stops the drawing
  843. //
  844. // Signals:
  845. //
  846. // Modifies:
  847. //
  848. // Algorithm:
  849. //
  850. // History: dd-mmm-yy Author Comment
  851. // 29-Nov-93 alexgo 32bit port
  852. //
  853. // Notes:
  854. //
  855. //--------------------------------------------------------------------------
  856. int CALLBACK __loadds MfCallbackFuncForGetColorSet
  857. (HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
  858. LPARAM lpobj)
  859. {
  860. VDATEHEAP();
  861. return ((CMfObject FAR*) lpobj)->CallbackFuncForGetColorSet(hdc, lpHTable,
  862. lpMFR, nObj);
  863. }
  864. //+-------------------------------------------------------------------------
  865. //
  866. // Member: CMfObject::CallbackFuncForGetColorSet
  867. //
  868. // Synopsis: Merges all the color palettes in the metafile into
  869. // one palette (called when GetColorSet enumerates the metafile)
  870. //
  871. // Effects:
  872. //
  873. // Arguments: [hdc] -- the device context
  874. // [lpHTable] -- pointer to the MF handle table
  875. // [lpMFR] -- pointer to metafile record
  876. // [nObj] -- number of objects
  877. //
  878. // Requires:
  879. //
  880. // Returns: non-zero to continue, zero stops the drawing
  881. //
  882. // Signals:
  883. //
  884. // Modifies:
  885. //
  886. // Derivation:
  887. //
  888. // Algorithm:
  889. //
  890. // History: dd-mmm-yy Author Comment
  891. // 29-Nov-93 alexgo 32bit port
  892. //
  893. // Notes:
  894. //
  895. //--------------------------------------------------------------------------
  896. int CMfObject::CallbackFuncForGetColorSet(HDC /* UNUSED hdc */,
  897. LPHANDLETABLE /* UNUSED lpHTable */,
  898. LPMETARECORD lpMFR,
  899. int /* UNUSED nObj */)
  900. {
  901. VDATEHEAP();
  902. if (lpMFR->rdFunction == META_CREATEPALETTE)
  903. {
  904. LPLOGPALETTE lplogpal = (LPLOGPALETTE) &(lpMFR->rdParm[0]);
  905. UINT uPalSize = (lplogpal->palNumEntries) *
  906. sizeof(PALETTEENTRY)
  907. + 2 * sizeof(WORD);
  908. if (m_pColorSet == NULL)
  909. {
  910. // This is the first CreatePalette record.
  911. m_pColorSet = (LPLOGPALETTE)PubMemAlloc(uPalSize);
  912. if(NULL == m_pColorSet)
  913. {
  914. m_error = ResultFromScode(E_OUTOFMEMORY);
  915. return FALSE;
  916. }
  917. _xmemcpy(m_pColorSet, lplogpal, (size_t) uPalSize);
  918. }
  919. // if we hit more than one CreatePalette record then, we need to
  920. // merge those palette records.
  921. // REVIEW32:: err, we don't ever seem to do this
  922. // mergeing referred to above :(
  923. }
  924. return TRUE;
  925. }
  926. //+-------------------------------------------------------------------------
  927. //
  928. // Member: CMfObject::CallbackFuncForDraw
  929. //
  930. // Synopsis: Draws the metafile
  931. //
  932. // Effects:
  933. //
  934. // Arguments: [hdc] -- the device context
  935. // [lpHTable] -- pointer to the MF handle table
  936. // [lpMFR] -- pointer to metafile record
  937. // [nObj] -- number of objects
  938. //
  939. // Requires:
  940. //
  941. // Returns: non-zero to continue, zero stops the drawing
  942. //
  943. // Signals:
  944. //
  945. // Modifies:
  946. //
  947. // Derivation:
  948. //
  949. // Algorithm:
  950. //
  951. // History: dd-mmm-yy Author Comment
  952. // 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
  953. // 29-Nov-93 alexgo 32bit port
  954. //
  955. // Notes:
  956. //
  957. //--------------------------------------------------------------------------
  958. int CMfObject::CallbackFuncForDraw
  959. (HDC hdc, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, int nObj)
  960. {
  961. VDATEHEAP();
  962. if (!--m_nRecord)
  963. {
  964. m_nRecord = RECORD_COUNT;
  965. if (m_pfnContinue && !((*(m_pfnContinue))(m_dwContinue)))
  966. {
  967. m_error = ResultFromScode(E_ABORT);
  968. return FALSE;
  969. }
  970. }
  971. if (m_fMetaDC)
  972. {
  973. switch (lpMFR->rdFunction)
  974. {
  975. case META_SETWINDOWORG:
  976. SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
  977. FALSE);
  978. return TRUE;
  979. case META_OFFSETWINDOWORG:
  980. SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
  981. TRUE);
  982. return TRUE;
  983. case META_SETWINDOWEXT:
  984. SetPictExt (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
  985. return TRUE;
  986. case META_SCALEWINDOWEXT:
  987. ScalePictExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
  988. (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
  989. return TRUE;
  990. case META_SCALEVIEWPORTEXT:
  991. ScaleRectExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
  992. (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
  993. return TRUE;
  994. case META_SAVEDC:
  995. {
  996. BOOL fSucceeded = PushDc();
  997. LEVERIFY( fSucceeded );
  998. if (!fSucceeded)
  999. return FALSE;
  1000. break;
  1001. }
  1002. case META_RESTOREDC:
  1003. LEVERIFY( PopDc() );
  1004. break;
  1005. case META_SELECTPALETTE:
  1006. {
  1007. // All selectpalette records are recorded such that the
  1008. // palette is rendered in foreground mode. Rather than
  1009. // allowing the record to play out in this fashion, we
  1010. // grab the handle and select it ourselves, forcing it
  1011. // to background (using colors already mapped in the DC)
  1012. // Dupe the palette.
  1013. HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
  1014. // Select the dupe into the DC. EnumMetaFile calls DeleteObject
  1015. // on the palette handle in the metafile handle table. If that
  1016. // palette is currently selected into a DC, we rip and leak the
  1017. // resource.
  1018. LEVERIFY( NULL != SelectPalette(hdc, hPal, TRUE) );
  1019. // if we had previously saved a palette, we need to delete
  1020. // it (for the case of multiple SelectPalette calls in a
  1021. // MetaFile).
  1022. if (m_hPalLast)
  1023. {
  1024. DeleteObject(m_hPalLast);
  1025. }
  1026. // remember our duped palette so that it can be properly destroyed
  1027. // later.
  1028. m_hPalLast = hPal;
  1029. return TRUE;
  1030. }
  1031. case META_OFFSETVIEWPORTORG:
  1032. AssertSz(0, "OffsetViewportOrg() in metafile");
  1033. return TRUE;
  1034. case META_SETVIEWPORTORG:
  1035. AssertSz(0, "SetViewportOrg() in metafile");
  1036. return TRUE;
  1037. case META_SETVIEWPORTEXT:
  1038. AssertSz(0, "SetViewportExt() in metafile");
  1039. return TRUE;
  1040. case META_SETMAPMODE:
  1041. AssertSz(lpMFR->rdParm[0] == MM_ANISOTROPIC,
  1042. "SetmapMode() in metafile with invalid mapping mode");
  1043. return TRUE;
  1044. default:
  1045. break;
  1046. }
  1047. }
  1048. else
  1049. { // non-metafile DC. (ScreenDC or other DC...)
  1050. if (lpMFR->rdFunction == META_SELECTPALETTE)
  1051. {
  1052. // All selectpalette records are recorded such that the
  1053. // palette is rendered in foreground mode. Rather than
  1054. // allowing the record to play out in this fashion, we
  1055. // grab the handle and select it ourselves, forcing it
  1056. // to background (using colors already mapped in the DC)
  1057. HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
  1058. HPALETTE hPalOld = SelectPalette(hdc, hPal, TRUE);
  1059. if (!m_hPalDCOriginal)
  1060. {
  1061. m_hPalDCOriginal = hPalOld;
  1062. }
  1063. else
  1064. {
  1065. // This case gets hit if we have already stored
  1066. // the original palette from the DC. This means
  1067. // that hPalOld is a palette we have created using
  1068. // UtDupPal above. This means we need to delete
  1069. // the old palette and remember the new one.
  1070. if(hPalOld)
  1071. DeleteObject(hPalOld);
  1072. }
  1073. m_hPalLast = hPal;
  1074. return TRUE;
  1075. }
  1076. }
  1077. LEVERIFY( PlayMetaFileRecord (hdc, lpHTable, lpMFR, (unsigned) nObj) );
  1078. return TRUE;
  1079. }
  1080. //+-------------------------------------------------------------------------
  1081. //
  1082. // Member: CMfObject::SetPictOrg (private)
  1083. //
  1084. // Synopsis: Sets the hdc's origin via SetWindowOrg
  1085. //
  1086. // Effects:
  1087. //
  1088. // Arguments: [hdc] -- the device context
  1089. // [xOrg] -- the x origin
  1090. // [yOrg] -- the y origin
  1091. // [fOffset] -- if TRUE, [xOrg] and [yOrg] are offsets
  1092. //
  1093. // Requires:
  1094. //
  1095. // Returns: HRESULT
  1096. //
  1097. // Signals:
  1098. //
  1099. // Modifies:
  1100. //
  1101. // Derivation:
  1102. //
  1103. // Algorithm:
  1104. //
  1105. // History: dd-mmm-yy Author Comment
  1106. // 29-Nov-93 alexgo 32bit port
  1107. //
  1108. // Notes: used by the metafile interpreter
  1109. //
  1110. //--------------------------------------------------------------------------
  1111. INTERNAL_(void) CMfObject::SetPictOrg
  1112. (HDC hdc, int xOrg, int yOrg, BOOL fOffset)
  1113. {
  1114. VDATEHEAP();
  1115. if (fOffset)
  1116. {
  1117. m_pCurMdc->xMwo += xOrg;
  1118. m_pCurMdc->yMwo += yOrg;
  1119. }
  1120. else
  1121. {
  1122. m_pCurMdc->xMwo = xOrg;
  1123. m_pCurMdc->yMwo = yOrg;
  1124. }
  1125. if (m_pCurMdc->xMwe && m_pCurMdc->yMwe)
  1126. {
  1127. LEVERIFY ( SetWindowOrg (hdc, // Review (davepl) MEIN GOT!
  1128. (m_pCurMdc->xMwo -
  1129. MulDiv (m_pMetaInfo->xro, m_pCurMdc->xMwe,
  1130. m_pCurMdc->xre)),
  1131. (m_pCurMdc->yMwo -
  1132. MulDiv (m_pMetaInfo->yro, m_pCurMdc->yMwe,
  1133. m_pCurMdc->yre))) );
  1134. }
  1135. }
  1136. //+-------------------------------------------------------------------------
  1137. //
  1138. // Member: CMfObject::SetPictExt
  1139. //
  1140. // Synopsis: Sets teh metafile's extents
  1141. //
  1142. // Effects:
  1143. //
  1144. // Arguments: [hdc] -- the device context
  1145. // [xExt] -- the X-extent
  1146. // [yExt] -- the Y-extent
  1147. //
  1148. // Requires:
  1149. //
  1150. // Returns: void
  1151. //
  1152. // Signals:
  1153. //
  1154. // Modifies:
  1155. //
  1156. // Derivation:
  1157. //
  1158. // Algorithm:
  1159. //
  1160. // History: dd-mmm-yy Author Comment
  1161. // 30-Nov-93 alexgo 32bit port
  1162. //
  1163. // Notes: used by the metafile interpreter
  1164. //
  1165. //--------------------------------------------------------------------------
  1166. INTERNAL_(void) CMfObject::SetPictExt (HDC hdc, int xExt, int yExt)
  1167. {
  1168. VDATEHEAP();
  1169. m_pCurMdc->xMwe = xExt;
  1170. m_pCurMdc->yMwe = yExt;
  1171. // Assert( m_pCurMdc->xre && m_pCurMdc->yre );
  1172. int xNewExt = MulDiv (m_pMetaInfo->xwe, xExt, m_pCurMdc->xre);
  1173. int yNewExt = MulDiv (m_pMetaInfo->ywe, yExt, m_pCurMdc->yre);
  1174. int xNewOrg = m_pCurMdc->xMwo
  1175. - MulDiv (m_pMetaInfo->xro, xExt, m_pCurMdc->xre);
  1176. int yNewOrg = m_pCurMdc->yMwo
  1177. - MulDiv (m_pMetaInfo->yro, yExt, m_pCurMdc->yre);
  1178. LEVERIFY( SetWindowExt (hdc, xNewExt, yNewExt) );
  1179. LEVERIFY( SetWindowOrg (hdc, xNewOrg, yNewOrg) );
  1180. }
  1181. //+-------------------------------------------------------------------------
  1182. //
  1183. // Member: CMfObject::ScalePictExt
  1184. //
  1185. // Synopsis: Scales the metafile
  1186. //
  1187. // Effects:
  1188. //
  1189. // Arguments: [hdc] -- the device context
  1190. // [xNum] -- the x numerator
  1191. // [xDenom] -- the x demominator
  1192. // [yNum] -- the y numberator
  1193. // [yDenom] -- the y demoninator
  1194. //
  1195. // Requires:
  1196. //
  1197. // Returns: void
  1198. //
  1199. // Signals:
  1200. //
  1201. // Modifies:
  1202. //
  1203. // Derivation:
  1204. //
  1205. // Algorithm:
  1206. //
  1207. // History: dd-mmm-yy Author Comment
  1208. // 30-Nov-93 alexgo 32bit port
  1209. //
  1210. // Notes: used by the metafile interpreter
  1211. //
  1212. //--------------------------------------------------------------------------
  1213. INTERNAL_(void) CMfObject::ScalePictExt (HDC hdc,
  1214. int xNum,
  1215. int xDenom,
  1216. int yNum,
  1217. int yDenom)
  1218. {
  1219. VDATEHEAP();
  1220. Assert( xDenom && yDenom );
  1221. int xNewExt = MulDiv (m_pCurMdc->xMwe, xNum, xDenom);
  1222. int yNewExt = MulDiv (m_pCurMdc->yMwe, yNum, yDenom);
  1223. SetPictExt(hdc, xNewExt, yNewExt);
  1224. }
  1225. //+-------------------------------------------------------------------------
  1226. //
  1227. // Member: CMfObject::ScaleRectExt
  1228. //
  1229. // Synopsis: scales the viewport
  1230. //
  1231. // Effects:
  1232. //
  1233. // Arguments: [hdc] -- the device context
  1234. // [xNum] -- the x numerator
  1235. // [xDenom] -- the x demominator
  1236. // [yNum] -- the y numberator
  1237. // [yDenom] -- the y demoninator
  1238. //
  1239. // Requires:
  1240. //
  1241. // Returns: void
  1242. //
  1243. // Signals:
  1244. //
  1245. // Modifies:
  1246. //
  1247. // Derivation:
  1248. //
  1249. // Algorithm:
  1250. //
  1251. // History: dd-mmm-yy Author Comment
  1252. // 30-Nov-93 alexgo 32bit port
  1253. //
  1254. // Notes: Used by the metafile interpreter
  1255. //
  1256. //--------------------------------------------------------------------------
  1257. INTERNAL_(void) CMfObject::ScaleRectExt(HDC hdc,
  1258. int xNum,
  1259. int xDenom,
  1260. int yNum,
  1261. int yDenom)
  1262. {
  1263. VDATEHEAP();
  1264. AssertSz( xDenom, "Denominator is 0 for x-rect scaling");
  1265. AssertSz( yDenom, "Denominator is 0 for y-rect scaling");
  1266. m_pCurMdc->xre = MulDiv (m_pCurMdc->xre, xNum, xDenom);
  1267. m_pCurMdc->yre = MulDiv (m_pCurMdc->yre, yNum, yDenom);
  1268. SetPictExt (hdc, m_pCurMdc->xMwe, m_pCurMdc->yMwe);
  1269. }
  1270. //+-------------------------------------------------------------------------
  1271. //
  1272. // Member: CMfObject::PushDC
  1273. //
  1274. // Synopsis: pushes metafile info onto a stack
  1275. //
  1276. // Effects:
  1277. //
  1278. // Arguments: void
  1279. //
  1280. // Requires:
  1281. //
  1282. // Returns: BOOL -- TRUE if successful, FALSE otherwise
  1283. //
  1284. // Signals:
  1285. //
  1286. // Modifies:
  1287. //
  1288. // Derivation:
  1289. //
  1290. // Algorithm:
  1291. //
  1292. // History: dd-mmm-yy Author Comment
  1293. // 30-Nov-93 alexgo 32bit port
  1294. //
  1295. // Notes: Used by the metafile interpreter engine.
  1296. //
  1297. //--------------------------------------------------------------------------
  1298. INTERNAL_(BOOL) CMfObject::PushDc (void)
  1299. {
  1300. VDATEHEAP();
  1301. LPMETADC pNode = NULL;
  1302. pNode = (LPMETADC) PrivMemAlloc(sizeof(METADC));
  1303. if (pNode)
  1304. {
  1305. *pNode = *m_pCurMdc;
  1306. m_pCurMdc->pNext = pNode;
  1307. pNode->pNext = NULL;
  1308. m_pCurMdc = pNode;
  1309. return TRUE;
  1310. }
  1311. m_error = ResultFromScode(E_OUTOFMEMORY);
  1312. return FALSE;
  1313. }
  1314. //+-------------------------------------------------------------------------
  1315. //
  1316. // Member: CMfObject::PopDC
  1317. //
  1318. // Synopsis: pops metafile info from the metafile info stack
  1319. //
  1320. // Effects:
  1321. //
  1322. // Arguments: void
  1323. //
  1324. // Requires:
  1325. //
  1326. // Returns: BOOL -- TRUE if successful, FALSE otherwise (more pops
  1327. // than pushes)
  1328. //
  1329. // Signals:
  1330. //
  1331. // Modifies:
  1332. //
  1333. // Derivation:
  1334. //
  1335. // Algorithm:
  1336. //
  1337. // History: dd-mmm-yy Author Comment
  1338. // 30-Nov-93 alexgo 32bit port
  1339. //
  1340. // Notes: used in the metafile interpreter
  1341. //
  1342. //--------------------------------------------------------------------------
  1343. INTERNAL_(BOOL) CMfObject::PopDc (void)
  1344. {
  1345. VDATEHEAP();
  1346. LPMETADC pPrev = (LPMETADC) (m_pMetaInfo);
  1347. LPMETADC pCur = ((LPMETADC) (m_pMetaInfo))->pNext;
  1348. if (NULL == pCur)
  1349. {
  1350. LEWARN( NULL == pCur, "More pops than pushes from DC stack" );
  1351. return FALSE;
  1352. }
  1353. while (pCur->pNext)
  1354. {
  1355. pPrev = pCur;
  1356. pCur = pCur->pNext;
  1357. }
  1358. if (pCur)
  1359. {
  1360. PrivMemFree(pCur);
  1361. }
  1362. pPrev->pNext = NULL;
  1363. m_pCurMdc = pPrev;
  1364. return TRUE;
  1365. }
  1366. //+-------------------------------------------------------------------------
  1367. //
  1368. // Member: CMfObject::CleanStack
  1369. //
  1370. // Synopsis: Deletes the stack of metafile info
  1371. //
  1372. // Effects:
  1373. //
  1374. // Arguments: void
  1375. //
  1376. // Requires:
  1377. //
  1378. // Returns: void
  1379. //
  1380. // Signals:
  1381. //
  1382. // Modifies:
  1383. //
  1384. // Derivation:
  1385. //
  1386. // Algorithm:
  1387. //
  1388. // History: dd-mmm-yy Author Comment
  1389. // 30-Nov-93 alexgo 32bit port
  1390. //
  1391. // Notes: used in the metafile interpreter
  1392. //
  1393. //--------------------------------------------------------------------------
  1394. INTERNAL_(void) CMfObject::CleanStack (void)
  1395. {
  1396. VDATEHEAP();
  1397. LPMETADC pCur;
  1398. while (NULL != (pCur = ((LPMETADC) (m_pMetaInfo))->pNext))
  1399. {
  1400. ((LPMETADC) (m_pMetaInfo))->pNext = pCur->pNext;
  1401. PrivMemFree(pCur);
  1402. }
  1403. PrivMemFree(m_pMetaInfo);
  1404. m_pCurMdc = NULL;
  1405. m_pMetaInfo = NULL;
  1406. }
  1407. //+-------------------------------------------------------------------------
  1408. //
  1409. // Function: QD2GDI
  1410. //
  1411. // Synopsis: Converts macintosh pictures to Win32 GDI metafiles
  1412. //
  1413. // Effects:
  1414. //
  1415. // Arguments: [hBits] -- handle to the mac picture bits
  1416. //
  1417. // Requires:
  1418. //
  1419. // Returns: HMETAFILE
  1420. //
  1421. // Signals:
  1422. //
  1423. // Modifies:
  1424. //
  1425. // Algorithm: Loads ole2conv.dll and calls QD2GDI in that dll
  1426. //
  1427. // History: dd-mmm-yy Author Comment
  1428. // 30-Nov-93 alexgo 32bit port
  1429. //
  1430. // Notes:
  1431. //
  1432. //--------------------------------------------------------------------------
  1433. FARINTERNAL_(HMETAFILE) QD2GDI (HANDLE hBits)
  1434. {
  1435. VDATEHEAP();
  1436. USERPREFS userPrefs =
  1437. {
  1438. {'Q','D','2','G','D','I'}, //signature
  1439. 2, //structure version number
  1440. sizeof(USERPREFS), //structure size
  1441. NULL, //source filename
  1442. NULL, //or source handle
  1443. NULL, //returned memory-based
  1444. //metafile
  1445. 3, //simulated pattern lines
  1446. 5, //use max dimension
  1447. //non-squarer pen
  1448. 1, //arithmetic transfer
  1449. 1, //create opaque text
  1450. 1, //simulate non-rectangular
  1451. //regions
  1452. 0, //don't optimize for PowerPoint
  1453. {0,0,0,0,0,0} //reserved
  1454. };
  1455. HINSTANCE hinstFilter;
  1456. void (FAR PASCAL *qd2gdiPtr)( USERPREFS FAR *, PICTINFO FAR *);
  1457. PICTINFO pictinfo;
  1458. hinstFilter = LoadLibrary(OLESTR("OLECNV32.DLL"));
  1459. #if 0
  1460. //REVIEW:CHICAGO
  1461. //HINSTANCE_ERROR not defined in chicago
  1462. if (hinstFilter < (HINSTANCE)HINSTANCE_ERROR)
  1463. {
  1464. return NULL;
  1465. }
  1466. #endif
  1467. if (hinstFilter == NULL)
  1468. {
  1469. return NULL;
  1470. }
  1471. *((FARPROC*)&qd2gdiPtr) = GetProcAddress(hinstFilter, "QD2GDI");
  1472. userPrefs.sourceFilename = NULL;
  1473. userPrefs.sourceHandle = hBits;
  1474. pictinfo.hmf = NULL;
  1475. if (qd2gdiPtr == NULL)
  1476. {
  1477. goto errRtn;
  1478. }
  1479. (*qd2gdiPtr)( (USERPREFS FAR *)&userPrefs, (PICTINFO FAR *)&pictinfo);
  1480. errRtn:
  1481. LEVERIFY( FreeLibrary(hinstFilter) );
  1482. return (HMETAFILE)pictinfo.hmf;
  1483. }
  1484. //+-------------------------------------------------------------------------
  1485. //
  1486. // Function: MfGetSize
  1487. //
  1488. // Synopsis: Returns the size of a metafile
  1489. //
  1490. // Effects:
  1491. //
  1492. // Arguments: [lphmf] -- pointer to the metafile handle
  1493. //
  1494. // Requires:
  1495. //
  1496. // Returns: DWORD -- the size of the metafile
  1497. //
  1498. // Signals:
  1499. //
  1500. // Modifies:
  1501. //
  1502. // Algorithm:
  1503. //
  1504. // History: dd-mmm-yy Author Comment
  1505. // 30-Nov-93 alexgo 32bit port
  1506. //
  1507. // Notes:
  1508. //
  1509. //--------------------------------------------------------------------------
  1510. INTERNAL_(DWORD) MfGetSize (LPHANDLE lphmf)
  1511. {
  1512. VDATEHEAP();
  1513. return GetMetaFileBitsEx((HMETAFILE)*lphmf,0,NULL);
  1514. }
  1515. //+-------------------------------------------------------------------------
  1516. //
  1517. // Function: OleIsDcMeta
  1518. //
  1519. // Synopsis: Returns whether a device context is really a metafile
  1520. //
  1521. // Effects:
  1522. //
  1523. // Arguments: [hdc] -- the device context
  1524. //
  1525. // Requires:
  1526. //
  1527. // Returns: BOOL (TRUE if a metafile)
  1528. //
  1529. // Signals:
  1530. //
  1531. // Modifies:
  1532. //
  1533. // Algorithm:
  1534. //
  1535. // History: dd-mmm-yy Author Comment
  1536. // 30-Nov-93 alexgo 32bit port
  1537. //
  1538. // Notes:
  1539. //
  1540. //--------------------------------------------------------------------------
  1541. STDAPI_(BOOL) OleIsDcMeta (HDC hdc)
  1542. {
  1543. VDATEHEAP();
  1544. return (GetDeviceCaps (hdc, TECHNOLOGY) == DT_METAFILE);
  1545. }
  1546. //+-------------------------------------------------------------------------
  1547. //
  1548. // Member: CMfObject::Load
  1549. //
  1550. // Synopsis: Loads an metafile object from the given stream
  1551. //
  1552. // Effects:
  1553. //
  1554. // Arguments: [lpstream] -- the stream from which to load
  1555. // [fReadHeaderOnly] -- if TRUE, then only the header is
  1556. // read
  1557. //
  1558. // Requires:
  1559. //
  1560. // Returns: HRESULT
  1561. //
  1562. // Signals:
  1563. //
  1564. // Modifies:
  1565. //
  1566. // Derivation: IOlePresObj
  1567. //
  1568. // Algorithm:
  1569. //
  1570. // History: dd-mmm-yy Author Comment
  1571. // 30-Nov-93 alexgo 32bit port
  1572. //
  1573. // Notes:
  1574. //
  1575. //--------------------------------------------------------------------------
  1576. STDMETHODIMP CMfObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
  1577. {
  1578. VDATEHEAP();
  1579. DWORD dwBuf[4];
  1580. HRESULT error;
  1581. /* read dwCompression, width, height, size of data */
  1582. error = StRead(lpstream, dwBuf, 4*sizeof(DWORD));
  1583. if (error)
  1584. {
  1585. return error;
  1586. }
  1587. AssertSz (dwBuf[0] == 0, "Picture compression factor is non-zero");
  1588. m_lWidth = (LONG) dwBuf[1];
  1589. m_lHeight = (LONG) dwBuf[2];
  1590. m_dwSize = dwBuf[3];
  1591. if (!m_dwSize || fReadHeaderOnly)
  1592. {
  1593. return NOERROR;
  1594. }
  1595. return UtGetHMFFromMFStm(lpstream, m_dwSize, m_fConvert,
  1596. (LPLPVOID) &m_hPres);
  1597. }
  1598. //+-------------------------------------------------------------------------
  1599. //
  1600. // Member: CMfObject::Save
  1601. //
  1602. // Synopsis: Saves the metafile to the given stream
  1603. //
  1604. // Effects:
  1605. //
  1606. // Arguments: [lpstream] -- the stream to save to
  1607. //
  1608. // Requires:
  1609. //
  1610. // Returns: HRESULT
  1611. //
  1612. // Signals:
  1613. //
  1614. // Modifies:
  1615. //
  1616. // Derivation: IOlePresObj
  1617. //
  1618. // Algorithm:
  1619. //
  1620. // History: dd-mmm-yy Author Comment
  1621. // 30-Nov-93 alexgo 32bit port
  1622. //
  1623. // Notes:
  1624. //
  1625. //--------------------------------------------------------------------------
  1626. STDMETHODIMP CMfObject::Save(LPSTREAM lpstream)
  1627. {
  1628. VDATEHEAP();
  1629. HRESULT error;
  1630. DWORD dwBuf[4];
  1631. /* write dwCompression, width, height, size of data */
  1632. dwBuf[0] = 0L;
  1633. dwBuf[1] = (DWORD) m_lWidth;
  1634. dwBuf[2] = (DWORD) m_lHeight;
  1635. dwBuf[3] = m_dwSize;
  1636. error = StWrite(lpstream, dwBuf, sizeof(dwBuf));
  1637. if (error)
  1638. {
  1639. return error;
  1640. }
  1641. // if blank object, don't write any more; no error.
  1642. if (IsBlank() || m_hPres == NULL)
  1643. {
  1644. StSetSize(lpstream, 0, TRUE);
  1645. return NOERROR;
  1646. }
  1647. return UtHMFToMFStm((LPLPVOID)&m_hPres, m_dwSize, lpstream);
  1648. }
  1649. //+-------------------------------------------------------------------------
  1650. //
  1651. // Member: CMfObject::GetExtent
  1652. //
  1653. // Synopsis: Retrieves the extents of the metafile
  1654. //
  1655. // Effects:
  1656. //
  1657. // Arguments: [dwDrawAspect] -- the drawing aspect we're interested in
  1658. // (must match the aspect of the current
  1659. // metafile)
  1660. // [lpsizel] -- where to put the extent info
  1661. //
  1662. // Requires:
  1663. //
  1664. // Returns: NOERROR, DV_E_DVASPECT, OLE_E_BLANK
  1665. //
  1666. // Signals:
  1667. //
  1668. // Modifies:
  1669. //
  1670. // Derivation: IOlePresObj
  1671. //
  1672. // Algorithm:
  1673. //
  1674. // History: dd-mmm-yy Author Comment
  1675. // 30-Nov-93 alexgo 32bit port
  1676. //
  1677. // Notes:
  1678. //
  1679. //--------------------------------------------------------------------------
  1680. STDMETHODIMP CMfObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
  1681. {
  1682. VDATEHEAP();
  1683. if (0 == (dwDrawAspect & m_dwAspect))
  1684. {
  1685. return ResultFromScode(DV_E_DVASPECT);
  1686. }
  1687. if (IsBlank())
  1688. {
  1689. return ResultFromScode(OLE_E_BLANK);
  1690. }
  1691. lpsizel->cx = m_lWidth;
  1692. lpsizel->cy = m_lHeight;
  1693. return NOERROR;
  1694. }
  1695. //+-------------------------------------------------------------------------
  1696. //
  1697. // Member: CMfObject::IsBlank
  1698. //
  1699. // Synopsis: Returns whether or not the metafile is blank
  1700. //
  1701. // Effects:
  1702. //
  1703. // Arguments: void
  1704. //
  1705. // Requires:
  1706. //
  1707. // Returns: TRUE/FALSE
  1708. //
  1709. // Signals:
  1710. //
  1711. // Modifies:
  1712. //
  1713. // Derivation: IOlePresObj
  1714. //
  1715. // Algorithm:
  1716. //
  1717. // History: dd-mmm-yy Author Comment
  1718. // 30-Nov-93 alexgo 32bit port
  1719. //
  1720. // Notes:
  1721. //
  1722. //--------------------------------------------------------------------------
  1723. STDMETHODIMP_(BOOL) CMfObject::IsBlank(void)
  1724. {
  1725. VDATEHEAP();
  1726. return (m_dwSize ? FALSE : TRUE);
  1727. }
  1728. //+-------------------------------------------------------------------------
  1729. //
  1730. // Member: CMfObject::LoadHPRES (private)
  1731. //
  1732. // Synopsis: Loads the presentation from the cache's stream and returns
  1733. // a handle to it
  1734. //
  1735. // Effects:
  1736. //
  1737. // Arguments: void
  1738. //
  1739. // Requires:
  1740. //
  1741. // Returns: HANDLE to the metafile
  1742. //
  1743. // Signals:
  1744. //
  1745. // Modifies:
  1746. //
  1747. // Derivation:
  1748. //
  1749. // Algorithm:
  1750. //
  1751. // History: dd-mmm-yy Author Comment
  1752. // 30-Nov-93 alexgo 32bit port
  1753. //
  1754. // Notes:
  1755. //
  1756. //--------------------------------------------------------------------------
  1757. INTERNAL_(HANDLE) CMfObject::LoadHPRES(void)
  1758. {
  1759. VDATEHEAP();
  1760. LPSTREAM pstm;
  1761. pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/, STGM_READ);
  1762. if (pstm)
  1763. {
  1764. LEVERIFY( SUCCEEDED(Load(pstm)));
  1765. pstm->Release();
  1766. }
  1767. return m_hPres;
  1768. }
  1769. //+-------------------------------------------------------------------------
  1770. //
  1771. // Member: CMfObject::DiscardHPRES
  1772. //
  1773. // Synopsis: deletes the stored metafile
  1774. //
  1775. // Effects:
  1776. //
  1777. // Arguments: void
  1778. //
  1779. // Requires:
  1780. //
  1781. // Returns: void
  1782. //
  1783. // Signals:
  1784. //
  1785. // Modifies:
  1786. //
  1787. // Derivation: IOlePresObj
  1788. //
  1789. // Algorithm:
  1790. //
  1791. // History: dd-mmm-yy Author Comment
  1792. // 30-Nov-93 alexgo 32bit port
  1793. //
  1794. // Notes:
  1795. //
  1796. //--------------------------------------------------------------------------
  1797. STDMETHODIMP_(void) CMfObject::DiscardHPRES(void)
  1798. {
  1799. VDATEHEAP();
  1800. if (m_hPres)
  1801. {
  1802. LEVERIFY( DeleteMetaFile (m_hPres) );
  1803. m_hPres = NULL;
  1804. }
  1805. }
  1806. //+-------------------------------------------------------------------------
  1807. //
  1808. // Member: CMfObject::GetCopyOfHPRES (private)
  1809. //
  1810. // Synopsis: makes a copy of the metafile (if one is present), otherwise
  1811. // just load it from the stream (but don't store it in [this]
  1812. // object)
  1813. //
  1814. // Effects:
  1815. //
  1816. // Arguments: void
  1817. //
  1818. // Requires:
  1819. //
  1820. // Returns: HANDLE to the metafile
  1821. //
  1822. // Signals:
  1823. //
  1824. // Modifies:
  1825. //
  1826. // Derivation:
  1827. //
  1828. // Algorithm:
  1829. //
  1830. // History: dd-mmm-yy Author Comment
  1831. // 30-Nov-93 alexgo 32bit port
  1832. //
  1833. // Notes:
  1834. //
  1835. //--------------------------------------------------------------------------
  1836. INTERNAL_(HANDLE) CMfObject::GetCopyOfHPRES(void)
  1837. {
  1838. VDATEHEAP();
  1839. HANDLE hPres;
  1840. // Make a copy if the presentation data is already loaded
  1841. if (m_hPres)
  1842. {
  1843. return CopyMetaFile(m_hPres, NULL);
  1844. }
  1845. // Load the presentation data now and return the same handle.
  1846. // No need to copy the data. If the caller wants the m_hPres to be
  1847. // set he would call LoadHPRES() directly.
  1848. hPres = LoadHPRES();
  1849. m_hPres = NULL; // NULL this, LoadHPRES set it.
  1850. return hPres;
  1851. }
  1852. //+-------------------------------------------------------------------------
  1853. //
  1854. // Member: CMfObject::Dump, public (_DEBUG only)
  1855. //
  1856. // Synopsis: return a string containing the contents of the data members
  1857. //
  1858. // Effects:
  1859. //
  1860. // Arguments: [ppszDump] - an out pointer to a null terminated character array
  1861. // [ulFlag] - flag determining prefix of all newlines of the
  1862. // out character array (default is 0 - no prefix)
  1863. // [nIndentLevel] - will add a indent prefix after the other prefix
  1864. // for ALL newlines (including those with no prefix)
  1865. //
  1866. // Requires:
  1867. //
  1868. // Returns: HRESULT
  1869. //
  1870. // Signals:
  1871. //
  1872. // Modifies: [ppszDump] - argument
  1873. //
  1874. // Derivation:
  1875. //
  1876. // Algorithm: use dbgstream to create a string containing information on the
  1877. // content of data structures
  1878. //
  1879. // History: dd-mmm-yy Author Comment
  1880. // 01-Feb-95 t-ScottH author
  1881. //
  1882. // Notes:
  1883. //
  1884. //--------------------------------------------------------------------------
  1885. #ifdef _DEBUG
  1886. HRESULT CMfObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
  1887. {
  1888. int i;
  1889. char *pszPrefix;
  1890. char *pszHRESULT;
  1891. char *pszDVASPECT;
  1892. dbgstream dstrPrefix;
  1893. dbgstream dstrDump(500);
  1894. // determine prefix of newlines
  1895. if ( ulFlag & DEB_VERBOSE )
  1896. {
  1897. dstrPrefix << this << " _VB ";
  1898. }
  1899. // determine indentation prefix for all newlines
  1900. for (i = 0; i < nIndentLevel; i++)
  1901. {
  1902. dstrPrefix << DUMPTAB;
  1903. }
  1904. pszPrefix = dstrPrefix.str();
  1905. // put data members in stream
  1906. dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
  1907. dstrDump << pszPrefix << "pMETAINFO (Metafile information) = " << m_pMetaInfo << endl;
  1908. dstrDump << pszPrefix << "pMETADC (current device context) = " << m_pCurMdc << endl;
  1909. dstrDump << pszPrefix << "IsMetaDeviceContext? = ";
  1910. if (m_fMetaDC == TRUE)
  1911. {
  1912. dstrDump << "TRUE" << endl;
  1913. }
  1914. else
  1915. {
  1916. dstrDump << "FALSE" << endl;
  1917. }
  1918. dstrDump << pszPrefix << "No. of Records in Metafile = " << m_nRecord << endl;
  1919. pszHRESULT = DumpHRESULT(m_error);
  1920. dstrDump << pszPrefix << "Error code = " << pszHRESULT << endl;
  1921. CoTaskMemFree(pszHRESULT);
  1922. dstrDump << pszPrefix << "pLOGPALETTE (Color set palette) = " << m_pColorSet << endl;
  1923. dstrDump << pszPrefix << "ConvertFromMac? = ";
  1924. if (m_fConvert == TRUE)
  1925. {
  1926. dstrDump << "TRUE" << endl;
  1927. }
  1928. else
  1929. {
  1930. dstrDump << "FALSE" << endl;
  1931. }
  1932. dstrDump << pszPrefix << "Continue = " << ((ULONG) m_dwContinue) << endl;
  1933. dstrDump << pszPrefix << "fp Continue = " << m_pfnContinue<< endl;
  1934. pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
  1935. dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
  1936. CoTaskMemFree(pszDVASPECT);
  1937. dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
  1938. dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
  1939. dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
  1940. dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
  1941. // cleanup and provide pointer to character array
  1942. *ppszDump = dstrDump.str();
  1943. if (*ppszDump == NULL)
  1944. {
  1945. *ppszDump = UtDupStringA(szDumpErrorMessage);
  1946. }
  1947. CoTaskMemFree(pszPrefix);
  1948. return NOERROR;
  1949. }
  1950. #endif // _DEBUG
  1951. //+-------------------------------------------------------------------------
  1952. //
  1953. // Function: DumpCMfObject, public (_DEBUG only)
  1954. //
  1955. // Synopsis: calls the CMfObject::Dump method, takes care of errors and
  1956. // returns the zero terminated string
  1957. //
  1958. // Effects:
  1959. //
  1960. // Arguments: [pMFO] - pointer to CMfObject
  1961. // [ulFlag] - flag determining prefix of all newlines of the
  1962. // out character array (default is 0 - no prefix)
  1963. // [nIndentLevel] - will add a indent prefix after the other prefix
  1964. // for ALL newlines (including those with no prefix)
  1965. //
  1966. // Requires:
  1967. //
  1968. // Returns: character array of structure dump or error (null terminated)
  1969. //
  1970. // Signals:
  1971. //
  1972. // Modifies:
  1973. //
  1974. // Algorithm:
  1975. //
  1976. // History: dd-mmm-yy Author Comment
  1977. // 01-Feb-95 t-ScottH author
  1978. //
  1979. // Notes:
  1980. //
  1981. //--------------------------------------------------------------------------
  1982. #ifdef _DEBUG
  1983. char *DumpCMfObject(CMfObject *pMFO, ULONG ulFlag, int nIndentLevel)
  1984. {
  1985. HRESULT hresult;
  1986. char *pszDump;
  1987. if (pMFO == NULL)
  1988. {
  1989. return UtDupStringA(szDumpBadPtr);
  1990. }
  1991. hresult = pMFO->Dump(&pszDump, ulFlag, nIndentLevel);
  1992. if (hresult != NOERROR)
  1993. {
  1994. CoTaskMemFree(pszDump);
  1995. return DumpHRESULT(hresult);
  1996. }
  1997. return pszDump;
  1998. }
  1999. #endif // _DEBUG