|
|
/*****************************************************************************
* * 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 ; }
// 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 ;
// 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 { RIP("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) { RIP("MF3216: iNormalizeHandle, bad stock object\n") ; ihW32Norm = -1 ; } } else { ihW32Norm = ihW32 + STOCK_LAST + 1 ; if ((UINT) ihW32Norm >= pLocalDC->cW32ToW16ObjectMap) { RIP("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) { RIP("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 { RIP("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). **************************************************************************/ 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) RIP("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) { RIP("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 ; }
// Mark the slot as available.
// And set the map entry for the W32ToW16 map to unmapped.
pLocalDC->pW16ObjHndlSlotStatus[ihW16].use = OPEN_AVAILABLE_SLOT ; 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: b = bCreateStockFont(pLocalDC, ihW32) ; break ;
case DEFAULT_PALETTE: default: // Logical palettes are handled in DoSelectPalette and should
// not get here.
RIP("MF3216: bCreateStockObject - Invalid Stock Object\n") ; b =FALSE ; break ; }
return (b) ; }
/***************************************************************************
* bCreateStockFont **************************************************************************/ BOOL bCreateStockFont(PLOCALDC pLocalDC, INT ihW32) { BOOL b ; INT i ; LOGFONTW LogFontW ; 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) { RIP("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 = GetObjectW(hFont, sizeof(LOGFONTW), &LogFontW) ; if (i <= (INT) offsetof(LOGFONTW,lfFaceName[0])) { PUTS("MF3216: bCreateStockFont - GetObjectW failed\n") ; goto error_exit ; }
// Zero out the remaining logfont structure.
for ( ; i < sizeof(LOGFONTW); i++) ((PBYTE) &LogFontW)[i] = 0;
// Create a LogFont for this stock font in the Win16 metafile.
b = DoExtCreateFont(pLocalDC, ihW32, &LogFontW); 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: RIP("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) ; }
|