Add and use the header files mssip.h and sipbase.h.
[wine/multimedia.git] / objects / metafile.c
blob0abf40c7ed84ad6055022f947beaeb7947048d10
1 /*
2 * Metafile functions
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
36 * the memory.
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.
43 * HDMD - 14/4/1999
46 #include "config.h"
48 #include <string.h>
49 #include <fcntl.h>
51 #include "wine/winbase16.h"
52 #include "wine/wingdi16.h"
53 #include "bitmap.h"
54 #include "global.h"
55 #include "wine/debug.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
59 #include "pshpack1.h"
60 typedef struct
62 DWORD dw1, dw2, dw3;
63 WORD w4;
64 CHAR filename[0x100];
65 } METAHEADERDISK;
66 #include "poppack.h"
68 typedef struct
70 GDIOBJHDR header;
71 METAHEADER *mh;
72 } METAFILEOBJ;
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 /******************************************************************
82 * MF_AddHandle
84 * Add a handle to an external handle table and return the index
86 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
88 int i;
90 for (i = 0; i < htlen; i++)
92 if (*(ht->objectHandle + i) == 0)
94 *(ht->objectHandle + i) = hobj;
95 return i;
98 return -1;
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)
111 HMETAFILE hmf = 0;
112 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf, NULL );
113 if (metaObj)
115 metaObj->mh = mh;
116 GDI_ReleaseObj( hmf );
118 return 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)
130 HMETAFILE16 hmf;
131 DWORD size = mh->mtSize * sizeof(WORD);
133 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
134 if(hmf)
136 METAHEADER *mh_dest = GlobalLock16(hmf);
137 memcpy(mh_dest, mh, size);
138 GlobalUnlock16(hmf);
140 HeapFree(GetProcessHeap(), 0, mh);
141 return hmf;
144 /******************************************************************
145 * MF_GetMetaHeader
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 );
153 if (metaObj)
155 ret = metaObj->mh;
156 GDI_ReleaseObj( hmf );
158 return ret;
161 /******************************************************************
162 * MF_GetMetaHeader16
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 );
204 return TRUE;
207 /******************************************************************
208 * MF_ReadMetaFile
210 * Returns a pointer to a memory based METAHEADER read in from file HFILE
213 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
215 METAHEADER *mh;
216 DWORD BytesRead, size;
218 size = sizeof(METAHEADER);
219 mh = HeapAlloc( GetProcessHeap(), 0, size );
220 if(!mh) return NULL;
221 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
222 BytesRead != size) {
223 HeapFree( GetProcessHeap(), 0, mh );
224 return NULL;
226 size = mh->mtSize * 2;
227 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
228 if(!mh) return NULL;
229 size -= sizeof(METAHEADER);
230 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
231 NULL) == 0 ||
232 BytesRead != size) {
233 HeapFree( GetProcessHeap(), 0, mh );
234 return NULL;
237 if (mh->mtType != METAFILE_MEMORY) {
238 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
239 mh->mtType = METAFILE_MEMORY;
241 return mh;
244 /******************************************************************
245 * GetMetaFile (GDI.124)
247 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
249 METAHEADER *mh;
250 HANDLE hFile;
252 TRACE("%s\n", lpFilename);
254 if(!lpFilename)
255 return 0;
257 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
258 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
259 return 0;
261 mh = MF_ReadMetaFile(hFile);
262 CloseHandle(hFile);
263 if(!mh) return 0;
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 )
274 METAHEADER *mh;
275 HANDLE hFile;
277 TRACE("%s\n", lpFilename);
279 if(!lpFilename)
280 return 0;
282 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
283 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
284 return 0;
286 mh = MF_ReadMetaFile(hFile);
287 CloseHandle(hFile);
288 if(!mh) return 0;
289 return MF_Create_HMETAFILE( mh );
294 /******************************************************************
295 * GetMetaFileW (GDI32.@)
297 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
299 METAHEADER *mh;
300 HANDLE hFile;
302 TRACE("%s\n", debugstr_w(lpFilename));
304 if(!lpFilename)
305 return 0;
307 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
308 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
309 return 0;
311 mh = MF_ReadMetaFile(hFile);
312 CloseHandle(hFile);
313 if(!mh) return 0;
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)
325 METAHEADERDISK *mhd;
326 HANDLE hfile;
327 METAHEADER *mh2;
329 if(mh->mtType != METAFILE_DISK) {
330 ERR("Not a disk based metafile\n");
331 return NULL;
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");
338 return NULL;
340 mh2 = MF_ReadMetaFile(hfile);
341 CloseHandle(hfile);
342 return mh2;
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)
353 METAHEADERDISK *mhd;
354 DWORD size;
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);
362 return mh;
365 /******************************************************************
366 * CopyMetaFile (GDI.151)
368 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
370 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
371 METAHEADER *mh2 = NULL;
372 HANDLE hFile;
374 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
376 if(!mh) return 0;
378 if(mh->mtType == METAFILE_DISK)
379 mh2 = MF_LoadDiskBasedMetaFile(mh);
380 else {
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 );
390 return 0;
392 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
393 CloseHandle(hFile);
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.
408 * RETURNS
410 * Handle to metafile copy on success, NULL on failure.
412 * BUGS
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;
422 HANDLE hFile;
424 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
426 if(!mh) return 0;
428 if(mh->mtType == METAFILE_DISK)
429 mh2 = MF_LoadDiskBasedMetaFile(mh);
430 else {
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 );
439 return 0;
441 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
442 CloseHandle(hFile);
443 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
446 return MF_Create_HMETAFILE( mh2 );
450 /******************************************************************
451 * CopyMetaFileW (GDI32.@)
453 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
454 LPCWSTR lpFilename )
456 HMETAFILE ret = 0;
457 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
458 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
460 if (p)
462 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
463 ret = CopyMetaFileA( hSrcMetaFile, p );
464 HeapFree( GetProcessHeap(), 0, p );
466 return ret;
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
475 * header.
477 * RETURNS
478 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
480 * BUGS
481 * This is not exactly what windows does, see _Undocumented_Windows_
482 * for details.
484 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
486 BOOL16 res=FALSE;
487 METAHEADER *mh = MF_GetMetaHeader16(hmf);
488 if (mh) {
489 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
490 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
491 if (mh->mtVersion == MFVERSION)
492 res=TRUE;
493 MF_ReleaseMetaHeader16(hmf);
495 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
496 return res;
500 /*******************************************************************
501 * MF_PlayMetaFile
503 * Helper for PlayMetaFile
505 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
508 METARECORD *mr;
509 HANDLETABLE16 *ht;
510 unsigned int offset = 0;
511 WORD i;
512 HPEN hPen;
513 HBRUSH hBrush;
514 HFONT hFont;
515 BOOL loaded = FALSE;
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;
521 loaded = TRUE;
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",
540 offset, mr->rdSize);
541 if (!mr->rdSize) {
542 TRACE(
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 );
562 if(loaded)
563 HeapFree( GetProcessHeap(), 0, mh );
564 return TRUE;
567 /******************************************************************
568 * PlayMetaFile (GDI.123)
571 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
573 BOOL16 ret;
574 METAHEADER *mh = MF_GetMetaHeader16( hmf );
575 ret = MF_PlayMetaFile( hdc, mh );
576 MF_ReleaseMetaHeader16( hmf );
577 return ret;
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);
604 METARECORD *mr;
605 HANDLETABLE16 *ht;
606 HGLOBAL16 hHT;
607 SEGPTR spht;
608 unsigned int offset = 0;
609 WORD i, seg;
610 HPEN hPen;
611 HBRUSH hBrush;
612 HFONT hFont;
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;
623 loaded = TRUE;
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);
637 seg = hmf | 7;
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 ))
650 result = FALSE;
651 break;
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 */
670 GlobalFree16(hHT);
671 if(loaded)
672 HeapFree( GetProcessHeap(), 0, mh );
673 MF_ReleaseMetaHeader16(hmf);
674 return result;
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).
685 * RETURNS
686 * TRUE on success, FALSE on failure.
688 * HISTORY
689 * Niels de carpentier, april 1996
691 BOOL WINAPI EnumMetaFile(
692 HDC hdc,
693 HMETAFILE hmf,
694 MFENUMPROC lpEnumFunc,
695 LPARAM lpData
697 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
698 METARECORD *mr;
699 HANDLETABLE *ht;
700 BOOL result = TRUE;
701 int i;
702 unsigned int offset = 0;
703 HPEN hPen;
704 HBRUSH hBrush;
705 HFONT hFont;
707 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
708 if (!mh) return 0;
709 if(mh->mtType == METAFILE_DISK)
711 /* Create a memory-based copy */
712 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
713 mh = mhTemp;
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");
732 break;
734 TRACE("Calling EnumFunc with record type %x\n",
735 mr->rdFunction);
736 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
738 result = FALSE;
739 break;
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 );
759 return result;
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.
771 * BUGS
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 */
785 short s1;
786 HANDLE16 hndl;
787 char *ptr;
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)
795 case META_EOF:
796 break;
798 case META_DELETEOBJECT:
799 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
800 *(ht->objectHandle + *(mr->rdParm)) = 0;
801 break;
803 case META_SETBKCOLOR:
804 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
805 break;
807 case META_SETBKMODE:
808 SetBkMode16(hdc, *(mr->rdParm));
809 break;
811 case META_SETMAPMODE:
812 SetMapMode16(hdc, *(mr->rdParm));
813 break;
815 case META_SETROP2:
816 SetROP216(hdc, *(mr->rdParm));
817 break;
819 case META_SETRELABS:
820 SetRelAbs16(hdc, *(mr->rdParm));
821 break;
823 case META_SETPOLYFILLMODE:
824 SetPolyFillMode16(hdc, *(mr->rdParm));
825 break;
827 case META_SETSTRETCHBLTMODE:
828 SetStretchBltMode16(hdc, *(mr->rdParm));
829 break;
831 case META_SETTEXTCOLOR:
832 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
833 break;
835 case META_SETWINDOWORG:
836 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
837 break;
839 case META_SETWINDOWEXT:
840 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
841 break;
843 case META_SETVIEWPORTORG:
844 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
845 break;
847 case META_SETVIEWPORTEXT:
848 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
849 break;
851 case META_OFFSETWINDOWORG:
852 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
853 break;
855 case META_SCALEWINDOWEXT:
856 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
857 *(mr->rdParm + 1), *(mr->rdParm));
858 break;
860 case META_OFFSETVIEWPORTORG:
861 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
862 break;
864 case META_SCALEVIEWPORTEXT:
865 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
866 *(mr->rdParm + 1), *(mr->rdParm));
867 break;
869 case META_LINETO:
870 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
871 break;
873 case META_MOVETO:
874 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
875 break;
877 case META_EXCLUDECLIPRECT:
878 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
879 *(mr->rdParm + 1), *(mr->rdParm) );
880 break;
882 case META_INTERSECTCLIPRECT:
883 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
884 *(mr->rdParm + 1), *(mr->rdParm) );
885 break;
887 case META_ARC:
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));
892 break;
894 case META_ELLIPSE:
895 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
896 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
897 break;
899 case META_FLOODFILL:
900 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
901 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
902 break;
904 case META_PIE:
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));
909 break;
911 case META_RECTANGLE:
912 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
913 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
914 break;
916 case META_ROUNDRECT:
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));
920 break;
922 case META_PATBLT:
923 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
924 *(mr->rdParm + 3), *(mr->rdParm + 2),
925 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
926 break;
928 case META_SAVEDC:
929 SaveDC(hdc);
930 break;
932 case META_SETPIXEL:
933 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
934 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
935 break;
937 case META_OFFSETCLIPRGN:
938 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
939 break;
941 case META_TEXTOUT:
942 s1 = *(mr->rdParm);
943 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
944 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
945 (char *)(mr->rdParm + 1), s1);
946 break;
948 case META_POLYGON:
949 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
950 break;
952 case META_POLYPOLYGON:
953 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
954 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
955 break;
957 case META_POLYLINE:
958 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
959 break;
961 case META_RESTOREDC:
962 RestoreDC(hdc, (INT16)*(mr->rdParm));
963 break;
965 case META_SELECTOBJECT:
966 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
967 break;
969 case META_CHORD:
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));
974 break;
976 case META_CREATEPATTERNBRUSH:
977 switch (*(mr->rdParm))
979 case BS_PATTERN:
980 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
981 MF_AddHandle(ht, nHandles,
982 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
983 infohdr->biHeight,
984 infohdr->biPlanes,
985 infohdr->biBitCount,
986 (LPSTR)(mr->rdParm +
987 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
988 break;
990 case BS_DIBPATTERN:
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)));
998 GlobalFree16(hndl);
999 break;
1001 default:
1002 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1003 mr->rdParm[0]);
1004 break;
1006 break;
1008 case META_CREATEPENINDIRECT:
1009 MF_AddHandle(ht, nHandles,
1010 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1011 break;
1013 case META_CREATEFONTINDIRECT:
1014 MF_AddHandle(ht, nHandles,
1015 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1016 break;
1018 case META_CREATEBRUSHINDIRECT:
1019 MF_AddHandle(ht, nHandles,
1020 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1021 break;
1023 case META_CREATEPALETTE:
1024 MF_AddHandle(ht, nHandles,
1025 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1026 break;
1028 case META_SETTEXTALIGN:
1029 SetTextAlign16(hdc, *(mr->rdParm));
1030 break;
1032 case META_SELECTPALETTE:
1033 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1034 *(mr->rdParm));
1035 break;
1037 case META_SETMAPPERFLAGS:
1038 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1039 break;
1041 case META_REALIZEPALETTE:
1042 GDIRealizePalette16(hdc);
1043 break;
1045 case META_ESCAPE:
1046 FIXME("META_ESCAPE unimplemented.\n");
1047 break;
1049 case META_EXTTEXTOUT:
1050 MF_Play_MetaExtTextOut( hdc, mr );
1051 break;
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]));
1062 break;
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]));
1073 break;
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]));
1089 DeleteDC(hdcSrc);
1091 break;
1093 case META_BITBLT:
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]));
1106 DeleteDC(hdcSrc);
1108 break;
1110 case META_CREATEREGION:
1112 HRGN hrgn = CreateRectRgn(0,0,0,0);
1114 MF_Play_MetaCreateRegion(mr, hrgn);
1115 MF_AddHandle(ht, nHandles, hrgn);
1117 break;
1119 case META_FILLREGION:
1120 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1121 *(ht->objectHandle + *(mr->rdParm)));
1122 break;
1124 case META_FRAMEREGION:
1125 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1126 *(ht->objectHandle + *(mr->rdParm+2)),
1127 *(mr->rdParm+1), *(mr->rdParm));
1128 break;
1130 case META_INVERTREGION:
1131 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1132 break;
1134 case META_PAINTREGION:
1135 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1136 break;
1138 case META_SELECTCLIPREGION:
1139 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1140 break;
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)));
1154 GlobalFree16(hndl);
1155 break;
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,
1173 DIB_RGB_COLORS,
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]));
1180 break;
1182 case META_SETTEXTCHAREXTRA:
1183 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1184 break;
1186 case META_SETTEXTJUSTIFICATION:
1187 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1188 break;
1190 case META_EXTFLOODFILL:
1191 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1192 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1193 *(mr->rdParm));
1194 break;
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,
1204 mr->rdParm[0]);
1205 break;
1208 #define META_UNIMP(x) case x: \
1209 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1210 break;
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)
1224 #undef META_UNIMP
1226 default:
1227 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1228 mr->rdFunction);
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));
1240 unsigned int i = 0;
1241 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1242 handles);
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);
1249 return TRUE;
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);
1264 return 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(
1276 HGLOBAL16 hMem
1277 /* [in] handle to a memory region holding a metafile */
1280 TRACE("hmf out: %04x\n", hMem);
1282 return 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.
1292 * RETURNS
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 );
1315 if (!mh) return 0;
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);
1333 UINT mfSize;
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;
1340 if (!buf) {
1341 TRACE("returning size %d\n", mfSize);
1342 return mfSize;
1344 if(mfSize > nSize) mfSize = nSize;
1345 memmove(buf, mh, mfSize);
1346 return mfSize;
1349 /******************************************************************
1350 * GetWinMetaFileBits [GDI32.@]
1352 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1353 UINT cbBuffer, LPBYTE lpbBuffer,
1354 INT fnMapMode, HDC hdcRef)
1356 HDC hdcmf;
1357 HMETAFILE hmf;
1358 UINT ret;
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);
1367 return ret;
1370 /******************************************************************
1371 * MF_Play_MetaCreateRegion
1373 * Handles META_CREATEREGION for PlayMetaFileRecord().
1377 * The layout of the record looks something like this:
1379 * rdParm meaning
1380 * 0 Always 0?
1381 * 1 Always 6?
1382 * 2 Looks like a handle? - not constant
1383 * 3 0 or 1 ??
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
1388 * 11-... n bands
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
1392 * written as
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?
1398 * HDMD - 18/12/97
1402 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1404 WORD band, pair;
1405 WORD *start, *end;
1406 INT16 y0, y1;
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 );
1414 return FALSE;
1417 end = start + *start + 3;
1418 if(end > (WORD *)mr + mr->rdSize) {
1419 WARN("End points outside record.\n");
1420 DeleteObject( hrgn2 );
1421 return FALSE;
1424 if(*start != *end) {
1425 WARN("Mismatched delimiters.\n");
1426 DeleteObject( hrgn2 );
1427 return FALSE;
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 );
1439 return TRUE;
1443 /******************************************************************
1444 * MF_Play_MetaExtTextOut
1446 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1449 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1451 LPINT16 dxx;
1452 LPSTR sot;
1453 DWORD len;
1454 WORD s1;
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 */
1463 if (isrect)
1464 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1466 if (mr->rdSize == len / 2)
1467 dxx = NULL; /* determine if array present */
1468 else
1469 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1470 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1471 else {
1472 TRACE("%s len: %ld\n", sot, mr->rdSize);
1473 WARN(
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,
1482 /* rectangle */
1483 sot, /* string */
1484 s1, dxx); /* length, dx array */
1485 if (dxx)
1486 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1487 return TRUE;