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

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: mf.cpp
//
// Contents: Implentation of hte metafile picture object
//
// Classes: CMfObject
//
// Functions: OleIsDcMeta
//
// History: dd-mmm-yy Author Comment
// 01-Feb-95 t-ScottH added Dump method to CMfObject
// added DumpCMfObject API
// initialize m_pfnContinue in constructor
// 25-Jan-94 alexgo first pass at converting to Cairo-style
// memory allocations.
// 11-Jan-93 alexgo added VDATEHEAP macros to every
// function and method
// 31-Dec-93 ErikGav chicago port
// 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
// in CallbackFuncForDraw
// 07-Dec-93 ChrisWe made default params to StSetSize explicit
// 07-Dec-93 alexgo merged 16bit RC9 changes
// 29-Nov-93 alexgo 32bit port
// 04-Jun-93 srinik support for demand loading and discarding
// of caches
// 13-Mar-92 srinik created
//
//--------------------------------------------------------------------------
#include <le2int.h>
#include <qd2gdi.h>
#include "mf.h"
#ifdef _DEBUG
#include <dbgdump.h>
#endif // _DEBUG
#define M_HPRES() (m_hPres ? m_hPres : LoadHPRES())
/*
* IMPLEMENTATION of CMfObject
*
*/
//+-------------------------------------------------------------------------
//
// Member: CMfObject::CMfObject
//
// Synopsis: constructor for the metafile object
//
// Effects:
//
// Arguments: [pCacheNode] -- pointer to the cache node for this object
// [dwAspect] -- drawing aspect for the object
// [fConvert] -- specifies whether to convert from Mac
// QuickDraw format
//
// Requires:
//
// Returns:
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 13-Feb-95 t-ScottH initialize m_pfnContinue
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
CMfObject::CMfObject(LPCACHENODE pCacheNode, DWORD dwAspect, BOOL fConvert)
{
VDATEHEAP();
m_ulRefs = 1;
m_hPres = NULL;
m_dwSize = 0;
m_dwAspect = dwAspect;
m_pCacheNode = pCacheNode;
m_dwContinue = 0;
m_pfnContinue = NULL;
m_lWidth = 0;
m_lHeight = 0;
m_fConvert = fConvert;
m_pMetaInfo = NULL;
m_pCurMdc = NULL;
m_fMetaDC = FALSE;
m_nRecord = 0;
m_error = NOERROR;
m_pColorSet = NULL;
m_hPalDCOriginal = NULL;
m_hPalLast = NULL;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::~CMfObject
//
// Synopsis: Destroys a metafile presentation object
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
CMfObject::~CMfObject (void)
{
VDATEHEAP();
CMfObject::DiscardHPRES();
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::QueryInterface
//
// Synopsis: returns supported interfaces
//
// Effects:
//
// Arguments: [iid] -- the requested interface ID
// [ppvObj] -- where to put the interface pointer
//
// Requires:
//
// Returns: NOERROR, E_NOINTERFACE
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::QueryInterface (REFIID iid, void FAR* FAR* ppvObj)
{
VDATEHEAP();
if (IsEqualIID(iid, IID_IUnknown) || IsEqualIID(iid, IID_IOlePresObj))
{
*ppvObj = this;
AddRef();
return NOERROR;
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::AddRef
//
// Synopsis: Increments the reference count
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: ULONG -- the new reference count
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CMfObject::AddRef(void)
{
VDATEHEAP();
return ++m_ulRefs;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::Release
//
// Synopsis: decrements the reference count
//
// Effects: deletes the object once the ref count goes to zero
//
// Arguments: void
//
// Requires:
//
// Returns: ULONG -- the new reference count
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CMfObject::Release(void)
{
VDATEHEAP();
if (--m_ulRefs == 0) {
delete this;
return 0;
}
return m_ulRefs;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetData
//
// Synopsis: Retrieves data in the specified format from the object
//
// Effects:
//
// Arguments: [pformatetcIn] -- the requested data format
// [pmedium] -- where to put the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObject
//
// Algorithm: Does error checking and then gets a copy of the metafilepict
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::GetData(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
{
VDATEHEAP();
SCODE sc;
// null out in case of error
pmedium->tymed = (DWORD) TYMED_NULL;
pmedium->pUnkForRelease = NULL;
if (!(pformatetcIn->tymed & (DWORD) TYMED_MFPICT))
{
sc = DV_E_TYMED;
}
else if (pformatetcIn->cfFormat != CF_METAFILEPICT)
{
sc = DV_E_CLIPFORMAT;
}
else if (IsBlank())
{
sc = OLE_E_BLANK;
}
// here we actually try to get the data
else if (NULL == (pmedium->hGlobal = GetHmfp()))
{
sc = E_OUTOFMEMORY;
}
else {
pmedium->tymed = (DWORD) TYMED_MFPICT;
return NOERROR;
}
return ResultFromScode(sc);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetDataHere
//
// Synopsis: Retrieves data of the specified format into the specified
// medium
//
// Effects:
//
// Arguments: [pformatetcIn] -- the requested data format
// [pmedium] -- where to put the data
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm: Does error checking and then copies the metafile into a
// stream.
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::GetDataHere
(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium)
{
VDATEHEAP();
SCODE sc;
if (pformatetcIn->cfFormat != CF_METAFILEPICT)
{
sc = DV_E_CLIPFORMAT;
}
else if (pmedium->tymed != (DWORD) TYMED_ISTREAM)
{
sc = DV_E_TYMED;
}
else if (pmedium->pstm == NULL)
{
sc = E_INVALIDARG;
}
else if (IsBlank())
{
sc = OLE_E_BLANK;
}
else
{
HANDLE hpres = M_HPRES();
return UtHMFToPlaceableMFStm(&hpres, m_dwSize, m_lWidth,
m_lHeight, pmedium->pstm);
}
return ResultFromScode(sc);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::SetDataWDO
//
// Synopsis: Stores a metafile in this object
//
// Effects:
//
// Arguments: [pformatetc] -- format of the data coming in
// [pmedium] -- the new metafile (data)
// [fRelease] -- if true, then we'll release the [pmedium]
// [pDataObj] -- unused for MF objects
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm: does error checking and then stores the new data.
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::SetDataWDO (LPFORMATETC pformatetc,
STGMEDIUM * pmedium,
BOOL fRelease,
IDataObject * /* UNUSED */)
{
VDATEHEAP();
HRESULT error;
BOOL fTakeData = FALSE;
if (pformatetc->cfFormat != CF_METAFILEPICT)
{
return ResultFromScode(DV_E_CLIPFORMAT);
}
if (pmedium->tymed != (DWORD) TYMED_MFPICT)
{
return ResultFromScode(DV_E_TYMED);
}
if ((pmedium->pUnkForRelease == NULL) && fRelease)
{
// we can take the ownership of the data
fTakeData = TRUE;
}
// ChangeData will keep the data if fRelease is TRUE, else it copies
error = ChangeData (pmedium->hGlobal, fTakeData);
if (fTakeData)
{
pmedium->tymed = (DWORD) TYMED_NULL;
}
else if (fRelease)
{
ReleaseStgMedium(pmedium);
}
return error;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetHmfp (internal)
//
// Synopsis: Gets a copy of the stored metafile presentation
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HANDLE
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(HANDLE) CMfObject::GetHmfp (void)
{
VDATEHEAP();
return UtGetHMFPICT((HMETAFILE)GetCopyOfHPRES(), TRUE, m_lWidth,
m_lHeight);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::ChangeData (internal)
//
// Synopsis: Swaps the stored metafile presentation
//
// Effects:
//
// Arguments: [hMfp] -- the new metafile
// [fDelete] -- if TRUE, then delete [hMfp]
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port, fixed GlobalUnlock bug
// Notes:
//
// If the routine fails then the object will be left with it's old data.
// If fDelete is TRUE, then hMeta, and the hMF it contains will be deleted
// whether the routine is successful or not.
//
//--------------------------------------------------------------------------
INTERNAL CMfObject::ChangeData (HANDLE hMfp, BOOL fDelete)
{
VDATEHEAP();
HANDLE hNewMF;
LPMETAFILEPICT lpMetaPict;
DWORD dwSize;
HRESULT error = NOERROR;
if ((lpMetaPict = (LPMETAFILEPICT) GlobalLock (hMfp)) == NULL)
{
if (fDelete)
{
LEVERIFY( NULL == GlobalFree (hMfp) );
}
return E_OUTOFMEMORY;
}
if (!fDelete) {
if (NULL == (hNewMF = CopyMetaFile (lpMetaPict->hMF, NULL)))
{
return E_OUTOFMEMORY;
}
}
else
{
hNewMF = lpMetaPict->hMF;
}
if (lpMetaPict->mm != MM_ANISOTROPIC)
{
error = ResultFromScode(E_UNSPEC);
LEWARN( error, "Mapping mode is not anisotropic" );
}
else if (0 == (dwSize = MfGetSize (&hNewMF)))
{
error = ResultFromScode(OLE_E_BLANK);
}
else
{
if (m_hPres)
{
LEVERIFY( DeleteMetaFile (m_hPres) );
}
m_hPres = (HMETAFILE)hNewMF;
m_dwSize = dwSize;
m_lWidth = lpMetaPict->xExt;
m_lHeight = lpMetaPict->yExt;
}
GlobalUnlock (hMfp);
if (error != NOERROR)
{
LEVERIFY( DeleteMetaFile ((HMETAFILE)hNewMF) );
}
if (fDelete)
{
LEVERIFY( NULL == GlobalFree (hMfp) );
}
return error;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::Draw
//
// Synopsis: Draws the stored presentation
//
// Effects:
//
// Arguments: [pvAspect] -- the drawing aspect
// [hicTargetDev] -- the target device
// [hdcDraw] -- hdc to draw into
// [lprcBounds] -- bounding rectangle to draw into
// [lprcWBounds] -- bounding rectangle for the metafile
// [pfnContinue] -- function to call while drawing
// [dwContinue] -- parameter to [pfnContinue]
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm: Sets the viewport and metafile boundaries, then plays
// the metafile
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::Draw (void * /* UNUSED pvAspect */,
HDC /* UNUSED hicTargetDev */,
HDC hdcDraw,
LPCRECTL lprcBounds,
LPCRECTL lprcWBounds,
BOOL (CALLBACK * pfnContinue)(ULONG_PTR),
ULONG_PTR dwContinue)
{
VDATEHEAP();
m_error = NOERROR;
int iRgn;
int iOldDc;
RECT rect;
LPRECT lpRrc = (LPRECT) &rect;
Assert(lprcBounds);
if (!M_HPRES())
{
return ResultFromScode(OLE_E_BLANK);
}
rect.left = lprcBounds->left;
rect.right = lprcBounds->right;
rect.top = lprcBounds->top;
rect.bottom = lprcBounds->bottom;
iOldDc = SaveDC (hdcDraw);
if (0 == iOldDc)
{
return ResultFromScode(E_OUTOFMEMORY);
}
m_nRecord = RECORD_COUNT;
m_fMetaDC = OleIsDcMeta (hdcDraw);
if (!m_fMetaDC) {
iRgn = IntersectClipRect (hdcDraw, lpRrc->left, lpRrc->top,
lpRrc->right, lpRrc->bottom);
Assert( ERROR != iRgn );
if (iRgn == NULLREGION) {
goto errRtn;
}
if (iRgn == ERROR) {
m_error = ResultFromScode(E_UNSPEC);
goto errRtn;
}
// Because the LPToDP conversion takes the current world
// transform into consideration, we must check to see
// if we are in a GM_ADVANCED device context. If so,
// save its state and reset to GM_COMPATIBLE while we
// convert LP to DP (then restore the DC).
if (GM_ADVANCED == GetGraphicsMode(hdcDraw))
{
HDC screendc = GetDC(NULL);
RECT rect = {0, 0, 1000, 1000};
HDC emfdc = CreateEnhMetaFile(screendc, NULL, &rect, NULL);
PlayMetaFile( emfdc, m_hPres);
HENHMETAFILE hemf = CloseEnhMetaFile(emfdc);
PlayEnhMetaFile( hdcDraw, hemf, lpRrc);
DeleteEnhMetaFile( hemf );
goto errRtn;
}
else
{
LEVERIFY( LPtoDP (hdcDraw, (LPPOINT) lpRrc, 2) );
}
LEVERIFY( 0 != SetMapMode (hdcDraw, MM_ANISOTROPIC) );
LEVERIFY( SetViewportOrg (hdcDraw, lpRrc->left, lpRrc->top) );
LEVERIFY( SetViewportExt (hdcDraw, lpRrc->right - lpRrc->left,
lpRrc->bottom - lpRrc->top) );
}
else
{
iOldDc = -1;
if (!lprcWBounds)
{
return ResultFromScode(E_DRAW);
}
m_pMetaInfo = (LPMETAINFO)PrivMemAlloc(sizeof(METAINFO));
if( !m_pMetaInfo )
{
AssertSz(m_pMetaInfo, "Memory allocation failed");
m_error = ResultFromScode(E_OUTOFMEMORY);
goto errRtn;
}
m_pCurMdc = (LPMETADC) (m_pMetaInfo);
m_pMetaInfo->xwo = lprcWBounds->left;
m_pMetaInfo->ywo = lprcWBounds->top;
m_pMetaInfo->xwe = lprcWBounds->right;
m_pMetaInfo->ywe = lprcWBounds->bottom;
m_pMetaInfo->xro = lpRrc->left - lprcWBounds->left;
m_pMetaInfo->yro = lpRrc->top - lprcWBounds->top;
m_pCurMdc->xre = lpRrc->right - lpRrc->left;
m_pCurMdc->yre = lpRrc->bottom - lpRrc->top;
m_pCurMdc->xMwo = 0;
m_pCurMdc->yMwo = 0;
m_pCurMdc->xMwe = 0;
m_pCurMdc->yMwe = 0;
m_pCurMdc->pNext = NULL;
}
m_pfnContinue = pfnContinue;
m_dwContinue = dwContinue;
// m_hPalDCOriginal and m_hPalLast are used to clean up any
// palettes that are selected into a DC during the metafile
// enumeration.
m_hPalDCOriginal = NULL;
m_hPalLast = NULL;
LEVERIFY( EnumMetaFile(hdcDraw, m_hPres, MfCallbackFuncForDraw,
(LPARAM) this) );
if (m_fMetaDC)
{
CleanStack();
}
// if m_hPalLast exists at this point, we have duped a palette
// and it needs to be freed.
if (m_hPalLast)
{
HPALETTE hPalTemp;
// when calling SelectPalette on a Metafile DC, the old
// palette is not returned. We need to select another
// palette into the metafile DC so DeleteObject can be
// called. To do this, we will use the stock palette.
if (m_fMetaDC)
{
hPalTemp = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
}
else
{
// Get the original palette selected in the DC.
hPalTemp = m_hPalDCOriginal;
}
// hPalTemp could be NULL...
if (hPalTemp)
{
// Should this palette be selected in the foreground?
// [Probably not, this code is well-tested]
SelectPalette(hdcDraw, hPalTemp, TRUE);
}
DeleteObject(m_hPalLast);
}
m_fMetaDC = FALSE;
errRtn:
LEVERIFY( RestoreDC (hdcDraw, iOldDc) );
return m_error;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetColorSet
//
// Synopsis: Retrieves the logical palette associated with the metafile
//
// Effects:
//
// Arguments: [pvAspect] -- the drawing aspect
// [hicTargetDev] -- target device
// [ppColorSet] -- where to put the logical palette pointer
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm: Plays the metafile into a new metafile. The play callback
// function stores the metafile palette which is then returned.
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::GetColorSet (LPVOID /* UNUSED pvAspect */,
HDC /* UNUSED hicTargetDev */,
LPLOGPALETTE * ppColorSet)
{
VDATEHEAP();
if (IsBlank() || !M_HPRES())
{
return ResultFromScode(OLE_E_BLANK);
}
m_pColorSet = NULL;
HDC hdcMeta = CreateMetaFile(NULL);
if (NULL == hdcMeta)
{
return ResultFromScode(E_OUTOFMEMORY);
}
m_error = NOERROR;
LEVERIFY( EnumMetaFile(hdcMeta, m_hPres, MfCallbackFuncForGetColorSet,
(LPARAM) this) );
HMETAFILE hMetaFile = CloseMetaFile(hdcMeta);
if( hMetaFile )
{
DeleteMetaFile(hMetaFile);
}
if( m_error != NOERROR )
{
return m_error;
}
if ((*ppColorSet = m_pColorSet) == NULL)
{
return ResultFromScode(S_FALSE);
}
return NOERROR;
}
//+-------------------------------------------------------------------------
//
// Function: MfCallBackFunForDraw
//
// Synopsis: callback function for drawing metafiles -- call's the caller's
// draw method (via a passed in this pointer)
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [lpHTable] -- pointer to the MF handle table
// [lpMFR] -- pointer to metafile record
// [nObj] -- number of objects
//
// Requires:
//
// Returns: non-zero to continue, zero stops the drawing
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
int CALLBACK __loadds MfCallbackFuncForDraw
(HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
LPARAM lpobj)
{
VDATEHEAP();
return ((CMfObject FAR*) lpobj)->CallbackFuncForDraw(hdc, lpHTable,
lpMFR, nObj);
}
//+-------------------------------------------------------------------------
//
// Function: MfCallbackFuncForGetColorSet
//
// Synopsis: callback function for grabbing the palette from a metafile
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [lpHTable] -- pointer to the MF handle table
// [lpMFR] -- pointer to metafile record
// [nObj] -- number of objects
//
// Requires:
//
// Returns: non-zero to continue, zero stops the drawing
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
int CALLBACK __loadds MfCallbackFuncForGetColorSet
(HDC hdc, HANDLETABLE FAR* lpHTable, METARECORD FAR* lpMFR, int nObj,
LPARAM lpobj)
{
VDATEHEAP();
return ((CMfObject FAR*) lpobj)->CallbackFuncForGetColorSet(hdc, lpHTable,
lpMFR, nObj);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::CallbackFuncForGetColorSet
//
// Synopsis: Merges all the color palettes in the metafile into
// one palette (called when GetColorSet enumerates the metafile)
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [lpHTable] -- pointer to the MF handle table
// [lpMFR] -- pointer to metafile record
// [nObj] -- number of objects
//
// Requires:
//
// Returns: non-zero to continue, zero stops the drawing
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
int CMfObject::CallbackFuncForGetColorSet(HDC /* UNUSED hdc */,
LPHANDLETABLE /* UNUSED lpHTable */,
LPMETARECORD lpMFR,
int /* UNUSED nObj */)
{
VDATEHEAP();
if (lpMFR->rdFunction == META_CREATEPALETTE)
{
LPLOGPALETTE lplogpal = (LPLOGPALETTE) &(lpMFR->rdParm[0]);
UINT uPalSize = (lplogpal->palNumEntries) *
sizeof(PALETTEENTRY)
+ 2 * sizeof(WORD);
if (m_pColorSet == NULL)
{
// This is the first CreatePalette record.
m_pColorSet = (LPLOGPALETTE)PubMemAlloc(uPalSize);
if(NULL == m_pColorSet)
{
m_error = ResultFromScode(E_OUTOFMEMORY);
return FALSE;
}
_xmemcpy(m_pColorSet, lplogpal, (size_t) uPalSize);
}
// if we hit more than one CreatePalette record then, we need to
// merge those palette records.
// REVIEW32:: err, we don't ever seem to do this
// mergeing referred to above :(
}
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::CallbackFuncForDraw
//
// Synopsis: Draws the metafile
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [lpHTable] -- pointer to the MF handle table
// [lpMFR] -- pointer to metafile record
// [nObj] -- number of objects
//
// Requires:
//
// Returns: non-zero to continue, zero stops the drawing
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 17-Dec-93 ChrisWe fixed second argument to SelectPalette calls
// 29-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
int CMfObject::CallbackFuncForDraw
(HDC hdc, LPHANDLETABLE lpHTable, LPMETARECORD lpMFR, int nObj)
{
VDATEHEAP();
if (!--m_nRecord)
{
m_nRecord = RECORD_COUNT;
if (m_pfnContinue && !((*(m_pfnContinue))(m_dwContinue)))
{
m_error = ResultFromScode(E_ABORT);
return FALSE;
}
}
if (m_fMetaDC)
{
switch (lpMFR->rdFunction)
{
case META_SETWINDOWORG:
SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
FALSE);
return TRUE;
case META_OFFSETWINDOWORG:
SetPictOrg (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0],
TRUE);
return TRUE;
case META_SETWINDOWEXT:
SetPictExt (hdc, (SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
return TRUE;
case META_SCALEWINDOWEXT:
ScalePictExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
(SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
return TRUE;
case META_SCALEVIEWPORTEXT:
ScaleRectExt (hdc, (SHORT)lpMFR->rdParm[3], (SHORT)lpMFR->rdParm[2],
(SHORT)lpMFR->rdParm[1], (SHORT)lpMFR->rdParm[0]);
return TRUE;
case META_SAVEDC:
{
BOOL fSucceeded = PushDc();
LEVERIFY( fSucceeded );
if (!fSucceeded)
return FALSE;
break;
}
case META_RESTOREDC:
LEVERIFY( PopDc() );
break;
case META_SELECTPALETTE:
{
// All selectpalette records are recorded such that the
// palette is rendered in foreground mode. Rather than
// allowing the record to play out in this fashion, we
// grab the handle and select it ourselves, forcing it
// to background (using colors already mapped in the DC)
// Dupe the palette.
HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
// Select the dupe into the DC. EnumMetaFile calls DeleteObject
// on the palette handle in the metafile handle table. If that
// palette is currently selected into a DC, we rip and leak the
// resource.
LEVERIFY( NULL != SelectPalette(hdc, hPal, TRUE) );
// if we had previously saved a palette, we need to delete
// it (for the case of multiple SelectPalette calls in a
// MetaFile).
if (m_hPalLast)
{
DeleteObject(m_hPalLast);
}
// remember our duped palette so that it can be properly destroyed
// later.
m_hPalLast = hPal;
return TRUE;
}
case META_OFFSETVIEWPORTORG:
AssertSz(0, "OffsetViewportOrg() in metafile");
return TRUE;
case META_SETVIEWPORTORG:
AssertSz(0, "SetViewportOrg() in metafile");
return TRUE;
case META_SETVIEWPORTEXT:
AssertSz(0, "SetViewportExt() in metafile");
return TRUE;
case META_SETMAPMODE:
AssertSz(lpMFR->rdParm[0] == MM_ANISOTROPIC,
"SetmapMode() in metafile with invalid mapping mode");
return TRUE;
default:
break;
}
}
else
{ // non-metafile DC. (ScreenDC or other DC...)
if (lpMFR->rdFunction == META_SELECTPALETTE)
{
// All selectpalette records are recorded such that the
// palette is rendered in foreground mode. Rather than
// allowing the record to play out in this fashion, we
// grab the handle and select it ourselves, forcing it
// to background (using colors already mapped in the DC)
HPALETTE hPal = UtDupPalette((HPALETTE) lpHTable->objectHandle[lpMFR->rdParm[0]]);
HPALETTE hPalOld = SelectPalette(hdc, hPal, TRUE);
if (!m_hPalDCOriginal)
{
m_hPalDCOriginal = hPalOld;
}
else
{
// This case gets hit if we have already stored
// the original palette from the DC. This means
// that hPalOld is a palette we have created using
// UtDupPal above. This means we need to delete
// the old palette and remember the new one.
if(hPalOld)
DeleteObject(hPalOld);
}
m_hPalLast = hPal;
return TRUE;
}
}
LEVERIFY( PlayMetaFileRecord (hdc, lpHTable, lpMFR, (unsigned) nObj) );
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::SetPictOrg (private)
//
// Synopsis: Sets the hdc's origin via SetWindowOrg
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [xOrg] -- the x origin
// [yOrg] -- the y origin
// [fOffset] -- if TRUE, [xOrg] and [yOrg] are offsets
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 29-Nov-93 alexgo 32bit port
//
// Notes: used by the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(void) CMfObject::SetPictOrg
(HDC hdc, int xOrg, int yOrg, BOOL fOffset)
{
VDATEHEAP();
if (fOffset)
{
m_pCurMdc->xMwo += xOrg;
m_pCurMdc->yMwo += yOrg;
}
else
{
m_pCurMdc->xMwo = xOrg;
m_pCurMdc->yMwo = yOrg;
}
if (m_pCurMdc->xMwe && m_pCurMdc->yMwe)
{
LEVERIFY ( SetWindowOrg (hdc, // Review (davepl) MEIN GOT!
(m_pCurMdc->xMwo -
MulDiv (m_pMetaInfo->xro, m_pCurMdc->xMwe,
m_pCurMdc->xre)),
(m_pCurMdc->yMwo -
MulDiv (m_pMetaInfo->yro, m_pCurMdc->yMwe,
m_pCurMdc->yre))) );
}
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::SetPictExt
//
// Synopsis: Sets teh metafile's extents
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [xExt] -- the X-extent
// [yExt] -- the Y-extent
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: used by the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(void) CMfObject::SetPictExt (HDC hdc, int xExt, int yExt)
{
VDATEHEAP();
m_pCurMdc->xMwe = xExt;
m_pCurMdc->yMwe = yExt;
// Assert( m_pCurMdc->xre && m_pCurMdc->yre );
int xNewExt = MulDiv (m_pMetaInfo->xwe, xExt, m_pCurMdc->xre);
int yNewExt = MulDiv (m_pMetaInfo->ywe, yExt, m_pCurMdc->yre);
int xNewOrg = m_pCurMdc->xMwo
- MulDiv (m_pMetaInfo->xro, xExt, m_pCurMdc->xre);
int yNewOrg = m_pCurMdc->yMwo
- MulDiv (m_pMetaInfo->yro, yExt, m_pCurMdc->yre);
LEVERIFY( SetWindowExt (hdc, xNewExt, yNewExt) );
LEVERIFY( SetWindowOrg (hdc, xNewOrg, yNewOrg) );
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::ScalePictExt
//
// Synopsis: Scales the metafile
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [xNum] -- the x numerator
// [xDenom] -- the x demominator
// [yNum] -- the y numberator
// [yDenom] -- the y demoninator
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: used by the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(void) CMfObject::ScalePictExt (HDC hdc,
int xNum,
int xDenom,
int yNum,
int yDenom)
{
VDATEHEAP();
Assert( xDenom && yDenom );
int xNewExt = MulDiv (m_pCurMdc->xMwe, xNum, xDenom);
int yNewExt = MulDiv (m_pCurMdc->yMwe, yNum, yDenom);
SetPictExt(hdc, xNewExt, yNewExt);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::ScaleRectExt
//
// Synopsis: scales the viewport
//
// Effects:
//
// Arguments: [hdc] -- the device context
// [xNum] -- the x numerator
// [xDenom] -- the x demominator
// [yNum] -- the y numberator
// [yDenom] -- the y demoninator
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: Used by the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(void) CMfObject::ScaleRectExt(HDC hdc,
int xNum,
int xDenom,
int yNum,
int yDenom)
{
VDATEHEAP();
AssertSz( xDenom, "Denominator is 0 for x-rect scaling");
AssertSz( yDenom, "Denominator is 0 for y-rect scaling");
m_pCurMdc->xre = MulDiv (m_pCurMdc->xre, xNum, xDenom);
m_pCurMdc->yre = MulDiv (m_pCurMdc->yre, yNum, yDenom);
SetPictExt (hdc, m_pCurMdc->xMwe, m_pCurMdc->yMwe);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::PushDC
//
// Synopsis: pushes metafile info onto a stack
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: BOOL -- TRUE if successful, FALSE otherwise
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: Used by the metafile interpreter engine.
//
//--------------------------------------------------------------------------
INTERNAL_(BOOL) CMfObject::PushDc (void)
{
VDATEHEAP();
LPMETADC pNode = NULL;
pNode = (LPMETADC) PrivMemAlloc(sizeof(METADC));
if (pNode)
{
*pNode = *m_pCurMdc;
m_pCurMdc->pNext = pNode;
pNode->pNext = NULL;
m_pCurMdc = pNode;
return TRUE;
}
m_error = ResultFromScode(E_OUTOFMEMORY);
return FALSE;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::PopDC
//
// Synopsis: pops metafile info from the metafile info stack
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: BOOL -- TRUE if successful, FALSE otherwise (more pops
// than pushes)
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: used in the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(BOOL) CMfObject::PopDc (void)
{
VDATEHEAP();
LPMETADC pPrev = (LPMETADC) (m_pMetaInfo);
LPMETADC pCur = ((LPMETADC) (m_pMetaInfo))->pNext;
if (NULL == pCur)
{
LEWARN( NULL == pCur, "More pops than pushes from DC stack" );
return FALSE;
}
while (pCur->pNext)
{
pPrev = pCur;
pCur = pCur->pNext;
}
if (pCur)
{
PrivMemFree(pCur);
}
pPrev->pNext = NULL;
m_pCurMdc = pPrev;
return TRUE;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::CleanStack
//
// Synopsis: Deletes the stack of metafile info
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes: used in the metafile interpreter
//
//--------------------------------------------------------------------------
INTERNAL_(void) CMfObject::CleanStack (void)
{
VDATEHEAP();
LPMETADC pCur;
while (NULL != (pCur = ((LPMETADC) (m_pMetaInfo))->pNext))
{
((LPMETADC) (m_pMetaInfo))->pNext = pCur->pNext;
PrivMemFree(pCur);
}
PrivMemFree(m_pMetaInfo);
m_pCurMdc = NULL;
m_pMetaInfo = NULL;
}
//+-------------------------------------------------------------------------
//
// Function: QD2GDI
//
// Synopsis: Converts macintosh pictures to Win32 GDI metafiles
//
// Effects:
//
// Arguments: [hBits] -- handle to the mac picture bits
//
// Requires:
//
// Returns: HMETAFILE
//
// Signals:
//
// Modifies:
//
// Algorithm: Loads ole2conv.dll and calls QD2GDI in that dll
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
FARINTERNAL_(HMETAFILE) QD2GDI (HANDLE hBits)
{
VDATEHEAP();
USERPREFS userPrefs =
{
{'Q','D','2','G','D','I'}, //signature
2, //structure version number
sizeof(USERPREFS), //structure size
NULL, //source filename
NULL, //or source handle
NULL, //returned memory-based
//metafile
3, //simulated pattern lines
5, //use max dimension
//non-squarer pen
1, //arithmetic transfer
1, //create opaque text
1, //simulate non-rectangular
//regions
0, //don't optimize for PowerPoint
{0,0,0,0,0,0} //reserved
};
HINSTANCE hinstFilter;
void (FAR PASCAL *qd2gdiPtr)( USERPREFS FAR *, PICTINFO FAR *);
PICTINFO pictinfo;
hinstFilter = LoadLibrary(OLESTR("OLECNV32.DLL"));
#if 0
//REVIEW:CHICAGO
//HINSTANCE_ERROR not defined in chicago
if (hinstFilter < (HINSTANCE)HINSTANCE_ERROR)
{
return NULL;
}
#endif
if (hinstFilter == NULL)
{
return NULL;
}
*((FARPROC*)&qd2gdiPtr) = GetProcAddress(hinstFilter, "QD2GDI");
userPrefs.sourceFilename = NULL;
userPrefs.sourceHandle = hBits;
pictinfo.hmf = NULL;
if (qd2gdiPtr == NULL)
{
goto errRtn;
}
(*qd2gdiPtr)( (USERPREFS FAR *)&userPrefs, (PICTINFO FAR *)&pictinfo);
errRtn:
LEVERIFY( FreeLibrary(hinstFilter) );
return (HMETAFILE)pictinfo.hmf;
}
//+-------------------------------------------------------------------------
//
// Function: MfGetSize
//
// Synopsis: Returns the size of a metafile
//
// Effects:
//
// Arguments: [lphmf] -- pointer to the metafile handle
//
// Requires:
//
// Returns: DWORD -- the size of the metafile
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(DWORD) MfGetSize (LPHANDLE lphmf)
{
VDATEHEAP();
return GetMetaFileBitsEx((HMETAFILE)*lphmf,0,NULL);
}
//+-------------------------------------------------------------------------
//
// Function: OleIsDcMeta
//
// Synopsis: Returns whether a device context is really a metafile
//
// Effects:
//
// Arguments: [hdc] -- the device context
//
// Requires:
//
// Returns: BOOL (TRUE if a metafile)
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDAPI_(BOOL) OleIsDcMeta (HDC hdc)
{
VDATEHEAP();
return (GetDeviceCaps (hdc, TECHNOLOGY) == DT_METAFILE);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::Load
//
// Synopsis: Loads an metafile object from the given stream
//
// Effects:
//
// Arguments: [lpstream] -- the stream from which to load
// [fReadHeaderOnly] -- if TRUE, then only the header is
// read
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::Load(LPSTREAM lpstream, BOOL fReadHeaderOnly)
{
VDATEHEAP();
DWORD dwBuf[4];
HRESULT error;
/* read dwCompression, width, height, size of data */
error = StRead(lpstream, dwBuf, 4*sizeof(DWORD));
if (error)
{
return error;
}
AssertSz (dwBuf[0] == 0, "Picture compression factor is non-zero");
m_lWidth = (LONG) dwBuf[1];
m_lHeight = (LONG) dwBuf[2];
m_dwSize = dwBuf[3];
if (!m_dwSize || fReadHeaderOnly)
{
return NOERROR;
}
return UtGetHMFFromMFStm(lpstream, m_dwSize, m_fConvert,
(LPLPVOID) &m_hPres);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::Save
//
// Synopsis: Saves the metafile to the given stream
//
// Effects:
//
// Arguments: [lpstream] -- the stream to save to
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::Save(LPSTREAM lpstream)
{
VDATEHEAP();
HRESULT error;
DWORD dwBuf[4];
/* write dwCompression, width, height, size of data */
dwBuf[0] = 0L;
dwBuf[1] = (DWORD) m_lWidth;
dwBuf[2] = (DWORD) m_lHeight;
dwBuf[3] = m_dwSize;
error = StWrite(lpstream, dwBuf, sizeof(dwBuf));
if (error)
{
return error;
}
// if blank object, don't write any more; no error.
if (IsBlank() || m_hPres == NULL)
{
StSetSize(lpstream, 0, TRUE);
return NOERROR;
}
return UtHMFToMFStm((LPLPVOID)&m_hPres, m_dwSize, lpstream);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetExtent
//
// Synopsis: Retrieves the extents of the metafile
//
// Effects:
//
// Arguments: [dwDrawAspect] -- the drawing aspect we're interested in
// (must match the aspect of the current
// metafile)
// [lpsizel] -- where to put the extent info
//
// Requires:
//
// Returns: NOERROR, DV_E_DVASPECT, OLE_E_BLANK
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP CMfObject::GetExtent(DWORD dwDrawAspect, LPSIZEL lpsizel)
{
VDATEHEAP();
if (0 == (dwDrawAspect & m_dwAspect))
{
return ResultFromScode(DV_E_DVASPECT);
}
if (IsBlank())
{
return ResultFromScode(OLE_E_BLANK);
}
lpsizel->cx = m_lWidth;
lpsizel->cy = m_lHeight;
return NOERROR;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::IsBlank
//
// Synopsis: Returns whether or not the metafile is blank
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: TRUE/FALSE
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(BOOL) CMfObject::IsBlank(void)
{
VDATEHEAP();
return (m_dwSize ? FALSE : TRUE);
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::LoadHPRES (private)
//
// Synopsis: Loads the presentation from the cache's stream and returns
// a handle to it
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HANDLE to the metafile
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(HANDLE) CMfObject::LoadHPRES(void)
{
VDATEHEAP();
LPSTREAM pstm;
pstm = m_pCacheNode->GetStm(TRUE /*fSeekToPresBits*/, STGM_READ);
if (pstm)
{
LEVERIFY( SUCCEEDED(Load(pstm)));
pstm->Release();
}
return m_hPres;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::DiscardHPRES
//
// Synopsis: deletes the stored metafile
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: void
//
// Signals:
//
// Modifies:
//
// Derivation: IOlePresObj
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
STDMETHODIMP_(void) CMfObject::DiscardHPRES(void)
{
VDATEHEAP();
if (m_hPres)
{
LEVERIFY( DeleteMetaFile (m_hPres) );
m_hPres = NULL;
}
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::GetCopyOfHPRES (private)
//
// Synopsis: makes a copy of the metafile (if one is present), otherwise
// just load it from the stream (but don't store it in [this]
// object)
//
// Effects:
//
// Arguments: void
//
// Requires:
//
// Returns: HANDLE to the metafile
//
// Signals:
//
// Modifies:
//
// Derivation:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 30-Nov-93 alexgo 32bit port
//
// Notes:
//
//--------------------------------------------------------------------------
INTERNAL_(HANDLE) CMfObject::GetCopyOfHPRES(void)
{
VDATEHEAP();
HANDLE hPres;
// Make a copy if the presentation data is already loaded
if (m_hPres)
{
return CopyMetaFile(m_hPres, NULL);
}
// Load the presentation data now and return the same handle.
// No need to copy the data. If the caller wants the m_hPres to be
// set he would call LoadHPRES() directly.
hPres = LoadHPRES();
m_hPres = NULL; // NULL this, LoadHPRES set it.
return hPres;
}
//+-------------------------------------------------------------------------
//
// Member: CMfObject::Dump, public (_DEBUG only)
//
// Synopsis: return a string containing the contents of the data members
//
// Effects:
//
// Arguments: [ppszDump] - an out pointer to a null terminated character array
// [ulFlag] - flag determining prefix of all newlines of the
// out character array (default is 0 - no prefix)
// [nIndentLevel] - will add a indent prefix after the other prefix
// for ALL newlines (including those with no prefix)
//
// Requires:
//
// Returns: HRESULT
//
// Signals:
//
// Modifies: [ppszDump] - argument
//
// Derivation:
//
// Algorithm: use dbgstream to create a string containing information on the
// content of data structures
//
// History: dd-mmm-yy Author Comment
// 01-Feb-95 t-ScottH author
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef _DEBUG
HRESULT CMfObject::Dump(char **ppszDump, ULONG ulFlag, int nIndentLevel)
{
int i;
char *pszPrefix;
char *pszHRESULT;
char *pszDVASPECT;
dbgstream dstrPrefix;
dbgstream dstrDump(500);
// determine prefix of newlines
if ( ulFlag & DEB_VERBOSE )
{
dstrPrefix << this << " _VB ";
}
// determine indentation prefix for all newlines
for (i = 0; i < nIndentLevel; i++)
{
dstrPrefix << DUMPTAB;
}
pszPrefix = dstrPrefix.str();
// put data members in stream
dstrDump << pszPrefix << "No. of References = " << m_ulRefs << endl;
dstrDump << pszPrefix << "pMETAINFO (Metafile information) = " << m_pMetaInfo << endl;
dstrDump << pszPrefix << "pMETADC (current device context) = " << m_pCurMdc << endl;
dstrDump << pszPrefix << "IsMetaDeviceContext? = ";
if (m_fMetaDC == TRUE)
{
dstrDump << "TRUE" << endl;
}
else
{
dstrDump << "FALSE" << endl;
}
dstrDump << pszPrefix << "No. of Records in Metafile = " << m_nRecord << endl;
pszHRESULT = DumpHRESULT(m_error);
dstrDump << pszPrefix << "Error code = " << pszHRESULT << endl;
CoTaskMemFree(pszHRESULT);
dstrDump << pszPrefix << "pLOGPALETTE (Color set palette) = " << m_pColorSet << endl;
dstrDump << pszPrefix << "ConvertFromMac? = ";
if (m_fConvert == TRUE)
{
dstrDump << "TRUE" << endl;
}
else
{
dstrDump << "FALSE" << endl;
}
dstrDump << pszPrefix << "Continue = " << ((ULONG) m_dwContinue) << endl;
dstrDump << pszPrefix << "fp Continue = " << m_pfnContinue<< endl;
pszDVASPECT = DumpDVASPECTFlags(m_dwAspect);
dstrDump << pszPrefix << "Aspect flags = " << pszDVASPECT << endl;
CoTaskMemFree(pszDVASPECT);
dstrDump << pszPrefix << "Size = " << m_dwSize << endl;
dstrDump << pszPrefix << "Width = " << m_lWidth << endl;
dstrDump << pszPrefix << "Height = " << m_lHeight << endl;
dstrDump << pszPrefix << "pCacheNode = " << m_pCacheNode << endl;
// cleanup and provide pointer to character array
*ppszDump = dstrDump.str();
if (*ppszDump == NULL)
{
*ppszDump = UtDupStringA(szDumpErrorMessage);
}
CoTaskMemFree(pszPrefix);
return NOERROR;
}
#endif // _DEBUG
//+-------------------------------------------------------------------------
//
// Function: DumpCMfObject, public (_DEBUG only)
//
// Synopsis: calls the CMfObject::Dump method, takes care of errors and
// returns the zero terminated string
//
// Effects:
//
// Arguments: [pMFO] - pointer to CMfObject
// [ulFlag] - flag determining prefix of all newlines of the
// out character array (default is 0 - no prefix)
// [nIndentLevel] - will add a indent prefix after the other prefix
// for ALL newlines (including those with no prefix)
//
// Requires:
//
// Returns: character array of structure dump or error (null terminated)
//
// Signals:
//
// Modifies:
//
// Algorithm:
//
// History: dd-mmm-yy Author Comment
// 01-Feb-95 t-ScottH author
//
// Notes:
//
//--------------------------------------------------------------------------
#ifdef _DEBUG
char *DumpCMfObject(CMfObject *pMFO, ULONG ulFlag, int nIndentLevel)
{
HRESULT hresult;
char *pszDump;
if (pMFO == NULL)
{
return UtDupStringA(szDumpBadPtr);
}
hresult = pMFO->Dump(&pszDump, ulFlag, nIndentLevel);
if (hresult != NOERROR)
{
CoTaskMemFree(pszDump);
return DumpHRESULT(hresult);
}
return pszDump;
}
#endif // _DEBUG