Windows2003-3790/windows/advcore/gdiplus/engine/gpmf3216/misc.c

867 lines
27 KiB
C
Raw Normal View History

2001-01-01 00:00:00 +01:00
/*****************************************************************************
*
* misc - Entry points for Win32 to Win 16 converter
*
* Date: 7/1/91
* Author: Jeffrey Newman (c-jeffn)
*
* Copyright 1991 Microsoft Corp
*****************************************************************************/
#include "precomp.h"
#pragma hdrstop
extern fnGetTransform pfnGetTransform;
typedef struct EMROFFICECOMMENT
{
EMR emr;
DWORD cbData; // Size of following fields and data
DWORD ident; // GDICOMMENT_IDENTIFIER
DWORD iComment; // Comment type e.g. GDICOMMENT_WINDOWS_METAFILE
} EMROFFICECOMMENT, *PEMROFFICECOMMENT;
BOOL WINAPI DoGdiCommentMultiFormats
(
PLOCALDC pLocalDC,
PEMRGDICOMMENT_MULTIFORMATS pemr
);
/***************************************************************************
* ExtFloodFill - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoExtFloodFill
(
PLOCALDC pLocalDC,
int x,
int y,
COLORREF crColor,
DWORD iMode
)
{
POINTL ptl ;
BOOL b ;
ptl.x = (LONG) x ;
ptl.y = (LONG) y ;
b = bXformRWorldToPPage(pLocalDC, &ptl, 1) ;
if (b == FALSE)
goto exit1 ;
b = bEmitWin16ExtFloodFill(pLocalDC, LOWORD(ptl.x), LOWORD(ptl.y), crColor, LOWORD(iMode)) ;
exit1:
return(b) ;
}
/***************************************************************************
* MoveToEx - Win32 to Win16 Metafile Converter Entry Point
*
* NOTE ON CURRENT POSITION
* ------------------------
* There are only three Win16 functions that use and update the
* current position (CP). They are:
*
* MoveTo
* LineTo
* (Ext)TextOut with TA_UPDATECP text alignment option
*
* In Win32, CP is used in many more functions and has two
* interpretations based on the state of the current path.
* As a result, it is easier and more robust to rely on the
* helper DC to keep track of the CP than doing it in the
* converter. To do this, we need to do the following:
*
* 1. The converter will update the CP in the helper DC in all
* records that modify the CP.
*
* 2. The converter will keep track of the CP in the converted
* metafile at all time.
*
* 3. In LineTo and (Ext)TextOut, the metafile CP is compared to
* that of the helper DC. If they are different, a MoveTo record
* is emitted. This is done in bValidateMetaFileCP().
*
* 4. The converter should emit a MoveTo record the first time the
* CP is used in the converted metafile.
*
* - HockL July 2, 1992
**************************************************************************/
BOOL WINAPI DoMoveTo
(
PLOCALDC pLocalDC,
LONG x,
LONG y
)
{
BOOL b ;
POINTL ptl ;
// Whether we are recording for a path or acutally emitting
// a drawing order we must pass the drawing order to the helper DC
// so the helper can maintain the current positon.
// If we're recording the drawing orders for a path
// then just pass the drawing order to the helper DC.
// Do not emit any Win16 drawing orders.
POINTL p = {x, y};
if (pfnSetVirtualResolution == NULL)
{
if (!bXformWorkhorse(&p, 1, &pLocalDC->xformRWorldToRDev))
{
return FALSE;
}
}
b = MoveToEx(pLocalDC->hdcHelper, (INT) p.x, (INT) p.y, (LPPOINT) &ptl) ;
if (pLocalDC->flags & RECORDING_PATH)
return(b) ;
// Update the CP in the converted metafile.
b = bValidateMetaFileCP(pLocalDC, x, y) ;
return(b) ;
}
/***************************************************************************
* bValidateMetaFiloeCP - Update the current position in the converted
* metafile.
*
* x and y are assumed to be in the record time world coordinates.
*
**************************************************************************/
BOOL bValidateMetaFileCP(PLOCALDC pLocalDC, LONG x, LONG y)
{
BOOL b ;
POINT pt ;
// Compute the new current position in the play time page coord.
pt.x = x ;
pt.y = y ;
if (!bXformRWorldToPPage(pLocalDC, (PPOINTL) &pt, 1L))
return(FALSE);
// No need to emit the record if the converted metafile has
// the same CP.
if (pLocalDC->ptCP.x == pt.x && pLocalDC->ptCP.y == pt.y)
return(TRUE);
// Call the Win16 routine to emit the move to the metafile.
b = bEmitWin16MoveTo(pLocalDC, LOWORD(pt.x), LOWORD(pt.y)) ;
// Update the mf16 current position.
pLocalDC->ptCP = pt ;
return(b) ;
}
/***************************************************************************
* SaveDC - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoSaveDC
(
PLOCALDC pLocalDC
)
{
BOOL b;
PLOCALDC pLocalDCNew;
b = FALSE;
// Save the helper DC's state first
if (!SaveDC(pLocalDC->hdcHelper))
{
RIPS("MF3216: DoSaveDC, SaveDC failed\n");
return(b);
}
// Allocate some memory for the LocalDC.
pLocalDCNew = (PLOCALDC) LocalAlloc(LMEM_FIXED, sizeof(LOCALDC));
if (pLocalDCNew == (PLOCALDC) NULL)
{
RIPS("MF3216: DoSaveDC, LocalAlloc failed\n");
return(b);
}
// Copy the data from the current LocalDC to the new one just allocated.
*pLocalDCNew = *pLocalDC;
// Link in the new level.
pLocalDC->pLocalDCSaved = pLocalDCNew;
pLocalDC->iLevel++;
// We don't want to restore a PS clip path unless we are doing it at the
// same level
pLocalDC->iSavePSClipPath = 0;
// Emit Win16 drawing order.
b = bEmitWin16SaveDC(pLocalDC);
return(b);
}
/***************************************************************************
* RestoreDC - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoRestoreDC
(
PLOCALDC pLocalDC,
int nSavedDC
)
{
BOOL b;
INT iLevel;
PLOCALDC pLocalDCNext;
PLOCALDC pLocalDCTmp;
BOOL bRet;
WORD wEscape ;
b = FALSE;
// First check to make sure this is a relative save level.
if (nSavedDC > 0)
return(b);
// Compute an absolute level.
iLevel = pLocalDC->iLevel + nSavedDC;
// The helper DC should have caught bogus levels.
ASSERTGDI((iLevel >= 0) && ((UINT) iLevel < pLocalDC->iLevel),
"MF3216: DoRestoreDC, Bogus RestoreDC");
// Before restoring the DC level.. If we are in an XOR pass and we want to
// restore the DC level to a level that is less than the Level that we started
// the pass at, we simply treat this as the end of the pass and to the start over
if( pLocalDC->iXORPass == DRAWXORPASS && iLevel <= pLocalDC->iXORPassDCLevel )
{
pLocalDC->iXORPass = OBJECTRECREATION ;
if(!DoRemoveObjects( pLocalDC ))
return FALSE ;
bRet = DoMoveTo(pLocalDC, pLocalDC->pOldPosition.x, pLocalDC->pOldPosition.y) ;
wEscape = ENDPSIGNORE;
if(!bEmitWin16Escape(pLocalDC, POSTSCRIPT_IGNORE, sizeof(wEscape), (LPSTR)&wEscape, NULL))
return FALSE ;
wEscape = CLIP_SAVE ;
if(!bEmitWin16Escape(pLocalDC, CLIP_TO_PATH, sizeof(wEscape), (LPSTR)&wEscape, NULL))
return FALSE ;
return TRUE ;
}
else if(pLocalDC->iXORPass == ERASEXORPASS && iLevel <= pLocalDC->iXORPassDCLevel )
{
pLocalDC->iXORPass = NOTXORPASS ;
pLocalDC->pbChange = NULL ;
DoSetRop2(pLocalDC, pLocalDC->iROP);
if(!DoRestoreDC(pLocalDC, -1))
return FALSE ;
wEscape = CLIP_RESTORE ;
if(!bEmitWin16Escape(pLocalDC, CLIP_TO_PATH, sizeof(wEscape), (LPSTR)&wEscape, NULL))
return FALSE ;
if (!bEmitWin16EmitSrcCopyComment(pLocalDC, msocommentEndSrcCopy))
{
return FALSE;
}
pLocalDC->iXORPassDCLevel = -1 ;
}
// We can't restore the DC if we are in an XOR pass
// Restore the helper DC's state first
// If we can restore the helper DC, we know that it is a balanced restore.
// Otherwise, we return an error.
if (!RestoreDC(pLocalDC->hdcHelper, nSavedDC))
return(b);
// Restore down to the level we want.
wEscape = CLIP_RESTORE ;
while(pLocalDC->iSavePSClipPath > 0)
{
bEmitWin16Escape(pLocalDC, CLIP_TO_PATH, sizeof(wEscape), (LPSTR)&wEscape, NULL);
// Ignore failure in this case...
pLocalDC->iSavePSClipPath--;
}
pLocalDCNext = pLocalDC->pLocalDCSaved;
while ((UINT) iLevel < pLocalDCNext->iLevel)
{
pLocalDCTmp = pLocalDCNext;
pLocalDCNext = pLocalDCNext->pLocalDCSaved;
// For each DC that has the PSClipPath set, we need to restore a PSClipPath
while(pLocalDCTmp->iSavePSClipPath > 0)
{
bEmitWin16Escape(pLocalDC, CLIP_TO_PATH, sizeof(wEscape), (LPSTR)&wEscape, NULL);
// Ignore failure in this case...
pLocalDCTmp->iSavePSClipPath--;
}
if (LocalFree(pLocalDCTmp))
ASSERTGDI(FALSE, "MF3216: DoRestoreDC, LocalFree failed");
}
// Restore the state of our local DC to that level.
// keep some of the attributes in the current DC
pLocalDCNext->ulBytesEmitted = pLocalDC->ulBytesEmitted;
pLocalDCNext->ulMaxRecord = pLocalDC->ulMaxRecord;
pLocalDCNext->nObjectHighWaterMark = pLocalDC->nObjectHighWaterMark;
pLocalDCNext->pbCurrent = pLocalDC->pbCurrent;
pLocalDCNext->pbRecord = pLocalDC->pbRecord;
pLocalDCNext->pbChange = pLocalDC->pbChange;
pLocalDCNext->cW16ObjHndlSlotStatus = pLocalDC->cW16ObjHndlSlotStatus;
pLocalDCNext->pW16ObjHndlSlotStatus = pLocalDC->pW16ObjHndlSlotStatus;
pLocalDCNext->iROP = pLocalDC->iROP;
pLocalDCNext->pOldPosition = pLocalDC->pOldPosition;
pLocalDCNext->iXORPass = pLocalDC->iXORPass;
pLocalDCNext->iXORPassDCLevel = pLocalDC->iXORPassDCLevel;
pLocalDCNext->pW16RecreationSlot = pLocalDC->pW16RecreationSlot;
// now restore the other attributes
*pLocalDC = *pLocalDCNext;
// Free the local copy of the DC.
if (LocalFree(pLocalDCNext))
ASSERTGDI(FALSE, "MF3216: DoRestoreDC, LocalFree failed");
// Emit the record to the Win16 metafile.
b = bEmitWin16RestoreDC(pLocalDC, LOWORD(nSavedDC)) ;
return (b) ;
}
/***************************************************************************
* SetRop2 - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoSetRop2
(
PLOCALDC pLocalDC,
DWORD rop
)
{
BOOL b ;
if (pLocalDC->iXORPass == DRAWXORPASS)
{
// If we are drawing during an XOR pass then the only ROP we support is
// SRCCOPY and then we set it to XOR
if (rop == R2_COPYPEN)
{
rop = R2_XORPEN;
}
else
{
pLocalDC->flags |= ERR_XORCLIPPATH;
return FALSE;
}
}
// Do it to the helper DC.
SetROP2(pLocalDC->hdcHelper, rop);
// Emit the Win16 metafile drawing order.
b = bEmitWin16SetROP2(pLocalDC, LOWORD(rop)) ;
return(b) ;
}
/***************************************************************************
* SetBkMode - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoSetBkMode
(
PLOCALDC pLocalDC,
DWORD iBkMode
)
{
BOOL b ;
// Do it to the helper DC. It needs this in a path bracket
// if a text string is drawn.
SetBkMode(pLocalDC->hdcHelper, (int) iBkMode);
// Emit the Win16 metafile drawing order.
b = bEmitWin16SetBkMode(pLocalDC, LOWORD(iBkMode)) ;
return(b) ;
}
/***************************************************************************
* SetBkColor - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL APIENTRY DoSetBkColor
(
PLOCALDC pLocalDC,
COLORREF crColor
)
{
BOOL b ;
pLocalDC->crBkColor = crColor; // used by brushes
// Emit the Win16 metafile drawing order.
b = bEmitWin16SetBkColor(pLocalDC, crColor) ;
return(b) ;
}
/***************************************************************************
* GdiComment - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoGdiComment
(
PLOCALDC pLocalDC,
PEMR pemr
)
{
BOOL b;
PEMRGDICOMMENT_PUBLIC pemrComment = (PEMRGDICOMMENT_PUBLIC) pemr;
PEMROFFICECOMMENT pemrOffice = (PEMROFFICECOMMENT) pemr;
if (pemrOffice->emr.nSize == sizeof(EMROFFICECOMMENT)
&& pemrOffice->ident == msosignature)
{
// This is not necessarily a SrcCopy comment, but an Office Comment
return (bEmitWin16EmitSrcCopyComment(pLocalDC, LOWORD(pemrOffice->iComment)));
}
// If it's not a public comment, just return TRUE.
if (pemrComment->emr.nSize < sizeof(EMRGDICOMMENT_PUBLIC)
|| pemrComment->ident != GDICOMMENT_IDENTIFIER)
return(TRUE);
// Handle public comments.
// A public comment consists of a public comment identifier,
// a comment type, plus any accompanying data.
switch (pemrComment->iComment)
{
case GDICOMMENT_MULTIFORMATS:
b = DoGdiCommentMultiFormats(pLocalDC, (PEMRGDICOMMENT_MULTIFORMATS) pemr);
break;
case GDICOMMENT_BEGINGROUP:
case GDICOMMENT_ENDGROUP:
case GDICOMMENT_WINDOWS_METAFILE:
default:
b = TRUE;
break;
}
return(b) ;
}
BOOL WINAPI DoGdiCommentMultiFormats
(
PLOCALDC pLocalDC,
PEMRGDICOMMENT_MULTIFORMATS pemrcmf
)
{
DWORD i;
DWORD cSizeOld;
int iBase;
XFORM xformNew, xformScale;
POINTL aptlFrame[4];
RECTL rclFrame;
UINT cbwmfNew;
SIZEL szlDeviceNew, szlMillimetersNew;
BOOL bRet = FALSE;
PBYTE pbwmfNew = (PBYTE) NULL;
HDC hdcemfNew = (HDC) 0;
HENHMETAFILE hemf = (HENHMETAFILE) 0;
HENHMETAFILE hemfNew = (HENHMETAFILE) 0;
PENHMETAHEADER pemfh;
WIN16LOGBRUSH Win16LogBrush;
PMETARECORD pmr;
VOID* pvTemp = NULL;
#if DBG
int iSWO = 0;
int iSWE = 0;
#endif
// We will convert the enhanced metafile format only.
// Find the enhanced metafile data.
for (i = 0; i < pemrcmf->nFormats; i++)
{
if (pemrcmf->aemrformat[i].dSignature == ENHMETA_SIGNATURE
&& pemrcmf->aemrformat[i].nVersion <= META_FORMAT_ENHANCED)
break;
}
// If we cannot find a recognized format, return failure.
if (i >= pemrcmf->nFormats)
{
PUTS("MF3216: DoGdiCommentMultiFormats - no recognized format found\n");
goto dgcmf_exit;
}
// Get the embedded enhanced metafile.
hemf = SetEnhMetaFileBits((UINT) pemrcmf->aemrformat[i].cbData,
&((PBYTE) &pemrcmf->ident)[pemrcmf->aemrformat[i].offData]);
if (!hemf)
goto dgcmf_exit;
// Now the fun begins - we have to convert the enhanced metafile to
// Windows metafile.
// Since the multiformats record takes a logical rectangle, we have to
// set up a proper transform for the enhanced metafile. We do it by
// creating a new enhanced metafile and playing the embedded metafile
// into the new metafile with the proper transform setup.
// In addition, the new metafile may have a different resolution than the
// metafile. We need to take this into account when setting up
// the transform.
// Get the world to device transform for the logical rectangle.
if( pfnGetTransform != NULL )
{
if (!(pfnGetTransform)(pLocalDC->hdcHelper, XFORM_WORLD_TO_DEVICE, &xformNew))
goto dgcmf_exit;
}
else
{
xformNew = xformIdentity ;
}
// Compute the device scales.
szlDeviceNew.cx = GetDeviceCaps(pLocalDC->hdcRef, HORZRES);
szlDeviceNew.cy = GetDeviceCaps(pLocalDC->hdcRef, VERTRES);
szlMillimetersNew.cx = GetDeviceCaps(pLocalDC->hdcRef, HORZSIZE);
szlMillimetersNew.cy = GetDeviceCaps(pLocalDC->hdcRef, VERTSIZE);
pemfh = (PENHMETAHEADER) pLocalDC->pMf32Bits;
xformScale.eM11 = ((FLOAT) szlDeviceNew.cx / (FLOAT) szlMillimetersNew.cx)
/ ((FLOAT) pemfh->szlDevice.cx / (FLOAT) pemfh->szlMillimeters.cx);
xformScale.eM12 = 0.0f;
xformScale.eM21 = 0.0f;
xformScale.eM22 = ((FLOAT) szlDeviceNew.cy / (FLOAT) szlMillimetersNew.cy)
/ ((FLOAT) pemfh->szlDevice.cy / (FLOAT) pemfh->szlMillimeters.cy);
xformScale.eDx = 0.0f;
xformScale.eDy = 0.0f;
// Compute the resulting transform to apply to the new metafile.
if (!bCombineTransform(&xformNew, &xformNew, &xformScale))
goto dgcmf_exit;
// Create the new enhanced metafile.
// Compute the new metafile frame.
aptlFrame[0].x = pemrcmf->rclOutput.left;
aptlFrame[0].y = pemrcmf->rclOutput.top;
aptlFrame[1].x = pemrcmf->rclOutput.right;
aptlFrame[1].y = pemrcmf->rclOutput.top;
aptlFrame[2].x = pemrcmf->rclOutput.right;
aptlFrame[2].y = pemrcmf->rclOutput.bottom;
aptlFrame[3].x = pemrcmf->rclOutput.left;
aptlFrame[3].y = pemrcmf->rclOutput.bottom;
if (!bXformWorkhorse(aptlFrame, 4, &xformNew))
goto dgcmf_exit;
rclFrame.left = MulDiv(100 * MIN4(aptlFrame[0].x, aptlFrame[1].x,
aptlFrame[2].x, aptlFrame[3].x),
szlMillimetersNew.cx,
szlDeviceNew.cx);
rclFrame.right = MulDiv(100 * MAX4(aptlFrame[0].x, aptlFrame[1].x,
aptlFrame[2].x, aptlFrame[3].x),
szlMillimetersNew.cx,
szlDeviceNew.cx);
rclFrame.top = MulDiv(100 * MIN4(aptlFrame[0].y, aptlFrame[1].y,
aptlFrame[2].y, aptlFrame[3].y),
szlMillimetersNew.cy,
szlDeviceNew.cy);
rclFrame.bottom = MulDiv(100 * MAX4(aptlFrame[0].y, aptlFrame[1].y,
aptlFrame[2].y, aptlFrame[3].y),
szlMillimetersNew.cy,
szlDeviceNew.cy);
hdcemfNew = CreateEnhMetaFileA(pLocalDC->hdcRef, (LPCSTR) NULL,
(CONST RECT *) &rclFrame, (LPCSTR) NULL);
if (!hdcemfNew)
goto dgcmf_exit;
if (!SetGraphicsMode(hdcemfNew, GM_ADVANCED))
goto dgcmf_exit;
// Set up the transform in the new metafile.
if (!SetWorldTransform(hdcemfNew, &xformNew))
goto dgcmf_exit;
// Play the embedded metafile into the new metafile.
// This call ensures balanced level etc.
(void) PlayEnhMetaFile(hdcemfNew, hemf, (LPRECT) &pemrcmf->rclOutput);
// Close the new metafile.
hemfNew = CloseEnhMetaFile(hdcemfNew);
hdcemfNew = (HDC) 0; // used by clean up code below
// Convert the new enhanced metafile to windows metafile.
if (!(cbwmfNew = GetWinMetaFileBits(hemfNew, 0, (LPBYTE) NULL,
MM_ANISOTROPIC, pLocalDC->hdcRef)))
goto dgcmf_exit;
if (!(pbwmfNew = (PBYTE) LocalAlloc(LMEM_FIXED, cbwmfNew)))
goto dgcmf_exit;
if (cbwmfNew != GetWinMetaFileBits(hemfNew, cbwmfNew, pbwmfNew,
MM_ANISOTROPIC, pLocalDC->hdcRef))
goto dgcmf_exit;
// We now have the converted windows metafile. We need to include it into
// our current data stream. There are a few things to be aware of:
//
// 1. Expand the object handle slot table. The converted metafile may
// contain some undeleted objects. These objects are likely
// the "stock" objects in the converter. As a result, we need to
// expand the slot table by the number of object handles in the
// converted metafile.
// 2. The object index must be changed to the current object index.
// We are going to do this by the lazy method, i.e. we will elevate
// the current object index base to one higher than the current max
// object index in the current data stream. This is because Windows uses
// some an insane scheme for object index and this is the cheapest
// method. We elevate the object index base by filling up the empty
// indexes with dummy objects that are freed when we are done.
// 3. Remove the now useless comments.
// 4. Skip header and eof.
// 5. Set up the transform to place the embedded metafile into the data
// stream. We know that the metafile bits returned by the converter
// contains only a SetWindowOrg and a SetWindowExt record.
// By implementation, we can simply remove both the SetWindowOrg and
// SetWindowExt records from the data stream. The window origin and
// extents have been set up when we begin converting this enhanced
// metafile.
// Expand the object handle slot table.
if (((PMETAHEADER) pbwmfNew)->mtNoObjects)
{
cSizeOld = (DWORD) pLocalDC->cW16ObjHndlSlotStatus;
if (cSizeOld + ((PMETAHEADER)pbwmfNew)->mtNoObjects > (UINT) (WORD) MAXWORD)
goto dgcmf_exit; // w16 handle index is only 16-bit
pLocalDC->cW16ObjHndlSlotStatus += ((PMETAHEADER)pbwmfNew)->mtNoObjects;
i = pLocalDC->cW16ObjHndlSlotStatus * sizeof(W16OBJHNDLSLOTSTATUS);
// Allocate in a new pointer in case the allocation fails
pvTemp = LocalReAlloc(pLocalDC->pW16ObjHndlSlotStatus, i, LMEM_MOVEABLE);
if (pvTemp == NULL)
{
// Restore the old size and keep the memory...
pLocalDC->cW16ObjHndlSlotStatus = cSizeOld;
goto dgcmf_exit;
}
pLocalDC->pW16ObjHndlSlotStatus = (PW16OBJHNDLSLOTSTATUS) pvTemp;
for (i = cSizeOld; i < pLocalDC->cW16ObjHndlSlotStatus; i++)
{
pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT;
pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
}
}
// Find the new base for the object index.
for (iBase = pLocalDC->cW16ObjHndlSlotStatus - 1; iBase >= 0; iBase--)
{
if (pLocalDC->pW16ObjHndlSlotStatus[iBase].use != OPEN_AVAILABLE_SLOT)
break;
}
iBase++;
// Fill up the object index table with dummy objects.
Win16LogBrush.lbStyle = BS_SOLID;
Win16LogBrush.lbColor = 0;
Win16LogBrush.lbHatch = 0;
for (i = 0; i < (DWORD) iBase; i++)
{
if (pLocalDC->pW16ObjHndlSlotStatus[i].use == OPEN_AVAILABLE_SLOT)
{
if (!bEmitWin16CreateBrushIndirect(pLocalDC, &Win16LogBrush))
goto dgcmf_exit;
pLocalDC->pW16ObjHndlSlotStatus[i].use = REALIZED_DUMMY;
}
}
// Update the high water mark.
if (iBase + ((PMETAHEADER) pbwmfNew)->mtNoObjects - 1 > pLocalDC->nObjectHighWaterMark)
pLocalDC->nObjectHighWaterMark = iBase + ((PMETAHEADER) pbwmfNew)->mtNoObjects - 1;
// Save DC states.
if (!bEmitWin16SaveDC(pLocalDC))
goto dgcmf_exit;
// Enumerate the records and fix them up as necessary.
for (pmr = (PMETARECORD) (pbwmfNew + sizeof(METAHEADER));
pmr->rdFunction != 0;
pmr = (PMETARECORD) ((PWORD) pmr + pmr->rdSize))
{
switch (pmr->rdFunction)
{
case META_SETWINDOWORG:
ASSERTGDI(++iSWO <= 1,
"MF3216: DoGdiCommentMultiFormats - unexpected SWO record\n");
break;
case META_SETWINDOWEXT:
ASSERTGDI(++iSWE <= 1,
"MF3216: DoGdiCommentMultiFormats - unexpected SWE record\n");
break;
case META_ESCAPE:
if (!IS_META_ESCAPE_ENHANCED_METAFILE((PMETA_ESCAPE_ENHANCED_METAFILE) pmr))
goto default_alt;
break;
case META_RESTOREDC:
ASSERTGDI((int)(SHORT)pmr->rdParm[0] < 0,
"MF3216: DoGdiCommentMultiFormats - bogus RestoreDC record\n");
goto default_alt;
case META_SELECTCLIPREGION:
if (pmr->rdParm[0] != 0) // allow for default clipping!
{
pmr->rdParm[0] += (WORD)iBase;
pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = REALIZED_OBJECT;
}
goto default_alt;
case META_FRAMEREGION:
case META_FILLREGION:
pmr->rdParm[1] += (WORD)iBase;
pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[1]].use = REALIZED_OBJECT;
// fall through
case META_PAINTREGION:
case META_INVERTREGION:
case META_DELETEOBJECT:
case META_SELECTPALETTE:
case META_SELECTOBJECT:
pmr->rdParm[0] += (WORD)iBase;
if (pmr->rdFunction != META_DELETEOBJECT)
pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = REALIZED_OBJECT;
else
pLocalDC->pW16ObjHndlSlotStatus[pmr->rdParm[0]].use = OPEN_AVAILABLE_SLOT;
// fall through
default:
default_alt:
if (!bEmit(pLocalDC, (PVOID) pmr, pmr->rdSize * sizeof(WORD)))
goto dgcmf_exit;
vUpdateMaxRecord(pLocalDC, pmr);
break;
}
}
// Restore DC states.
if (!bEmitWin16RestoreDC(pLocalDC, (WORD) -1))
goto dgcmf_exit;
// Remove the dummy objects from the handle table.
for (i = 0; i < (DWORD) iBase; i++)
{
if (pLocalDC->pW16ObjHndlSlotStatus[i].use == REALIZED_DUMMY)
{
if (!bEmitWin16DeleteObject(pLocalDC, (WORD) i))
goto dgcmf_exit;
pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT;
}
}
// Shrink the object handle slot table.
if (((PMETAHEADER) pbwmfNew)->mtNoObjects)
{
DWORD cUndel = 0; // number of objects not deleted
DWORD iUndelMax = iBase - 1; // the max undeleted object index
for (i = iBase; i < pLocalDC->cW16ObjHndlSlotStatus; i++)
{
if (pLocalDC->pW16ObjHndlSlotStatus[i].use != OPEN_AVAILABLE_SLOT)
{
cUndel++;
iUndelMax = i;
}
}
pLocalDC->cW16ObjHndlSlotStatus = max(cSizeOld + cUndel, iUndelMax + 1);
}
// Everything is golden.
bRet = TRUE;
dgcmf_exit:
if (pbwmfNew)
if (LocalFree(pbwmfNew))
ASSERTGDI(FALSE, "MF3216: DoGdiCommentMultiFormats - LocalFree failed\n");
if (hemf)
DeleteEnhMetaFile(hemf);
if (hdcemfNew)
hemfNew = CloseEnhMetaFile(hdcemfNew); // hemfNew will be deleted next
if (hemfNew)
DeleteEnhMetaFile(hemfNew);
return(bRet);
}
/***************************************************************************
* EOF - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL APIENTRY DoEOF
(
PLOCALDC pLocalDC
)
{
BOOL b ;
b = bEmitWin16EOF(pLocalDC) ;
return(b) ;
}