/* * Metafile functions * * Copyright David W. Metcalfe, 1994 * Niels de Carpentier, Albrecht Kleine 1996 * */ #include #include #include "gdi.h" #include "bitmap.h" #include "file.h" #include "metafile.h" #include "stddebug.h" #include "debug.h" #define HTINCR 10 /* handle table allocation size increment */ static HANDLE hHT; /* handle of the handle table */ static int HTLen; /* allocated length of handle table */ /****************************************************************** * GetMetafile GDI.124 By Kenny MacDonald 30 Nov 94 */ HMETAFILE16 GetMetaFile(LPSTR lpFilename) { HMETAFILE16 hmf; METAHEADER *mh; HFILE hFile; DWORD size; dprintf_metafile(stddeb,"GetMetaFile: %s\n", lpFilename); if (!lpFilename) return 0; hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE); mh = (METAHEADER *)GlobalLock16(hmf); if (!mh) { GlobalFree16(hmf); return 0; } if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR) { GlobalFree16(hmf); return 0; } if (FILE_Read(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR) { GlobalFree16(hmf); return 0; } size = mh->mtSize * 2; /* alloc memory for whole metafile */ GlobalUnlock16(hmf); hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE); mh = (METAHEADER *)GlobalLock16(hmf); if (!mh) { GlobalFree16(hmf); return 0; } if (FILE_Read(hFile, (char*)mh + mh->mtHeaderSize * 2, size - mh->mtHeaderSize * 2) == HFILE_ERROR) { GlobalFree16(hmf); return 0; } _lclose(hFile); if (mh->mtType != 1) { GlobalFree16(hmf); return 0; } GlobalUnlock16(hmf); return hmf; } /****************************************************************** * CreateMetafile GDI.125 */ HANDLE CreateMetaFile(LPCSTR lpFilename) { DC *dc; HANDLE handle; METAHEADER *mh; int hFile; dprintf_metafile(stddeb,"CreateMetaFile: %s\n", lpFilename); handle = GDI_AllocObject(sizeof(DC), METAFILE_DC_MAGIC); if (!handle) return 0; dc = (DC *)GDI_HEAP_LIN_ADDR(handle); if (!(dc->w.hMetaFile = GlobalAlloc16(GMEM_MOVEABLE, sizeof(METAHEADER)))) { GDI_FreeObject(handle); return 0; } dc->w.bitsPerPixel = screenDepth; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); mh->mtHeaderSize = MFHEADERSIZE / 2; mh->mtVersion = MFVERSION; mh->mtSize = MFHEADERSIZE / 2; mh->mtNoObjects = 0; mh->mtMaxRecord = 0; mh->mtNoParameters = 0; if (lpFilename) /* disk based metafile */ { mh->mtType = 1; /* disk */ hFile = _lcreat(lpFilename, 0); if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1) { GlobalFree16(dc->w.hMetaFile); return 0; } mh->mtNoParameters = hFile; /* store file descriptor here */ /* windows probably uses this too*/ } else /* memory based metafile */ mh->mtType = 0; /* create the handle table */ HTLen = HTINCR; hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(HANDLETABLE16) * HTLen); GlobalUnlock16(dc->w.hMetaFile); dprintf_metafile(stddeb,"CreateMetaFile: returning %04x\n", handle); return handle; } /****************************************************************** * CopyMetafile GDI.151 Niels de Carpentier, April 1996 */ HMETAFILE16 CopyMetaFile(HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename) { HMETAFILE16 handle = 0; METAHEADER *mh; METAHEADER *mh2; int hFile; dprintf_metafile(stddeb,"CopyMetaFile: %s\n", lpFilename); mh = (METAHEADER *)GlobalLock16(hSrcMetaFile); if (!mh) return 0; if (lpFilename) /* disk based metafile */ { int i,j; hFile = _lcreat(lpFilename, 0); j=mh->mtType; mh->mtType=1; /* disk file version stores 1 here */ i=_lwrite32(hFile, (char *)mh, mh->mtSize * 2) ; mh->mtType=j; /* restore old value [0 or 1] */ _lclose(hFile); if (i == -1) return 0; } else /* memory based metafile */ { handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2); mh2 = (METAHEADER *)GlobalLock16(handle); memcpy(mh2,mh, mh->mtSize * 2); GlobalUnlock16(handle); } return handle; } /****************************************************************** * IsValidMetaFile (GDI.410) * (This is not exactly what windows does, see "Undoc Win") */ BOOL IsValidMetaFile(HMETAFILE16 hmf) { BOOL resu=FALSE; METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf); if (mh) if (mh->mtType == 1 || mh->mtType == 0) if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16)) if (mh->mtVersion == MFVERSION) resu=TRUE; GlobalUnlock16(hmf); dprintf_metafile(stddeb,"IsValidMetaFile %x => %d\n",hmf,resu); return resu; } /****************************************************************** * CloseMetafile GDI.126 */ HMETAFILE16 CloseMetaFile(HDC hdc) { DC *dc; METAHEADER *mh; HMETAFILE16 hmf; HFILE hFile; dprintf_metafile(stddeb,"CloseMetaFile\n"); dc = (DC *)GDI_GetObjPtr(hdc, METAFILE_DC_MAGIC); if (!dc) return 0; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); /* Construct the end of metafile record - this is documented * in SDK Knowledgebase Q99334. */ if (!MF_MetaParam0(dc, META_EOF)) { GlobalFree16(dc->w.hMetaFile); return 0; } if (mh->mtType == 1) /* disk based metafile */ { hFile = mh->mtNoParameters; mh->mtNoParameters = 0; if (_llseek(hFile, 0L, 0) == -1) { GlobalFree16(dc->w.hMetaFile); return 0; } if (_lwrite32(hFile, (char *)mh, MFHEADERSIZE) == -1) { GlobalFree16(dc->w.hMetaFile); return 0; } _lclose(hFile); } /* delete the handle table */ GlobalFree16(hHT); hmf = dc->w.hMetaFile; GlobalUnlock16(hmf); GDI_FreeObject(hdc); return hmf; } /****************************************************************** * DeleteMetafile GDI.127 */ BOOL DeleteMetaFile(HMETAFILE16 hmf) { METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf); if (!mh) return FALSE; GlobalFree16(hmf); return TRUE; } /****************************************************************** * PlayMetafile GDI.123 */ BOOL PlayMetaFile(HDC hdc, HMETAFILE16 hmf) { METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf); METARECORD *mr; HANDLETABLE16 *ht; int offset = 0; WORD i; dprintf_metafile(stddeb,"PlayMetaFile(%04x %04x)\n",hdc,hmf); /* create the handle table */ hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT, sizeof(HANDLETABLE16) * mh->mtNoObjects); ht = (HANDLETABLE16 *)GlobalLock16(hHT); /* loop through metafile playing records */ offset = mh->mtHeaderSize * 2; while (offset < mh->mtSize * 2) { mr = (METARECORD *)((char *)mh + offset); dprintf_metafile(stddeb,"offset = %04x size = %08lx function = %04x\n", offset,mr->rdSize,mr->rdFunction); offset += mr->rdSize * 2; PlayMetaFileRecord(hdc, ht, mr, mh->mtNoObjects); } /* free objects in handle table */ for(i = 0; i < mh->mtNoObjects; i++) if(*(ht->objectHandle + i) != 0) DeleteObject(*(ht->objectHandle + i)); /* free handle table */ GlobalFree16(hHT); return TRUE; } /****************************************************************** * EnumMetafile GDI.175 * Niels de carpentier, april 1996 */ BOOL EnumMetaFile(HDC hdc, HMETAFILE16 hmf, MFENUMPROC16 lpEnumFunc,LPARAM lpData) { METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf); METARECORD *mr; SEGPTR ht, spRecord; int offset = 0; dprintf_metafile(stddeb,"EnumMetaFile(%04x, %04x, %08lx, %08lx)\n", hdc, hmf, (DWORD)lpEnumFunc, lpData); /* create the handle table */ hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(HANDLETABLE16) * mh->mtNoObjects); ht = WIN16_GlobalLock16(hHT); offset = mh->mtHeaderSize * 2; /* loop through metafile records */ spRecord = WIN16_GlobalLock16(hmf); while (offset < (mh->mtSize * 2)) { mr = (METARECORD *)((char *)mh + offset); if (!lpEnumFunc( hdc, (HANDLETABLE16 *)ht, (METARECORD *)((UINT32)spRecord + offset), mh->mtNoObjects, (LONG)lpData)) break; offset += (mr->rdSize * 2); } /* free handle table */ GlobalFree16(hHT); return TRUE; } /******************************************************************* * MF_GetDIBitsPointer [internal helper for e.g. PlayMetaFileRecord] * * Returns offset to DIB bits or 0 if error * (perhaps should be moved to (objects/dib.c ?) */ static LPSTR MF_GetDIBitsPointer(LPBITMAPINFO info) { int offset; if (info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER)) { if (info->bmiHeader.biClrUsed) { if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount)) offset = info->bmiHeader.biClrUsed * 4; else offset = (1 << info->bmiHeader.biBitCount) * 4; } else offset = (1 << info->bmiHeader.biBitCount) * 4; } else if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) { if (info->bmiHeader.biClrUsed) { if (info->bmiHeader.biClrUsed < (1 << info->bmiHeader.biBitCount)) offset = info->bmiHeader.biClrUsed * 3; else offset = (1 << info->bmiHeader.biBitCount) * 3; } else offset = (1 << info->bmiHeader.biBitCount) * 3; } else { fprintf(stderr,"Unknown size for BITMAPHEADER in MetaFile!\n"); return NULL; } return (LPSTR)info + info->bmiHeader.biSize + offset; } /****************************************************************** * PlayMetaFileRecord GDI.176 */ void PlayMetaFileRecord(HDC hdc, HANDLETABLE16 *ht, METARECORD *mr, WORD nHandles) { short s1; HANDLE hndl; char *ptr; BITMAPINFOHEADER *infohdr; dprintf_metafile(stddeb,"PlayMetaFileRecord(%04x %08lx %08lx %04x)\n", hdc,(LONG)ht, (LONG)mr, nHandles); switch (mr->rdFunction) { case META_EOF: break; case META_DELETEOBJECT: DeleteObject(*(ht->objectHandle + *(mr->rdParam))); *(ht->objectHandle + *(mr->rdParam)) = 0; break; case META_SETBKCOLOR: SetBkColor(hdc, *(mr->rdParam)); break; case META_SETBKMODE: SetBkMode(hdc, *(mr->rdParam)); break; case META_SETMAPMODE: SetMapMode(hdc, *(mr->rdParam)); break; case META_SETROP2: SetROP2(hdc, *(mr->rdParam)); break; case META_SETRELABS: SetRelAbs(hdc, *(mr->rdParam)); break; case META_SETPOLYFILLMODE: SetPolyFillMode(hdc, *(mr->rdParam)); break; case META_SETSTRETCHBLTMODE: SetStretchBltMode(hdc, *(mr->rdParam)); break; case META_SETTEXTCOLOR: SetTextColor(hdc, MAKELONG(*(mr->rdParam), *(mr->rdParam + 1))); break; case META_SETWINDOWORG: SetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_SETWINDOWEXT: SetWindowExt(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_SETVIEWPORTORG: SetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_SETVIEWPORTEXT: SetViewportExt(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_OFFSETWINDOWORG: OffsetWindowOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_SCALEWINDOWEXT: ScaleWindowExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_OFFSETVIEWPORTORG: OffsetViewportOrg(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_SCALEVIEWPORTEXT: ScaleViewportExt(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_LINETO: LineTo(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_MOVETO: MoveTo(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_EXCLUDECLIPRECT: ExcludeClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_INTERSECTCLIPRECT: IntersectClipRect(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_ARC: Arc(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5), *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_ELLIPSE: Ellipse(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_FLOODFILL: FloodFill(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), MAKELONG(*(mr->rdParam + 1), *(mr->rdParam))); break; case META_PIE: Pie(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5), *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_RECTANGLE: Rectangle(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_ROUNDRECT: RoundRect(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_PATBLT: PatBlt(hdc, *(mr->rdParam + 5), *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2), MAKELONG(*(mr->rdParam), *(mr->rdParam + 1))); break; case META_SAVEDC: SaveDC(hdc); break; case META_SETPIXEL: SetPixel(hdc, *(mr->rdParam + 3), *(mr->rdParam + 2), MAKELONG(*(mr->rdParam + 1), *(mr->rdParam))); break; case META_OFFSETCLIPRGN: OffsetClipRgn(hdc, *(mr->rdParam + 1), *(mr->rdParam)); break; case META_TEXTOUT: s1 = *(mr->rdParam); TextOut16(hdc, *(mr->rdParam + ((s1 + 1) >> 1) + 2), *(mr->rdParam + ((s1 + 1) >> 1) + 1), (char *)(mr->rdParam + 1), s1); break; case META_POLYGON: Polygon16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam)); break; case META_POLYPOLYGON: PolyPolygon16(hdc, (LPPOINT16)(mr->rdParam + *(mr->rdParam) + 1), (LPINT16)(mr->rdParam + 1), *(mr->rdParam)); break; case META_POLYLINE: Polyline16(hdc, (LPPOINT16)(mr->rdParam + 1), *(mr->rdParam)); break; case META_RESTOREDC: RestoreDC(hdc, *(mr->rdParam)); break; case META_SELECTOBJECT: SelectObject(hdc, *(ht->objectHandle + *(mr->rdParam))); break; case META_CHORD: Chord(hdc, *(mr->rdParam + 7), *(mr->rdParam + 6), *(mr->rdParam + 5), *(mr->rdParam + 4), *(mr->rdParam + 3), *(mr->rdParam + 2), *(mr->rdParam + 1), *(mr->rdParam)); break; case META_CREATEPATTERNBRUSH: switch (*(mr->rdParam)) { case BS_PATTERN: infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2); MF_AddHandle(ht, nHandles, CreatePatternBrush(CreateBitmap(infohdr->biWidth, infohdr->biHeight, infohdr->biPlanes, infohdr->biBitCount, (LPSTR)(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4)))); break; case BS_DIBPATTERN: s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2; hndl = GlobalAlloc16(GMEM_MOVEABLE, s1); ptr = GlobalLock16(hndl); memcpy(ptr, mr->rdParam + 2, s1); GlobalUnlock16(hndl); MF_AddHandle(ht, nHandles, CreateDIBPatternBrush(hndl, *(mr->rdParam + 1))); GlobalFree16(hndl); } break; case META_CREATEPENINDIRECT: MF_AddHandle(ht, nHandles, CreatePenIndirect((LOGPEN16 *)(&(mr->rdParam)))); break; case META_CREATEFONTINDIRECT: MF_AddHandle(ht, nHandles, CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParam)))); break; case META_CREATEBRUSHINDIRECT: MF_AddHandle(ht, nHandles, CreateBrushIndirect((LOGBRUSH16 *)(&(mr->rdParam)))); break; /* W. Magro: Some new metafile operations. Not all debugged. */ case META_CREATEPALETTE: MF_AddHandle(ht, nHandles, CreatePalette((LPLOGPALETTE)mr->rdParam)); break; case META_SETTEXTALIGN: SetTextAlign(hdc, *(mr->rdParam)); break; case META_SELECTPALETTE: SelectPalette(hdc, *(ht->objectHandle + *(mr->rdParam+1)),*(mr->rdParam)); break; case META_SETMAPPERFLAGS: SetMapperFlags(hdc, *(mr->rdParam)); break; case META_REALIZEPALETTE: RealizePalette(hdc); break; case META_ESCAPE: dprintf_metafile(stddeb,"PlayMetaFileRecord: META_ESCAPE unimplemented.\n"); break; /* --- Begin of fixed or new metafile operations. July 1996 ----*/ case META_EXTTEXTOUT: { LPINT16 dxx; DWORD len; s1 = mr->rdParam[2]; /* String length */ len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short) + sizeof(UINT16) + sizeof(RECT16); if (mr->rdSize == len / 2) dxx = NULL; /* No array present */ else if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2) dxx = &mr->rdParam[8+(s1+1)/2]; /* start of array */ else { fprintf(stderr, "PlayMetaFileRecord ExtTextOut mr->rdSize = %08lx, count = %x\n", mr->rdSize, s1); dxx = NULL; } ExtTextOut16( hdc, mr->rdParam[1], /* X position */ mr->rdParam[0], /* Y position */ mr->rdParam[3], /* options */ (LPRECT16) &mr->rdParam[4], /* rectangle */ (char *)(mr->rdParam + 8), /* string */ s1, dxx); /* length, dx array */ if (dxx) dprintf_metafile(stddeb,"EXTTEXTOUT len: %ld (%hd %hd) [%s].\n", mr->rdSize,dxx[0],dxx[1],(char*) &(mr->rdParam[8]) ); } break; case META_STRETCHDIB: { LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[11]); LPSTR bits = MF_GetDIBitsPointer(info); if (bits) StretchDIBits(hdc,mr->rdParam[10],mr->rdParam[9],mr->rdParam[8], mr->rdParam[7],mr->rdParam[6],mr->rdParam[5], mr->rdParam[4],mr->rdParam[3],bits,info, mr->rdParam[2],MAKELONG(mr->rdParam[0],mr->rdParam[1])); } break; case META_DIBSTRETCHBLT: { LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParam[10]); LPSTR bits = MF_GetDIBitsPointer(info); if (bits) StretchDIBits(hdc,mr->rdParam[9],mr->rdParam[8],mr->rdParam[7], mr->rdParam[6],mr->rdParam[5],mr->rdParam[4], mr->rdParam[3],mr->rdParam[2],bits,info, DIB_RGB_COLORS,MAKELONG(mr->rdParam[0],mr->rdParam[1])); } break; case META_STRETCHBLT: { HDC hdcSrc=CreateCompatibleDC(hdc); HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[10], /*Width */ mr->rdParam[11], /*Height*/ mr->rdParam[13], /*Planes*/ mr->rdParam[14], /*BitsPixel*/ (LPSTR)&mr->rdParam[15]); /*bits*/ SelectObject(hdcSrc,hbitmap); StretchBlt(hdc,mr->rdParam[9],mr->rdParam[8], mr->rdParam[7],mr->rdParam[6], hdcSrc,mr->rdParam[5],mr->rdParam[4], mr->rdParam[3],mr->rdParam[2], MAKELONG(mr->rdParam[0],mr->rdParam[1])); DeleteDC(hdcSrc); } break; case META_BITBLT: /* <-- not yet debugged */ { HDC hdcSrc=CreateCompatibleDC(hdc); HBITMAP16 hbitmap=CreateBitmap(mr->rdParam[7]/*Width */,mr->rdParam[8]/*Height*/, mr->rdParam[10]/*Planes*/,mr->rdParam[11]/*BitsPixel*/, (LPSTR)&mr->rdParam[12]/*bits*/); SelectObject(hdcSrc,hbitmap); BitBlt(hdc,mr->rdParam[6],mr->rdParam[5], mr->rdParam[4],mr->rdParam[3], hdcSrc, mr->rdParam[2],mr->rdParam[1], MAKELONG(0,mr->rdParam[0])); DeleteDC(hdcSrc); } break; default: fprintf(stddeb,"PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction); } } /****************************************************************** * GetMetaFileBits by William Magro, 19 Sep 1995 * * Trade in a meta file object handle for a handle to the meta file memory */ HANDLE GetMetaFileBits(HMETAFILE16 hmf) { dprintf_metafile(stddeb,"GetMetaFileBits: hMem out: %04x\n", hmf); return hmf; } /****************************************************************** * SetMetaFileBits by William Magro, 19 Sep 1995 * * Trade in a meta file memory handle for a handle to a meta file object */ HMETAFILE16 SetMetaFileBits(HANDLE hMem) { dprintf_metafile(stddeb,"SetMetaFileBits: hmf out: %04x\n", hMem); return hMem; } /****************************************************************** * MF_WriteRecord */ HMETAFILE16 MF_WriteRecord(HMETAFILE16 hmf, METARECORD *mr, WORD rlen) { DWORD len; METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf); if (mh->mtType == 0) /* memory based metafile */ { len = mh->mtSize * 2 + rlen; GlobalUnlock16(hmf); hmf = GlobalReAlloc16(hmf, len, GMEM_MOVEABLE); /* hmf can change */ mh = (METAHEADER *)GlobalLock16(hmf); memcpy((WORD *)mh + mh->mtSize, mr, rlen); } else if (mh->mtType == 1) /* disk based metafile */ { dprintf_metafile(stddeb,"Writing record to disk\n"); if (_lwrite32(mh->mtNoParameters, (char *)mr, rlen) == -1) { GlobalUnlock16(hmf); return 0; } } else { GlobalUnlock16(hmf); return 0; } mh->mtSize += rlen / 2; mh->mtMaxRecord = MAX(mh->mtMaxRecord, rlen / 2); GlobalUnlock16(hmf); return hmf; } /****************************************************************** * MF_AddHandle * * Add a handle to an external handle table and return the index */ int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HANDLE hobj) { int i; for (i = 0; i < htlen; i++) { if (*(ht->objectHandle + i) == 0) { *(ht->objectHandle + i) = hobj; return i; } } return -1; } /****************************************************************** * MF_AddHandleInternal * * Add a handle to the internal handle table and return the index */ int MF_AddHandleInternal(HANDLE hobj) { int i; HANDLETABLE16 *ht = (HANDLETABLE16 *)GlobalLock16(hHT); for (i = 0; i < HTLen; i++) { if (*(ht->objectHandle + i) == 0) { *(ht->objectHandle + i) = hobj; GlobalUnlock16(hHT); return i; } } GlobalUnlock16(hHT); if (!(hHT = GlobalReAlloc16(hHT, HTINCR, GMEM_MOVEABLE | GMEM_ZEROINIT))) return -1; HTLen += HTINCR; ht = (HANDLETABLE16 *)GlobalLock16(hHT); *(ht->objectHandle + i) = hobj; GlobalUnlock16(hHT); return i; } /****************************************************************** * MF_MetaParam0 */ BOOL MF_MetaParam0(DC *dc, short func) { char buffer[8]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 3; mr->rdFunction = func; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_MetaParam1 */ BOOL MF_MetaParam1(DC *dc, short func, short param1) { char buffer[8]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 4; mr->rdFunction = func; *(mr->rdParam) = param1; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_MetaParam2 */ BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2) { char buffer[10]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 5; mr->rdFunction = func; *(mr->rdParam) = param2; *(mr->rdParam + 1) = param1; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_MetaParam4 */ BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2, short param3, short param4) { char buffer[14]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 7; mr->rdFunction = func; *(mr->rdParam) = param4; *(mr->rdParam + 1) = param3; *(mr->rdParam + 2) = param2; *(mr->rdParam + 3) = param1; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_MetaParam6 */ BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2, short param3, short param4, short param5, short param6) { char buffer[18]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 9; mr->rdFunction = func; *(mr->rdParam) = param6; *(mr->rdParam + 1) = param5; *(mr->rdParam + 2) = param4; *(mr->rdParam + 3) = param3; *(mr->rdParam + 4) = param2; *(mr->rdParam + 5) = param1; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_MetaParam8 */ BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2, short param3, short param4, short param5, short param6, short param7, short param8) { char buffer[22]; METARECORD *mr = (METARECORD *)&buffer; HMETAFILE16 handle; mr->rdSize = 11; mr->rdFunction = func; *(mr->rdParam) = param8; *(mr->rdParam + 1) = param7; *(mr->rdParam + 2) = param6; *(mr->rdParam + 3) = param5; *(mr->rdParam + 4) = param4; *(mr->rdParam + 5) = param3; *(mr->rdParam + 6) = param2; *(mr->rdParam + 7) = param1; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_CreateBrushIndirect */ BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush) { int index; HMETAFILE16 handle; char buffer[sizeof(METARECORD) - 2 + sizeof(LOGBRUSH16)]; METARECORD *mr = (METARECORD *)&buffer; METAHEADER *mh; mr->rdSize = (sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2) / 2; mr->rdFunction = META_CREATEBRUSHINDIRECT; memcpy(&(mr->rdParam), logbrush, sizeof(LOGBRUSH16)); if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))) return FALSE; mr->rdSize = sizeof(METARECORD) / 2; mr->rdFunction = META_SELECTOBJECT; if ((index = MF_AddHandleInternal(hBrush)) == -1) return FALSE; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); *(mr->rdParam) = index; if (index >= mh->mtNoObjects) mh->mtNoObjects++; GlobalUnlock16(dc->w.hMetaFile); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_CreatePatternBrush */ BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH16 *logbrush) { DWORD len, bmSize, biSize; HANDLE hmr; METARECORD *mr; BITMAPOBJ *bmp; BITMAPINFO *info; BITMAPINFOHEADER *infohdr; int index; HMETAFILE16 handle; char buffer[sizeof(METARECORD)]; METAHEADER *mh; switch (logbrush->lbStyle) { case BS_PATTERN: bmp = (BITMAPOBJ *)GDI_GetObjPtr((HANDLE)logbrush->lbHatch, BITMAP_MAGIC); if (!bmp) return FALSE; len = sizeof(METARECORD) + sizeof(BITMAPINFOHEADER) + (bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes) + 6; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); memset(mr, 0, len); mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = len / 2; *(mr->rdParam) = logbrush->lbStyle; *(mr->rdParam + 1) = DIB_RGB_COLORS; infohdr = (BITMAPINFOHEADER *)(mr->rdParam + 2); infohdr->biSize = sizeof(BITMAPINFOHEADER); infohdr->biWidth = bmp->bitmap.bmWidth; infohdr->biHeight = bmp->bitmap.bmHeight; infohdr->biPlanes = bmp->bitmap.bmPlanes; infohdr->biBitCount = bmp->bitmap.bmBitsPixel; memcpy(mr->rdParam + (sizeof(BITMAPINFOHEADER) / 2) + 4, PTR_SEG_TO_LIN(bmp->bitmap.bmBits), bmp->bitmap.bmHeight * bmp->bitmap.bmWidthBytes); break; case BS_DIBPATTERN: info = (BITMAPINFO *)GlobalLock16((HANDLE)logbrush->lbHatch); if (info->bmiHeader.biCompression) bmSize = info->bmiHeader.biSizeImage; else bmSize = (info->bmiHeader.biWidth * info->bmiHeader.biBitCount + 31) / 32 * 8 * info->bmiHeader.biHeight; biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); len = sizeof(METARECORD) + biSize + bmSize + 2; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); memset(mr, 0, len); mr->rdFunction = META_DIBCREATEPATTERNBRUSH; mr->rdSize = len / 2; *(mr->rdParam) = logbrush->lbStyle; *(mr->rdParam + 1) = LOWORD(logbrush->lbColor); memcpy(mr->rdParam + 2, info, biSize + bmSize); break; default: return FALSE; } if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, len))) { GlobalFree16(hmr); return FALSE; } GlobalFree16(hmr); mr = (METARECORD *)&buffer; mr->rdSize = sizeof(METARECORD) / 2; mr->rdFunction = META_SELECTOBJECT; if ((index = MF_AddHandleInternal(hBrush)) == -1) return FALSE; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); *(mr->rdParam) = index; if (index >= mh->mtNoObjects) mh->mtNoObjects++; GlobalUnlock16(dc->w.hMetaFile); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_CreatePenIndirect */ BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen) { int index; HMETAFILE16 handle; char buffer[sizeof(METARECORD) - 2 + sizeof(LOGPEN16)]; METARECORD *mr = (METARECORD *)&buffer; METAHEADER *mh; mr->rdSize = (sizeof(METARECORD) + sizeof(LOGPEN16) - 2) / 2; mr->rdFunction = META_CREATEPENINDIRECT; memcpy(&(mr->rdParam), logpen, sizeof(LOGPEN16)); if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))) return FALSE; mr->rdSize = sizeof(METARECORD) / 2; mr->rdFunction = META_SELECTOBJECT; if ((index = MF_AddHandleInternal(hPen)) == -1) return FALSE; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); *(mr->rdParam) = index; if (index >= mh->mtNoObjects) mh->mtNoObjects++; GlobalUnlock16(dc->w.hMetaFile); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_CreateFontIndirect */ BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT16 *logfont) { int index; HMETAFILE16 handle; char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)]; METARECORD *mr = (METARECORD *)&buffer; METAHEADER *mh; mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2; mr->rdFunction = META_CREATEFONTINDIRECT; memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT16)); if (!(dc->w.hMetaFile = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))) return FALSE; mr->rdSize = sizeof(METARECORD) / 2; mr->rdFunction = META_SELECTOBJECT; if ((index = MF_AddHandleInternal(hFont)) == -1) return FALSE; mh = (METAHEADER *)GlobalLock16(dc->w.hMetaFile); *(mr->rdParam) = index; if (index >= mh->mtNoObjects) mh->mtNoObjects++; GlobalUnlock16(dc->w.hMetaFile); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; return handle; } /****************************************************************** * MF_TextOut */ BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count) { HMETAFILE16 handle; DWORD len; HANDLE hmr; METARECORD *mr; len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); memset(mr, 0, len); mr->rdSize = len / 2; mr->rdFunction = META_TEXTOUT; *(mr->rdParam) = count; memcpy(mr->rdParam + 1, str, count); *(mr->rdParam + ((count + 1) >> 1) + 1) = y; *(mr->rdParam + ((count + 1) >> 1) + 2) = x; handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; GlobalFree16(hmr); return handle; } /****************************************************************** * MF_ExtTextOut */ BOOL MF_ExtTextOut(DC *dc, short x, short y, UINT16 flags, const RECT16 *rect, LPCSTR str, short count, const INT16 *lpDx) { HMETAFILE16 handle; DWORD len; HANDLE hmr; METARECORD *mr; len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short) + sizeof(UINT16) + sizeof(RECT16); if (lpDx) len+=count*sizeof(INT16); if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); memset(mr, 0, len); mr->rdSize = len / 2; mr->rdFunction = META_EXTTEXTOUT; *(mr->rdParam) = y; *(mr->rdParam + 1) = x; *(mr->rdParam + 2) = count; *(mr->rdParam + 3) = flags; if (rect) memcpy(mr->rdParam + 4, rect, sizeof(RECT16)); memcpy(mr->rdParam + 8, str, count); if (lpDx) memcpy(mr->rdParam + 8+ ((count + 1) >> 1),lpDx,count*sizeof(INT16)); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; GlobalFree16(hmr); return handle; } /****************************************************************** * MF_MetaPoly - implements Polygon and Polyline */ BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count) { HMETAFILE16 handle; DWORD len; HANDLE hmr; METARECORD *mr; len = sizeof(METARECORD) + (count * 4); if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); memset(mr, 0, len); mr->rdSize = len / 2; mr->rdFunction = func; *(mr->rdParam) = count; memcpy(mr->rdParam + 1, pt, count * 4); handle = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2); dc->w.hMetaFile = handle; GlobalFree16(hmr); return handle; } /****************************************************************** * MF_BitBlt */ BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width, short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop) { HMETAFILE16 handle; DWORD len; HANDLE hmr; METARECORD *mr; DC *dcSrc; BITMAP16 BM; if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0; GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM); len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); mr->rdFunction = META_BITBLT; *(mr->rdParam + 7) = BM.bmWidth; *(mr->rdParam + 8) = BM.bmHeight; *(mr->rdParam + 9) = BM.bmWidthBytes; *(mr->rdParam +10) = BM.bmPlanes; *(mr->rdParam +11) = BM.bmBitsPixel; dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop); if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +12)) { mr->rdSize = len / sizeof(INT16); *(mr->rdParam) = HIWORD(rop); *(mr->rdParam + 1) = ySrc; *(mr->rdParam + 2) = xSrc; *(mr->rdParam + 3) = height; *(mr->rdParam + 4) = width; *(mr->rdParam + 5) = yDest; *(mr->rdParam + 6) = xDest; handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2); } else handle = 0; dcDest->w.hMetaFile = handle; GlobalFree16(hmr); return handle; } /********************************************************************** * MF_StretchBlt * this function contains TWO ways for procesing StretchBlt in metafiles, * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT * via #define STRETCH_VIA_DIB */ #define STRETCH_VIA_DIB #undef STRETCH_VIA_DIB BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest, short heightDest, HDC hdcSrc, short xSrc, short ySrc, short widthSrc, short heightSrc, DWORD rop) { HMETAFILE16 handle; DWORD len; HANDLE hmr; METARECORD *mr; DC *dcSrc; BITMAP16 BM; #ifdef STRETCH_VIA_DIB LPBITMAPINFOHEADER lpBMI; WORD nBPP; #endif if (!(dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC ))) return 0; GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM); #ifdef STRETCH_VIA_DIB nBPP = BM.bmPlanes * BM.bmBitsPixel; len = sizeof(METARECORD) + 10 * sizeof(INT16) + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); mr->rdFunction = META_DIBSTRETCHBLT; lpBMI=(LPBITMAPINFOHEADER)(mr->rdParam+10); lpBMI->biSize = sizeof(BITMAPINFOHEADER); lpBMI->biWidth = BM.bmWidth; lpBMI->biHeight = BM.bmHeight; lpBMI->biPlanes = 1; lpBMI->biBitCount = nBPP; /* 1,4,8 or 24 */ lpBMI->biClrUsed = nBPP != 24 ? 1 << nBPP : 0; lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight; lpBMI->biCompression = BI_RGB; lpBMI->biXPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSX),3937,100); lpBMI->biYPelsPerMeter = MulDiv32(GetDeviceCaps(hdcSrc,LOGPIXELSY),3937,100); lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */ dprintf_metafile(stddeb,"MF_StretchBltViaDIB->len = %ld rop=%lx PixYPM=%ld Caps=%d\n", len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY)); if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight, MF_GetDIBitsPointer((LPBITMAPINFO)lpBMI), /* DIB bits */ (LPBITMAPINFO)lpBMI,DIB_RGB_COLORS)) /* DIB info structure */ #else len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight; if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len))) return FALSE; mr = (METARECORD *)GlobalLock16(hmr); mr->rdFunction = META_STRETCHBLT; *(mr->rdParam +10) = BM.bmWidth; *(mr->rdParam +11) = BM.bmHeight; *(mr->rdParam +12) = BM.bmWidthBytes; *(mr->rdParam +13) = BM.bmPlanes; *(mr->rdParam +14) = BM.bmBitsPixel; dprintf_metafile(stddeb,"MF_StretchBlt->len = %ld rop=%lx \n",len,rop); if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,mr->rdParam +15)) #endif { mr->rdSize = len / sizeof(INT16); *(mr->rdParam) = LOWORD(rop); *(mr->rdParam + 1) = HIWORD(rop); *(mr->rdParam + 2) = heightSrc; *(mr->rdParam + 3) = widthSrc; *(mr->rdParam + 4) = ySrc; *(mr->rdParam + 5) = xSrc; *(mr->rdParam + 6) = heightDest; *(mr->rdParam + 7) = widthDest; *(mr->rdParam + 8) = yDest; *(mr->rdParam + 9) = xDest; handle = MF_WriteRecord(dcDest->w.hMetaFile, mr, mr->rdSize * 2); } else handle = 0; dcDest->w.hMetaFile = handle; GlobalFree16(hmr); return handle; }