/****************************** Module Header ******************************\ * Module Name: Meta.c * * This file contains the routines for playing the GDI metafile. Most of these * routines are adopted from windows gdi code. Most of the code is from * win3.0 except for the GetEvent code which is taken from win2.1 * * Created: 11-Oct-1989 * * Copyright (c) 1985, 1986, 1987, 1988, 1989 Microsoft Corporation * * * Public Functions: * PlayMetaFile * PlayMetaFileRecord * GetMetaFile * DeleteMetaFile * Private Functions: * GetEvent * IsDIBBlackAndWhite * * History: * 02-Jul-1991 -by- John Colleran [johnc] * Combined From Win 3.1 and WLO 1.0 sources \***************************************************************************/ #include #include #ifdef WIN32 #include "firewall.h" #endif #include "gdi16.h" HDC hScreenDC = 0; METACACHE MetaCache = { 0, 0, 0, 0 }; UINT INTERNAL GetFileNumber (LPMETAFILE lpMF); HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo); WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo); #define MAX_META_DISPATCH 0x48 FARPROC alpfnMetaFunc[MAX_META_DISPATCH+1] = /* 00 */ {(FARPROC)ScaleWindowExt, /* 01 */ (FARPROC)SetBkColor, /* 02 */ (FARPROC)SetBkMode, /* 03 */ (FARPROC)SetMapMode, /* 04 */ (FARPROC)SetROP2, /* 05 */ DEFIFWIN16((FARPROC)SetRelAbs), /* 06 */ (FARPROC)SetPolyFillMode, /* 07 */ (FARPROC)SetStretchBltMode, /* 08 */ (FARPROC)SetTextCharacterExtra, /* 09 */ (FARPROC)SetTextColor, /* 0A */ (FARPROC)SetTextJustification, /* 0B */ (FARPROC)SetWindowOrg, /* 0C */ (FARPROC)SetWindowExt, /* 0D */ (FARPROC)SetViewportOrg, /* 0E */ (FARPROC)SetViewportExt, /* 0F */ (FARPROC)OffsetWindowOrg, /* 10 */ 0, /* 11 */ DEFIFWIN16((FARPROC)OffsetViewportOrg), /* 12 */ DEFIFWIN16((FARPROC)ScaleViewportExt), /* 13 */ (FARPROC)LineTo, /* 14 */ DEFIFWIN16((FARPROC)MoveTo), /* 15 */ (FARPROC)ExcludeClipRect, /* 16 */ (FARPROC)IntersectClipRect, /* 17 */ (FARPROC)Arc, /* 18 */ (FARPROC)Ellipse, /* 19 */ (FARPROC)FloodFill, /* 1A */ (FARPROC)Pie, /* 1B */ (FARPROC)Rectangle, /* 1C */ (FARPROC)RoundRect, /* 1D */ (FARPROC)PatBlt, /* 1E */ (FARPROC)SaveDC, /* 1F */ (FARPROC)SetPixel, /* 20 */ (FARPROC)OffsetClipRgn, /* 21 */ 0, // TextOut, /* 22 */ 0, // BitBlt, /* 23 */ 0, // StretchBlt. /* 24 */ 0, // Polygon, /* 25 */ 0, // Polyline, /* 26 */ 0, // Escape, /* 27 */ (FARPROC)RestoreDC, /* 28 */ 0, // FillRegion, /* 29 */ 0, // FrameRegion, /* 2A */ 0, // InvertRegion, /* 2B */ 0, // PaintRegion, /* 2C */ (FARPROC)SelectClipRgn, /* 2D */ 0, // SelectObject, /* 2E */ (FARPROC)SetTextAlign, /* 2F */ 0, // DrawText, /* 30 */ (FARPROC)Chord, /* 31 */ (FARPROC)SetMapperFlags, /* 32 */ 0, // ExtTextOut, /* 33 */ 0, // SetDibsToDevice, /* 34 */ 0, // SelectPalette, /* 35 */ 0, // RealizePalette, /* 36 */ 0, // AnimatePalette, /* 37 */ 0, // SetPaletteEntries, /* 38 */ 0, // PolyPolygon, /* 39 */ 0, // ResizePalette, /* 3A */ 0, /* 3B */ 0, /* 3C */ 0, /* 3D */ 0, /* 3E */ 0, /* 3F */ 0, /* 40 */ 0, // DIBBitblt, /* 41 */ 0, // DIBStretchBlt, /* 42 */ 0, // DIBCreatePatternBrush, /* 43 */ 0, // StretchDIB, /* 44 */ 0, /* 45 */ 0, /* 46 */ 0, /* 47 */ 0, /* 48 */ (FARPROC)ExtFloodFill }; #if 0 // this is going to gdi.dll /***************************** Public Function ****************************\ * BOOL APIENTRY PlayMetaFile(hdc, hmf) * HDC hDC; * HMETAFILE hMF; * * Play a windows metafile. * * History: * Tue 27-Mar-1990 11:11:45 -by- Paul Klingler [paulk] * Ported from Windows \***************************************************************************/ BOOL GDIENTRY PlayMetaFile(HDC hdc, HMETAFILE hmf) { WORD i; WORD noObjs; BOOL bPrint=FALSE; LPMETAFILE lpmf; int oldMapMode = -1; LPMETARECORD lpmr = NULL; LPHANDLETABLE pht = NULL; HANDLE hht = NULL; #ifndef WIN32 HFONT hLFont; HBRUSH hLBrush; HPALETTE hLPal; HPEN hLPen; HRGN hClipRgn; HRGN hRegion; DWORD oldWndExt; DWORD oldVprtExt; #endif //WIN32 GdiLogFunc("PlayMetaFile"); if(!IsValidMetaFile(hmf)) goto exitPlayMetaFile; if(lpmf = (LPMETAFILE)GlobalLock(hmf)) { if((noObjs = lpmf->MetaFileHeader.mtNoObjects) > 0) { if(!(hht = GlobalAlloc(GMEM_ZEROINIT|GMEM_MOVEABLE, (sizeof(HANDLE) * lpmf->MetaFileHeader.mtNoObjects) + sizeof(WORD )))) { goto exitPlayMetaFile10; } pht = (LPHANDLETABLE)GlobalLock(hht); } #ifdef CR1 IMP: Optmizations playing into another metafile. Look at the win3.0 IMP: code #endif // !!!!! what if this is a metafile DC #ifndef WIN32 /* save the old objects so we can put them back */ hLPen = GetCurrentObject( hdc, OBJ_PEN ); hLBrush = GetCurrentObject( hdc, OBJ_BRUSH); hLFont = GetCurrentObject( hdc, OBJ_FONT); hClipRgn = GetCurrentObject( hdc, OBJ_RGN); hLPal = GetCurrentObject( hdc, OBJ_PALETTE); if(hRegion = GetCurrentObject( hdc, OBJ_RGN)) { if(hClipRgn = CreateRectRgn(0,0,0,0)) CombineRgn(hClipRgn,hRegion,hRegion,RGN_COPY); } #endif // WIN32 // we should really remove this abort proc thing. while(lpmr = GetEvent(lpmf,lpmr,FALSE)) { #if 0 //!!!!! if(GET_pAbortProc(pdc)) #else if( 0 ) #endif //!!!!! { //!!!!! if((bPrint = (*(pdc->pAbortProc))(hdc,0)) == FALSE) { GetEvent(lpmf,lpmr,TRUE); RestoreDC(hdc,0); goto exitPlayMetaFile20; } } PlayMetaFileRecord(hdc,pht,lpmr,noObjs); } bPrint = TRUE; exitPlayMetaFile20: /* if we fail restoring an object, we need to select some default object so that we can DeleteObject any Metafile- selected objects */ #ifndef WIN32 if(!SelectObject(hdc,hLPen)) SelectObject(hdc,GetStockObject(BLACK_PEN)); if(!SelectObject(hdc,hLBrush)) SelectObject(hdc,GetStockObject(BLACK_BRUSH)); if(!SelectPalette(hdc, GetCurrentObject( hdc, OBJ_PALETTE), FALSE)) SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), FALSE); if(!SelectObject(hdc,hLFont)) { /* if we cannot select the original font back in, we ** select the system font. this will allow us to delete ** the metafile font selected. to insure that the system ** font gets selected, we reset the DC's transform to ** default. after the selection, we restore this stuff */ oldVprtExt = GetViewportExt(hdc); oldWndExt = GetWindowExt(hdc); oldMapMode = SetMapMode(hdc,MM_TEXT); SelectObject(hdc,GetStockObject(SYSTEM_FONT)); SetMapMode(hdc,oldMapMode); SetWindowExt(hdc,LOWORD (oldWndExt),HIWORD (oldWndExt)); SetViewportExt(hdc,LOWORD (oldVprtExt),HIWORD (oldVprtExt)); } if(hClipRgn) { SelectObject(hdc,hClipRgn); DeleteObject(hClipRgn); } #endif // WIN32 for(i = 0; i < lpmf->MetaFileHeader.mtNoObjects; ++i) { if(pht->objectHandle[i]) DeleteObject(pht->objectHandle[i]); } #ifndef WIN32 /* if we fiddled with the map mode because we could not ** restore the original font, then maybe we can restore the ** font now */ if(oldMapMode > 0) SelectObject(hdc,hLFont); #endif // WIN32 if(hht) { GlobalUnlock(hht); GlobalFree(hht); } exitPlayMetaFile10: GlobalUnlock(hmf); } exitPlayMetaFile: return(bPrint); } #endif // this is going to gdi.dll /***************************** Internal Function **************************\ * BOOL NEAR PASCAL IsDIBBlackAndWhite * * Check to see if this DIB is a black and white DIB (and should be * converted into a mono bitmap as opposed to a color bitmap). * * Returns: TRUE it is a B&W bitmap * FALSE this is for color * * Effects: ? * * Warnings: ? * * History: \***************************************************************************/ BOOL INTERNAL IsDIBBlackAndWhite(LPBITMAPINFOHEADER lpDIBInfo) { LPDWORD lpRGB; GdiLogFunc3( " IsDIBBlackAndWhite"); /* pointer color table */ lpRGB = (LPDWORD)((LPBITMAPINFO)lpDIBInfo)->bmiColors; if ((lpDIBInfo->biBitCount == 1 && lpDIBInfo->biPlanes == 1) && (lpRGB[0] == (DWORD)0) && (lpRGB[1] == (DWORD)0xFFFFFF)) return(TRUE); else return(FALSE); } /***************************** Internal Function **************************\ * BigRead * * allows reads of greater than 64K * * Returns: Number of bytes read * \***************************************************************************/ DWORD INTERNAL BigRead(UINT fileNumber, LPSTR lpRecord, DWORD dwSizeRec) { DWORD dwRead = dwSizeRec; HPBYTE hpStuff; GdiLogFunc2( " BigRead"); hpStuff = (HPBYTE)lpRecord; while (dwRead > MAXFILECHUNK) { if (_lread(fileNumber, (LPSTR)hpStuff, MAXFILECHUNK) != MAXFILECHUNK) return(0); dwRead -= MAXFILECHUNK; hpStuff += MAXFILECHUNK; } if (_lread(fileNumber, (LPSTR)hpStuff, (UINT)dwRead) != (UINT)dwRead) return(0); return(dwSizeRec); } /***************************** Internal Function **************************\ * UseStretchDIBits * * set this directly to the device using StretchDIBits. * if DIB is black&white, don't do this. * * Returns: * TRUE --- operation successful * FALSE -- decided not to use StretchDIBits * * Effects: ? * * Warnings: ? * * History: \***************************************************************************/ BOOL INTERNAL UseStretchDIB(HDC hDC, WORD magic, LPMETARECORD lpMR) { LPBITMAPINFOHEADER lpDIBInfo; int sExtX, sExtY; int sSrcX, sSrcY; int DstX, DstY, DstXE, DstYE; if (magic == META_DIBBITBLT) { lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8]; DstX = lpMR->rdParm[7]; DstY = lpMR->rdParm[6]; sSrcX = lpMR->rdParm[3]; sSrcY = lpMR->rdParm[2]; DstXE = sExtX = lpMR->rdParm[5]; DstYE = sExtY = lpMR->rdParm[4]; } else { lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10]; DstX = lpMR->rdParm[9]; DstY = lpMR->rdParm[8]; DstXE = lpMR->rdParm[7]; DstYE = lpMR->rdParm[6]; sSrcX = lpMR->rdParm[5]; sSrcY = lpMR->rdParm[4]; sExtX = lpMR->rdParm[3]; sExtY = lpMR->rdParm[2]; } /* if DIB is black&white, we don't really want to do this */ if (IsDIBBlackAndWhite(lpDIBInfo)) return(FALSE); StretchDIBits(hDC, DstX, DstY, DstXE, DstYE, sSrcX, sSrcY, sExtX, sExtY, (LPBYTE)((LPSTR)lpDIBInfo + lpDIBInfo->biSize + GetSizeOfColorTable(lpDIBInfo)), (LPBITMAPINFO)lpDIBInfo, DIB_RGB_COLORS, (MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0]))); return(TRUE); } /***************************** Internal Function **************************\ * GetEvent * * This routine will now open a disk metafile in READ_ONLY mode. This will * allow us to play read-only metafiles or to share such file. * * [amitc: 06/19/91] \***************************************************************************/ LPMETARECORD INTERNAL GetEvent(LPMETAFILE lpMF, HPMETARECORD lpMR, BOOL bFree) // BOOL bFree; /* non-zero ==> done with metafile */ { int fileNumber = 0; WORD i; LPWORD lpCache = NULL; LPWORD lpMRbuf; HANDLE hMF; DWORD rdSize; GdiLogFunc2( " GetEvent"); #ifdef WIN32 hMF = GlobalHandle(lpMF); #else hMF = LOWORD(GlobalHandle(HIWORD((DWORD)(lpMF)))); #endif ASSERTGDI( hMF != (HANDLE)NULL, "GetEvent: Global Handle failed"); if (lpMF->MetaFileHeader.mtType == MEMORYMETAFILE) { /* Are we at the end of the metafile */ if(lpMR && lpMR->rdFunction == 0) return((LPMETARECORD)0); /* done with metafile, so free up the temp selector */ else if (bFree) { if (lpMR) #ifndef WIN32 FreeSelector(HIWORD(lpMR)); #endif return((LPMETARECORD)0); } else { /* if we don't already have a selector, get one */ if (lpMR == NULL) { #ifdef WIN32 lpMR = (HPMETARECORD)((LPMETADATA)lpMF)->metaDataStuff; // lpMR = (LPMETARECORD)GlobalLock(lpMF->hMetaData); #else lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)&lpMF->MetaFileNumber)),LOWORD((DWORD)&lpMF->MetaFileNumber)); #endif } else lpMR = (LPMETARECORD) (((HPWORD)lpMR)+lpMR->rdSize); /* end of the metafile. free up the selector we were using */ if (lpMR->rdFunction == 0) { #ifndef WIN32 FreeSelector(HIWORD(lpMR)); #endif return((LPMETARECORD)0); } } return(lpMR); } else if (lpMF->MetaFileHeader.mtType == DISKMETAFILE) { if (bFree) goto errGetEvent; /* never TRUE on the first call to GetEvent */ if (lpMR == NULL) { if ((fileNumber = OpenFile((LPSTR)lpMF->MetaFileBuffer.szPathName, (LPOFSTRUCT)&(lpMF->MetaFileBuffer), (WORD)OF_PROMPT|OF_REOPEN|OF_READ)) != -1) { if (lpMF->MetaFileRecordHandle = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)(lpMF->MetaFileHeader.mtMaxRecord * sizeof(WORD)))) { lpMR = (LPMETARECORD)GlobalLock(lpMF->MetaFileRecordHandle); lpMF->MetaFilePosition = _lread(lpMF->MetaFileNumber = fileNumber, (LPSTR)&lpMF->MetaFileHeader, sizeof(METAHEADER)); // Check for an Aldus header if (*((LPDWORD)&(lpMF->MetaFileHeader)) == 0x9AC6CDD7) { _llseek( fileNumber, 22, 0); lpMF->MetaFilePosition = 22 + _lread(fileNumber,(LPSTR)(&(lpMF->MetaFileHeader)),sizeof(METAHEADER)); } lpMF->MetaFileHeader.mtType = DISKMETAFILE; if (!MetaCache.hCache) { MetaCache.hCache = AllocBuffer(&MetaCache.wCacheSize); MetaCache.wCacheSize >>= 1; MetaCache.hMF = hMF; /* force cache fill on first access */ MetaCache.wCachePos = MetaCache.wCacheSize; } if (!(lpMF->MetaFileBuffer.fFixedDisk)) { _lclose(fileNumber); /* need to update the following for floppy files -- amitc */ fileNumber = 0 ; lpMF->MetaFileNumber = 0 ; } } } else return((LPMETARECORD)0); } /* update fileNumber, this is so that floopy based files can be closed and not left open -- amitc */ fileNumber = lpMF->MetaFileNumber ; if (lpMR) { if (MetaCache.hMF == hMF) { lpCache = (LPWORD) GlobalLock(MetaCache.hCache); lpMRbuf = (LPWORD) lpMR; // Make sure we can read the size and function fields if (MetaCache.wCachePos >= (WORD)(MetaCache.wCacheSize - 2)) { WORD cwCopy; if (!fileNumber) if ((fileNumber = GetFileNumber(lpMF)) == -1) goto errGetEvent; // We need to fill up the cache but save any data already // in the cache cwCopy = MetaCache.wCacheSize - MetaCache.wCachePos; for (i = 0; i < cwCopy; i++) { lpCache[i] = lpCache[MetaCache.wCacheSize-(cwCopy-i)]; } lpMF->MetaFilePosition += _lread(fileNumber, (LPSTR) (lpCache + cwCopy), (MetaCache.wCacheSize-cwCopy) << 1); MetaCache.wCachePos = 0; } lpCache += MetaCache.wCachePos; rdSize = ((LPMETARECORD)lpCache)->rdSize; /* Check for end */ if (!((LPMETARECORD)lpCache)->rdFunction) goto errGetEvent; // Make sure we can read the rest of the metafile record if (rdSize + MetaCache.wCachePos > MetaCache.wCacheSize) { if (!fileNumber) if ((fileNumber = GetFileNumber(lpMF)) == -1) goto errGetEvent; for (i=MetaCache.wCachePos; i < MetaCache.wCacheSize; ++i) *lpMRbuf++ = *lpCache++; lpMF->MetaFilePosition += BigRead(fileNumber, (LPSTR) lpMRbuf, (DWORD)(rdSize + (DWORD)MetaCache.wCachePos - (DWORD)MetaCache.wCacheSize) << 1); // Mark the cache as depleted because we just read // directly into the metafile record rather than the cache MetaCache.wCachePos = MetaCache.wCacheSize; } else { ASSERTGDI( HIWORD(rdSize) == 0, "Huge rdsize"); for (i = 0; i < LOWORD(rdSize); ++i) *lpMRbuf++ = *lpCache++; MetaCache.wCachePos += LOWORD(rdSize); } GlobalUnlock(MetaCache.hCache); return lpMR; } if ((fileNumber = GetFileNumber(lpMF)) == -1) goto errGetEvent; lpMF->MetaFilePosition += _lread(fileNumber, (LPSTR)&lpMR->rdSize, sizeof(DWORD)); lpMF->MetaFilePosition += BigRead(fileNumber, (LPSTR)&lpMR->rdFunction, (DWORD)(lpMR->rdSize * sizeof(WORD)) - sizeof(DWORD)); if (!(lpMF->MetaFileBuffer.fFixedDisk)) { _lclose(fileNumber); lpMF->MetaFileNumber = 0 ; fileNumber = 0 ; } if (lpMR->rdFunction == 0) { errGetEvent:; if (lpMF->MetaFileBuffer.fFixedDisk || fileNumber) _lclose(lpMF->MetaFileNumber); GlobalUnlock(lpMF->MetaFileRecordHandle); GlobalFree(lpMF->MetaFileRecordHandle); lpMF->MetaFileNumber = 0; if (MetaCache.hMF == hMF) { if (lpCache) GlobalUnlock(MetaCache.hCache); GlobalFree(MetaCache.hCache); MetaCache.hCache = MetaCache.hMF = 0; } return((LPMETARECORD)0); } } return(lpMR); } return((LPMETARECORD)0); } /***************************** Internal Function **************************\ * void GDIENTRY PlayMetaFileRecord * * Plays a metafile record by executing the GDI function call contained * withing the metafile record * * Effects: * \***************************************************************************/ #if 0 // this is going to gdi.dll void GDIENTRY PlayMetaFileRecord( HDC hdc, LPHANDLETABLE lpHandleTable, LPMETARECORD lpMR, WORD noObjs ) { WORD magic; HANDLE hObject; HANDLE hOldObject; HBRUSH hBrush; HRGN hRgn; HANDLE hPal; BOOL bExtraSel = FALSE; dprintf( 3," PlayMetaFileRecord 0x%lX", lpMR); if (!ISDCVALID(hdc)) return; magic = lpMR->rdFunction; /* being safe, make sure that the lp will give us full access to ** the record header without overstepping a segment boundary. */ #ifndef WIN32 if ((unsigned)(LOWORD((DWORD)lpMR)) > 0x7000) { lpMR = (LPMETARECORD)MAKELP(AllocSelector(HIWORD((DWORD)lpMR)),LOWORD((DWORD)lpMR)); bExtraSel = TRUE; } #endif // WIN32 switch (magic & 255) { case (META_BITBLT & 255): case (META_STRETCHBLT & 255): { HDC hSDC; HANDLE hBitmap; LPBITMAP lpBitmap; int delta = 0; /* if playing into another Metafile, do direct copy */ if (PlayIntoAMetafile(lpMR, hdc)) goto errPlayMetaFileRecord20; if ((lpMR->rdSize - 3) == (magic >> 8)) { hSDC = hdc; delta = 1; } else { if (hSDC = CreateCompatibleDC(hdc)) { if (magic == META_BITBLT) lpBitmap = (LPBITMAP)&lpMR->rdParm[8]; else lpBitmap = (LPBITMAP)&lpMR->rdParm[10]; //!!!!! ALERT DWORD align on NT if (hBitmap = CreateBitmap(lpBitmap->bmWidth, lpBitmap->bmHeight, lpBitmap->bmPlanes, lpBitmap->bmBitsPixel, (LPBYTE)&lpBitmap->bmBits)) hOldObject = SelectObject(hSDC, hBitmap); else goto errPlayMetaFileRecord10; } else goto errPlayMetaFileRecord20; } if (hSDC) { if (magic == META_BITBLT) BitBlt(hdc, lpMR->rdParm[7 + delta], lpMR->rdParm[6 + delta], lpMR->rdParm[5 + delta], lpMR->rdParm[4 + delta], hSDC, lpMR->rdParm[3], lpMR->rdParm[2], MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); else StretchBlt(hdc, lpMR->rdParm[9 + delta], lpMR->rdParm[8 + delta], lpMR->rdParm[7 + delta], lpMR->rdParm[6 + delta], hSDC, lpMR->rdParm[5], lpMR->rdParm[4], lpMR->rdParm[3], lpMR->rdParm[2], MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); } if (hSDC != hdc) { if (SelectObject(hSDC, hOldObject)) DeleteObject(hBitmap); errPlayMetaFileRecord10:; DeleteDC(hSDC); errPlayMetaFileRecord20:; } } break; case (META_DIBBITBLT & 255): case (META_DIBSTRETCHBLT & 255): { HDC hSDC; HANDLE hBitmap; LPBITMAPINFOHEADER lpDIBInfo ; int delta = 0; HANDLE hOldPal; /* if playing into another metafile, do direct copy */ if (PlayIntoAMetafile(lpMR, hdc)) goto errPlayMetaFileRecord40; if ((lpMR->rdSize - 3) == (magic >> 8)) { hSDC = hdc; delta = 1; } else { if( (magic & 255) == (META_DIBSTRETCHBLT & 255) ) if (UseStretchDIB(hdc, magic, lpMR)) goto errPlayMetaFileRecord40; if (hSDC = CreateCompatibleDC(hdc)) { /* set up the memDC to have the same palette */ hOldPal = SelectPalette(hSDC, GetCurrentObject(hdc,OBJ_PALETTE), TRUE); if (magic == META_DIBBITBLT) lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[8]; else lpDIBInfo = (LPBITMAPINFOHEADER)&lpMR->rdParm[10]; /* now create the bitmap for the MemDC and fill in the bits */ /* the processing for old and new format of metafiles is different here (till hBitmap is obtained) */ /* new metafile version */ hBitmap = CreateBitmapForDC (hdc,lpDIBInfo); if (hBitmap) hOldObject = SelectObject (hSDC, hBitmap) ; else goto errPlayMetaFileRecord30 ; } else goto errPlayMetaFileRecord40; } if (hSDC) { if (magic == META_DIBBITBLT) BitBlt(hdc, lpMR->rdParm[7 + delta], lpMR->rdParm[6 + delta], lpMR->rdParm[5 + delta], lpMR->rdParm[4 + delta], hSDC, lpMR->rdParm[3], lpMR->rdParm[2], MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); else StretchBlt(hdc, lpMR->rdParm[9 + delta], lpMR->rdParm[8 + delta], lpMR->rdParm[7 + delta], lpMR->rdParm[6 + delta], hSDC, lpMR->rdParm[5], lpMR->rdParm[4], lpMR->rdParm[3], lpMR->rdParm[2], MAKELONG(lpMR->rdParm[0], lpMR->rdParm[1])); } if (hSDC != hdc) { /* Deselect hDC's palette from memDC */ SelectPalette(hSDC, hOldPal, TRUE); if (SelectObject(hSDC, hOldObject)) DeleteObject(hBitmap); errPlayMetaFileRecord30:; DeleteDC(hSDC); errPlayMetaFileRecord40:; } } break; case (META_SELECTOBJECT & 255): { HANDLE hObject; if (hObject = lpHandleTable->objectHandle[lpMR->rdParm[0]]) SelectObject(hdc, hObject); } break; case (META_CREATEPENINDIRECT & 255): { #ifdef WIN32 LOGPEN lp; lp.lopnStyle = lpMR->rdParm[0]; lp.lopnWidth.x = lpMR->rdParm[1]; lp.lopnColor = *((COLORREF *)&lpMR->rdParm[3]); if (hObject = CreatePenIndirect(&lp)) #else if (hObject = CreatePenIndirect((LPLOGPEN)&lpMR->rdParm[0])) #endif AddToHandleTable(lpHandleTable, hObject, noObjs); break; } case (META_CREATEFONTINDIRECT & 255): { LOGFONT lf; LPLOGFONT lplf = &lf; LOGFONT32FROM16( lplf, ((LPLOGFONT)&lpMR->rdParm[0])); if (hObject = CreateFontIndirect(lplf)) AddToHandleTable(lpHandleTable, hObject, noObjs); } break; case (META_CREATEPATTERNBRUSH & 255): { HANDLE hBitmap; LPBITMAP lpBitmap; lpBitmap = (LPBITMAP)lpMR->rdParm; //!!!!! ALERT DWORD align on NT if (hBitmap = CreateBitmapIndirect(lpBitmap)) { LPBITMAPINFO lpbmInfo; HANDLE hmemInfo; hmemInfo = GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE, sizeof(BITMAPINFO) + 2<<(lpBitmap->bmPlanes*lpBitmap->bmBitsPixel)); lpbmInfo = (LPBITMAPINFO)GlobalLock( hmemInfo); lpbmInfo->bmiHeader.biPlanes = lpBitmap->bmPlanes; lpbmInfo->bmiHeader.biBitCount = lpBitmap->bmBitsPixel; SetDIBits( (HDC)NULL, hBitmap, 0, lpBitmap->bmHeight, (LPBYTE)&lpMR->rdParm[8], lpbmInfo, DIB_RGB_COLORS ); if (hObject = CreatePatternBrush(hBitmap)) AddToHandleTable(lpHandleTable, hObject, noObjs); GlobalUnlock(hmemInfo); GlobalFree(hmemInfo); DeleteObject(hBitmap); } } break; case (META_DIBCREATEPATTERNBRUSH & 255): { HDC hMemDC ; HANDLE hBitmap; LPBITMAPINFOHEADER lpDIBInfo ; WORD nDIBSize; /* number of WORDs in packed DIB */ HANDLE hDIB; LPWORD lpDIB; LPWORD lpSourceDIB; WORD i; if (lpMR->rdParm[0] == BS_PATTERN) { /* the address of the second paramter is the address of the DIB header, extract it */ lpDIBInfo = (BITMAPINFOHEADER FAR *) &lpMR->rdParm[2]; /* now create a device dependend bitmap compatible to the default screen DC - hScreenDC and extract the bits from the DIB into it. The following function does all these, and returns a HANDLE to the device dependent BItmap. */ /* we will use a dummy memory DC compatible to the screen DC */ hMemDC = CreateCompatibleDC (hScreenDC) ; hBitmap = CreateBitmapForDC (hScreenDC,lpDIBInfo) ; if (hBitmap) { if (hObject = CreatePatternBrush(hBitmap)) AddToHandleTable(lpHandleTable, hObject, noObjs); DeleteObject(hBitmap); } /* delete the dummy memory DC for new version Metafiles*/ DeleteDC (hMemDC) ; } /* this is a DIBPattern brush */ else { /* get size of just the packed DIB */ nDIBSize = (WORD) (lpMR->rdSize - 4); if ((hDIB = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(LONG)(nDIBSize << 1)))) { lpDIB = (WORD FAR *) GlobalLock (hDIB); lpSourceDIB = (WORD FAR *)&lpMR->rdParm[2]; /* copy the DIB into our new memory block */ for (i = 0; i < nDIBSize; i++) *lpDIB++ = *lpSourceDIB++; GlobalUnlock (hDIB); if (hObject = CreateDIBPatternBrush(hDIB, lpMR->rdParm[1])) AddToHandleTable(lpHandleTable, hObject, noObjs); GlobalFree(hDIB); } } } break; case (META_CREATEBRUSHINDIRECT & 255): { #ifdef WIN32 LOGBRUSH lb; lb.lbStyle = lpMR->rdParm[0]; lb.lbColor = *((COLORREF *)&lpMR->rdParm[1]); lb.lbHatch = lpMR->rdParm[3]; if (hObject = CreateBrushIndirect(&lb)) #else if (hObject = CreateBrushIndirect((LPLOGBRUSH)&lpMR->rdParm[0])) #endif AddToHandleTable(lpHandleTable, hObject, noObjs); break; } case (META_POLYLINE & 255): { LPPOINT lppt; Polyline(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]); FREECONVERT(lppt); break; } case (META_POLYGON & 255): { LPPOINT lppt; Polygon(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1],lpMR->rdParm[0])), lpMR->rdParm[0]); FREECONVERT(lppt); break; } case (META_POLYPOLYGON & 255): { LPPOINT lppt; #ifdef WIN32 WORD cPts=0; WORD ii; for(ii=0; iirdParm[0]; ii++) cPts += ((LPWORD)&lpMR->rdParm[1])[ii]; #endif // WIN32 PolyPolygon(hdc, (lppt=CONVERTPTS(&lpMR->rdParm[1] + lpMR->rdParm[0], cPts)), (LPINT)&lpMR->rdParm[1], lpMR->rdParm[0]); FREECONVERT(lppt); } break; case (META_EXTTEXTOUT & 255): { LPWORD lpdx; LPSTR lpch; LPRECT lprt; lprt = (lpMR->rdParm[3] & (ETO_OPAQUE|ETO_CLIPPED)) ? (LPRECT)&lpMR->rdParm[4] : 0; lpch = (LPSTR)&lpMR->rdParm[4] + ((lprt) ? sizeof(RECT) : 0); /* dx array starts at next word boundary after char string */ lpdx = (LPWORD)(lpch + ((lpMR->rdParm[2] + 1) & 0xFFFE)); /* check to see if there is a Dx array by seeing if structure ends after the string itself */ if ( ((DWORD)((LPWORD)lpdx - (LPWORD)(lpMR))) >= lpMR->rdSize) lpdx = NULL; else lpdx = (LPWORD)CONVERTINTS((signed short FAR *)lpdx, lpMR->rdParm[2]); ExtTextOut(hdc, lpMR->rdParm[1], lpMR->rdParm[0], lpMR->rdParm[3], lprt, (LPSTR)lpch, lpMR->rdParm[2], (LPINT)lpdx); if (lpdx != (LPWORD)NULL) FREECONVERT(lpdx); break; } case (META_TEXTOUT & 255): TextOut(hdc, lpMR->rdParm[lpMR->rdSize-4], lpMR->rdParm[lpMR->rdSize-5], (LPSTR)&lpMR->rdParm[1], lpMR->rdParm[0]); break; case (META_ESCAPE & 255): { LPSTR lpStuff; if (lpMR->rdParm[0] != MFCOMMENT) { lpStuff = (LPSTR)&lpMR->rdParm[2]; #ifdef OLDEXTTEXTOUT if (lpMR->rdParm[0] == EXTTEXTOUT) { EXTTEXTDATA ExtData; ExtData.xPos = lpMR->rdParm[2]; ExtData.yPos = lpMR->rdParm[3]; ExtData.cch = lpMR->rdParm[4]; ExtData.rcClip = *((LPRECT)&lpMR->rdParm[5]); ExtData.lpString = (LPSTR)&lpMR->rdParm[9]; ExtData.lpWidths = (WORD FAR *)&lpMR->rdParm[9+((ExtData.cch+1)/2)]; lpStuff = (LPSTR)&ExtData; } #endif Escape(hdc, lpMR->rdParm[0], lpMR->rdParm[1], lpStuff, (LPSTR)0); } } break; case (META_FRAMEREGION & 255): if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]])) FrameRgn(hdc, hRgn, hBrush, lpMR->rdParm[3], lpMR->rdParm[2]); break; case (META_PAINTREGION & 255): if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) PaintRgn(hdc, hRgn); break; case (META_INVERTREGION & 255): if(hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) InvertRgn(hdc, hRgn); break; case (META_FILLREGION & 255): if((hRgn = lpHandleTable->objectHandle[lpMR->rdParm[0]]) && (hBrush = lpHandleTable->objectHandle[lpMR->rdParm[1]])) FillRgn(hdc, hRgn, hBrush); break; #ifdef DEADCODE #ifdef GDI104 case (META_DRAWTEXT & 255): MFDrawText(hdc, (LPPOINT)&lpMR->rdParm[6], lpMR->rdParm[1], (LPPOINT)&lpMR->rdParm[2], lpMR->rdParm[0]); break; #endif #endif /* *** in win2, METACREATEREGION records contained an entire region object, *** including the full header. this header changed in win3. *** *** to remain compatible, the region records will be saved with the *** win2 header. here we read a win2 header with region, and actually *** create a win3 header with same region internals */ case (META_CREATEREGION & 255): { #if 0 //!!!!! HANDLE hRgn; WORD *pRgn; WORD iChar; LPWORD *lpTemp; iChar = lpMR->rdSize*2 - sizeof(WIN2OBJHEAD) - RECHDRSIZE; if (hRgn = LocalAlloc(LMEM_ZEROINIT, iChar + sizeof(ILOBJHEAD))) { pRgn = (WORD *)Lock IT(hRgn); *((WIN2OBJHEAD *)pRgn) = *((WIN2OBJHEAD FAR *)&lpMR->rdParm[0]); ((ILOBJHEAD *)pRgn)->ilObjMetaList = 0; lpTemp = (LPWORD)&(lpMR->rdParm[0]); ((WIN2OBJHEAD FAR *)lpTemp)++; ((ILOBJHEAD *)pRgn)++; /* --> actual region */ for(i = 0; i < (iChar >> 1) ; i++) *pRgn++ = *lpTemp++; pRgn = (WORD *)lock IT(hRgn); ((PRGN)pRgn)->rgnSize = iChar + sizeof(ILOBJHEAD); AddToHandleTable(lpHandleTable, hRgn, noObjs); } #endif //!!!!! HANDLE hRgn = NULL; HANDLE hRgn2 = NULL; WORD cScans; WORD cPnts; WORD cbIncr; LPWIN3REGION lpW3Rgn = (LPWIN3REGION)lpMR->rdParm; LPSCAN lpScan = lpW3Rgn->aScans; LPWORD lpXs; for( cScans=lpW3Rgn->cScans; cScans>0; cScans--) { // If this is the first scan then hRgn2 IS the region // otherwise OR it in if( hRgn == NULL ) { // Create the first region in this scan hRgn = CreateRectRgn( lpScan->scnPntsX[0], lpScan->scnPntTop, lpScan->scnPntsX[1], lpScan->scnPntBottom); // Allocate a worker region hRgn2 = CreateRectRgn( 1, 1, 2, 2); } else { SetRectRgn( hRgn2, lpScan->scnPntsX[0], lpScan->scnPntTop, lpScan->scnPntsX[1], lpScan->scnPntBottom ); CombineRgn( hRgn, hRgn, hRgn2, RGN_OR ); } lpXs = &lpScan->scnPntsX[2]; // If there are more regions on this scan OR them in for(cPnts = (WORD)(lpScan->scnPntCnt-2); cPnts>0; cPnts-=2) { SetRectRgn( hRgn2, *lpXs++, lpScan->scnPntTop, *lpXs++, lpScan->scnPntBottom ); CombineRgn( hRgn, hRgn, hRgn2, RGN_OR ); } cbIncr = (WORD)sizeof(SCAN) + (WORD)(lpScan->scnPntCnt-2); cbIncr = (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2); cbIncr = (WORD)sizeof(SCAN) + (WORD)sizeof(WORD)*(WORD)(lpScan->scnPntCnt-2); cbIncr = (WORD)sizeof(SCAN) + (WORD)(sizeof(WORD)*(lpScan->scnPntCnt-2)); lpScan = (LPSCAN)((LPBYTE)lpScan + cbIncr); } if( hRgn2 != NULL ) DeleteObject( hRgn2 ); AddToHandleTable(lpHandleTable, hRgn, noObjs); } break; case (META_DELETEOBJECT & 255): { HANDLE h; if (h = lpHandleTable->objectHandle[lpMR->rdParm[0]]) { DeleteObjectPriv(h); lpHandleTable->objectHandle[lpMR->rdParm[0]] = NULL; } } break; case (META_CREATEPALETTE & 255): if (hObject = CreatePalette((LPLOGPALETTE)&lpMR->rdParm[0])) AddToHandleTable(lpHandleTable, hObject, noObjs); break; case (META_SELECTPALETTE & 255): if(hPal = lpHandleTable->objectHandle[lpMR->rdParm[0]]) { SelectPalette(hdc, hPal, 0); } break; case (META_REALIZEPALETTE & 255): RealizePalette(hdc); break; case (META_SETPALENTRIES & 255): /* we know the palette being set is the current palette */ SetPaletteEntriesPriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0], lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]); break; case (META_ANIMATEPALETTE & 255): AnimatePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0], lpMR->rdParm[1], (LPPALETTEENTRY)&lpMR->rdParm[2]); break; case (META_RESIZEPALETTE & 255): ResizePalettePriv(GetCurrentObject(hdc,OBJ_PALETTE), lpMR->rdParm[0]); break; case (META_SETDIBTODEV & 255): { LPBITMAPINFOHEADER lpBitmapInfo; WORD ColorSize; /* if playing into another metafile, do direct copy */ if (PlayIntoAMetafile(lpMR, hdc)) goto DontReallyPlay; lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[9]); if (lpBitmapInfo->biClrUsed) { ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * (WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ? sizeof(RGBQUAD) : sizeof(WORD)); } else if (lpBitmapInfo->biBitCount == 24) ColorSize = 0; else ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) * (WORD)(lpMR->rdParm[0] == DIB_RGB_COLORS ? sizeof(RGBQUAD) : sizeof(WORD)); ColorSize += sizeof(BITMAPINFOHEADER); SetDIBitsToDevice(hdc, lpMR->rdParm[8], lpMR->rdParm[7], lpMR->rdParm[6], lpMR->rdParm[5], lpMR->rdParm[4], lpMR->rdParm[3], lpMR->rdParm[2], lpMR->rdParm[1], (BYTE FAR *)(((BYTE FAR *)lpBitmapInfo) + ColorSize), (LPBITMAPINFO) lpBitmapInfo, lpMR->rdParm[0]); DontReallyPlay:; } break; case (META_STRETCHDIB & 255): { LPBITMAPINFOHEADER lpBitmapInfo; WORD ColorSize; /* if playing into another metafile, do direct copy */ if (PlayIntoAMetafile(lpMR, hdc)) goto DontReallyPlay2; lpBitmapInfo = (LPBITMAPINFOHEADER)&(lpMR->rdParm[11]); if (lpBitmapInfo->biClrUsed) { ColorSize = ((WORD)lpBitmapInfo->biClrUsed) * (WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ? sizeof(RGBQUAD) : sizeof(WORD)); } else if (lpBitmapInfo->biBitCount == 24) ColorSize = 0; else ColorSize = (WORD)(1 << lpBitmapInfo->biBitCount) * (WORD)(lpMR->rdParm[2] == DIB_RGB_COLORS ? sizeof(RGBQUAD) : sizeof(WORD)); ColorSize += sizeof(BITMAPINFOHEADER); StretchDIBits(hdc, lpMR->rdParm[10], lpMR->rdParm[9], lpMR->rdParm[8], lpMR->rdParm[7], lpMR->rdParm[6], lpMR->rdParm[5], lpMR->rdParm[4], lpMR->rdParm[3], (LPBYTE)(((BYTE FAR *)lpBitmapInfo) + ColorSize), (LPBITMAPINFO) lpBitmapInfo, lpMR->rdParm[2], MAKELONG(lpMR->rdParm[1], lpMR->rdParm[0])); DontReallyPlay2:; } break; // Function that have new parameters on WIN32 // Or have DWORDs that stayed DWORDs; all other INTs to DWORDs #ifdef WIN32 case (META_MOVETO & 255): MoveTo( hdc, (long)lpMR->rdParm[1], (long)lpMR->rdParm[0], NULL ); break; case (META_RESTOREDC & 255): RestoreDC( hdc, (long)(signed short)lpMR->rdParm[0] ); break; case (META_SETBKCOLOR & 255): SetBkColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); break; case (META_SETTEXTCOLOR & 255): SetTextColor( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); break; case (META_SETPIXEL & 255): SetPixel( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2], (UINT)*((LPDWORD)lpMR->rdParm) ); break; case (META_SETMAPPERFLAGS & 255): SetMapperFlags( hdc, (UINT)*((LPDWORD)lpMR->rdParm) ); break; case (META_FLOODFILL & 255): FloodFill( hdc, (UINT)lpMR->rdParm[3], (UINT)lpMR->rdParm[2], (UINT)*((LPDWORD)lpMR->rdParm) ); break; case (META_EXTFLOODFILL & 255): ExtFloodFill( hdc, (UINT)lpMR->rdParm[4], (UINT)lpMR->rdParm[3], (UINT)*((LPDWORD)&lpMR->rdParm[1]), (UINT)lpMR->rdParm[0] ); break; // These puppies all got a new NULL and have only two parameters and a DC. case (META_SETWINDOWORG & 255): case (META_SETWINDOWEXT & 255): case (META_SETVIEWPORTORG & 255): case (META_SETVIEWPORTEXT & 255): case (META_OFFSETWINDOWORG & 255): case (META_SCALEWINDOWEXT & 255): case (META_OFFSETVIEWPORTORG & 255): case (META_SCALEVIEWPORTEXT & 255): { FARPROC lpProc; ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch1"); lpProc = alpfnMetaFunc[magic&0x00ff]; ASSERTGDI( lpProc != (FARPROC)NULL, "function not in dispatch table1 "); if (lpProc != (FARPROC)NULL) (*lpProc)(hdc, (long)(short)lpMR->rdParm[1], (long)(short)lpMR->rdParm[0], NULL ); } break; #endif // WIN32 default: { FARPROC lpProc; signed short *pshort; ASSERTGDI((magic&0x00ff) <= MAX_META_DISPATCH, "Unknown function to dispatch"); lpProc = alpfnMetaFunc[magic&0x00ff]; ASSERTGDI( (lpProc != (FARPROC)NULL) || (magic == META_SETRELABS), "function not in dispatch table"); if ((lpProc == (FARPROC)NULL)) return; // Switch to the corresponding dispatcher by number of parameters // The number of parameters in the dispatch number does not include the DC. switch (magic >> 8) { typedef int (FAR PASCAL *META1PROC)(HDC); typedef int (FAR PASCAL *META2PROC)(HDC, int); typedef int (FAR PASCAL *META3PROC)(HDC, int, int); typedef int (FAR PASCAL *META4PROC)(HDC, int, int, int); typedef int (FAR PASCAL *META5PROC)(HDC, int, int, int, int); typedef int (FAR PASCAL *META6PROC)(HDC, int, int, int, int, int); typedef int (FAR PASCAL *META7PROC)(HDC, int, int, int, int, int, int); typedef int (FAR PASCAL *META9PROC)(HDC, int, int, int, int, int, int, int, int); case 0: (*((META1PROC)lpProc))(hdc); break; case 1: (*((META2PROC)lpProc))(hdc,lpMR->rdParm[0]); break; case 2: (*((META3PROC)lpProc))(hdc,lpMR->rdParm[1],lpMR->rdParm[0]); break; case 3: (*((META4PROC)lpProc))(hdc,lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); break; case 4: (*((META5PROC)lpProc))(hdc,lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); break; case 5: (*((META6PROC)lpProc))(hdc,lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); break; case 6: (*((META7PROC)lpProc))(hdc,lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); break; case 8: (*((META9PROC)lpProc))(hdc,lpMR->rdParm[7],lpMR->rdParm[6],lpMR->rdParm[5],lpMR->rdParm[4],lpMR->rdParm[3],lpMR->rdParm[2],lpMR->rdParm[1],lpMR->rdParm[0]); break; default: ASSERTGDI( FALSE, "No dispatch for this count of args"); break; } } break; } #ifndef WIN32 if (bExtraSel) FreeSelector(HIWORD(lpMR)); #endif // WIN32 } #endif // this is going to gdi.dll /****************************** Internal Function **************************\ * AddToHandleTable * * Adds an object to the metafile table of objects * * \***************************************************************************/ VOID INTERNAL AddToHandleTable(LPHANDLETABLE lpHandleTable, HANDLE hObject, WORD noObjs) { WORD i; GdiLogFunc3( " AddToHandleTable"); /* linear search through table for first open slot */ for (i = 0; ((lpHandleTable->objectHandle[i] != NULL) && (i < noObjs)); ++i); if (i < noObjs) /* ok index */ lpHandleTable->objectHandle[i] = hObject; else { ASSERTGDI( 0, "Too many objects in table"); FatalExit(METAEXITCODE); /* Why can't we store the handle? */ } } /****************************** Internal Function **************************\ * GetFileNumber * * Returns the DOS file number for a metafiles file * -1 if failure * \***************************************************************************/ UINT INTERNAL GetFileNumber(LPMETAFILE lpMF) { int fileNumber; GdiLogFunc3( " GetFileNumber"); if (!(fileNumber = lpMF->MetaFileNumber)) { if ((fileNumber = OpenFile((LPSTR) lpMF->MetaFileBuffer.szPathName, (LPOFSTRUCT) &(lpMF->MetaFileBuffer), (WORD)OF_PROMPT | OF_REOPEN | OF_READ) ) != -1) { _llseek(fileNumber, (long)lpMF->MetaFilePosition, 0); /* need to update MetaFileNumber for floppy files -- amitc */ lpMF->MetaFileNumber = fileNumber ; } } return fileNumber; } #if 0 /****************************** Internal Function **************************\ * IsValidMetaFile(HANDLE hMetaData) * * Validates a metafile * * Returns TRUE iff hMetaData is a valid metafile * \***************************************************************************/ BOOL GDIENTRY IsValidMetaFile(HANDLE hMetaData) { LPMETADATA lpMetaData; BOOL status = FALSE; GdiLogFunc3( " IsValidMetaFile"); /* if this is a valid metafile we will save the version in a global variable */ if (hMetaData && (lpMetaData = (LPMETADATA) GlobalLock(hMetaData))) { status = ( (lpMetaData->dataHeader.mtType == MEMORYMETAFILE || lpMetaData->dataHeader.mtType == DISKMETAFILE) && (lpMetaData->dataHeader.mtHeaderSize == HEADERSIZE) && ((lpMetaData->dataHeader.mtVersion ==METAVERSION) || (lpMetaData->dataHeader.mtVersion ==METAVERSION100)) ); GlobalUnlock(hMetaData); } return status; } #endif #define INITIALBUFFERSIZE 16384 /****************************** Internal Function **************************\ * * AllocBuffer - Allocates a buffer as "large" as possible * \***************************************************************************/ HANDLE INTERNAL AllocBuffer(LPWORD piBufferSize) { WORD iCurBufferSize = INITIALBUFFERSIZE; HANDLE hBuffer; GdiLogFunc3( " AllocBuffer"); while (!(hBuffer = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, (LONG) iCurBufferSize)) && iCurBufferSize) iCurBufferSize >>= 1; *piBufferSize = iCurBufferSize; return (iCurBufferSize) ? hBuffer : NULL; } /****************************** Internal Function **************************\ * CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo) * * This routine takes a memory device context and a DIB bitmap, creates a * compatible bitmap for the DC and fills it with the bits from the DIB (co- * -nverting to the device dependent format). The pointer to the DIB bits * start immediately after the color table in the INFO header. ** * ** * The routine returns the handle to the bitmap with the bits filled in if * everything goes well else it returns NULL. ** \***************************************************************************/ HANDLE INTERNAL CreateBitmapForDC (HDC hMemDC, LPBITMAPINFOHEADER lpDIBInfo) { HBITMAP hBitmap ; LPBYTE lpDIBits ; GdiLogFunc3( " CreateBitmapForDC"); /* preserve monochrome if it started out as monochrome ** and check for REAL Black&white monochrome as opposed ** to a 2-color DIB */ if (IsDIBBlackAndWhite(lpDIBInfo)) hBitmap = CreateBitmap ((WORD)lpDIBInfo->biWidth, (WORD)lpDIBInfo->biHeight, 1, 1, (LPBYTE) NULL); else /* otherwise, make a compatible bitmap */ hBitmap = CreateCompatibleBitmap (hMemDC, (WORD)lpDIBInfo->biWidth, (WORD)lpDIBInfo->biHeight); if (!hBitmap) goto CreateBitmapForDCErr ; /* take a pointer past the header of the DIB, to the start of the color table */ lpDIBits = (LPBYTE) lpDIBInfo + sizeof (BITMAPINFOHEADER) ; /* take the pointer past the color table */ lpDIBits += GetSizeOfColorTable (lpDIBInfo) ; /* get the bits from the DIB into the Bitmap */ if (!SetDIBits (hMemDC, hBitmap, 0, (WORD)lpDIBInfo->biHeight, lpDIBits, (LPBITMAPINFO)lpDIBInfo, 0)) { DeleteObject(hBitmap); goto CreateBitmapForDCErr ; } /* return success */ return (hBitmap) ; CreateBitmapForDCErr: /* returm failure for function */ return (NULL) ; } /****************************** Internal Function **************************\ * GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo) * * Returns the number of bytes in the color table for the giving info header * \***************************************************************************/ WORD INTERNAL GetSizeOfColorTable (LPBITMAPINFOHEADER lpDIBInfo) { GdiLogFunc3( "GetSizeOfColorTable"); if (lpDIBInfo->biClrUsed) return((WORD)lpDIBInfo->biClrUsed * (WORD)sizeof(RGBQUAD)); else { switch (lpDIBInfo->biBitCount) { case 1: return (2 * sizeof (RGBQUAD)) ; break ; case 4: return (16 * sizeof (RGBQUAD)) ; break ; case 8: return (256 * sizeof (RGBQUAD)) ; break ; default: return (0) ; break ; } } } #if 0 // this is going to gdi.dll /***************************** Public Function ****************************\ * BOOL APIENTRY DeleteMetaFile(hmf) * * Frees a metafile handle. * * Effects: * \***************************************************************************/ BOOL GDIENTRY DeleteMetaFile(HMETAFILE hmf) { GdiLogFunc("DeleteMetaFile"); GlobalFree(hmf); return(TRUE); } /***************************** Public Function ****************************\ * HMETAFILE APIENTRY GetMetaFile(pzFilename) * * Returns a metafile handle for a disk based metafile. * * Effects: * * History: * Sat 14-Oct-1989 14:21:37 -by- Paul Klingler [paulk] * Wrote it. \***************************************************************************/ HMETAFILE GDIENTRY GetMetaFile(LPSTR pzFilename) { BOOL status=FALSE; UINT cBytes; int file; HMETAFILE hmf; LPMETAFILE lpmf; GdiLogFunc("GetMetaFile"); // Allocate the Metafile if(hmf = GlobalAlloc(GMEM_DDESHARE|GMEM_MOVEABLE,(DWORD)sizeof(METAFILE))) { lpmf = (LPMETAFILE)GlobalLock(hmf); // Make sure the file Exists if((file = OpenFile(pzFilename, &(lpmf->MetaFileBuffer), (WORD)OF_PROMPT | OF_EXIST)) == -1L) { ASSERTGDI( FALSE, "GetMetaFile: Metafile does not exist"); goto exitGetMetaFile; } // Open the file if((file = OpenFile(pzFilename, &(lpmf->MetaFileBuffer), (WORD)OF_PROMPT | OF_REOPEN | OF_READWRITE)) == -1) { ASSERTGDI( FALSE, "GetMetaFile: Unable to open Metafile"); goto exitGetMetaFile; } cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER)); // Check for an Aldus header if (*((LPDWORD)&(lpmf->MetaFileHeader)) == 0x9AC6CDD7) { _llseek( file, 22, 0); cBytes = (UINT)_lread(file,(LPSTR)(&(lpmf->MetaFileHeader)),sizeof(METAHEADER)); } _lclose(file); // Validate the metafile if(cBytes == sizeof(METAHEADER)) { lpmf->MetaFileHeader.mtType = DISKMETAFILE; status = TRUE; } exitGetMetaFile: GlobalUnlock(hmf); } if(status == FALSE) { GlobalFree(hmf); hmf = NULL; } return(hmf); } #endif // this is going to gdi.dll #ifdef WIN32 #undef GetViewportExt DWORD GetViewportExt32(HDC hdc) { SIZE sz; GetViewportExt( hdc, &sz ); return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); } #undef GetWindowExt DWORD GetWindowExt32(HDC hdc) { SIZE sz; GetWindowExt( hdc, &sz ); return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); } #undef SetViewportExt DWORD SetViewportExt32(HDC hdc, UINT x, UINT y) { SIZE sz; SetViewportExt( hdc, x, y, &sz ); return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); } #undef SetWindowExt DWORD SetWindowExt32(HDC hdc, UINT x, UINT y) { SIZE sz; SetWindowExt( hdc, x, y, &sz ); return(MAKELONG(LOWORD(sz.cx),LOWORD(sz.cy))); } /* Convert WORD arrays into DWORDs */ LPINT ConvertInts( signed short * pWord, UINT cWords ) { UINT ii; LPINT pInt; pInt = (LPINT)LocalAlloc( LMEM_FIXED, cWords * sizeof(UINT)); for( ii=0; ii