Windows2003-3790/windows/advcore/gdiplus/engine/gpmf3216/objects.c
2020-09-30 16:53:55 +02:00

1478 lines
51 KiB
C

/*****************************************************************************
*
* objects - Entry points for Win32 to Win 16 converter
*
* Date: 7/1/91
* Author: Jeffrey Newman (c-jeffn)
*
* Copyright 1991 Microsoft Corp
*
*
* 14-Jan-1992
* Jeffrey Newman
*
* CR1: 14-Jan-1992 - this entire comment and the design that it
* specifies.
*
* The Object system in mf3216.
*
* Overview
*
* The Win32 objects (represented by object handle indicies) must be
* mapped to Win16 objects (also represented by object handle indices).
* Win32 uses stock objects, Win16 does not. MF3216 uses a scheme
* for lazy stock object creation. Through lazy stock object creation
* no unused objects will be emitted into the Win16 metafile.
*
* Objects in a Win16 metafile are maintained in an Object Table. The
* object table is not recorded in the Win16 metafile. It is created at
* play-time. Each entry in the Win16-Object-Table is called a slot.
* Slots are allocated one per object. If an object is deleted then the
* slot becomes available for the next object created. The first object-
* slot, starting from 0, in a linear search, that is available will be
* used to hold the next create object request.
*
* Objects in either a Win32 or a Win16 metafile are represented as an
* index into the Object Table. Every object created must occupy
* the same slot at play-time that it would have occupied at record-time.
*
* Win32 objects have an object ID (index in the handle table) recorded
* with them. Win16 objects do not.
*
* Data Structures
*
* There are two primary data structures used in the translation of
* Win32 objects to Win16 objects. Both of them are dynamically
* allocated arrays. The size of these arrays are determined by
* estimating the number of objects required in the Win16 metafile from
* the size of the handle table used in the Win32 metafile. The size of
* the handle table is recorded in the Win32 metafile header.
*
* The data structure piW16ObjectHandleSlotStatus is used to represent
* the status of the Win16 handle table as it would appear at any point
* during the Win16 metafile playback process. A slot is either in
* use or free.
*
* The data structure piW32ToW16ObjectMap is a translation table
* from the Win32 object indicies to the Win16 object indicies.
* The position in the array (aka the index into the array) is the
* Win32 handle. The value in this entry is the Win16 slot number
* for the handle.
*
* The first 16 entries in piW32ToW16ObjectMap array are used for the
* stock objects.
*
* Support Routines
*
* bInitHandleTableManager
*
* 1] Allocate memory for pW16ObjHndlSlotStatus and
* piW32ToW16ObjectMap arrays.
*
* 2] Initialize pW16ObjHndlSlotStatus and
* piW32ToW16ObjectMap to empty and UNMAPPED respectively.
*
* 3] Returns a TRUE if there were no problems with the
* initialization, FALSE if anything went wrong.
*
* 4] It is expected that this routie will be called once from
* the entry level routine when translation is first started.
*
* iNormalizeHandle
*
* 1] The idea behind this routine is to isolate the handling
* of stock object handles to one place.
*
* 2] Input will be a Win32 handle index, either stock or a
* standard object.
*
* 3] Output will be the index of the entry in the
* piW32ToW16ObjectMap table that corresponds to the W32
* handle. If an error is detected -1 is returned.
*
* 4] All the stock objects will be between the range of 0
* and LAST_STOCK, and all the non-stock objects will be
* greater than LAST_STOCK.
*
* iGetW16ObjectHandleSlot
*
* 1] This routine searches the pW16ObjHndlSlotStatus array
* looking for the first available open slot.
*
* 2] Mark the slot found as to its intended use.
*
* 3] Returns the first open slot if found, else return -1.
*
* 4] In essence this routine mimics the actions of the
* Win16 play-time handle allocation system, in either
* Win3.0 or Win3.1
*
* 5] We also keep track of the max object count here.
*
* iAllocateW16Handle
*
* 1] This routine actually does the handle allocation.
*
* 2] It sets the entry in pW16ObjHndlSlotStatus array
* for the slot allocated by iGetW16ObjectHandleSlot to
* an "in-use" status (for the intended use).
*
* 3] It returns a ihW16 (an index handle to the Win16 handle
* table, aka the Win16 handle slot number).
*
* iValidateHandle
*
* 1] This routine does a lot more than validate a Win32 handle.
* It does some limited error checking on the Win32 handle,
* to make sure its within a reasonable range. Then if a
* Win16 handle table slot has already been allocated for
* this Win32 handle it will return the Win16 handle that
* was previously allocated. Alternatively, if a Win16
* handle has not been previously allocated for a Win32
* STOCK handle it will allocate a W16 handle and return the
* Win16 handle. This function is called by FillRgn, FrameRgn
* and SelectObject to allow lazy allocation of stock objects.
*
* 2] Input is a Win32 handle, either a stock or a non-stock
* handle.
*
* 3] Output is a Win16 handle, this is the value in the
* Win32-index of the piW32ToW16ObjectMap. If a stock object
* does not exist, it will create one.
*
* 4] If there is an error a -1 is returned.
*
* Doer Routines
*
* All the Doers return a bool. TRUE if everything went OK.
* FALSE if there were any problems.
*
* NOTE: The Doers that create an object actually must do
* quite a bit of work to translate the object's prameters.
* This is in addition to managing the handle table. The
* work outlined below just deals with the management of the
* handle table.
*
* DoSelectObject
*
* 1] For stock objects this is the workhorse routine.
*
* 2] For normal, non-stock, objects this routine will verify
* that an object has been created for this Win32 object-index.
* Then it will emit a Win16SelectObject metafile record.
*
* 3] For stock objects things get a little more complicated.
* First this routine must make sure a Win16 object has been
* created for this stock object. If a Win16 object has not
* been created yet, then it will be. After a Win16 object
* is created a Win16SelectObject record will be emitted for
* the object.
*
* DoDeleteObject
*
* 1] The object handle is checked for reasonable limits.
* We will also make sure that the Win16 slot has a handle
* allocated to it. If it does not then we will return an
* error.
*
* 2] If this is a stock object we fail and return an error.
*
* 3] If this is a non-stock object we emit a Win16DeleteObject
* record. Then we set pW16ObjHndlSlotStatus to
* indicate that this slot is available. We also set
* piW32ToW16ObjectMap to -1 (UNMAPPED).
*
* DoCreatePen
* DoExtCreatePen
* DoCreateBrushIndirect
* DoCreateMonoBrush
* DoCreateDIBPatternBrush
* DoExtCreateFont
*
* 1] Make sure the Win32 handle is not already being used
* for something else. If it is return an error.
*
* 2] Validate the handle for this Object. This will return
* a Win16 object table index (actually a slot number).
* We really don't care what the slot number is as long
* as we got one. DoDeleteObject and DoSelectObject always
* refer to handles by their Win32 object indicies, and there
* is no place else where used.
*
* 3] Emit a Win16CreateObject metafile record.
*
*
* Special Routines
*
* bCommonRegionCode
* Need to list the bitblt routines that use handles also
*
* 1] These routines just need to create objects in the Win16
* metafile. There are no corresponding objects in the Win32
* metafile.
*
* 2] Allocate a Win16 handle.
*
* 3] Use the object as needed. This includes emitting a
* region or bitmap object into the Win16 metafile.
*
* 4] De-allocate the object. This include emitting a
* DeleteObject record.
*
* CR1
* Paths require the current pen to selected into the helperDC.
* In order to keep track of create, select, & delete of the pen
* object we will add an extra field to the W16ObjectHandleSlotStatus
* array entries. This new field will contain either a NULL handle
* or a valid Win32 handle. Currently only pens need to be selected
* into the helper DC for paths, so they are the only objects whose
* W32 handle field is not NULL.
*
*****************************************************************************/
#include "precomp.h"
#pragma hdrstop
#define ABS(A) ((A) < 0 ? (-(A)) : (A))
// Stock objects Name Stock
// Object
// ID
LOGBRUSH albStock[] = {
{BS_SOLID, 0x0FFFFFF, 0}, // White Brush 0
{BS_SOLID, 0x0C0C0C0, 0}, // Ligh Grey Brush 1
{BS_SOLID, 0x0808080, 0}, // Grey Brush 2
{BS_SOLID, 0x0404040, 0}, // Dark Grey Brush 3
{BS_SOLID, 0x0000000, 0}, // Black Brush 4
{BS_HOLLOW, 0x0000000, 0} // Hollow Brush 5
} ;
LOGPEN alpnStock[] = {
{PS_SOLID, 0, 0, 0x0FFFFFF}, // White Pen 6
{PS_SOLID, 0, 0, 0x0000000}, // Black Pen 7
{PS_NULL, 0, 0, 0x0FFFFFF} // Null Pen 8
} ;
// Internal function prototypes.
BOOL bCreateStockObject(PLOCALDC pLocalDC, INT ihw32Norm) ;
BOOL bCreateStockFont(PLOCALDC pLocalDC, INT ihW32) ;
/***************************************************************************
* bInitHandleTableManager - Init the Handle Table Manager.
*
* 1] Allocate memory for pW16ObjHndlSlotStatus and
* piW32ToW16ObjectMap arrays.
*
* 2] Initialize pW16ObjHndlSlotStatus and
* piW32ToW16ObjectMap to empty and UNMAPPED respectively.
*
* 3] Returns a TRUE if there were no problems with the
* initialization, FALSE if anything went wrong.
*
* 4] It is expected that this routie will be called once from
* the entry level routine when translation is first started.
*
**************************************************************************/
BOOL bInitHandleTableManager(PLOCALDC pLocalDC, PENHMETAHEADER pmf32header)
{
BOOL b ;
UINT i ;
b = FALSE ;
// The total number of handles required will be the stock handles
// plus the handles used by the Win32 metafile plus one extra
// for temporary brush used in opaque rectangle in textout.
pLocalDC->cW32ToW16ObjectMap = pmf32header->nHandles + (STOCK_LAST + 1) + 1;
// Allocate storage for the translation map.
i = pLocalDC->cW32ToW16ObjectMap * sizeof(INT) ;
pLocalDC->piW32ToW16ObjectMap = (PINT) LocalAlloc(LMEM_FIXED, i) ;
if (pLocalDC->piW32ToW16ObjectMap == NULL)
goto error_exit ;
// Initialize the W32 to W16 object map to UNMAPPED (-1).
// Since we never will have mapping to -1 we can test for
// -1 in the map to make sure we are not double allocating a slot.
for (i = 0 ; i < pLocalDC->cW32ToW16ObjectMap ; i++)
pLocalDC->piW32ToW16ObjectMap[i] = UNMAPPED ;
// Allocate storage for the slot status tables.
// The number of Win16 object table slot may expand during conversion
// due to temporary bitmaps and regions. It is my educated guess
// that we will never need more than 5 extra slots, because we
// only use a slot for a very short time, then free it. We are
// allocating 256 extra slots in the name of robustness.
// Note that the multi-format comment record may take up some
// of these slots and increase the high water mark for object index.
// We need to expand the table when required.
pLocalDC->cW16ObjHndlSlotStatus = pLocalDC->cW32ToW16ObjectMap + 256 ;
if (pLocalDC->cW16ObjHndlSlotStatus > (UINT) (WORD) MAXWORD)
goto error_exit ; // w16 handle index is only 16-bit
i = pLocalDC->cW16ObjHndlSlotStatus * sizeof(W16OBJHNDLSLOTSTATUS) ;
pLocalDC->pW16ObjHndlSlotStatus
= (PW16OBJHNDLSLOTSTATUS) LocalAlloc(LMEM_FIXED, i) ;
if (pLocalDC->pW16ObjHndlSlotStatus == NULL)
goto error_exit ;
// Initialize the W16ObjectHandleSlotStatus to a state where every
// handle is available.
for (i = 0 ; i < pLocalDC->cW16ObjHndlSlotStatus ; i++)
{
pLocalDC->pW16ObjHndlSlotStatus[i].use = OPEN_AVAILABLE_SLOT ;
pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
pLocalDC->pW16ObjHndlSlotStatus[i].iXORPassCreation = NOTXORPASS ;
pLocalDC->pW16ObjHndlSlotStatus[i].pbCreatRec = NULL ;
}
// Initialize the pW32hPal palette handle table.
// This table is used to store the W32 palette handles created during
// the conversion.
pLocalDC->cW32hPal = pmf32header->nHandles;
i = pLocalDC->cW32hPal * sizeof(HPALETTE);
pLocalDC->pW32hPal = (HPALETTE *) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, i) ;
if (pLocalDC->pW32hPal == NULL)
goto error_exit ;
b = TRUE;
error_exit:
if (!b)
{
if (pLocalDC->piW32ToW16ObjectMap)
{
if (LocalFree(pLocalDC->piW32ToW16ObjectMap))
ASSERTGDI(FALSE, "MF3216: LocalFree failed");
pLocalDC->piW32ToW16ObjectMap = (PINT) NULL;
}
if (pLocalDC->pW16ObjHndlSlotStatus)
{
if (LocalFree(pLocalDC->pW16ObjHndlSlotStatus))
ASSERTGDI(FALSE, "MF3216: LocalFree failed");
pLocalDC->pW16ObjHndlSlotStatus = NULL;
}
}
return(b) ;
}
/***************************************************************************
* bDeleteW16Object - Delete a W16 Object.
*
* This is the routine that is called to Delete a W16 Object that has
* no corresponding W32 object. Region and Bitmaps are two examples.
**************************************************************************/
BOOL bDeleteW16Object(PLOCALDC pLocalDC, INT ihW16)
{
BOOL b ;
ASSERTGDI
(
pLocalDC->pW16ObjHndlSlotStatus[ihW16].use != OPEN_AVAILABLE_SLOT,
"MF3216: bDeleteW16Object, bad use value"
);
// Mark the W16 Slot just freed as available.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].use = OPEN_AVAILABLE_SLOT ;
// Emit a Win16 DeleteOject record for the Object
b = bEmitWin16DeleteObject(pLocalDC, LOWORD(ihW16)) ;
return (b) ;
}
/***************************************************************************
* iGetW16ObjectHandleSlot - return the first W16 open slot in the handle
* table.
*
* 1] This routine searches the pW16ObjHndlSlotStatus array
* looking for the first available open slot.
*
* 2] Mark the slot found as to its intended use.
*
* 3] Returns the first open slot if found, else return -1.
*
* 4] In essence this routine mimics the actions of the
* Win16 play-time handle allocation system, in either
* Win3.0 or Win3.1
*
* 5] We also keep track of the max object count here.
*
**************************************************************************/
INT iGetW16ObjectHandleSlot(PLOCALDC pLocalDC, INT iIntendedUse)
{
BOOL b ;
UINT i ;
b = FALSE ;
// Search for an available slot.
for (i = 0 ; i < pLocalDC->cW16ObjHndlSlotStatus ; i++)
{
if (pLocalDC->pW16ObjHndlSlotStatus[i].use == OPEN_AVAILABLE_SLOT)
{
b = TRUE ;
break ;
}
}
// If a slot was found then mark its intended use.
// Also set the W32 handle that may be associated with this
// W16 handle to NULL. (Meaning no association at this time.)
if (b)
{
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle == 0,
"MF3216: iGetW16ObjectHandleSlot: w32Handle is not 0");
pLocalDC->pW16ObjHndlSlotStatus[i].use = iIntendedUse ;
pLocalDC->pW16ObjHndlSlotStatus[i].w32Handle = 0 ;
pLocalDC->pW16ObjHndlSlotStatus[i].iXORPassCreation = pLocalDC->iXORPass ;
pLocalDC->pW16ObjHndlSlotStatus[i].pbCreatRec = pLocalDC->pbRecord ;
// Update the number of object counts. This will be used
// when we update the metafile header.
if ((INT) i >= pLocalDC->nObjectHighWaterMark)
pLocalDC->nObjectHighWaterMark = (INT) i;
return((INT) i);
}
else
{
RIPS("MF3216: iGetW16ObjectHandleSlot, Slot not found\n") ;
return(-1) ;
}
}
/***************************************************************************
* iNormalizeHandle
*
* CR1 - this entire routine is part of the handle system redesign.
*
* 1] The idea behind this routine is to isolate the handling
* of stock object handles to one place.
*
* 2] Input will be a Win32 handle index, either stock or a
* standard object.
*
* 3] Output will be the index of the entry in the
* piW32ToW16ObjectMap table that corresponds to the W32
* handle. If an error is detected -1 is returned.
*
* 4] All the stock objects will be between the range of 0
* and LAST_STOCK, and all the non-stock objects will be
* greater than LAST_STOCK.
*
**************************************************************************/
INT iNormalizeHandle(PLOCALDC pLocalDC, INT ihW32)
{
INT ihW32Norm ;
if (ihW32 & ENHMETA_STOCK_OBJECT)
{
ihW32Norm = ihW32 & ~ENHMETA_STOCK_OBJECT ;
if ((UINT) ihW32Norm > STOCK_LAST)
{
RIPS("MF3216: iNormalizeHandle, bad stock object\n") ;
ihW32Norm = -1 ;
}
}
else
{
ihW32Norm = ihW32 + STOCK_LAST + 1 ;
if ((UINT) ihW32Norm >= pLocalDC->cW32ToW16ObjectMap)
{
RIPS("MF3216: iNormalizeHandle, bad standard object\n") ;
ihW32Norm = -1 ;
}
}
return(ihW32Norm) ;
}
/***************************************************************************
* iAllocateW16Handle
*
* CR1 - this entire routine is part of the handle system redesign.
* It is to be called from the object creation routines.
*
* 1] This routine actually does the handle allocation.
*
* 2] It sets the entry in pW16ObjHndlSlotStatus array
* for the slot allocated by iGetW16ObjectHandleSlot to
* an "in-use" status (for the intended use).
*
* 3] It returns a ihW16 (an index handle to the Win16 handle
* table, aka the Win16 handle slot number).
*
**************************************************************************/
INT iAllocateW16Handle(PLOCALDC pLocalDC, INT ihW32, INT iIntendedUse)
{
INT ihW32Norm,
ihW16 ;
// Assume the worst, set up for a failed return code.
ihW16 = -1 ;
// Normalize the handle.
ihW32Norm = iNormalizeHandle(pLocalDC, ihW32) ;
if (ihW32Norm == -1)
goto error_exit ;
// Check for double allocation of a Win32 handle index.
// If we find a double allocation, this would indicate an error
// in the Win32 metafile.
// Error out on this due to the possibility of
// a brush being used for a bitmap, or some other wrong use of a handle.
if (pLocalDC->piW32ToW16ObjectMap[ihW32Norm] != UNMAPPED)
{
RIPS("MF3216: iAllocateW16Handle, Double W32 handle allocation detected\n") ;
goto error_exit ;
}
// Get a slot in the Win16 handle table.
ihW16 = iGetW16ObjectHandleSlot(pLocalDC, iIntendedUse) ;
if (ihW16 == -1)
goto error_exit ;
// Set the W32 to W16 slot mapping
pLocalDC->piW32ToW16ObjectMap[ihW32Norm] = ihW16 ;
error_exit:
return(ihW16) ;
}
/***************************************************************************
* iValidateHandle
*
* CR1 - this entire routine is part of the handle system redesign.
*
* 1] This routine does a lot more than validate a Win32 handle.
* It does some limited error checking on the Win32 handle,
* to make sure its within a reasonable range. Then if a
* Win16 handle table slot has already been allocated for
* this Win32 handle it will return the Win16 handle that
* was previously allocated. Alternatively, if a Win16
* handle has not been previously allocated for a Win32
* STOCK handle it will allocate a W16 handle and return the
* Win16 handle. This function is called by FillRgn, FrameRgn
* and SelectObject to allow lazy allocation of stock objects.
*
* 2] Input is a Win32 handle, either a stock or a non-stock
* handle.
*
* 3] Output is a Win16 handle, this is the value in the
* Win32-index of the piW32ToW16ObjectMap. If a stock object
* does not exist, it will create one.
*
* 4] If there is an error a -1 is returned.
**************************************************************************/
INT iValidateHandle(PLOCALDC pLocalDC, INT ihW32)
{
INT ihW32Norm,
ihW16 ;
// Assume the worst.
ihW16 = -1 ;
// NOTE: Normalizing the W32 handles takes care of checking
// for a reasonable W32 handle value.
ihW32Norm = iNormalizeHandle(pLocalDC, ihW32) ;
if (ihW32Norm == -1)
goto error_exit ;
// Check the W32ToW16 map, to determine if this W32 handle has
// already been allocated a W16 slot.
ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
if (ihW16 == UNMAPPED)
{
// There is no mapping from W32 to W16. This implies
// that the object in question does not exist. If this is
// a stock object, then we will create the object at this time.
// Alternatively, if this is a non-stock object then we have an
// error condition.
if ((DWORD) ihW32Norm <= STOCK_LAST)
{
if (bCreateStockObject(pLocalDC, ihW32))
ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
else
ihW16 = -1 ;
}
else
{
RIPS("MF3216: iValidateHandle - Unmapped Standard Object\n") ;
ihW16 = -1 ;
}
}
error_exit:
return (ihW16) ;
}
/***************************************************************************
* DoDeleteObject - Win32 to Win16 Metafile Converter Entry Point
*
* CR1 - Most of this routine was rewritten to conform to the new
* objects management system.
*
* 1] The object handle is checked for reasonable limits.
* We will also make sure that the Win16 slot has a handle
* allocated to it. If it does not then we will return an
* error.
*
* 2] If this is a stock object we fail and return an error.
*
* 3] If this is a non-stock object we emit a Win16DeleteObject
* record. Then we set pW16ObjHndlSlotStatus to
* indicate that this slot is available. We also set
* piW32ToW16ObjectMap to -1 (UNMAPPED).
*
* 4] If we are in the first pass of an XOR-ClipPath rendering
* then we verify if this object was created during this pass
* If the object wasn't created during this pass, we will need
* to recreate the object when we start the second pass so that
* any call to SelectObject will return with the proper object
* selected (GillesK)
**************************************************************************/
BOOL WINAPI DoDeleteObject
(
PLOCALDC pLocalDC,
INT ihObject
)
{
BOOL b ;
INT ihW16,
ihW32Norm;
// Assume the worst.
b = FALSE ;
// Normalize the W32 handle.
ihW32Norm = iNormalizeHandle(pLocalDC, ihObject) ;
if (ihW32Norm == -1)
goto error_exit ;
// Make sure we're not deleting a stock object.
if ((DWORD) ihW32Norm <= STOCK_LAST)
{
PUTS("MF3216: DoDeleteObject, attempt to delete a stock object\n") ;
return(TRUE);
}
// If this is a palette, then we do not delete the win16 object.
// We do delete our local version of the palette.
if (pLocalDC->pW32hPal && pLocalDC->pW32hPal[ihObject])
{
b = DeleteObject(pLocalDC->pW32hPal[ihObject]);
pLocalDC->pW32hPal[ihObject] = 0;
if (b == FALSE)
RIPS("MF3216: DoDeleteObject - DeleteObject (hPalette) failed\n") ;
return (b) ;
}
// Map the ihW32 to a ihW16 (object handle table slot).
ihW16 = pLocalDC->piW32ToW16ObjectMap[ihW32Norm] ;
if (ihW16 == UNMAPPED)
{
RIPS("MF3216: DoDeleteObject, attempt to delete a non-existent object\n");
goto error_exit ;
}
// Make sure the object is one that we expect.
// There is no region object or bitmap object in the enhanced metafiles.
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH
|| pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN
|| pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_FONT,
"MF3216: DoDeleteObject, Invalid Object Deletion\n") ;
// If there was a Win32 handle associated with this Win16 handle
// then the w32Handle field of the W16ObjHndlSlotStatus[ihW16]
// entry in the handle slot status array will be non-null. If
// it is non-null then we should delete the Win32 handle at this time.
if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0)
{
if (!DeleteObject(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle))
{
ASSERTGDI(FALSE, "MF3216: DoDeleteObject, DeleteObject failed");
}
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle = 0 ;
}
if( pLocalDC->iXORPass == DRAWXORPASS && pLocalDC->pW16ObjHndlSlotStatus[ihW16].iXORPassCreation != DRAWXORPASS )
{
// If we delete an object that was created before this pass
// the we need to save the object creation record so that
// we can recreate the object once this pass is over
// We create a linked list of objects that we have to recreate.
PW16RECREATIONSLOT pW16RecreationSlot = (PW16RECREATIONSLOT) LocalAlloc( LMEM_FIXED, sizeof( W16RECREATIONSLOT ) ) ;
if( pW16RecreationSlot == NULL )
goto error_exit ;
pW16RecreationSlot->slot = ihW16 ;
pW16RecreationSlot->pbCreatRec = pLocalDC->pW16ObjHndlSlotStatus[ihW16].pbCreatRec ;
pW16RecreationSlot->pNext = pLocalDC->pW16RecreationSlot ;
pLocalDC->pW16RecreationSlot = pW16RecreationSlot ;
}
// Mark the slot as available.
// And set the map entry for the W32ToW16 map to unmapped.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].use = OPEN_AVAILABLE_SLOT ;
pLocalDC->pW16ObjHndlSlotStatus[ihW16].pbCreatRec = NULL ;
pLocalDC->piW32ToW16ObjectMap[ihW32Norm] = UNMAPPED ;
// Emit the delete drawing order.
b = bEmitWin16DeleteObject(pLocalDC, LOWORD(ihW16)) ;
error_exit:
return (b) ;
}
/***************************************************************************
* DoSelectObject - Win32 to Win16 Metafile Converter Entry Point
*
* CR1 - Major rewrite due to handle system redesign.
*
* DoSelectObject
*
* 1] For stock objects this is the workhorse routine.
*
* 2] For normal, non-stock, objects this routine will verify
* that an object has been created for this Win32 object-index.
* Then it will emit a Win16SelectObject metafile record.
*
* 3] For stock objects things get a little more complicated.
* First this routine must make sure a Win16 object has been
* created for this stock object. If a Win16 object has not
* been created yet, then it will be. After a Win16 object
* is created a Win16SelectObject record will be emitted for
* the object.
**************************************************************************/
BOOL WINAPI DoSelectObject
(
PLOCALDC pLocalDC,
LONG ihObject
)
{
BOOL b ;
INT ihW16;
// Assume the worst.
b = FALSE ;
// Make sure that the W16 object exists before we emit the
// SelectObject record. Stock objects may not have been created
// and iValidateHandle will take care of creating them.
ihW16 = iValidateHandle(pLocalDC, ihObject) ;
if (ihW16 == -1)
goto error_exit ;
// Make sure the object is one that we expect.
// There is no region object or bitmap object in the enhanced metafiles.
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH
|| pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN
|| pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_FONT,
"MF3216: DoSelectObject, Invalid Object Deletion\n") ;
// Remember the currently selected pen. This is used in path and text.
if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_PEN)
pLocalDC->lhpn32 = ihObject;
// Remember the currently selected brush. This is used in text.
if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].use == REALIZED_BRUSH)
pLocalDC->lhbr32 = ihObject;
// If there was a Win32 handle associated with this Win16 handle
// then the w32Handle field of the W16ObjHndlSlotStatus[ihW16]
// entry in the handle slot status array will be non-null. If
// it is non-null then we should select the W32 object into the
// helper DC at this time.
if (pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0)
SelectObject(pLocalDC->hdcHelper,
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle) ;
b = bEmitWin16SelectObject(pLocalDC, LOWORD(ihW16)) ;
error_exit:
return(b) ;
}
/***************************************************************************
* bCreateStockObject
**************************************************************************/
BOOL bCreateStockObject(PLOCALDC pLocalDC, INT ihW32)
{
BOOL b ;
INT i ;
ASSERTGDI((ihW32 & ENHMETA_STOCK_OBJECT) != 0,
"MF3216: bCreateStockObject, invalid stock handle");
switch (ihW32 & ~ENHMETA_STOCK_OBJECT)
{
case WHITE_BRUSH:
case LTGRAY_BRUSH:
case GRAY_BRUSH:
case DKGRAY_BRUSH:
case BLACK_BRUSH:
case NULL_BRUSH:
b = DoCreateBrushIndirect(pLocalDC, ihW32, &albStock[ihW32 & ~ENHMETA_STOCK_OBJECT]) ;
break ;
case WHITE_PEN:
case BLACK_PEN:
case NULL_PEN:
i = (ihW32 & ~ENHMETA_STOCK_OBJECT) - WHITE_PEN ;
b = DoCreatePen(pLocalDC, ihW32, (PLOGPEN) &alpnStock[i]) ;
break ;
case OEM_FIXED_FONT:
case ANSI_FIXED_FONT:
case ANSI_VAR_FONT:
case SYSTEM_FONT:
case DEVICE_DEFAULT_FONT:
case SYSTEM_FIXED_FONT:
case DEFAULT_GUI_FONT:
b = bCreateStockFont(pLocalDC, ihW32) ;
break ;
case DEFAULT_PALETTE:
default:
// Logical palettes are handled in DoSelectPalette and should
// not get here.
RIPS("MF3216: bCreateStockObject - Invalid Stock Object\n") ;
b =FALSE ;
break ;
}
return (b) ;
}
/***************************************************************************
* bCreateStockFont
**************************************************************************/
BOOL bCreateStockFont(PLOCALDC pLocalDC, INT ihW32)
{
BOOL b ;
INT i ;
LOGFONTA LogFontA ;
HANDLE hFont ;
b = FALSE ;
ASSERTGDI((ihW32 & ENHMETA_STOCK_OBJECT) != 0,
"MF3216: bCreateStockObject, invalid stock handle");
// Get a handle to this logfont.
hFont = GetStockObject(ihW32 & ~ENHMETA_STOCK_OBJECT) ;
if (hFont == (HANDLE) 0)
{
RIPS("MF3216: bCreateStockFont, GetStockObject (font) failed\n") ;
goto error_exit ;
}
// Get the logfont data. Assume we get at least one char in the
// facename string.
i = GetObjectA(hFont, sizeof(LOGFONTA), &LogFontA) ;
if (i <= (INT) offsetof(LOGFONTA,lfFaceName[0]))
{
PUTS("MF3216: bCreateStockFont - GetObjectW failed\n") ;
goto error_exit ;
}
// Zero out the remaining logfont structure.
for ( ; i < sizeof(LOGFONTA); i++)
((PBYTE) &LogFontA)[i] = 0;
// Create a LogFont for this stock font in the Win16 metafile.
b = DoExtCreateFont(pLocalDC,
ihW32,
&LogFontA);
error_exit:
return (b) ;
}
/***************************************************************************
* CreateBrushIndirect - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoCreateBrushIndirect
(
PLOCALDC pLocalDC,
INT ihBrush,
LPLOGBRUSH lpLogBrush
)
{
WIN16LOGBRUSH Win16LogBrush ;
BOOL b ;
INT ihW16 ;
LOGBRUSH LogBrush ;
b = FALSE ;
// Only 3 brush styles are allowed.
if (lpLogBrush->lbStyle != BS_SOLID
&& lpLogBrush->lbStyle != BS_HATCHED
&& lpLogBrush->lbStyle != BS_HOLLOW)
goto error_exit ;
// Make a copy of the logical brush.
LogBrush = *lpLogBrush;
// The first 6 hatched styles map directly from Win32 to Win16.
// The remaining hatched brushes are simulated using DIB pattern
// brushes. Note that the background color of a hatched brush
// is the current background color but that of a DIB pattern brush
// is given at create time! We will use the current background color
// in the DIB pattern brush when it is created. As a result, the
// output of these brushes may look different!
if (LogBrush.lbStyle == BS_HATCHED)
{
switch (LogBrush.lbHatch)
{
case HS_HORIZONTAL:
case HS_VERTICAL:
case HS_FDIAGONAL:
case HS_BDIAGONAL:
case HS_CROSS:
case HS_DIAGCROSS:
break;
default:
RIPS("MF3216: Unknown hatched pattern\n");
LogBrush.lbStyle = BS_SOLID;
break;
}
}
// Allocate the W16 handle.
ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
if (ihW16 == -1)
goto error_exit ;
// Create the w32 brush and store it in the w16 slot table.
// This brush is needed by the helper DC for BitBlt simulations.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
= CreateBrushIndirect(lpLogBrush) ;
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
"MF3216: CreateBrushIndirect failed");
// Assign all the Win32 brush attributes to Win16 brush attributes.
Win16LogBrush.lbStyle = (WORD) LogBrush.lbStyle ;
Win16LogBrush.lbColor = LogBrush.lbColor ;
Win16LogBrush.lbHatch = (SHORT) LogBrush.lbHatch ;
// Call the Win16 routine to emit the brush to the metafile.
b = bEmitWin16CreateBrushIndirect(pLocalDC, &Win16LogBrush) ;
error_exit:
return(b) ;
}
/******************************Public*Routine******************************\
* CreateMonoDib
*
* This is the same as CreateBitmap except that the bits are assumed
* to be DWORD aligned and that the scans start from the bottom of the bitmap.
*
* This routine is temporary until CreateDIBitmap supports monochrome bitmaps
*
* History:
* Wed Jul 01 11:02:24 1992 -by- Hock San Lee [hockl]
* Wrote it.
\**************************************************************************/
HBITMAP CreateMonoDib
(
LPBITMAPINFO pbmi,
CONST BYTE * pjBits,
UINT iUsage
)
{
HBITMAP hbm;
ASSERTGDI(pbmi->bmiHeader.biPlanes == 1, "CreateMonoDib: bad biPlanes value");
ASSERTGDI(pbmi->bmiHeader.biBitCount == 1, "CreateMonoDib: bad biBitCount value");
hbm = CreateBitmap((int) pbmi->bmiHeader.biWidth,
(int) pbmi->bmiHeader.biHeight,
(UINT) 1,
(UINT) 1,
(CONST VOID *) NULL);
if (!hbm)
return(hbm);
SetDIBits((HDC) 0, hbm, 0, (UINT) pbmi->bmiHeader.biHeight,
(CONST VOID *) pjBits, pbmi, iUsage);
return(hbm);
}
/***************************************************************************
* CreateMonoBrush - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoCreateMonoBrush
(
PLOCALDC pLocalDC,
DWORD ihBrush,
PBITMAPINFO pBitmapInfo,
DWORD cbBitmapInfo,
PBYTE pBits,
DWORD cbBits,
DWORD iUsage
)
{
BOOL b ;
INT ihW16;
DWORD ul ;
BYTE pbmi[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)];
HBITMAP hbm;
b = FALSE ;
// Need to make a copy of the bitmap info header, for a few reasons
// 1] the memory mapped file is write protected.
// 2] the iUsage may be (is) use palatte indicies, and we need
// use RGB colors.
((PBITMAPINFO) pbmi)->bmiHeader = pBitmapInfo->bmiHeader;
// Need to make sure the iUsage is DIB_RGB_COLORS
// and the palette is initialized to Black and White.
ul = 0 ;
((PBITMAPINFO) pbmi)->bmiColors[0] = (*((RGBQUAD *) &(ul))) ;
ul = 0x00ffffff ;
((PBITMAPINFO) pbmi)->bmiColors[1] = (*((RGBQUAD *) &(ul))) ;
// Allocate the W16 handle.
ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
if (ihW16 == -1)
goto error_exit ;
// Create the w32 brush and store it in the w16 slot table.
// This brush is needed by the helper DC for BitBlt simulations.
if ((hbm = CreateMonoDib
(
pBitmapInfo,
(CONST BYTE *) pBits,
(UINT) iUsage
)
)
)
{
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
= CreatePatternBrush(hbm);
if (!DeleteObject(hbm))
ASSERTGDI(FALSE, "MF3216: DoCreateMonoBrush, DeleteObject failed");
}
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
"MF3216: CreatePatternBrush failed");
// Call the Win16 routine to emit the brush to the metafile.
b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
(PBITMAPINFO) pbmi,
sizeof(pbmi),
pBits,
cbBits,
(WORD) DIB_RGB_COLORS,
(WORD) BS_PATTERN // Mono brush!
) ;
error_exit:
return(b) ;
}
/***************************************************************************
* CreateDIPatternBrush - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoCreateDIBPatternBrush
(
PLOCALDC pLocalDC,
DWORD ihBrush,
PBITMAPINFO pBitmapInfo,
DWORD cbBitmapInfo,
PBYTE pBits,
DWORD cbBits,
DWORD iUsage
)
{
BOOL b;
INT ihW16;
HBITMAP hbm;
PBYTE pBits24;
DWORD cbBits24;
BITMAPINFOHEADER bmih;
hbm = (HBITMAP) 0;
pBits24 = (PBYTE) NULL;
b = FALSE ;
// Allocate the W16 handle.
ihW16 = iAllocateW16Handle(pLocalDC, ihBrush, REALIZED_BRUSH);
if (ihW16 == -1)
goto error_exit ;
// Create the w32 brush and store it in the w16 slot table.
// We assume that the bitmap info is followed by the bits immediately,
// i.e. it is a packed dib.
// This brush is needed by the helper DC for BitBlt simulations.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
= CreateDIBPatternBrushPt((LPVOID) pBitmapInfo, (UINT) iUsage);
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
"MF3216: CreateDIBPatternBrushPt failed");
// We need to convert new bitmap info formats to the win3 formats.
if (pBitmapInfo->bmiHeader.biPlanes != 1
|| pBitmapInfo->bmiHeader.biBitCount == 16
|| pBitmapInfo->bmiHeader.biBitCount == 32)
{
if (!(hbm = CreateDIBitmap(pLocalDC->hdcHelper,
(LPBITMAPINFOHEADER) pBitmapInfo,
CBM_INIT | CBM_CREATEDIB,
pBits,
(LPBITMAPINFO) pBitmapInfo,
(UINT) iUsage)))
goto error_exit ;
bmih = *(PBITMAPINFOHEADER) pBitmapInfo;
bmih.biPlanes = 1;
bmih.biBitCount = 24;
bmih.biCompression = BI_RGB;
bmih.biSizeImage = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
cbBits24 = CJSCAN(bmih.biWidth,bmih.biPlanes,bmih.biBitCount)
* ABS(bmih.biHeight);
pBits24 = (LPBYTE) LocalAlloc(LMEM_FIXED, cbBits24);
if (pBits24 == (LPBYTE) NULL)
goto error_exit;
// Get bitmap info and bits in 24bpp.
if (!GetDIBits(pLocalDC->hdcHelper,
hbm,
0,
(UINT) bmih.biHeight,
pBits24,
(LPBITMAPINFO) &bmih,
DIB_RGB_COLORS))
goto error_exit;
b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
(PBITMAPINFO) &bmih,
sizeof(bmih),
pBits24,
cbBits24,
(WORD) DIB_RGB_COLORS,
(WORD) BS_DIBPATTERN
) ;
}
else
{
// Call the Win16 routine to emit the brush to the metafile.
b = bEmitWin16CreateDIBPatternBrush(pLocalDC,
pBitmapInfo,
cbBitmapInfo,
pBits,
cbBits,
(WORD) iUsage,
(WORD) BS_DIBPATTERN
) ;
}
error_exit:
if (hbm)
DeleteObject(hbm);
if (pBits24)
LocalFree((HANDLE) pBits24);
return(b) ;
}
/***************************************************************************
* CreatePen - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoCreatePen
(
PLOCALDC pLocalDC,
INT ihPen,
PLOGPEN pLogPen
)
{
EXTLOGPEN ExtLogPen ;
BOOL b ;
ExtLogPen.elpPenStyle = PS_GEOMETRIC | pLogPen->lopnStyle ;
ExtLogPen.elpWidth = (UINT) pLogPen->lopnWidth.x ;
ExtLogPen.elpBrushStyle = BS_SOLID ;
ExtLogPen.elpColor = pLogPen->lopnColor ;
ExtLogPen.elpNumEntries = 0 ;
// ExtLogPen.elpHatch = 0 ;
// ExtLogPen.elpStyleEntry[0] = 0;
b = DoExtCreatePen(pLocalDC, ihPen, &ExtLogPen) ;
return (b) ;
}
/***************************************************************************
* ExtCreatePen - Win32 to Win16 Metafile Converter Entry Point
**************************************************************************/
BOOL WINAPI DoExtCreatePen
(
PLOCALDC pLocalDC,
INT ihPen,
PEXTLOGPEN pExtLogPen
)
{
BOOL b ;
WORD iStyle ;
POINTS ptsWidth ;
INT ihW16 ;
UINT iPenStyle ;
POINTL ptlWidth ;
COLORREF crColor ;
b = FALSE;
// Get pen style.
iPenStyle = pExtLogPen->elpPenStyle & PS_STYLE_MASK ;
switch(iPenStyle)
{
case PS_SOLID:
case PS_DASH:
case PS_DOT:
case PS_DASHDOT:
case PS_DASHDOTDOT:
case PS_NULL:
case PS_INSIDEFRAME:
break ;
case PS_ALTERNATE:
iPenStyle = PS_DOT ;
break ;
case PS_USERSTYLE:
default:
// CR1: default to solid.
iPenStyle = PS_SOLID ;
break ;
}
// Get pen color.
switch (pExtLogPen->elpBrushStyle)
{
case BS_SOLID:
case BS_HATCHED:
crColor = pExtLogPen->elpColor ;
break;
// If the extended pen contains a hollow brush, then
// we will emit a NULL pen.
case BS_NULL: // BS_HOLLOW is the same as BS_NULL
iPenStyle = PS_NULL ;
crColor = 0 ;
break;
// Win3.x does not support pens with bitmap patterns.
// So we will just use solid pens here. Since we do not
// know what pen color to use, we choose the text color.
case BS_PATTERN:
case BS_DIBPATTERN:
case BS_DIBPATTERNPT:
default:
crColor = pLocalDC->crTextColor ;
break;
}
// Get pen width.
// If this is a cosmetic pen then the width is 0.
ptlWidth.y = 0 ;
if ((pExtLogPen->elpPenStyle & PS_TYPE_MASK) == PS_COSMETIC)
ptlWidth.x = 0 ;
else
ptlWidth.x = pExtLogPen->elpWidth ;
// Allocate the W16 handle.
ihW16 = iAllocateW16Handle(pLocalDC, ihPen, REALIZED_PEN);
if (ihW16 == -1)
goto error_exit ;
// This is where we need to create a pen for helper DC.
// We do not select it into the helper DC at this time.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle
= CreatePen((int) iPenStyle, ptlWidth.x, crColor) ;
ASSERTGDI(pLocalDC->pW16ObjHndlSlotStatus[ihW16].w32Handle != 0,
"MF3216: DoExtCreatePen, CreatePen failed");
// Get pen width in play time page units.
ptlWidth.x = (LONG) iMagnitudeXform(pLocalDC, (INT) ptlWidth.x, CX_MAG);
// Set the Win16 pen attributes
iStyle = (WORD) iPenStyle ;
ptsWidth.x = (WORD) ptlWidth.x ;
ptsWidth.y = (WORD) ptlWidth.y ;
// Call the Win16 routine to emit the pen to the metafile.
b = bEmitWin16CreatePen(pLocalDC, iStyle, &ptsWidth, crColor) ;
error_exit:
return(b) ;
}
/***************************************************************************
* DoRemoveObjects - Remove the objects that were created in the first
* XOR pass
**************************************************************************/
BOOL WINAPI DoRemoveObjects(
PLOCALDC pLocalDC
)
{
BOOL b = TRUE ;
UINT i;
INT iNorm ;
INT ihW32Norm ;
ASSERTGDI( pLocalDC->iXORPass == OBJECTRECREATION,
"DoRemoveObject used with the wrong XOR Pass" ) ;
// GillesK
// We have to go through the list of 16-bit handles and delete
// every single object that was created during this pass. This
// is necessary to make sure that we have the exact same state
// of objects when we restart the second pass so that no object
// creation will fail and give wrong results.
// Don't touch the stock objects
for( i = STOCK_LAST + 1 ; i < pLocalDC->cW32ToW16ObjectMap ; i++ )
{
iNorm = pLocalDC->piW32ToW16ObjectMap[i] ;
if( iNorm != UNMAPPED && pLocalDC->pW16ObjHndlSlotStatus[iNorm].iXORPassCreation == DRAWXORPASS )
{
// If there was a Win32 handle associated with this Win16 handle
// then the w32Handle field of the W16ObjHndlSlotStatus[ihW16]
// entry in the handle slot status array will be non-null. If
// it is non-null then we should delete the Win32 handle at this time.
b = DoDeleteObject( pLocalDC, i- ( STOCK_LAST + 1 ) ) ;
if( !b )
break ;
}
}
return b ;
}
/***************************************************************************
* DoDeleteRecreationSlots - Remove the recreation object slots because
* they will not be used.
**************************************************************************/
BOOL WINAPI DoDeleteRecreationSlots(
PLOCALDC pLocalDC
)
{
BOOL b = TRUE ;
while(pLocalDC->pW16RecreationSlot != NULL)
{
PW16RECREATIONSLOT l_pSlot = pLocalDC->pW16RecreationSlot ;
pLocalDC->pW16RecreationSlot = pLocalDC->pW16RecreationSlot->pNext ;
LocalFree(l_pSlot) ;
}
return b ;
}