4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
10 * These functions are primarily involved with metafile playback or anything
11 * that touches a HMETAFILE.
12 * For recording of metafiles look in graphics/metafiledrv/
14 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
15 * global memory handles so these cannot be interchanged.
17 * Memory-based metafiles are just stored as a continuous block of memory with
18 * a METAHEADER at the head with METARECORDs appended to it. mtType is
19 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
20 * disk-based metafile - even mtType is METAFILE_MEMORY.
21 * 16bit HMETAFILE16s are global handles to this block
22 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
24 * Disk-based metafiles are rather different. HMETAFILE16s point to a
25 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
26 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27 * more 0, then 2 which may be a time stamp of the file and then the path of
28 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
36 #include "wine/winbase16.h"
41 #include "debugtools.h"
44 DEFAULT_DEBUG_CHANNEL(metafile);
46 /******************************************************************
49 * Add a handle to an external handle table and return the index
51 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
55 for (i = 0; i < htlen; i++)
57 if (*(ht->objectHandle + i) == 0)
59 *(ht->objectHandle + i) = hobj;
67 /******************************************************************
68 * MF_Create_HMETATFILE
70 * Creates a (32 bit) HMETAFILE object from a METAHEADER
72 * HMETAFILEs are GDI objects.
74 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
77 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
81 GDI_ReleaseObj( hmf );
86 /******************************************************************
87 * MF_Create_HMETATFILE16
89 * Creates a HMETAFILE16 object from a METAHEADER
91 * HMETAFILE16s are Global memory handles.
93 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
96 DWORD size = mh->mtSize * sizeof(WORD);
98 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
101 METAHEADER *mh_dest = GlobalLock16(hmf);
102 memcpy(mh_dest, mh, size);
105 HeapFree(GetProcessHeap(), 0, mh);
109 /******************************************************************
112 * Returns ptr to METAHEADER associated with HMETAFILE
113 * Should be followed by call to MF_ReleaseMetaHeader
115 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
117 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
118 return metaObj ? metaObj->mh : 0;
121 /******************************************************************
124 * Returns ptr to METAHEADER associated with HMETAFILE16
125 * Should be followed by call to MF_ReleaseMetaHeader16
127 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
129 return GlobalLock16(hmf);
132 /******************************************************************
133 * MF_ReleaseMetaHeader
135 * Releases METAHEADER associated with HMETAFILE
137 static void MF_ReleaseMetaHeader( HMETAFILE hmf )
139 GDI_ReleaseObj( hmf );
142 /******************************************************************
143 * MF_ReleaseMetaHeader16
145 * Releases METAHEADER associated with HMETAFILE16
147 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
149 return GlobalUnlock16( hmf );
153 /******************************************************************
154 * DeleteMetaFile16 (GDI.127)
156 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
158 return !GlobalFree16( hmf );
161 /******************************************************************
162 * DeleteMetaFile (GDI32.@)
164 * Delete a memory-based metafile.
167 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
169 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
170 if (!metaObj) return FALSE;
171 HeapFree( GetProcessHeap(), 0, metaObj->mh );
172 GDI_FreeObject( hmf, metaObj );
176 /******************************************************************
179 * Returns a pointer to a memory based METAHEADER read in from file HFILE
182 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
185 DWORD BytesRead, size;
187 size = sizeof(METAHEADER);
188 mh = HeapAlloc( GetProcessHeap(), 0, size );
190 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
192 HeapFree( GetProcessHeap(), 0, mh );
195 size = mh->mtSize * 2;
196 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
198 size -= sizeof(METAHEADER);
199 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
202 HeapFree( GetProcessHeap(), 0, mh );
206 if (mh->mtType != METAFILE_MEMORY) {
207 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
208 mh->mtType = METAFILE_MEMORY;
213 /******************************************************************
214 * GetMetaFile16 (GDI.124)
216 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
221 TRACE("%s\n", lpFilename);
226 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
227 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
230 mh = MF_ReadMetaFile(hFile);
233 return MF_Create_HMETAFILE16( mh );
236 /******************************************************************
237 * GetMetaFileA (GDI32.@)
239 * Read a metafile from a file. Returns handle to a memory-based metafile.
241 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
246 TRACE("%s\n", lpFilename);
251 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
252 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
255 mh = MF_ReadMetaFile(hFile);
258 return MF_Create_HMETAFILE( mh );
263 /******************************************************************
264 * GetMetaFileW (GDI32.@)
266 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
271 TRACE("%s\n", debugstr_w(lpFilename));
276 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
277 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
280 mh = MF_ReadMetaFile(hFile);
283 return MF_Create_HMETAFILE( mh );
287 /******************************************************************
288 * MF_LoadDiskBasedMetaFile
290 * Creates a new memory-based metafile from a disk-based one.
292 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
298 if(mh->mtType != METAFILE_DISK) {
299 ERR("Not a disk based metafile\n");
302 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
304 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
305 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
306 WARN("Can't open file of disk based metafile\n");
309 mh2 = MF_ReadMetaFile(hfile);
314 /******************************************************************
315 * MF_CreateMetaHeaderDisk
317 * Take a memory based METAHEADER and change it to a disk based METAHEADER
318 * assosiated with filename. Note: Trashes contents of old one.
320 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
325 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
326 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
327 mh->mtType = METAFILE_DISK;
328 size = HeapSize( GetProcessHeap(), 0, mh );
329 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
330 strcpy(mhd->filename, filename);
334 /******************************************************************
335 * CopyMetaFile16 (GDI.151)
337 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
339 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
340 METAHEADER *mh2 = NULL;
343 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
347 if(mh->mtType == METAFILE_DISK)
348 mh2 = MF_LoadDiskBasedMetaFile(mh);
350 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
351 memcpy( mh2, mh, mh->mtSize * 2 );
353 MF_ReleaseMetaHeader16( hSrcMetaFile );
355 if(lpFilename) { /* disk based metafile */
356 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
357 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
358 HeapFree( GetProcessHeap(), 0, mh2 );
361 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
363 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
366 return MF_Create_HMETAFILE16( mh2 );
370 /******************************************************************
371 * CopyMetaFileA (GDI32.@)
373 * Copies the metafile corresponding to hSrcMetaFile to either
374 * a disk file, if a filename is given, or to a new memory based
375 * metafile, if lpFileName is NULL.
379 * Handle to metafile copy on success, NULL on failure.
383 * Copying to disk returns NULL even if successful.
385 HMETAFILE WINAPI CopyMetaFileA(
386 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
387 LPCSTR lpFilename /* [in] filename if copying to a file */
389 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
390 METAHEADER *mh2 = NULL;
393 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
397 if(mh->mtType == METAFILE_DISK)
398 mh2 = MF_LoadDiskBasedMetaFile(mh);
400 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
401 memcpy( mh2, mh, mh->mtSize * 2 );
403 MF_ReleaseMetaHeader( hSrcMetaFile );
405 if(lpFilename) { /* disk based metafile */
406 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
407 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
408 HeapFree( GetProcessHeap(), 0, mh2 );
411 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
413 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
416 return MF_Create_HMETAFILE( mh2 );
420 /******************************************************************
421 * CopyMetaFileW (GDI32.@)
423 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
426 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
427 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
428 HeapFree( GetProcessHeap(), 0, p );
433 /******************************************************************
434 * IsValidMetaFile (GDI.410)
436 * Attempts to check if a given metafile is correctly formatted.
437 * Currently, the only things verified are several properties of the
441 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
444 * This is not exactly what windows does, see _Undocumented_Windows_
447 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
450 METAHEADER *mh = MF_GetMetaHeader16(hmf);
452 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
453 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
454 if (mh->mtVersion == MFVERSION)
456 MF_ReleaseMetaHeader16(hmf);
458 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
463 /*******************************************************************
466 * Helper for PlayMetaFile
468 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
473 unsigned int offset = 0;
480 if (!mh) return FALSE;
481 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
482 mh = MF_LoadDiskBasedMetaFile(mh);
483 if(!mh) return FALSE;
487 /* save the current pen, brush and font */
488 hPen = GetCurrentObject(hdc, OBJ_PEN);
489 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
490 hFont = GetCurrentObject(hdc, OBJ_FONT);
492 /* create the handle table */
493 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
494 sizeof(HANDLETABLE16) * mh->mtNoObjects);
495 if(!ht) return FALSE;
497 /* loop through metafile playing records */
498 offset = mh->mtHeaderSize * 2;
499 while (offset < mh->mtSize * 2)
501 mr = (METARECORD *)((char *)mh + offset);
502 TRACE("offset=%04x,size=%08lx\n",
506 "Entry got size 0 at offset %d, total mf length is %ld\n",
507 offset,mh->mtSize*2);
508 break; /* would loop endlessly otherwise */
510 offset += mr->rdSize * 2;
511 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
514 SelectObject(hdc, hBrush);
515 SelectObject(hdc, hPen);
516 SelectObject(hdc, hFont);
518 /* free objects in handle table */
519 for(i = 0; i < mh->mtNoObjects; i++)
520 if(*(ht->objectHandle + i) != 0)
521 DeleteObject(*(ht->objectHandle + i));
523 /* free handle table */
524 HeapFree( GetProcessHeap(), 0, ht );
526 HeapFree( GetProcessHeap(), 0, mh );
530 /******************************************************************
531 * PlayMetaFile16 (GDI.123)
534 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
537 METAHEADER *mh = MF_GetMetaHeader16( hmf );
538 ret = MF_PlayMetaFile( hdc, mh );
539 MF_ReleaseMetaHeader16( hmf );
543 /******************************************************************
544 * PlayMetaFile (GDI32.@)
546 * Renders the metafile specified by hmf in the DC specified by
547 * hdc. Returns FALSE on failure, TRUE on success.
549 BOOL WINAPI PlayMetaFile(
550 HDC hdc, /* [in] handle of DC to render in */
551 HMETAFILE hmf /* [in] handle of metafile to render */
555 METAHEADER *mh = MF_GetMetaHeader( hmf );
556 ret = MF_PlayMetaFile( hdc, mh );
557 MF_ReleaseMetaHeader( hmf );
562 /******************************************************************
563 * EnumMetaFile16 (GDI.175)
566 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
567 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
569 METAHEADER *mh = MF_GetMetaHeader16(hmf);
574 unsigned int offset = 0;
579 BOOL16 result = TRUE, loaded = FALSE;
581 TRACE("(%04x, %04x, %08lx, %08lx)\n",
582 hdc, hmf, (DWORD)lpEnumFunc, lpData);
585 if(!mh) return FALSE;
586 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
587 mh = MF_LoadDiskBasedMetaFile(mh);
588 if(!mh) return FALSE;
592 /* save the current pen, brush and font */
593 hPen = GetCurrentObject(hdc, OBJ_PEN);
594 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
595 hFont = GetCurrentObject(hdc, OBJ_FONT);
597 /* create the handle table */
599 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
600 sizeof(HANDLETABLE16) * mh->mtNoObjects);
601 spht = K32WOWGlobalLock16(hHT);
604 offset = mh->mtHeaderSize * 2;
606 /* loop through metafile records */
608 while (offset < (mh->mtSize * 2))
610 mr = (METARECORD *)((char *)mh + offset);
611 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
612 (METARECORD *)MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
613 mh->mtNoObjects, (LONG)lpData ))
620 offset += (mr->rdSize * 2);
623 SelectObject(hdc, hBrush);
624 SelectObject(hdc, hPen);
625 SelectObject(hdc, hFont);
627 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
629 /* free objects in handle table */
630 for(i = 0; i < mh->mtNoObjects; i++)
631 if(*(ht->objectHandle + i) != 0)
632 DeleteObject(*(ht->objectHandle + i));
634 /* free handle table */
637 HeapFree( GetProcessHeap(), 0, mh );
638 MF_ReleaseMetaHeader16(hmf);
642 /******************************************************************
643 * EnumMetaFile (GDI32.@)
645 * Loop through the metafile records in hmf, calling the user-specified
646 * function for each one, stopping when the user's function returns FALSE
647 * (which is considered to be failure)
648 * or when no records are left (which is considered to be success).
651 * TRUE on success, FALSE on failure.
654 * Niels de carpentier, april 1996
656 BOOL WINAPI EnumMetaFile(
659 MFENUMPROC lpEnumFunc,
662 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
667 unsigned int offset = 0;
672 TRACE("(%08x,%08x,%p,%p)\n",
673 hdc, hmf, lpEnumFunc, (void*)lpData);
675 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
676 mhTemp = MF_LoadDiskBasedMetaFile(mh);
679 MF_ReleaseMetaHeader(hmf);
686 /* We need to copy this thing instead of use it directly because we
687 * have to close the hmf handle for the purpose of avoiding deadlock.
689 mhTemp = HeapAlloc( GetProcessHeap(), 0, mh->mtHeaderSize + mh->mtSize*2 );
692 MF_ReleaseMetaHeader(hmf);
695 memcpy( mhTemp, mh, mh->mtHeaderSize + mh->mtSize*2 );
698 MF_ReleaseMetaHeader(hmf);
699 hmf = 0; /* just in case */
701 /* save the current pen, brush and font */
702 hPen = GetCurrentObject(hdc, OBJ_PEN);
703 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
704 hFont = GetCurrentObject(hdc, OBJ_FONT);
706 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
707 sizeof(HANDLETABLE) * mh->mtNoObjects);
709 /* loop through metafile records */
710 offset = mh->mtHeaderSize * 2;
712 while (offset < (mh->mtSize * 2))
714 mr = (METARECORD *)((char *)mh + offset);
715 TRACE("Calling EnumFunc with record type %x\n",
717 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
723 offset += (mr->rdSize * 2);
726 /* restore pen, brush and font */
727 SelectObject(hdc, hBrush);
728 SelectObject(hdc, hPen);
729 SelectObject(hdc, hFont);
731 /* free objects in handle table */
732 for(i = 0; i < mh->mtNoObjects; i++)
733 if(*(ht->objectHandle + i) != 0)
734 DeleteObject(*(ht->objectHandle + i));
736 /* free handle table */
737 HeapFree( GetProcessHeap(), 0, ht);
738 /* free a copy of metafile */
739 HeapFree( GetProcessHeap(), 0, mh );
743 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
744 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
745 /******************************************************************
746 * PlayMetaFileRecord16 (GDI.176)
748 * Render a single metafile record specified by *mr in the DC hdc, while
749 * using the handle table *ht, of length nHandles,
750 * to store metafile objects.
753 * The following metafile records are unimplemented:
755 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
756 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
757 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
760 void WINAPI PlayMetaFileRecord16(
761 HDC16 hdc, /* [in] DC to render metafile into */
762 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
763 METARECORD *mr, /* [in] pointer to metafile record to render */
764 UINT16 nHandles /* [in] size of handle table */
769 BITMAPINFOHEADER *infohdr;
771 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
772 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
774 switch (mr->rdFunction)
779 case META_DELETEOBJECT:
780 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
781 *(ht->objectHandle + *(mr->rdParm)) = 0;
784 case META_SETBKCOLOR:
785 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
789 SetBkMode16(hdc, *(mr->rdParm));
792 case META_SETMAPMODE:
793 SetMapMode16(hdc, *(mr->rdParm));
797 SetROP216(hdc, *(mr->rdParm));
801 SetRelAbs16(hdc, *(mr->rdParm));
804 case META_SETPOLYFILLMODE:
805 SetPolyFillMode16(hdc, *(mr->rdParm));
808 case META_SETSTRETCHBLTMODE:
809 SetStretchBltMode16(hdc, *(mr->rdParm));
812 case META_SETTEXTCOLOR:
813 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
816 case META_SETWINDOWORG:
817 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
820 case META_SETWINDOWEXT:
821 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
824 case META_SETVIEWPORTORG:
825 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
828 case META_SETVIEWPORTEXT:
829 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
832 case META_OFFSETWINDOWORG:
833 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
836 case META_SCALEWINDOWEXT:
837 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
838 *(mr->rdParm + 1), *(mr->rdParm));
841 case META_OFFSETVIEWPORTORG:
842 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
845 case META_SCALEVIEWPORTEXT:
846 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
847 *(mr->rdParm + 1), *(mr->rdParm));
851 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
855 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
858 case META_EXCLUDECLIPRECT:
859 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
860 *(mr->rdParm + 1), *(mr->rdParm) );
863 case META_INTERSECTCLIPRECT:
864 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
865 *(mr->rdParm + 1), *(mr->rdParm) );
869 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
870 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
871 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
872 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
876 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
877 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
881 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
882 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
886 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
887 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
888 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
889 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
893 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
894 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
898 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
899 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
900 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
904 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
905 *(mr->rdParm + 3), *(mr->rdParm + 2),
906 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
914 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
915 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
918 case META_OFFSETCLIPRGN:
919 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
924 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
925 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
926 (char *)(mr->rdParm + 1), s1);
930 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
933 case META_POLYPOLYGON:
934 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
935 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
939 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
943 RestoreDC(hdc, (INT16)*(mr->rdParm));
946 case META_SELECTOBJECT:
947 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
951 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
952 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
953 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
954 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
957 case META_CREATEPATTERNBRUSH:
958 switch (*(mr->rdParm))
961 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
962 MF_AddHandle(ht, nHandles,
963 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
968 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
972 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
973 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
974 ptr = GlobalLock16(hndl);
975 memcpy(ptr, mr->rdParm + 2, s1);
976 GlobalUnlock16(hndl);
977 MF_AddHandle(ht, nHandles,
978 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
983 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
989 case META_CREATEPENINDIRECT:
990 MF_AddHandle(ht, nHandles,
991 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
994 case META_CREATEFONTINDIRECT:
995 MF_AddHandle(ht, nHandles,
996 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
999 case META_CREATEBRUSHINDIRECT:
1000 MF_AddHandle(ht, nHandles,
1001 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1004 case META_CREATEPALETTE:
1005 MF_AddHandle(ht, nHandles,
1006 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1009 case META_SETTEXTALIGN:
1010 SetTextAlign16(hdc, *(mr->rdParm));
1013 case META_SELECTPALETTE:
1014 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1018 case META_SETMAPPERFLAGS:
1019 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1022 case META_REALIZEPALETTE:
1023 GDIRealizePalette16(hdc);
1027 FIXME("META_ESCAPE unimplemented.\n");
1030 case META_EXTTEXTOUT:
1031 MF_Play_MetaExtTextOut( hdc, mr );
1034 case META_STRETCHDIB:
1036 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1037 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1038 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1039 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1040 mr->rdParm[4],mr->rdParm[3],bits,info,
1041 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1045 case META_DIBSTRETCHBLT:
1047 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1048 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1049 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1050 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1051 mr->rdParm[3],mr->rdParm[2],bits,info,
1052 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1056 case META_STRETCHBLT:
1058 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1059 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1060 mr->rdParm[11], /*Height*/
1061 mr->rdParm[13], /*Planes*/
1062 mr->rdParm[14], /*BitsPixel*/
1063 (LPSTR)&mr->rdParm[15]); /*bits*/
1064 SelectObject(hdcSrc,hbitmap);
1065 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1066 mr->rdParm[7],mr->rdParm[6],
1067 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1068 mr->rdParm[3],mr->rdParm[2],
1069 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1076 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1077 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1078 mr->rdParm[8]/*Height*/,
1079 mr->rdParm[10]/*Planes*/,
1080 mr->rdParm[11]/*BitsPixel*/,
1081 (LPSTR)&mr->rdParm[12]/*bits*/);
1082 SelectObject(hdcSrc,hbitmap);
1083 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1084 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1085 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1086 MAKELONG(0,mr->rdParm[0]));
1091 case META_CREATEREGION:
1093 HRGN hrgn = CreateRectRgn(0,0,0,0);
1095 MF_Play_MetaCreateRegion(mr, hrgn);
1096 MF_AddHandle(ht, nHandles, hrgn);
1100 case META_FILLREGION:
1101 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1102 *(ht->objectHandle + *(mr->rdParm)));
1105 case META_FRAMEREGION:
1106 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1107 *(ht->objectHandle + *(mr->rdParm+2)),
1108 *(mr->rdParm+1), *(mr->rdParm));
1111 case META_INVERTREGION:
1112 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1115 case META_PAINTREGION:
1116 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1119 case META_SELECTCLIPREGION:
1120 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1123 case META_DIBCREATEPATTERNBRUSH:
1124 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1125 but there's no difference */
1127 TRACE("%d\n",*(mr->rdParm));
1128 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1129 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1130 ptr = GlobalLock16(hndl);
1131 memcpy(ptr, mr->rdParm + 2, s1);
1132 GlobalUnlock16(hndl);
1133 MF_AddHandle(ht, nHandles,
1134 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1138 case META_DIBBITBLT:
1139 /* In practice I've found that there are two layouts for
1140 META_DIBBITBLT, one (the first here) is the usual one when a src
1141 dc is actually passed to it, the second occurs when the src dc is
1142 passed in as NULL to the creating BitBlt. As the second case has
1143 no dib, a size check will suffice to distinguish.
1145 Caolan.McNamara@ul.ie */
1147 if (mr->rdSize > 12) {
1148 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1149 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1151 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1152 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1153 mr->rdParm[5], mr->rdParm[4], bits, info,
1155 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1156 } else { /* equivalent to a PatBlt */
1157 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1158 mr->rdParm[6], mr->rdParm[5],
1159 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1163 case META_SETTEXTCHAREXTRA:
1164 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1167 case META_SETTEXTJUSTIFICATION:
1168 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1171 case META_EXTFLOODFILL:
1172 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1173 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1177 case META_SETDIBTODEV:
1179 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1180 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1181 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1182 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1183 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1184 mr->rdParm[2], mr->rdParm[1], bits, info,
1189 #define META_UNIMP(x) case x: \
1190 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1192 META_UNIMP(META_DRAWTEXT)
1193 META_UNIMP(META_ANIMATEPALETTE)
1194 META_UNIMP(META_SETPALENTRIES)
1195 META_UNIMP(META_RESIZEPALETTE)
1196 META_UNIMP(META_RESETDC)
1197 META_UNIMP(META_STARTDOC)
1198 META_UNIMP(META_STARTPAGE)
1199 META_UNIMP(META_ENDPAGE)
1200 META_UNIMP(META_ABORTDOC)
1201 META_UNIMP(META_ENDDOC)
1202 META_UNIMP(META_CREATEBRUSH)
1203 META_UNIMP(META_CREATEBITMAPINDIRECT)
1204 META_UNIMP(META_CREATEBITMAP)
1208 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1213 /******************************************************************
1214 * PlayMetaFileRecord (GDI32.@)
1216 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1217 METARECORD *metarecord, UINT handles )
1219 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1220 handles*sizeof(HANDLETABLE16));
1222 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1224 for (i=0; i<handles; i++)
1225 ht->objectHandle[i] = handletable->objectHandle[i];
1226 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1227 for (i=0; i<handles; i++)
1228 handletable->objectHandle[i] = ht->objectHandle[i];
1229 GlobalFree((HGLOBAL)ht);
1233 /******************************************************************
1234 * GetMetaFileBits (GDI.159)
1236 * Trade in a metafile object handle for a handle to the metafile memory.
1240 HGLOBAL16 WINAPI GetMetaFileBits16(
1241 HMETAFILE16 hmf /* [in] metafile handle */
1244 TRACE("hMem out: %04x\n", hmf);
1248 /******************************************************************
1249 * SetMetaFileBits (GDI.160)
1251 * Trade in a metafile memory handle for a handle to a metafile object.
1252 * The memory region should hold a proper metafile, otherwise
1253 * problems will occur when it is used. Validity of the memory is not
1254 * checked. The function is essentially just the identity function.
1256 HMETAFILE16 WINAPI SetMetaFileBits16(
1258 /* [in] handle to a memory region holding a metafile */
1261 TRACE("hmf out: %04x\n", hMem);
1266 /******************************************************************
1267 * SetMetaFileBitsBetter (GDI.196)
1269 * Trade in a metafile memory handle for a handle to a metafile object,
1270 * making a cursory check (using IsValidMetaFile()) that the memory
1271 * handle points to a valid metafile.
1274 * Handle to a metafile on success, NULL on failure..
1276 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1278 if( IsValidMetaFile16( hMeta ) )
1279 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1280 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1281 return (HMETAFILE16)0;
1284 /******************************************************************
1285 * SetMetaFileBitsEx (GDI32.@)
1287 * Create a metafile from raw data. No checking of the data is performed.
1288 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1290 HMETAFILE WINAPI SetMetaFileBitsEx(
1291 UINT size, /* [in] size of metafile, in bytes */
1292 const BYTE *lpData /* [in] pointer to metafile data */
1295 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1297 memcpy(mh, lpData, size);
1298 return MF_Create_HMETAFILE(mh);
1301 /*****************************************************************
1302 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1304 * Copies the data from metafile _hmf_ into the buffer _buf_.
1305 * If _buf_ is zero, returns size of buffer required. Otherwise,
1306 * returns number of bytes copied.
1308 UINT WINAPI GetMetaFileBitsEx(
1309 HMETAFILE hmf, /* [in] metafile */
1310 UINT nSize, /* [in] size of buf */
1311 LPVOID buf /* [out] buffer to receive raw metafile data */
1313 METAHEADER *mh = MF_GetMetaHeader(hmf);
1316 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1317 if (!mh) return 0; /* FIXME: error code */
1318 if(mh->mtType == METAFILE_DISK)
1319 FIXME("Disk-based metafile?\n");
1320 mfSize = mh->mtSize * 2;
1322 MF_ReleaseMetaHeader(hmf);
1323 TRACE("returning size %d\n", mfSize);
1326 if(mfSize > nSize) mfSize = nSize;
1327 memmove(buf, mh, mfSize);
1328 MF_ReleaseMetaHeader(hmf);
1332 /******************************************************************
1333 * GetWinMetaFileBits [GDI32.@]
1335 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1336 UINT cbBuffer, LPBYTE lpbBuffer,
1337 INT fnMapMode, HDC hdcRef)
1339 FIXME("(%d,%d,%p,%d,%d): stub\n",
1340 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1344 /******************************************************************
1345 * MF_Play_MetaCreateRegion
1347 * Handles META_CREATEREGION for PlayMetaFileRecord().
1351 * The layout of the record looks something like this:
1356 * 2 Looks like a handle? - not constant
1358 * 4 Total number of bytes
1359 * 5 No. of separate bands = n [see below]
1360 * 6 Largest number of x co-ords in a band
1361 * 7-10 Bounding box x1 y1 x2 y2
1364 * Regions are divided into bands that are uniform in the
1365 * y-direction. Each band consists of pairs of on/off x-coords and is
1367 * m y0 y1 x1 x2 x3 ... xm m
1368 * into successive rdParm[]s.
1370 * This is probably just a dump of the internal RGNOBJ?
1376 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1381 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1383 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1384 band++, start = end + 1) {
1385 if(*start / 2 != (*start + 1) / 2) {
1386 WARN("Delimiter not even.\n");
1387 DeleteObject( hrgn2 );
1391 end = start + *start + 3;
1392 if(end > (WORD *)mr + mr->rdSize) {
1393 WARN("End points outside record.\n");
1394 DeleteObject( hrgn2 );
1398 if(*start != *end) {
1399 WARN("Mismatched delimiters.\n");
1400 DeleteObject( hrgn2 );
1404 y0 = *(INT16 *)(start + 1);
1405 y1 = *(INT16 *)(start + 2);
1406 for(pair = 0; pair < *start / 2; pair++) {
1407 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1408 *(INT16 *)(start + 4 + 2*pair), y1 );
1409 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1412 DeleteObject( hrgn2 );
1417 /******************************************************************
1418 * MF_Play_MetaExtTextOut
1420 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1423 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1430 s1 = mr->rdParm[2]; /* String length */
1431 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1432 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1433 /* rec len without dx array */
1435 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1437 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1439 if (mr->rdSize == len / 2)
1440 dxx = NULL; /* determine if array present */
1442 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1443 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1445 TRACE("%s len: %ld\n", sot, mr->rdSize);
1447 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1448 len, s1, mr->rdSize, mr->rdParm[3]);
1449 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1451 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1452 mr->rdParm[0], /* Y position */
1453 mr->rdParm[3], /* options */
1454 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1457 s1, dxx); /* length, dx array */
1459 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);