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.
38 #include "wine/winbase16.h"
39 #include "wine/wingdi16.h"
45 #include "debugtools.h"
47 DEFAULT_DEBUG_CHANNEL(metafile);
58 #define MFHEADERSIZE (sizeof(METAHEADER))
59 #define MFVERSION 0x300
61 /******************************************************************
64 * Add a handle to an external handle table and return the index
66 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
70 for (i = 0; i < htlen; i++)
72 if (*(ht->objectHandle + i) == 0)
74 *(ht->objectHandle + i) = hobj;
82 /******************************************************************
83 * MF_Create_HMETATFILE
85 * Creates a (32 bit) HMETAFILE object from a METAHEADER
87 * HMETAFILEs are GDI objects.
89 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
92 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
96 GDI_ReleaseObj( hmf );
101 /******************************************************************
102 * MF_Create_HMETATFILE16
104 * Creates a HMETAFILE16 object from a METAHEADER
106 * HMETAFILE16s are Global memory handles.
108 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
111 DWORD size = mh->mtSize * sizeof(WORD);
113 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
116 METAHEADER *mh_dest = GlobalLock16(hmf);
117 memcpy(mh_dest, mh, size);
120 HeapFree(GetProcessHeap(), 0, mh);
124 /******************************************************************
127 * Returns ptr to METAHEADER associated with HMETAFILE
129 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
131 METAHEADER *ret = NULL;
132 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
136 GDI_ReleaseObj( hmf );
141 /******************************************************************
144 * Returns ptr to METAHEADER associated with HMETAFILE16
145 * Should be followed by call to MF_ReleaseMetaHeader16
147 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
149 return GlobalLock16(hmf);
152 /******************************************************************
153 * MF_ReleaseMetaHeader16
155 * Releases METAHEADER associated with HMETAFILE16
157 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
159 return GlobalUnlock16( hmf );
163 /******************************************************************
164 * DeleteMetaFile (GDI.127)
166 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
168 return !GlobalFree16( hmf );
171 /******************************************************************
172 * DeleteMetaFile (GDI32.@)
174 * Delete a memory-based metafile.
177 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
179 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
180 if (!metaObj) return FALSE;
181 HeapFree( GetProcessHeap(), 0, metaObj->mh );
182 GDI_FreeObject( hmf, metaObj );
186 /******************************************************************
189 * Returns a pointer to a memory based METAHEADER read in from file HFILE
192 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
195 DWORD BytesRead, size;
197 size = sizeof(METAHEADER);
198 mh = HeapAlloc( GetProcessHeap(), 0, size );
200 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
202 HeapFree( GetProcessHeap(), 0, mh );
205 size = mh->mtSize * 2;
206 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
208 size -= sizeof(METAHEADER);
209 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
212 HeapFree( GetProcessHeap(), 0, mh );
216 if (mh->mtType != METAFILE_MEMORY) {
217 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
218 mh->mtType = METAFILE_MEMORY;
223 /******************************************************************
224 * GetMetaFile (GDI.124)
226 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
231 TRACE("%s\n", lpFilename);
236 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
237 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
240 mh = MF_ReadMetaFile(hFile);
243 return MF_Create_HMETAFILE16( mh );
246 /******************************************************************
247 * GetMetaFileA (GDI32.@)
249 * Read a metafile from a file. Returns handle to a memory-based metafile.
251 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
256 TRACE("%s\n", lpFilename);
261 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
262 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
265 mh = MF_ReadMetaFile(hFile);
268 return MF_Create_HMETAFILE( mh );
273 /******************************************************************
274 * GetMetaFileW (GDI32.@)
276 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
281 TRACE("%s\n", debugstr_w(lpFilename));
286 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
287 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
290 mh = MF_ReadMetaFile(hFile);
293 return MF_Create_HMETAFILE( mh );
297 /******************************************************************
298 * MF_LoadDiskBasedMetaFile
300 * Creates a new memory-based metafile from a disk-based one.
302 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
308 if(mh->mtType != METAFILE_DISK) {
309 ERR("Not a disk based metafile\n");
312 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
314 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
315 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
316 WARN("Can't open file of disk based metafile\n");
319 mh2 = MF_ReadMetaFile(hfile);
324 /******************************************************************
325 * MF_CreateMetaHeaderDisk
327 * Take a memory based METAHEADER and change it to a disk based METAHEADER
328 * assosiated with filename. Note: Trashes contents of old one.
330 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
335 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
336 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
337 mh->mtType = METAFILE_DISK;
338 size = HeapSize( GetProcessHeap(), 0, mh );
339 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
340 strcpy(mhd->filename, filename);
344 /******************************************************************
345 * CopyMetaFile (GDI.151)
347 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
349 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
350 METAHEADER *mh2 = NULL;
353 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
357 if(mh->mtType == METAFILE_DISK)
358 mh2 = MF_LoadDiskBasedMetaFile(mh);
360 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
361 memcpy( mh2, mh, mh->mtSize * 2 );
363 MF_ReleaseMetaHeader16( hSrcMetaFile );
365 if(lpFilename) { /* disk based metafile */
366 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
367 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
368 HeapFree( GetProcessHeap(), 0, mh2 );
371 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
373 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
376 return MF_Create_HMETAFILE16( mh2 );
380 /******************************************************************
381 * CopyMetaFileA (GDI32.@)
383 * Copies the metafile corresponding to hSrcMetaFile to either
384 * a disk file, if a filename is given, or to a new memory based
385 * metafile, if lpFileName is NULL.
389 * Handle to metafile copy on success, NULL on failure.
393 * Copying to disk returns NULL even if successful.
395 HMETAFILE WINAPI CopyMetaFileA(
396 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
397 LPCSTR lpFilename /* [in] filename if copying to a file */
399 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
400 METAHEADER *mh2 = NULL;
403 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
407 if(mh->mtType == METAFILE_DISK)
408 mh2 = MF_LoadDiskBasedMetaFile(mh);
410 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
411 memcpy( mh2, mh, mh->mtSize * 2 );
414 if(lpFilename) { /* disk based metafile */
415 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
416 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
417 HeapFree( GetProcessHeap(), 0, mh2 );
420 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
422 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
425 return MF_Create_HMETAFILE( mh2 );
429 /******************************************************************
430 * CopyMetaFileW (GDI32.@)
432 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
435 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
436 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
437 HeapFree( GetProcessHeap(), 0, p );
442 /******************************************************************
443 * IsValidMetaFile (GDI.410)
445 * Attempts to check if a given metafile is correctly formatted.
446 * Currently, the only things verified are several properties of the
450 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
453 * This is not exactly what windows does, see _Undocumented_Windows_
456 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
459 METAHEADER *mh = MF_GetMetaHeader16(hmf);
461 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
462 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
463 if (mh->mtVersion == MFVERSION)
465 MF_ReleaseMetaHeader16(hmf);
467 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
472 /*******************************************************************
475 * Helper for PlayMetaFile
477 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
482 unsigned int offset = 0;
489 if (!mh) return FALSE;
490 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
491 mh = MF_LoadDiskBasedMetaFile(mh);
492 if(!mh) return FALSE;
496 /* save the current pen, brush and font */
497 hPen = GetCurrentObject(hdc, OBJ_PEN);
498 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
499 hFont = GetCurrentObject(hdc, OBJ_FONT);
501 /* create the handle table */
502 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
503 sizeof(HANDLETABLE16) * mh->mtNoObjects);
504 if(!ht) return FALSE;
506 /* loop through metafile playing records */
507 offset = mh->mtHeaderSize * 2;
508 while (offset < mh->mtSize * 2)
510 mr = (METARECORD *)((char *)mh + offset);
511 TRACE("offset=%04x,size=%08lx\n",
515 "Entry got size 0 at offset %d, total mf length is %ld\n",
516 offset,mh->mtSize*2);
517 break; /* would loop endlessly otherwise */
519 offset += mr->rdSize * 2;
520 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
523 SelectObject(hdc, hBrush);
524 SelectObject(hdc, hPen);
525 SelectObject(hdc, hFont);
527 /* free objects in handle table */
528 for(i = 0; i < mh->mtNoObjects; i++)
529 if(*(ht->objectHandle + i) != 0)
530 DeleteObject(*(ht->objectHandle + i));
532 /* free handle table */
533 HeapFree( GetProcessHeap(), 0, ht );
535 HeapFree( GetProcessHeap(), 0, mh );
539 /******************************************************************
540 * PlayMetaFile (GDI.123)
543 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
546 METAHEADER *mh = MF_GetMetaHeader16( hmf );
547 ret = MF_PlayMetaFile( hdc, mh );
548 MF_ReleaseMetaHeader16( hmf );
552 /******************************************************************
553 * PlayMetaFile (GDI32.@)
555 * Renders the metafile specified by hmf in the DC specified by
556 * hdc. Returns FALSE on failure, TRUE on success.
558 BOOL WINAPI PlayMetaFile(
559 HDC hdc, /* [in] handle of DC to render in */
560 HMETAFILE hmf /* [in] handle of metafile to render */
563 METAHEADER *mh = MF_GetMetaHeader( hmf );
564 return MF_PlayMetaFile( hdc, mh );
568 /******************************************************************
569 * EnumMetaFile16 (GDI.175)
572 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
573 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
575 METAHEADER *mh = MF_GetMetaHeader16(hmf);
580 unsigned int offset = 0;
585 BOOL16 result = TRUE, loaded = FALSE;
587 TRACE("(%04x, %04x, %08lx, %08lx)\n",
588 hdc, hmf, (DWORD)lpEnumFunc, lpData);
591 if(!mh) return FALSE;
592 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
593 mh = MF_LoadDiskBasedMetaFile(mh);
594 if(!mh) return FALSE;
598 /* save the current pen, brush and font */
599 hPen = GetCurrentObject(hdc, OBJ_PEN);
600 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
601 hFont = GetCurrentObject(hdc, OBJ_FONT);
603 /* create the handle table */
605 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
606 sizeof(HANDLETABLE16) * mh->mtNoObjects);
607 spht = K32WOWGlobalLock16(hHT);
610 offset = mh->mtHeaderSize * 2;
612 /* loop through metafile records */
614 while (offset < (mh->mtSize * 2))
616 mr = (METARECORD *)((char *)mh + offset);
617 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
618 (METARECORD *)MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
619 mh->mtNoObjects, (LONG)lpData ))
626 offset += (mr->rdSize * 2);
629 SelectObject(hdc, hBrush);
630 SelectObject(hdc, hPen);
631 SelectObject(hdc, hFont);
633 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
635 /* free objects in handle table */
636 for(i = 0; i < mh->mtNoObjects; i++)
637 if(*(ht->objectHandle + i) != 0)
638 DeleteObject(*(ht->objectHandle + i));
640 /* free handle table */
643 HeapFree( GetProcessHeap(), 0, mh );
644 MF_ReleaseMetaHeader16(hmf);
648 /******************************************************************
649 * EnumMetaFile (GDI32.@)
651 * Loop through the metafile records in hmf, calling the user-specified
652 * function for each one, stopping when the user's function returns FALSE
653 * (which is considered to be failure)
654 * or when no records are left (which is considered to be success).
657 * TRUE on success, FALSE on failure.
660 * Niels de carpentier, april 1996
662 BOOL WINAPI EnumMetaFile(
665 MFENUMPROC lpEnumFunc,
668 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
673 unsigned int offset = 0;
678 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
680 if(mh->mtType == METAFILE_DISK)
682 /* Create a memory-based copy */
683 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
687 /* save the current pen, brush and font */
688 hPen = GetCurrentObject(hdc, OBJ_PEN);
689 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
690 hFont = GetCurrentObject(hdc, OBJ_FONT);
692 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
693 sizeof(HANDLETABLE) * mh->mtNoObjects);
695 /* loop through metafile records */
696 offset = mh->mtHeaderSize * 2;
698 while (offset < (mh->mtSize * 2))
700 mr = (METARECORD *)((char *)mh + offset);
701 TRACE("Calling EnumFunc with record type %x\n",
703 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
709 offset += (mr->rdSize * 2);
712 /* restore pen, brush and font */
713 SelectObject(hdc, hBrush);
714 SelectObject(hdc, hPen);
715 SelectObject(hdc, hFont);
717 /* free objects in handle table */
718 for(i = 0; i < mh->mtNoObjects; i++)
719 if(*(ht->objectHandle + i) != 0)
720 DeleteObject(*(ht->objectHandle + i));
722 /* free handle table */
723 HeapFree( GetProcessHeap(), 0, ht);
724 /* free a copy of metafile */
725 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
729 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
730 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
731 /******************************************************************
732 * PlayMetaFileRecord (GDI.176)
734 * Render a single metafile record specified by *mr in the DC hdc, while
735 * using the handle table *ht, of length nHandles,
736 * to store metafile objects.
739 * The following metafile records are unimplemented:
741 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
742 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
743 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
746 void WINAPI PlayMetaFileRecord16(
747 HDC16 hdc, /* [in] DC to render metafile into */
748 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
749 METARECORD *mr, /* [in] pointer to metafile record to render */
750 UINT16 nHandles /* [in] size of handle table */
755 BITMAPINFOHEADER *infohdr;
757 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
758 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
760 switch (mr->rdFunction)
765 case META_DELETEOBJECT:
766 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
767 *(ht->objectHandle + *(mr->rdParm)) = 0;
770 case META_SETBKCOLOR:
771 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
775 SetBkMode16(hdc, *(mr->rdParm));
778 case META_SETMAPMODE:
779 SetMapMode16(hdc, *(mr->rdParm));
783 SetROP216(hdc, *(mr->rdParm));
787 SetRelAbs16(hdc, *(mr->rdParm));
790 case META_SETPOLYFILLMODE:
791 SetPolyFillMode16(hdc, *(mr->rdParm));
794 case META_SETSTRETCHBLTMODE:
795 SetStretchBltMode16(hdc, *(mr->rdParm));
798 case META_SETTEXTCOLOR:
799 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
802 case META_SETWINDOWORG:
803 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
806 case META_SETWINDOWEXT:
807 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
810 case META_SETVIEWPORTORG:
811 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
814 case META_SETVIEWPORTEXT:
815 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
818 case META_OFFSETWINDOWORG:
819 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
822 case META_SCALEWINDOWEXT:
823 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
824 *(mr->rdParm + 1), *(mr->rdParm));
827 case META_OFFSETVIEWPORTORG:
828 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
831 case META_SCALEVIEWPORTEXT:
832 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
833 *(mr->rdParm + 1), *(mr->rdParm));
837 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
841 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
844 case META_EXCLUDECLIPRECT:
845 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
846 *(mr->rdParm + 1), *(mr->rdParm) );
849 case META_INTERSECTCLIPRECT:
850 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
851 *(mr->rdParm + 1), *(mr->rdParm) );
855 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
856 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
857 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
858 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
862 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
863 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
867 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
868 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
872 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
873 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
874 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
875 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
879 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
880 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
884 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
885 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
886 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
890 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
891 *(mr->rdParm + 3), *(mr->rdParm + 2),
892 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
900 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
901 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
904 case META_OFFSETCLIPRGN:
905 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
910 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
911 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
912 (char *)(mr->rdParm + 1), s1);
916 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
919 case META_POLYPOLYGON:
920 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
921 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
925 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
929 RestoreDC(hdc, (INT16)*(mr->rdParm));
932 case META_SELECTOBJECT:
933 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
937 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
938 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
939 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
940 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
943 case META_CREATEPATTERNBRUSH:
944 switch (*(mr->rdParm))
947 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
948 MF_AddHandle(ht, nHandles,
949 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
954 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
958 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
959 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
960 ptr = GlobalLock16(hndl);
961 memcpy(ptr, mr->rdParm + 2, s1);
962 GlobalUnlock16(hndl);
963 MF_AddHandle(ht, nHandles,
964 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
969 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
975 case META_CREATEPENINDIRECT:
976 MF_AddHandle(ht, nHandles,
977 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
980 case META_CREATEFONTINDIRECT:
981 MF_AddHandle(ht, nHandles,
982 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
985 case META_CREATEBRUSHINDIRECT:
986 MF_AddHandle(ht, nHandles,
987 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
990 case META_CREATEPALETTE:
991 MF_AddHandle(ht, nHandles,
992 CreatePalette16((LPLOGPALETTE)mr->rdParm));
995 case META_SETTEXTALIGN:
996 SetTextAlign16(hdc, *(mr->rdParm));
999 case META_SELECTPALETTE:
1000 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1004 case META_SETMAPPERFLAGS:
1005 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1008 case META_REALIZEPALETTE:
1009 GDIRealizePalette16(hdc);
1013 FIXME("META_ESCAPE unimplemented.\n");
1016 case META_EXTTEXTOUT:
1017 MF_Play_MetaExtTextOut( hdc, mr );
1020 case META_STRETCHDIB:
1022 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1023 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1024 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1025 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1026 mr->rdParm[4],mr->rdParm[3],bits,info,
1027 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1031 case META_DIBSTRETCHBLT:
1033 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1034 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1035 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1036 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1037 mr->rdParm[3],mr->rdParm[2],bits,info,
1038 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1042 case META_STRETCHBLT:
1044 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1045 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1046 mr->rdParm[11], /*Height*/
1047 mr->rdParm[13], /*Planes*/
1048 mr->rdParm[14], /*BitsPixel*/
1049 (LPSTR)&mr->rdParm[15]); /*bits*/
1050 SelectObject(hdcSrc,hbitmap);
1051 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1052 mr->rdParm[7],mr->rdParm[6],
1053 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1054 mr->rdParm[3],mr->rdParm[2],
1055 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1062 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1063 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1064 mr->rdParm[8]/*Height*/,
1065 mr->rdParm[10]/*Planes*/,
1066 mr->rdParm[11]/*BitsPixel*/,
1067 (LPSTR)&mr->rdParm[12]/*bits*/);
1068 SelectObject(hdcSrc,hbitmap);
1069 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1070 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1071 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1072 MAKELONG(0,mr->rdParm[0]));
1077 case META_CREATEREGION:
1079 HRGN hrgn = CreateRectRgn(0,0,0,0);
1081 MF_Play_MetaCreateRegion(mr, hrgn);
1082 MF_AddHandle(ht, nHandles, hrgn);
1086 case META_FILLREGION:
1087 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1088 *(ht->objectHandle + *(mr->rdParm)));
1091 case META_FRAMEREGION:
1092 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1093 *(ht->objectHandle + *(mr->rdParm+2)),
1094 *(mr->rdParm+1), *(mr->rdParm));
1097 case META_INVERTREGION:
1098 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1101 case META_PAINTREGION:
1102 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1105 case META_SELECTCLIPREGION:
1106 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1109 case META_DIBCREATEPATTERNBRUSH:
1110 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1111 but there's no difference */
1113 TRACE("%d\n",*(mr->rdParm));
1114 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1115 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1116 ptr = GlobalLock16(hndl);
1117 memcpy(ptr, mr->rdParm + 2, s1);
1118 GlobalUnlock16(hndl);
1119 MF_AddHandle(ht, nHandles,
1120 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1124 case META_DIBBITBLT:
1125 /* In practice I've found that there are two layouts for
1126 META_DIBBITBLT, one (the first here) is the usual one when a src
1127 dc is actually passed to it, the second occurs when the src dc is
1128 passed in as NULL to the creating BitBlt. As the second case has
1129 no dib, a size check will suffice to distinguish.
1131 Caolan.McNamara@ul.ie */
1133 if (mr->rdSize > 12) {
1134 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1135 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1137 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1138 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1139 mr->rdParm[5], mr->rdParm[4], bits, info,
1141 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1142 } else { /* equivalent to a PatBlt */
1143 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1144 mr->rdParm[6], mr->rdParm[5],
1145 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1149 case META_SETTEXTCHAREXTRA:
1150 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1153 case META_SETTEXTJUSTIFICATION:
1154 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1157 case META_EXTFLOODFILL:
1158 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1159 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1163 case META_SETDIBTODEV:
1165 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1166 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1167 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1168 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1169 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1170 mr->rdParm[2], mr->rdParm[1], bits, info,
1175 #define META_UNIMP(x) case x: \
1176 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1178 META_UNIMP(META_DRAWTEXT)
1179 META_UNIMP(META_ANIMATEPALETTE)
1180 META_UNIMP(META_SETPALENTRIES)
1181 META_UNIMP(META_RESIZEPALETTE)
1182 META_UNIMP(META_RESETDC)
1183 META_UNIMP(META_STARTDOC)
1184 META_UNIMP(META_STARTPAGE)
1185 META_UNIMP(META_ENDPAGE)
1186 META_UNIMP(META_ABORTDOC)
1187 META_UNIMP(META_ENDDOC)
1188 META_UNIMP(META_CREATEBRUSH)
1189 META_UNIMP(META_CREATEBITMAPINDIRECT)
1190 META_UNIMP(META_CREATEBITMAP)
1194 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1199 /******************************************************************
1200 * PlayMetaFileRecord (GDI32.@)
1202 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1203 METARECORD *metarecord, UINT handles )
1205 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1206 handles*sizeof(HANDLETABLE16));
1208 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1210 for (i=0; i<handles; i++)
1211 ht->objectHandle[i] = handletable->objectHandle[i];
1212 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1213 for (i=0; i<handles; i++)
1214 handletable->objectHandle[i] = ht->objectHandle[i];
1215 GlobalFree((HGLOBAL)ht);
1219 /******************************************************************
1220 * GetMetaFileBits (GDI.159)
1222 * Trade in a metafile object handle for a handle to the metafile memory.
1226 HGLOBAL16 WINAPI GetMetaFileBits16(
1227 HMETAFILE16 hmf /* [in] metafile handle */
1230 TRACE("hMem out: %04x\n", hmf);
1234 /******************************************************************
1235 * SetMetaFileBits (GDI.160)
1237 * Trade in a metafile memory handle for a handle to a metafile object.
1238 * The memory region should hold a proper metafile, otherwise
1239 * problems will occur when it is used. Validity of the memory is not
1240 * checked. The function is essentially just the identity function.
1242 HMETAFILE16 WINAPI SetMetaFileBits16(
1244 /* [in] handle to a memory region holding a metafile */
1247 TRACE("hmf out: %04x\n", hMem);
1252 /******************************************************************
1253 * SetMetaFileBitsBetter (GDI.196)
1255 * Trade in a metafile memory handle for a handle to a metafile object,
1256 * making a cursory check (using IsValidMetaFile()) that the memory
1257 * handle points to a valid metafile.
1260 * Handle to a metafile on success, NULL on failure..
1262 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1264 if( IsValidMetaFile16( hMeta ) )
1265 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1266 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1267 return (HMETAFILE16)0;
1270 /******************************************************************
1271 * SetMetaFileBitsEx (GDI32.@)
1273 * Create a metafile from raw data. No checking of the data is performed.
1274 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1276 HMETAFILE WINAPI SetMetaFileBitsEx(
1277 UINT size, /* [in] size of metafile, in bytes */
1278 const BYTE *lpData /* [in] pointer to metafile data */
1281 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1283 memcpy(mh, lpData, size);
1284 return MF_Create_HMETAFILE(mh);
1287 /*****************************************************************
1288 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1290 * Copies the data from metafile _hmf_ into the buffer _buf_.
1291 * If _buf_ is zero, returns size of buffer required. Otherwise,
1292 * returns number of bytes copied.
1294 UINT WINAPI GetMetaFileBitsEx(
1295 HMETAFILE hmf, /* [in] metafile */
1296 UINT nSize, /* [in] size of buf */
1297 LPVOID buf /* [out] buffer to receive raw metafile data */
1299 METAHEADER *mh = MF_GetMetaHeader(hmf);
1302 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1303 if (!mh) return 0; /* FIXME: error code */
1304 if(mh->mtType == METAFILE_DISK)
1305 FIXME("Disk-based metafile?\n");
1306 mfSize = mh->mtSize * 2;
1308 TRACE("returning size %d\n", mfSize);
1311 if(mfSize > nSize) mfSize = nSize;
1312 memmove(buf, mh, mfSize);
1316 /******************************************************************
1317 * GetWinMetaFileBits [GDI32.@]
1319 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1320 UINT cbBuffer, LPBYTE lpbBuffer,
1321 INT fnMapMode, HDC hdcRef)
1323 FIXME("(%d,%d,%p,%d,%d): stub\n",
1324 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1328 /******************************************************************
1329 * MF_Play_MetaCreateRegion
1331 * Handles META_CREATEREGION for PlayMetaFileRecord().
1335 * The layout of the record looks something like this:
1340 * 2 Looks like a handle? - not constant
1342 * 4 Total number of bytes
1343 * 5 No. of separate bands = n [see below]
1344 * 6 Largest number of x co-ords in a band
1345 * 7-10 Bounding box x1 y1 x2 y2
1348 * Regions are divided into bands that are uniform in the
1349 * y-direction. Each band consists of pairs of on/off x-coords and is
1351 * m y0 y1 x1 x2 x3 ... xm m
1352 * into successive rdParm[]s.
1354 * This is probably just a dump of the internal RGNOBJ?
1360 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1365 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1367 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1368 band++, start = end + 1) {
1369 if(*start / 2 != (*start + 1) / 2) {
1370 WARN("Delimiter not even.\n");
1371 DeleteObject( hrgn2 );
1375 end = start + *start + 3;
1376 if(end > (WORD *)mr + mr->rdSize) {
1377 WARN("End points outside record.\n");
1378 DeleteObject( hrgn2 );
1382 if(*start != *end) {
1383 WARN("Mismatched delimiters.\n");
1384 DeleteObject( hrgn2 );
1388 y0 = *(INT16 *)(start + 1);
1389 y1 = *(INT16 *)(start + 2);
1390 for(pair = 0; pair < *start / 2; pair++) {
1391 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1392 *(INT16 *)(start + 4 + 2*pair), y1 );
1393 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1396 DeleteObject( hrgn2 );
1401 /******************************************************************
1402 * MF_Play_MetaExtTextOut
1404 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1407 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1414 s1 = mr->rdParm[2]; /* String length */
1415 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1416 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1417 /* rec len without dx array */
1419 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1421 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1423 if (mr->rdSize == len / 2)
1424 dxx = NULL; /* determine if array present */
1426 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1427 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1429 TRACE("%s len: %ld\n", sot, mr->rdSize);
1431 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1432 len, s1, mr->rdSize, mr->rdParm[3]);
1433 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1435 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1436 mr->rdParm[0], /* Y position */
1437 mr->rdParm[3], /* options */
1438 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1441 s1, dxx); /* length, dx array */
1443 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);