4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * These functions are primarily involved with metafile playback or anything
24 * that touches a HMETAFILE.
25 * For recording of metafiles look in graphics/metafiledrv/
27 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
28 * global memory handles so these cannot be interchanged.
30 * Memory-based metafiles are just stored as a continuous block of memory with
31 * a METAHEADER at the head with METARECORDs appended to it. mtType is
32 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
33 * disk-based metafile - even mtType is METAFILE_MEMORY.
34 * 16bit HMETAFILE16s are global handles to this block
35 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
37 * Disk-based metafiles are rather different. HMETAFILE16s point to a
38 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
39 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
40 * more 0, then 2 which may be a time stamp of the file and then the path of
41 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
51 #include "wine/winbase16.h"
52 #include "wine/wingdi16.h"
55 #include "wine/debug.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
74 #define MFHEADERSIZE (sizeof(METAHEADER))
75 #define MFVERSION 0x300
77 /* ### start build ### */
78 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
79 /* ### stop build ### */
81 /******************************************************************
84 * Add a handle to an external handle table and return the index
86 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
90 for (i = 0; i < htlen; i++)
92 if (*(ht->objectHandle + i) == 0)
94 *(ht->objectHandle + i) = hobj;
102 /******************************************************************
103 * MF_Create_HMETATFILE
105 * Creates a (32 bit) HMETAFILE object from a METAHEADER
107 * HMETAFILEs are GDI objects.
109 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
112 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf, NULL );
116 GDI_ReleaseObj( hmf );
121 /******************************************************************
122 * MF_Create_HMETATFILE16
124 * Creates a HMETAFILE16 object from a METAHEADER
126 * HMETAFILE16s are Global memory handles.
128 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
131 DWORD size = mh->mtSize * sizeof(WORD);
133 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
136 METAHEADER *mh_dest = GlobalLock16(hmf);
137 memcpy(mh_dest, mh, size);
140 HeapFree(GetProcessHeap(), 0, mh);
144 /******************************************************************
147 * Returns ptr to METAHEADER associated with HMETAFILE
149 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
151 METAHEADER *ret = NULL;
152 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
156 GDI_ReleaseObj( hmf );
161 /******************************************************************
164 * Returns ptr to METAHEADER associated with HMETAFILE16
165 * Should be followed by call to MF_ReleaseMetaHeader16
167 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
169 return GlobalLock16(hmf);
172 /******************************************************************
173 * MF_ReleaseMetaHeader16
175 * Releases METAHEADER associated with HMETAFILE16
177 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
179 return GlobalUnlock16( hmf );
183 /******************************************************************
184 * DeleteMetaFile (GDI.127)
185 * DeleteMetaFile16 (GDI32.@)
187 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
189 return !GlobalFree16( hmf );
192 /******************************************************************
193 * DeleteMetaFile (GDI32.@)
195 * Delete a memory-based metafile.
198 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
200 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
201 if (!metaObj) return FALSE;
202 HeapFree( GetProcessHeap(), 0, metaObj->mh );
203 GDI_FreeObject( hmf, metaObj );
207 /******************************************************************
210 * Returns a pointer to a memory based METAHEADER read in from file HFILE
213 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
216 DWORD BytesRead, size;
218 size = sizeof(METAHEADER);
219 mh = HeapAlloc( GetProcessHeap(), 0, size );
221 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
223 HeapFree( GetProcessHeap(), 0, mh );
226 size = mh->mtSize * 2;
227 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
229 size -= sizeof(METAHEADER);
230 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
233 HeapFree( GetProcessHeap(), 0, mh );
237 if (mh->mtType != METAFILE_MEMORY) {
238 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
239 mh->mtType = METAFILE_MEMORY;
244 /******************************************************************
245 * GetMetaFile (GDI.124)
247 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
252 TRACE("%s\n", lpFilename);
257 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
258 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
261 mh = MF_ReadMetaFile(hFile);
264 return MF_Create_HMETAFILE16( mh );
267 /******************************************************************
268 * GetMetaFileA (GDI32.@)
270 * Read a metafile from a file. Returns handle to a memory-based metafile.
272 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
277 TRACE("%s\n", lpFilename);
282 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
283 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
286 mh = MF_ReadMetaFile(hFile);
289 return MF_Create_HMETAFILE( mh );
294 /******************************************************************
295 * GetMetaFileW (GDI32.@)
297 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
302 TRACE("%s\n", debugstr_w(lpFilename));
307 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
308 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
311 mh = MF_ReadMetaFile(hFile);
314 return MF_Create_HMETAFILE( mh );
318 /******************************************************************
319 * MF_LoadDiskBasedMetaFile
321 * Creates a new memory-based metafile from a disk-based one.
323 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
329 if(mh->mtType != METAFILE_DISK) {
330 ERR("Not a disk based metafile\n");
333 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
335 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
336 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
337 WARN("Can't open file of disk based metafile\n");
340 mh2 = MF_ReadMetaFile(hfile);
345 /******************************************************************
346 * MF_CreateMetaHeaderDisk
348 * Take a memory based METAHEADER and change it to a disk based METAHEADER
349 * assosiated with filename. Note: Trashes contents of old one.
351 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
356 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
357 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
358 mh->mtType = METAFILE_DISK;
359 size = HeapSize( GetProcessHeap(), 0, mh );
360 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
361 strcpy(mhd->filename, filename);
365 /******************************************************************
366 * CopyMetaFile (GDI.151)
368 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
370 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
371 METAHEADER *mh2 = NULL;
374 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
378 if(mh->mtType == METAFILE_DISK)
379 mh2 = MF_LoadDiskBasedMetaFile(mh);
381 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
382 memcpy( mh2, mh, mh->mtSize * 2 );
384 MF_ReleaseMetaHeader16( hSrcMetaFile );
386 if(lpFilename) { /* disk based metafile */
387 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
388 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
389 HeapFree( GetProcessHeap(), 0, mh2 );
392 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
394 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
397 return MF_Create_HMETAFILE16( mh2 );
401 /******************************************************************
402 * CopyMetaFileA (GDI32.@)
404 * Copies the metafile corresponding to hSrcMetaFile to either
405 * a disk file, if a filename is given, or to a new memory based
406 * metafile, if lpFileName is NULL.
410 * Handle to metafile copy on success, NULL on failure.
414 * Copying to disk returns NULL even if successful.
416 HMETAFILE WINAPI CopyMetaFileA(
417 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
418 LPCSTR lpFilename /* [in] filename if copying to a file */
420 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
421 METAHEADER *mh2 = NULL;
424 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
428 if(mh->mtType == METAFILE_DISK)
429 mh2 = MF_LoadDiskBasedMetaFile(mh);
431 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
432 memcpy( mh2, mh, mh->mtSize * 2 );
435 if(lpFilename) { /* disk based metafile */
436 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
437 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
438 HeapFree( GetProcessHeap(), 0, mh2 );
441 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
443 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
446 return MF_Create_HMETAFILE( mh2 );
450 /******************************************************************
451 * CopyMetaFileW (GDI32.@)
453 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
457 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
458 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
462 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
463 ret = CopyMetaFileA( hSrcMetaFile, p );
464 HeapFree( GetProcessHeap(), 0, p );
470 /******************************************************************
471 * IsValidMetaFile (GDI.410)
473 * Attempts to check if a given metafile is correctly formatted.
474 * Currently, the only things verified are several properties of the
478 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
481 * This is not exactly what windows does, see _Undocumented_Windows_
484 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
487 METAHEADER *mh = MF_GetMetaHeader16(hmf);
489 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
490 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
491 if (mh->mtVersion == MFVERSION)
493 MF_ReleaseMetaHeader16(hmf);
495 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
500 /*******************************************************************
503 * Helper for PlayMetaFile
505 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
510 unsigned int offset = 0;
517 if (!mh) return FALSE;
518 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
519 mh = MF_LoadDiskBasedMetaFile(mh);
520 if(!mh) return FALSE;
524 /* save the current pen, brush and font */
525 hPen = GetCurrentObject(hdc, OBJ_PEN);
526 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
527 hFont = GetCurrentObject(hdc, OBJ_FONT);
529 /* create the handle table */
530 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
531 sizeof(HANDLETABLE16) * mh->mtNoObjects);
532 if(!ht) return FALSE;
534 /* loop through metafile playing records */
535 offset = mh->mtHeaderSize * 2;
536 while (offset < mh->mtSize * 2)
538 mr = (METARECORD *)((char *)mh + offset);
539 TRACE("offset=%04x,size=%08lx\n",
543 "Entry got size 0 at offset %d, total mf length is %ld\n",
544 offset,mh->mtSize*2);
545 break; /* would loop endlessly otherwise */
547 offset += mr->rdSize * 2;
548 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
551 SelectObject(hdc, hBrush);
552 SelectObject(hdc, hPen);
553 SelectObject(hdc, hFont);
555 /* free objects in handle table */
556 for(i = 0; i < mh->mtNoObjects; i++)
557 if(*(ht->objectHandle + i) != 0)
558 DeleteObject(*(ht->objectHandle + i));
560 /* free handle table */
561 HeapFree( GetProcessHeap(), 0, ht );
563 HeapFree( GetProcessHeap(), 0, mh );
567 /******************************************************************
568 * PlayMetaFile (GDI.123)
571 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
574 METAHEADER *mh = MF_GetMetaHeader16( hmf );
575 ret = MF_PlayMetaFile( hdc, mh );
576 MF_ReleaseMetaHeader16( hmf );
580 /******************************************************************
581 * PlayMetaFile (GDI32.@)
583 * Renders the metafile specified by hmf in the DC specified by
584 * hdc. Returns FALSE on failure, TRUE on success.
586 BOOL WINAPI PlayMetaFile(
587 HDC hdc, /* [in] handle of DC to render in */
588 HMETAFILE hmf /* [in] handle of metafile to render */
591 METAHEADER *mh = MF_GetMetaHeader( hmf );
592 return MF_PlayMetaFile( hdc, mh );
596 /******************************************************************
597 * EnumMetaFile (GDI.175)
600 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
601 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
603 METAHEADER *mh = MF_GetMetaHeader16(hmf);
608 unsigned int offset = 0;
613 BOOL16 result = TRUE, loaded = FALSE;
615 TRACE("(%04x, %04x, %08lx, %08lx)\n",
616 hdc, hmf, (DWORD)lpEnumFunc, lpData);
619 if(!mh) return FALSE;
620 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
621 mh = MF_LoadDiskBasedMetaFile(mh);
622 if(!mh) return FALSE;
626 /* save the current pen, brush and font */
627 hPen = GetCurrentObject(hdc, OBJ_PEN);
628 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
629 hFont = GetCurrentObject(hdc, OBJ_FONT);
631 /* create the handle table */
633 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
634 sizeof(HANDLETABLE16) * mh->mtNoObjects);
635 spht = K32WOWGlobalLock16(hHT);
638 offset = mh->mtHeaderSize * 2;
640 /* loop through metafile records */
642 while (offset < (mh->mtSize * 2))
644 mr = (METARECORD *)((char *)mh + offset);
646 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
647 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
648 mh->mtNoObjects, (LONG)lpData ))
655 offset += (mr->rdSize * 2);
658 SelectObject(hdc, hBrush);
659 SelectObject(hdc, hPen);
660 SelectObject(hdc, hFont);
662 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
664 /* free objects in handle table */
665 for(i = 0; i < mh->mtNoObjects; i++)
666 if(*(ht->objectHandle + i) != 0)
667 DeleteObject(*(ht->objectHandle + i));
669 /* free handle table */
672 HeapFree( GetProcessHeap(), 0, mh );
673 MF_ReleaseMetaHeader16(hmf);
677 /******************************************************************
678 * EnumMetaFile (GDI32.@)
680 * Loop through the metafile records in hmf, calling the user-specified
681 * function for each one, stopping when the user's function returns FALSE
682 * (which is considered to be failure)
683 * or when no records are left (which is considered to be success).
686 * TRUE on success, FALSE on failure.
689 * Niels de carpentier, april 1996
691 BOOL WINAPI EnumMetaFile(
694 MFENUMPROC lpEnumFunc,
697 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
702 unsigned int offset = 0;
707 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
709 if(mh->mtType == METAFILE_DISK)
711 /* Create a memory-based copy */
712 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
716 /* save the current pen, brush and font */
717 hPen = GetCurrentObject(hdc, OBJ_PEN);
718 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
719 hFont = GetCurrentObject(hdc, OBJ_FONT);
721 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
722 sizeof(HANDLETABLE) * mh->mtNoObjects);
724 /* loop through metafile records */
725 offset = mh->mtHeaderSize * 2;
727 while (offset < (mh->mtSize * 2))
729 mr = (METARECORD *)((char *)mh + offset);
730 if(mr->rdFunction == META_EOF) {
731 TRACE("Got META_EOF so stopping\n");
734 TRACE("Calling EnumFunc with record type %x\n",
736 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
742 offset += (mr->rdSize * 2);
745 /* restore pen, brush and font */
746 SelectObject(hdc, hBrush);
747 SelectObject(hdc, hPen);
748 SelectObject(hdc, hFont);
750 /* free objects in handle table */
751 for(i = 0; i < mh->mtNoObjects; i++)
752 if(*(ht->objectHandle + i) != 0)
753 DeleteObject(*(ht->objectHandle + i));
755 /* free handle table */
756 HeapFree( GetProcessHeap(), 0, ht);
757 /* free a copy of metafile */
758 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
762 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
763 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
764 /******************************************************************
765 * PlayMetaFileRecord (GDI.176)
767 * Render a single metafile record specified by *mr in the DC hdc, while
768 * using the handle table *ht, of length nHandles,
769 * to store metafile objects.
772 * The following metafile records are unimplemented:
774 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
775 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
776 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
779 void WINAPI PlayMetaFileRecord16(
780 HDC16 hdc, /* [in] DC to render metafile into */
781 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
782 METARECORD *mr, /* [in] pointer to metafile record to render */
783 UINT16 nHandles /* [in] size of handle table */
788 BITMAPINFOHEADER *infohdr;
790 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
791 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
793 switch (mr->rdFunction)
798 case META_DELETEOBJECT:
799 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
800 *(ht->objectHandle + *(mr->rdParm)) = 0;
803 case META_SETBKCOLOR:
804 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
808 SetBkMode16(hdc, *(mr->rdParm));
811 case META_SETMAPMODE:
812 SetMapMode16(hdc, *(mr->rdParm));
816 SetROP216(hdc, *(mr->rdParm));
820 SetRelAbs16(hdc, *(mr->rdParm));
823 case META_SETPOLYFILLMODE:
824 SetPolyFillMode16(hdc, *(mr->rdParm));
827 case META_SETSTRETCHBLTMODE:
828 SetStretchBltMode16(hdc, *(mr->rdParm));
831 case META_SETTEXTCOLOR:
832 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
835 case META_SETWINDOWORG:
836 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
839 case META_SETWINDOWEXT:
840 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
843 case META_SETVIEWPORTORG:
844 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
847 case META_SETVIEWPORTEXT:
848 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
851 case META_OFFSETWINDOWORG:
852 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
855 case META_SCALEWINDOWEXT:
856 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
857 *(mr->rdParm + 1), *(mr->rdParm));
860 case META_OFFSETVIEWPORTORG:
861 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
864 case META_SCALEVIEWPORTEXT:
865 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
866 *(mr->rdParm + 1), *(mr->rdParm));
870 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
874 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
877 case META_EXCLUDECLIPRECT:
878 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
879 *(mr->rdParm + 1), *(mr->rdParm) );
882 case META_INTERSECTCLIPRECT:
883 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
884 *(mr->rdParm + 1), *(mr->rdParm) );
888 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
889 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
890 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
891 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
895 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
896 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
900 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
901 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
905 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
906 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
907 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
908 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
912 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
913 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
917 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
918 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
919 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
923 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
924 *(mr->rdParm + 3), *(mr->rdParm + 2),
925 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
933 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
934 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
937 case META_OFFSETCLIPRGN:
938 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
943 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
944 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
945 (char *)(mr->rdParm + 1), s1);
949 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
952 case META_POLYPOLYGON:
953 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
954 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
958 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
962 RestoreDC(hdc, (INT16)*(mr->rdParm));
965 case META_SELECTOBJECT:
966 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
970 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
971 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
972 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
973 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
976 case META_CREATEPATTERNBRUSH:
977 switch (*(mr->rdParm))
980 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
981 MF_AddHandle(ht, nHandles,
982 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
987 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
991 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
992 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
993 ptr = GlobalLock16(hndl);
994 memcpy(ptr, mr->rdParm + 2, s1);
995 GlobalUnlock16(hndl);
996 MF_AddHandle(ht, nHandles,
997 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
1002 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1008 case META_CREATEPENINDIRECT:
1009 MF_AddHandle(ht, nHandles,
1010 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1013 case META_CREATEFONTINDIRECT:
1014 MF_AddHandle(ht, nHandles,
1015 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1018 case META_CREATEBRUSHINDIRECT:
1019 MF_AddHandle(ht, nHandles,
1020 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1023 case META_CREATEPALETTE:
1024 MF_AddHandle(ht, nHandles,
1025 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1028 case META_SETTEXTALIGN:
1029 SetTextAlign16(hdc, *(mr->rdParm));
1032 case META_SELECTPALETTE:
1033 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1037 case META_SETMAPPERFLAGS:
1038 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1041 case META_REALIZEPALETTE:
1042 GDIRealizePalette16(hdc);
1046 FIXME("META_ESCAPE unimplemented.\n");
1049 case META_EXTTEXTOUT:
1050 MF_Play_MetaExtTextOut( hdc, mr );
1053 case META_STRETCHDIB:
1055 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1056 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1057 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1058 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1059 mr->rdParm[4],mr->rdParm[3],bits,info,
1060 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1064 case META_DIBSTRETCHBLT:
1066 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1067 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1068 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1069 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1070 mr->rdParm[3],mr->rdParm[2],bits,info,
1071 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1075 case META_STRETCHBLT:
1077 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1078 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1079 mr->rdParm[11], /*Height*/
1080 mr->rdParm[13], /*Planes*/
1081 mr->rdParm[14], /*BitsPixel*/
1082 (LPSTR)&mr->rdParm[15]); /*bits*/
1083 SelectObject(hdcSrc,hbitmap);
1084 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1085 mr->rdParm[7],mr->rdParm[6],
1086 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1087 mr->rdParm[3],mr->rdParm[2],
1088 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1095 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1096 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1097 mr->rdParm[8]/*Height*/,
1098 mr->rdParm[10]/*Planes*/,
1099 mr->rdParm[11]/*BitsPixel*/,
1100 (LPSTR)&mr->rdParm[12]/*bits*/);
1101 SelectObject(hdcSrc,hbitmap);
1102 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1103 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1104 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1105 MAKELONG(0,mr->rdParm[0]));
1110 case META_CREATEREGION:
1112 HRGN hrgn = CreateRectRgn(0,0,0,0);
1114 MF_Play_MetaCreateRegion(mr, hrgn);
1115 MF_AddHandle(ht, nHandles, hrgn);
1119 case META_FILLREGION:
1120 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1121 *(ht->objectHandle + *(mr->rdParm)));
1124 case META_FRAMEREGION:
1125 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1126 *(ht->objectHandle + *(mr->rdParm+2)),
1127 *(mr->rdParm+1), *(mr->rdParm));
1130 case META_INVERTREGION:
1131 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1134 case META_PAINTREGION:
1135 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1138 case META_SELECTCLIPREGION:
1139 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1142 case META_DIBCREATEPATTERNBRUSH:
1143 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1144 but there's no difference */
1146 TRACE("%d\n",*(mr->rdParm));
1147 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1148 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1149 ptr = GlobalLock16(hndl);
1150 memcpy(ptr, mr->rdParm + 2, s1);
1151 GlobalUnlock16(hndl);
1152 MF_AddHandle(ht, nHandles,
1153 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1157 case META_DIBBITBLT:
1158 /* In practice I've found that there are two layouts for
1159 META_DIBBITBLT, one (the first here) is the usual one when a src
1160 dc is actually passed to it, the second occurs when the src dc is
1161 passed in as NULL to the creating BitBlt. As the second case has
1162 no dib, a size check will suffice to distinguish.
1164 Caolan.McNamara@ul.ie */
1166 if (mr->rdSize > 12) {
1167 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1168 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1170 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1171 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1172 mr->rdParm[5], mr->rdParm[4], bits, info,
1174 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1175 } else { /* equivalent to a PatBlt */
1176 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1177 mr->rdParm[6], mr->rdParm[5],
1178 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1182 case META_SETTEXTCHAREXTRA:
1183 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1186 case META_SETTEXTJUSTIFICATION:
1187 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1190 case META_EXTFLOODFILL:
1191 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1192 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1196 case META_SETDIBTODEV:
1198 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1199 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1200 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1201 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1202 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1203 mr->rdParm[2], mr->rdParm[1], bits, info,
1208 #define META_UNIMP(x) case x: \
1209 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1211 META_UNIMP(META_DRAWTEXT)
1212 META_UNIMP(META_ANIMATEPALETTE)
1213 META_UNIMP(META_SETPALENTRIES)
1214 META_UNIMP(META_RESIZEPALETTE)
1215 META_UNIMP(META_RESETDC)
1216 META_UNIMP(META_STARTDOC)
1217 META_UNIMP(META_STARTPAGE)
1218 META_UNIMP(META_ENDPAGE)
1219 META_UNIMP(META_ABORTDOC)
1220 META_UNIMP(META_ENDDOC)
1221 META_UNIMP(META_CREATEBRUSH)
1222 META_UNIMP(META_CREATEBITMAPINDIRECT)
1223 META_UNIMP(META_CREATEBITMAP)
1227 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1232 /******************************************************************
1233 * PlayMetaFileRecord (GDI32.@)
1235 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1236 METARECORD *metarecord, UINT handles )
1238 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1239 handles*sizeof(HANDLETABLE16));
1241 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1243 for (i=0; i<handles; i++)
1244 ht->objectHandle[i] = handletable->objectHandle[i];
1245 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1246 for (i=0; i<handles; i++)
1247 handletable->objectHandle[i] = ht->objectHandle[i];
1248 GlobalFree((HGLOBAL)ht);
1252 /******************************************************************
1253 * GetMetaFileBits (GDI.159)
1255 * Trade in a metafile object handle for a handle to the metafile memory.
1259 HGLOBAL16 WINAPI GetMetaFileBits16(
1260 HMETAFILE16 hmf /* [in] metafile handle */
1263 TRACE("hMem out: %04x\n", hmf);
1267 /******************************************************************
1268 * SetMetaFileBits (GDI.160)
1270 * Trade in a metafile memory handle for a handle to a metafile object.
1271 * The memory region should hold a proper metafile, otherwise
1272 * problems will occur when it is used. Validity of the memory is not
1273 * checked. The function is essentially just the identity function.
1275 HMETAFILE16 WINAPI SetMetaFileBits16(
1277 /* [in] handle to a memory region holding a metafile */
1280 TRACE("hmf out: %04x\n", hMem);
1285 /******************************************************************
1286 * SetMetaFileBitsBetter (GDI.196)
1288 * Trade in a metafile memory handle for a handle to a metafile object,
1289 * making a cursory check (using IsValidMetaFile()) that the memory
1290 * handle points to a valid metafile.
1293 * Handle to a metafile on success, NULL on failure..
1295 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1297 if( IsValidMetaFile16( hMeta ) )
1298 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1299 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1300 return (HMETAFILE16)0;
1303 /******************************************************************
1304 * SetMetaFileBitsEx (GDI32.@)
1306 * Create a metafile from raw data. No checking of the data is performed.
1307 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1309 HMETAFILE WINAPI SetMetaFileBitsEx(
1310 UINT size, /* [in] size of metafile, in bytes */
1311 const BYTE *lpData /* [in] pointer to metafile data */
1314 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1316 memcpy(mh, lpData, size);
1317 return MF_Create_HMETAFILE(mh);
1320 /*****************************************************************
1321 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1323 * Copies the data from metafile _hmf_ into the buffer _buf_.
1324 * If _buf_ is zero, returns size of buffer required. Otherwise,
1325 * returns number of bytes copied.
1327 UINT WINAPI GetMetaFileBitsEx(
1328 HMETAFILE hmf, /* [in] metafile */
1329 UINT nSize, /* [in] size of buf */
1330 LPVOID buf /* [out] buffer to receive raw metafile data */
1332 METAHEADER *mh = MF_GetMetaHeader(hmf);
1335 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1336 if (!mh) return 0; /* FIXME: error code */
1337 if(mh->mtType == METAFILE_DISK)
1338 FIXME("Disk-based metafile?\n");
1339 mfSize = mh->mtSize * 2;
1341 TRACE("returning size %d\n", mfSize);
1344 if(mfSize > nSize) mfSize = nSize;
1345 memmove(buf, mh, mfSize);
1349 /******************************************************************
1350 * GetWinMetaFileBits [GDI32.@]
1352 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1353 UINT cbBuffer, LPBYTE lpbBuffer,
1354 INT fnMapMode, HDC hdcRef)
1360 FIXME("(%d,%d,%p,%d,%d): stub\n",
1361 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1362 hdcmf = CreateMetaFileA(NULL);
1363 /* PlayEnhMetaFile(hdcmf, hemf, lpRect); where does the bounding rect come from? */
1364 hmf = CloseMetaFile(hdcmf);
1365 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1366 DeleteMetaFile(hmf);
1370 /******************************************************************
1371 * MF_Play_MetaCreateRegion
1373 * Handles META_CREATEREGION for PlayMetaFileRecord().
1377 * The layout of the record looks something like this:
1382 * 2 Looks like a handle? - not constant
1384 * 4 Total number of bytes
1385 * 5 No. of separate bands = n [see below]
1386 * 6 Largest number of x co-ords in a band
1387 * 7-10 Bounding box x1 y1 x2 y2
1390 * Regions are divided into bands that are uniform in the
1391 * y-direction. Each band consists of pairs of on/off x-coords and is
1393 * m y0 y1 x1 x2 x3 ... xm m
1394 * into successive rdParm[]s.
1396 * This is probably just a dump of the internal RGNOBJ?
1402 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1407 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1409 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1410 band++, start = end + 1) {
1411 if(*start / 2 != (*start + 1) / 2) {
1412 WARN("Delimiter not even.\n");
1413 DeleteObject( hrgn2 );
1417 end = start + *start + 3;
1418 if(end > (WORD *)mr + mr->rdSize) {
1419 WARN("End points outside record.\n");
1420 DeleteObject( hrgn2 );
1424 if(*start != *end) {
1425 WARN("Mismatched delimiters.\n");
1426 DeleteObject( hrgn2 );
1430 y0 = *(INT16 *)(start + 1);
1431 y1 = *(INT16 *)(start + 2);
1432 for(pair = 0; pair < *start / 2; pair++) {
1433 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1434 *(INT16 *)(start + 4 + 2*pair), y1 );
1435 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1438 DeleteObject( hrgn2 );
1443 /******************************************************************
1444 * MF_Play_MetaExtTextOut
1446 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1449 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1455 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1457 s1 = mr->rdParm[2]; /* String length */
1458 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1459 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1460 /* rec len without dx array */
1462 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1464 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1466 if (mr->rdSize == len / 2)
1467 dxx = NULL; /* determine if array present */
1469 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1470 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1472 TRACE("%s len: %ld\n", sot, mr->rdSize);
1474 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1475 len, s1, mr->rdSize, mr->rdParm[3]);
1476 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1478 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1479 mr->rdParm[0], /* Y position */
1480 mr->rdParm[3], /* options */
1481 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1484 s1, dxx); /* length, dx array */
1486 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);