- stubs for SHLWAPI.295 (create a URL shortcut ?) and SHLWAPI.394
[wine/multimedia.git] / objects / metafile.c
blobad0404a1df1a2cd6ac050632d90c3216d7fe2b63
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)
186 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
188 return !GlobalFree16( hmf );
191 /******************************************************************
192 * DeleteMetaFile (GDI32.@)
194 * Delete a memory-based metafile.
197 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
199 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
200 if (!metaObj) return FALSE;
201 HeapFree( GetProcessHeap(), 0, metaObj->mh );
202 GDI_FreeObject( hmf, metaObj );
203 return TRUE;
206 /******************************************************************
207 * MF_ReadMetaFile
209 * Returns a pointer to a memory based METAHEADER read in from file HFILE
212 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
214 METAHEADER *mh;
215 DWORD BytesRead, size;
217 size = sizeof(METAHEADER);
218 mh = HeapAlloc( GetProcessHeap(), 0, size );
219 if(!mh) return NULL;
220 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
221 BytesRead != size) {
222 HeapFree( GetProcessHeap(), 0, mh );
223 return NULL;
225 size = mh->mtSize * 2;
226 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
227 if(!mh) return NULL;
228 size -= sizeof(METAHEADER);
229 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
230 NULL) == 0 ||
231 BytesRead != size) {
232 HeapFree( GetProcessHeap(), 0, mh );
233 return NULL;
236 if (mh->mtType != METAFILE_MEMORY) {
237 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
238 mh->mtType = METAFILE_MEMORY;
240 return mh;
243 /******************************************************************
244 * GetMetaFile (GDI.124)
246 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
248 METAHEADER *mh;
249 HANDLE hFile;
251 TRACE("%s\n", lpFilename);
253 if(!lpFilename)
254 return 0;
256 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
257 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
258 return 0;
260 mh = MF_ReadMetaFile(hFile);
261 CloseHandle(hFile);
262 if(!mh) return 0;
263 return MF_Create_HMETAFILE16( mh );
266 /******************************************************************
267 * GetMetaFileA (GDI32.@)
269 * Read a metafile from a file. Returns handle to a memory-based metafile.
271 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
273 METAHEADER *mh;
274 HANDLE hFile;
276 TRACE("%s\n", lpFilename);
278 if(!lpFilename)
279 return 0;
281 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
282 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
283 return 0;
285 mh = MF_ReadMetaFile(hFile);
286 CloseHandle(hFile);
287 if(!mh) return 0;
288 return MF_Create_HMETAFILE( mh );
293 /******************************************************************
294 * GetMetaFileW (GDI32.@)
296 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
298 METAHEADER *mh;
299 HANDLE hFile;
301 TRACE("%s\n", debugstr_w(lpFilename));
303 if(!lpFilename)
304 return 0;
306 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
307 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
308 return 0;
310 mh = MF_ReadMetaFile(hFile);
311 CloseHandle(hFile);
312 if(!mh) return 0;
313 return MF_Create_HMETAFILE( mh );
317 /******************************************************************
318 * MF_LoadDiskBasedMetaFile
320 * Creates a new memory-based metafile from a disk-based one.
322 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
324 METAHEADERDISK *mhd;
325 HANDLE hfile;
326 METAHEADER *mh2;
328 if(mh->mtType != METAFILE_DISK) {
329 ERR("Not a disk based metafile\n");
330 return NULL;
332 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
334 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
335 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
336 WARN("Can't open file of disk based metafile\n");
337 return NULL;
339 mh2 = MF_ReadMetaFile(hfile);
340 CloseHandle(hfile);
341 return mh2;
344 /******************************************************************
345 * MF_CreateMetaHeaderDisk
347 * Take a memory based METAHEADER and change it to a disk based METAHEADER
348 * assosiated with filename. Note: Trashes contents of old one.
350 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
352 METAHEADERDISK *mhd;
353 DWORD size;
355 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
356 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
357 mh->mtType = METAFILE_DISK;
358 size = HeapSize( GetProcessHeap(), 0, mh );
359 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
360 strcpy(mhd->filename, filename);
361 return mh;
364 /******************************************************************
365 * CopyMetaFile (GDI.151)
367 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
369 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
370 METAHEADER *mh2 = NULL;
371 HANDLE hFile;
373 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
375 if(!mh) return 0;
377 if(mh->mtType == METAFILE_DISK)
378 mh2 = MF_LoadDiskBasedMetaFile(mh);
379 else {
380 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
381 memcpy( mh2, mh, mh->mtSize * 2 );
383 MF_ReleaseMetaHeader16( hSrcMetaFile );
385 if(lpFilename) { /* disk based metafile */
386 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
387 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
388 HeapFree( GetProcessHeap(), 0, mh2 );
389 return 0;
391 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
392 CloseHandle(hFile);
393 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
396 return MF_Create_HMETAFILE16( mh2 );
400 /******************************************************************
401 * CopyMetaFileA (GDI32.@)
403 * Copies the metafile corresponding to hSrcMetaFile to either
404 * a disk file, if a filename is given, or to a new memory based
405 * metafile, if lpFileName is NULL.
407 * RETURNS
409 * Handle to metafile copy on success, NULL on failure.
411 * BUGS
413 * Copying to disk returns NULL even if successful.
415 HMETAFILE WINAPI CopyMetaFileA(
416 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
417 LPCSTR lpFilename /* [in] filename if copying to a file */
419 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
420 METAHEADER *mh2 = NULL;
421 HANDLE hFile;
423 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
425 if(!mh) return 0;
427 if(mh->mtType == METAFILE_DISK)
428 mh2 = MF_LoadDiskBasedMetaFile(mh);
429 else {
430 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
431 memcpy( mh2, mh, mh->mtSize * 2 );
434 if(lpFilename) { /* disk based metafile */
435 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
436 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
437 HeapFree( GetProcessHeap(), 0, mh2 );
438 return 0;
440 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
441 CloseHandle(hFile);
442 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
445 return MF_Create_HMETAFILE( mh2 );
449 /******************************************************************
450 * CopyMetaFileW (GDI32.@)
452 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
453 LPCWSTR lpFilename )
455 HMETAFILE ret = 0;
456 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
457 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
459 if (p)
461 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
462 ret = CopyMetaFileA( hSrcMetaFile, p );
463 HeapFree( GetProcessHeap(), 0, p );
465 return ret;
469 /******************************************************************
470 * IsValidMetaFile (GDI.410)
472 * Attempts to check if a given metafile is correctly formatted.
473 * Currently, the only things verified are several properties of the
474 * header.
476 * RETURNS
477 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
479 * BUGS
480 * This is not exactly what windows does, see _Undocumented_Windows_
481 * for details.
483 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
485 BOOL16 res=FALSE;
486 METAHEADER *mh = MF_GetMetaHeader16(hmf);
487 if (mh) {
488 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
489 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
490 if (mh->mtVersion == MFVERSION)
491 res=TRUE;
492 MF_ReleaseMetaHeader16(hmf);
494 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
495 return res;
499 /*******************************************************************
500 * MF_PlayMetaFile
502 * Helper for PlayMetaFile
504 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
507 METARECORD *mr;
508 HANDLETABLE16 *ht;
509 unsigned int offset = 0;
510 WORD i;
511 HPEN hPen;
512 HBRUSH hBrush;
513 HFONT hFont;
514 BOOL loaded = FALSE;
516 if (!mh) return FALSE;
517 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
518 mh = MF_LoadDiskBasedMetaFile(mh);
519 if(!mh) return FALSE;
520 loaded = TRUE;
523 /* save the current pen, brush and font */
524 hPen = GetCurrentObject(hdc, OBJ_PEN);
525 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
526 hFont = GetCurrentObject(hdc, OBJ_FONT);
528 /* create the handle table */
529 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
530 sizeof(HANDLETABLE16) * mh->mtNoObjects);
531 if(!ht) return FALSE;
533 /* loop through metafile playing records */
534 offset = mh->mtHeaderSize * 2;
535 while (offset < mh->mtSize * 2)
537 mr = (METARECORD *)((char *)mh + offset);
538 TRACE("offset=%04x,size=%08lx\n",
539 offset, mr->rdSize);
540 if (!mr->rdSize) {
541 TRACE(
542 "Entry got size 0 at offset %d, total mf length is %ld\n",
543 offset,mh->mtSize*2);
544 break; /* would loop endlessly otherwise */
546 offset += mr->rdSize * 2;
547 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
550 SelectObject(hdc, hBrush);
551 SelectObject(hdc, hPen);
552 SelectObject(hdc, hFont);
554 /* free objects in handle table */
555 for(i = 0; i < mh->mtNoObjects; i++)
556 if(*(ht->objectHandle + i) != 0)
557 DeleteObject(*(ht->objectHandle + i));
559 /* free handle table */
560 HeapFree( GetProcessHeap(), 0, ht );
561 if(loaded)
562 HeapFree( GetProcessHeap(), 0, mh );
563 return TRUE;
566 /******************************************************************
567 * PlayMetaFile (GDI.123)
570 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
572 BOOL16 ret;
573 METAHEADER *mh = MF_GetMetaHeader16( hmf );
574 ret = MF_PlayMetaFile( hdc, mh );
575 MF_ReleaseMetaHeader16( hmf );
576 return ret;
579 /******************************************************************
580 * PlayMetaFile (GDI32.@)
582 * Renders the metafile specified by hmf in the DC specified by
583 * hdc. Returns FALSE on failure, TRUE on success.
585 BOOL WINAPI PlayMetaFile(
586 HDC hdc, /* [in] handle of DC to render in */
587 HMETAFILE hmf /* [in] handle of metafile to render */
590 METAHEADER *mh = MF_GetMetaHeader( hmf );
591 return MF_PlayMetaFile( hdc, mh );
595 /******************************************************************
596 * EnumMetaFile (GDI.175)
599 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
600 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
602 METAHEADER *mh = MF_GetMetaHeader16(hmf);
603 METARECORD *mr;
604 HANDLETABLE16 *ht;
605 HGLOBAL16 hHT;
606 SEGPTR spht;
607 unsigned int offset = 0;
608 WORD i, seg;
609 HPEN hPen;
610 HBRUSH hBrush;
611 HFONT hFont;
612 BOOL16 result = TRUE, loaded = FALSE;
614 TRACE("(%04x, %04x, %08lx, %08lx)\n",
615 hdc, hmf, (DWORD)lpEnumFunc, lpData);
618 if(!mh) return FALSE;
619 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
620 mh = MF_LoadDiskBasedMetaFile(mh);
621 if(!mh) return FALSE;
622 loaded = TRUE;
625 /* save the current pen, brush and font */
626 hPen = GetCurrentObject(hdc, OBJ_PEN);
627 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
628 hFont = GetCurrentObject(hdc, OBJ_FONT);
630 /* create the handle table */
632 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
633 sizeof(HANDLETABLE16) * mh->mtNoObjects);
634 spht = K32WOWGlobalLock16(hHT);
636 seg = hmf | 7;
637 offset = mh->mtHeaderSize * 2;
639 /* loop through metafile records */
641 while (offset < (mh->mtSize * 2))
643 mr = (METARECORD *)((char *)mh + offset);
645 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
646 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
647 mh->mtNoObjects, (LONG)lpData ))
649 result = FALSE;
650 break;
654 offset += (mr->rdSize * 2);
657 SelectObject(hdc, hBrush);
658 SelectObject(hdc, hPen);
659 SelectObject(hdc, hFont);
661 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
663 /* free objects in handle table */
664 for(i = 0; i < mh->mtNoObjects; i++)
665 if(*(ht->objectHandle + i) != 0)
666 DeleteObject(*(ht->objectHandle + i));
668 /* free handle table */
669 GlobalFree16(hHT);
670 if(loaded)
671 HeapFree( GetProcessHeap(), 0, mh );
672 MF_ReleaseMetaHeader16(hmf);
673 return result;
676 /******************************************************************
677 * EnumMetaFile (GDI32.@)
679 * Loop through the metafile records in hmf, calling the user-specified
680 * function for each one, stopping when the user's function returns FALSE
681 * (which is considered to be failure)
682 * or when no records are left (which is considered to be success).
684 * RETURNS
685 * TRUE on success, FALSE on failure.
687 * HISTORY
688 * Niels de carpentier, april 1996
690 BOOL WINAPI EnumMetaFile(
691 HDC hdc,
692 HMETAFILE hmf,
693 MFENUMPROC lpEnumFunc,
694 LPARAM lpData
696 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
697 METARECORD *mr;
698 HANDLETABLE *ht;
699 BOOL result = TRUE;
700 int i;
701 unsigned int offset = 0;
702 HPEN hPen;
703 HBRUSH hBrush;
704 HFONT hFont;
706 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
707 if (!mh) return 0;
708 if(mh->mtType == METAFILE_DISK)
710 /* Create a memory-based copy */
711 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
712 mh = mhTemp;
715 /* save the current pen, brush and font */
716 hPen = GetCurrentObject(hdc, OBJ_PEN);
717 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
718 hFont = GetCurrentObject(hdc, OBJ_FONT);
720 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
721 sizeof(HANDLETABLE) * mh->mtNoObjects);
723 /* loop through metafile records */
724 offset = mh->mtHeaderSize * 2;
726 while (offset < (mh->mtSize * 2))
728 mr = (METARECORD *)((char *)mh + offset);
729 if(mr->rdFunction == META_EOF) {
730 TRACE("Got META_EOF so stopping\n");
731 break;
733 TRACE("Calling EnumFunc with record type %x\n",
734 mr->rdFunction);
735 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
737 result = FALSE;
738 break;
741 offset += (mr->rdSize * 2);
744 /* restore pen, brush and font */
745 SelectObject(hdc, hBrush);
746 SelectObject(hdc, hPen);
747 SelectObject(hdc, hFont);
749 /* free objects in handle table */
750 for(i = 0; i < mh->mtNoObjects; i++)
751 if(*(ht->objectHandle + i) != 0)
752 DeleteObject(*(ht->objectHandle + i));
754 /* free handle table */
755 HeapFree( GetProcessHeap(), 0, ht);
756 /* free a copy of metafile */
757 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
758 return result;
761 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
762 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
763 /******************************************************************
764 * PlayMetaFileRecord (GDI.176)
766 * Render a single metafile record specified by *mr in the DC hdc, while
767 * using the handle table *ht, of length nHandles,
768 * to store metafile objects.
770 * BUGS
771 * The following metafile records are unimplemented:
773 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
774 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
775 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
778 void WINAPI PlayMetaFileRecord16(
779 HDC16 hdc, /* [in] DC to render metafile into */
780 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
781 METARECORD *mr, /* [in] pointer to metafile record to render */
782 UINT16 nHandles /* [in] size of handle table */
784 short s1;
785 HANDLE16 hndl;
786 char *ptr;
787 BITMAPINFOHEADER *infohdr;
789 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
790 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
792 switch (mr->rdFunction)
794 case META_EOF:
795 break;
797 case META_DELETEOBJECT:
798 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
799 *(ht->objectHandle + *(mr->rdParm)) = 0;
800 break;
802 case META_SETBKCOLOR:
803 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
804 break;
806 case META_SETBKMODE:
807 SetBkMode16(hdc, *(mr->rdParm));
808 break;
810 case META_SETMAPMODE:
811 SetMapMode16(hdc, *(mr->rdParm));
812 break;
814 case META_SETROP2:
815 SetROP216(hdc, *(mr->rdParm));
816 break;
818 case META_SETRELABS:
819 SetRelAbs16(hdc, *(mr->rdParm));
820 break;
822 case META_SETPOLYFILLMODE:
823 SetPolyFillMode16(hdc, *(mr->rdParm));
824 break;
826 case META_SETSTRETCHBLTMODE:
827 SetStretchBltMode16(hdc, *(mr->rdParm));
828 break;
830 case META_SETTEXTCOLOR:
831 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
832 break;
834 case META_SETWINDOWORG:
835 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
836 break;
838 case META_SETWINDOWEXT:
839 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
840 break;
842 case META_SETVIEWPORTORG:
843 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
844 break;
846 case META_SETVIEWPORTEXT:
847 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
848 break;
850 case META_OFFSETWINDOWORG:
851 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
852 break;
854 case META_SCALEWINDOWEXT:
855 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
856 *(mr->rdParm + 1), *(mr->rdParm));
857 break;
859 case META_OFFSETVIEWPORTORG:
860 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
861 break;
863 case META_SCALEVIEWPORTEXT:
864 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
865 *(mr->rdParm + 1), *(mr->rdParm));
866 break;
868 case META_LINETO:
869 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
870 break;
872 case META_MOVETO:
873 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
874 break;
876 case META_EXCLUDECLIPRECT:
877 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
878 *(mr->rdParm + 1), *(mr->rdParm) );
879 break;
881 case META_INTERSECTCLIPRECT:
882 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
883 *(mr->rdParm + 1), *(mr->rdParm) );
884 break;
886 case META_ARC:
887 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
888 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
889 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
890 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
891 break;
893 case META_ELLIPSE:
894 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
895 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
896 break;
898 case META_FLOODFILL:
899 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
900 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
901 break;
903 case META_PIE:
904 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
905 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
906 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
907 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
908 break;
910 case META_RECTANGLE:
911 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
912 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
913 break;
915 case META_ROUNDRECT:
916 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
917 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
918 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
919 break;
921 case META_PATBLT:
922 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
923 *(mr->rdParm + 3), *(mr->rdParm + 2),
924 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
925 break;
927 case META_SAVEDC:
928 SaveDC(hdc);
929 break;
931 case META_SETPIXEL:
932 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
933 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
934 break;
936 case META_OFFSETCLIPRGN:
937 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
938 break;
940 case META_TEXTOUT:
941 s1 = *(mr->rdParm);
942 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
943 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
944 (char *)(mr->rdParm + 1), s1);
945 break;
947 case META_POLYGON:
948 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
949 break;
951 case META_POLYPOLYGON:
952 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
953 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
954 break;
956 case META_POLYLINE:
957 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
958 break;
960 case META_RESTOREDC:
961 RestoreDC(hdc, (INT16)*(mr->rdParm));
962 break;
964 case META_SELECTOBJECT:
965 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
966 break;
968 case META_CHORD:
969 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
970 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
971 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
972 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
973 break;
975 case META_CREATEPATTERNBRUSH:
976 switch (*(mr->rdParm))
978 case BS_PATTERN:
979 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
980 MF_AddHandle(ht, nHandles,
981 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
982 infohdr->biHeight,
983 infohdr->biPlanes,
984 infohdr->biBitCount,
985 (LPSTR)(mr->rdParm +
986 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
987 break;
989 case BS_DIBPATTERN:
990 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
991 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
992 ptr = GlobalLock16(hndl);
993 memcpy(ptr, mr->rdParm + 2, s1);
994 GlobalUnlock16(hndl);
995 MF_AddHandle(ht, nHandles,
996 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
997 GlobalFree16(hndl);
998 break;
1000 default:
1001 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1002 mr->rdParm[0]);
1003 break;
1005 break;
1007 case META_CREATEPENINDIRECT:
1008 MF_AddHandle(ht, nHandles,
1009 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1010 break;
1012 case META_CREATEFONTINDIRECT:
1013 MF_AddHandle(ht, nHandles,
1014 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1015 break;
1017 case META_CREATEBRUSHINDIRECT:
1018 MF_AddHandle(ht, nHandles,
1019 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1020 break;
1022 case META_CREATEPALETTE:
1023 MF_AddHandle(ht, nHandles,
1024 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1025 break;
1027 case META_SETTEXTALIGN:
1028 SetTextAlign16(hdc, *(mr->rdParm));
1029 break;
1031 case META_SELECTPALETTE:
1032 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1033 *(mr->rdParm));
1034 break;
1036 case META_SETMAPPERFLAGS:
1037 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1038 break;
1040 case META_REALIZEPALETTE:
1041 GDIRealizePalette16(hdc);
1042 break;
1044 case META_ESCAPE:
1045 FIXME("META_ESCAPE unimplemented.\n");
1046 break;
1048 case META_EXTTEXTOUT:
1049 MF_Play_MetaExtTextOut( hdc, mr );
1050 break;
1052 case META_STRETCHDIB:
1054 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1055 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1056 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1057 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1058 mr->rdParm[4],mr->rdParm[3],bits,info,
1059 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1061 break;
1063 case META_DIBSTRETCHBLT:
1065 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1066 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1067 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1068 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1069 mr->rdParm[3],mr->rdParm[2],bits,info,
1070 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1072 break;
1074 case META_STRETCHBLT:
1076 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1077 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1078 mr->rdParm[11], /*Height*/
1079 mr->rdParm[13], /*Planes*/
1080 mr->rdParm[14], /*BitsPixel*/
1081 (LPSTR)&mr->rdParm[15]); /*bits*/
1082 SelectObject(hdcSrc,hbitmap);
1083 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1084 mr->rdParm[7],mr->rdParm[6],
1085 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1086 mr->rdParm[3],mr->rdParm[2],
1087 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1088 DeleteDC(hdcSrc);
1090 break;
1092 case META_BITBLT:
1094 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1095 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1096 mr->rdParm[8]/*Height*/,
1097 mr->rdParm[10]/*Planes*/,
1098 mr->rdParm[11]/*BitsPixel*/,
1099 (LPSTR)&mr->rdParm[12]/*bits*/);
1100 SelectObject(hdcSrc,hbitmap);
1101 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1102 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1103 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1104 MAKELONG(0,mr->rdParm[0]));
1105 DeleteDC(hdcSrc);
1107 break;
1109 case META_CREATEREGION:
1111 HRGN hrgn = CreateRectRgn(0,0,0,0);
1113 MF_Play_MetaCreateRegion(mr, hrgn);
1114 MF_AddHandle(ht, nHandles, hrgn);
1116 break;
1118 case META_FILLREGION:
1119 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1120 *(ht->objectHandle + *(mr->rdParm)));
1121 break;
1123 case META_FRAMEREGION:
1124 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1125 *(ht->objectHandle + *(mr->rdParm+2)),
1126 *(mr->rdParm+1), *(mr->rdParm));
1127 break;
1129 case META_INVERTREGION:
1130 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1131 break;
1133 case META_PAINTREGION:
1134 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1135 break;
1137 case META_SELECTCLIPREGION:
1138 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1139 break;
1141 case META_DIBCREATEPATTERNBRUSH:
1142 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1143 but there's no difference */
1145 TRACE("%d\n",*(mr->rdParm));
1146 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1147 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1148 ptr = GlobalLock16(hndl);
1149 memcpy(ptr, mr->rdParm + 2, s1);
1150 GlobalUnlock16(hndl);
1151 MF_AddHandle(ht, nHandles,
1152 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1153 GlobalFree16(hndl);
1154 break;
1156 case META_DIBBITBLT:
1157 /* In practice I've found that there are two layouts for
1158 META_DIBBITBLT, one (the first here) is the usual one when a src
1159 dc is actually passed to it, the second occurs when the src dc is
1160 passed in as NULL to the creating BitBlt. As the second case has
1161 no dib, a size check will suffice to distinguish.
1163 Caolan.McNamara@ul.ie */
1165 if (mr->rdSize > 12) {
1166 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1167 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1169 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1170 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1171 mr->rdParm[5], mr->rdParm[4], bits, info,
1172 DIB_RGB_COLORS,
1173 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1174 } else { /* equivalent to a PatBlt */
1175 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1176 mr->rdParm[6], mr->rdParm[5],
1177 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1179 break;
1181 case META_SETTEXTCHAREXTRA:
1182 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1183 break;
1185 case META_SETTEXTJUSTIFICATION:
1186 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1187 break;
1189 case META_EXTFLOODFILL:
1190 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1191 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1192 *(mr->rdParm));
1193 break;
1195 case META_SETDIBTODEV:
1197 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1198 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1199 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1200 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1201 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1202 mr->rdParm[2], mr->rdParm[1], bits, info,
1203 mr->rdParm[0]);
1204 break;
1207 #define META_UNIMP(x) case x: \
1208 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1209 break;
1210 META_UNIMP(META_DRAWTEXT)
1211 META_UNIMP(META_ANIMATEPALETTE)
1212 META_UNIMP(META_SETPALENTRIES)
1213 META_UNIMP(META_RESIZEPALETTE)
1214 META_UNIMP(META_RESETDC)
1215 META_UNIMP(META_STARTDOC)
1216 META_UNIMP(META_STARTPAGE)
1217 META_UNIMP(META_ENDPAGE)
1218 META_UNIMP(META_ABORTDOC)
1219 META_UNIMP(META_ENDDOC)
1220 META_UNIMP(META_CREATEBRUSH)
1221 META_UNIMP(META_CREATEBITMAPINDIRECT)
1222 META_UNIMP(META_CREATEBITMAP)
1223 #undef META_UNIMP
1225 default:
1226 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1227 mr->rdFunction);
1231 /******************************************************************
1232 * PlayMetaFileRecord (GDI32.@)
1234 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1235 METARECORD *metarecord, UINT handles )
1237 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1238 handles*sizeof(HANDLETABLE16));
1239 unsigned int i = 0;
1240 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1241 handles);
1242 for (i=0; i<handles; i++)
1243 ht->objectHandle[i] = handletable->objectHandle[i];
1244 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1245 for (i=0; i<handles; i++)
1246 handletable->objectHandle[i] = ht->objectHandle[i];
1247 GlobalFree((HGLOBAL)ht);
1248 return TRUE;
1251 /******************************************************************
1252 * GetMetaFileBits (GDI.159)
1254 * Trade in a metafile object handle for a handle to the metafile memory.
1258 HGLOBAL16 WINAPI GetMetaFileBits16(
1259 HMETAFILE16 hmf /* [in] metafile handle */
1262 TRACE("hMem out: %04x\n", hmf);
1263 return hmf;
1266 /******************************************************************
1267 * SetMetaFileBits (GDI.160)
1269 * Trade in a metafile memory handle for a handle to a metafile object.
1270 * The memory region should hold a proper metafile, otherwise
1271 * problems will occur when it is used. Validity of the memory is not
1272 * checked. The function is essentially just the identity function.
1274 HMETAFILE16 WINAPI SetMetaFileBits16(
1275 HGLOBAL16 hMem
1276 /* [in] handle to a memory region holding a metafile */
1279 TRACE("hmf out: %04x\n", hMem);
1281 return hMem;
1284 /******************************************************************
1285 * SetMetaFileBitsBetter (GDI.196)
1287 * Trade in a metafile memory handle for a handle to a metafile object,
1288 * making a cursory check (using IsValidMetaFile()) that the memory
1289 * handle points to a valid metafile.
1291 * RETURNS
1292 * Handle to a metafile on success, NULL on failure..
1294 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1296 if( IsValidMetaFile16( hMeta ) )
1297 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1298 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1299 return (HMETAFILE16)0;
1302 /******************************************************************
1303 * SetMetaFileBitsEx (GDI32.@)
1305 * Create a metafile from raw data. No checking of the data is performed.
1306 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1308 HMETAFILE WINAPI SetMetaFileBitsEx(
1309 UINT size, /* [in] size of metafile, in bytes */
1310 const BYTE *lpData /* [in] pointer to metafile data */
1313 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1314 if (!mh) return 0;
1315 memcpy(mh, lpData, size);
1316 return MF_Create_HMETAFILE(mh);
1319 /*****************************************************************
1320 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1322 * Copies the data from metafile _hmf_ into the buffer _buf_.
1323 * If _buf_ is zero, returns size of buffer required. Otherwise,
1324 * returns number of bytes copied.
1326 UINT WINAPI GetMetaFileBitsEx(
1327 HMETAFILE hmf, /* [in] metafile */
1328 UINT nSize, /* [in] size of buf */
1329 LPVOID buf /* [out] buffer to receive raw metafile data */
1331 METAHEADER *mh = MF_GetMetaHeader(hmf);
1332 UINT mfSize;
1334 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1335 if (!mh) return 0; /* FIXME: error code */
1336 if(mh->mtType == METAFILE_DISK)
1337 FIXME("Disk-based metafile?\n");
1338 mfSize = mh->mtSize * 2;
1339 if (!buf) {
1340 TRACE("returning size %d\n", mfSize);
1341 return mfSize;
1343 if(mfSize > nSize) mfSize = nSize;
1344 memmove(buf, mh, mfSize);
1345 return mfSize;
1348 /******************************************************************
1349 * GetWinMetaFileBits [GDI32.@]
1351 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1352 UINT cbBuffer, LPBYTE lpbBuffer,
1353 INT fnMapMode, HDC hdcRef)
1355 FIXME("(%d,%d,%p,%d,%d): stub\n",
1356 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1357 return 0;
1360 /******************************************************************
1361 * MF_Play_MetaCreateRegion
1363 * Handles META_CREATEREGION for PlayMetaFileRecord().
1367 * The layout of the record looks something like this:
1369 * rdParm meaning
1370 * 0 Always 0?
1371 * 1 Always 6?
1372 * 2 Looks like a handle? - not constant
1373 * 3 0 or 1 ??
1374 * 4 Total number of bytes
1375 * 5 No. of separate bands = n [see below]
1376 * 6 Largest number of x co-ords in a band
1377 * 7-10 Bounding box x1 y1 x2 y2
1378 * 11-... n bands
1380 * Regions are divided into bands that are uniform in the
1381 * y-direction. Each band consists of pairs of on/off x-coords and is
1382 * written as
1383 * m y0 y1 x1 x2 x3 ... xm m
1384 * into successive rdParm[]s.
1386 * This is probably just a dump of the internal RGNOBJ?
1388 * HDMD - 18/12/97
1392 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1394 WORD band, pair;
1395 WORD *start, *end;
1396 INT16 y0, y1;
1397 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1399 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1400 band++, start = end + 1) {
1401 if(*start / 2 != (*start + 1) / 2) {
1402 WARN("Delimiter not even.\n");
1403 DeleteObject( hrgn2 );
1404 return FALSE;
1407 end = start + *start + 3;
1408 if(end > (WORD *)mr + mr->rdSize) {
1409 WARN("End points outside record.\n");
1410 DeleteObject( hrgn2 );
1411 return FALSE;
1414 if(*start != *end) {
1415 WARN("Mismatched delimiters.\n");
1416 DeleteObject( hrgn2 );
1417 return FALSE;
1420 y0 = *(INT16 *)(start + 1);
1421 y1 = *(INT16 *)(start + 2);
1422 for(pair = 0; pair < *start / 2; pair++) {
1423 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1424 *(INT16 *)(start + 4 + 2*pair), y1 );
1425 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1428 DeleteObject( hrgn2 );
1429 return TRUE;
1433 /******************************************************************
1434 * MF_Play_MetaExtTextOut
1436 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1439 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1441 LPINT16 dxx;
1442 LPSTR sot;
1443 DWORD len;
1444 WORD s1;
1446 s1 = mr->rdParm[2]; /* String length */
1447 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1448 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1449 /* rec len without dx array */
1451 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1452 if (mr->rdParm[3])
1453 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1455 if (mr->rdSize == len / 2)
1456 dxx = NULL; /* determine if array present */
1457 else
1458 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1459 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1460 else {
1461 TRACE("%s len: %ld\n", sot, mr->rdSize);
1462 WARN(
1463 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1464 len, s1, mr->rdSize, mr->rdParm[3]);
1465 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1467 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1468 mr->rdParm[0], /* Y position */
1469 mr->rdParm[3], /* options */
1470 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1471 /* rectangle */
1472 sot, /* string */
1473 s1, dxx); /* length, dx array */
1474 if (dxx)
1475 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1476 return TRUE;