Fix an RPC server startup race introduced by me.
[wine/dcerpc.git] / dlls / gdi / metafile.c
blob42128e81f7ce052d35814982cc5296a8bee1d78e
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * NOTES
25 * These functions are primarily involved with metafile playback or anything
26 * that touches a HMETAFILE.
27 * For recording of metafiles look in graphics/metafiledrv/
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
32 * Memory-based metafiles are just stored as a continuous block of memory with
33 * a METAHEADER at the head with METARECORDs appended to it. mtType is
34 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
35 * disk-based metafile - even mtType is METAFILE_MEMORY.
36 * 16bit HMETAFILE16s are global handles to this block
37 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
38 * the memory.
39 * Disk-based metafiles are rather different. HMETAFILE16s point to a
40 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
41 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
42 * more 0, then 2 which may be a time stamp of the file and then the path of
43 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
45 * HDMD - 14/4/1999
48 #include "config.h"
50 #include <string.h>
51 #include <fcntl.h>
53 #include "wine/winbase16.h"
54 #include "wine/wingdi16.h"
55 #include "gdi.h"
56 #include "wownt32.h"
57 #include "winreg.h"
58 #include "winternl.h"
59 #include "gdi_private.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
64 #include "pshpack1.h"
65 typedef struct
67 DWORD dw1, dw2, dw3;
68 WORD w4;
69 CHAR filename[0x100];
70 } METAHEADERDISK;
71 #include "poppack.h"
73 typedef struct
75 GDIOBJHDR header;
76 METAHEADER *mh;
77 } METAFILEOBJ;
79 #define MFHEADERSIZE (sizeof(METAHEADER))
80 #define MFVERSION 0x300
83 /******************************************************************
84 * MF_AddHandle
86 * Add a handle to an external handle table and return the index
88 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
90 int i;
92 for (i = 0; i < htlen; i++)
94 if (*(ht->objectHandle + i) == 0)
96 *(ht->objectHandle + i) = hobj;
97 return i;
100 return -1;
104 /******************************************************************
105 * MF_Create_HMETATFILE
107 * Creates a (32 bit) HMETAFILE object from a METAHEADER
109 * HMETAFILEs are GDI objects.
111 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
113 HMETAFILE hmf = 0;
114 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
115 (HGDIOBJ *)&hmf, NULL );
116 if (metaObj)
118 metaObj->mh = mh;
119 GDI_ReleaseObj( hmf );
121 return hmf;
124 /******************************************************************
125 * MF_Create_HMETATFILE16
127 * Creates a HMETAFILE16 object from a METAHEADER
129 * HMETAFILE16s are Global memory handles.
131 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
133 HMETAFILE16 hmf;
134 DWORD size = mh->mtSize * sizeof(WORD);
136 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
137 if(hmf)
139 METAHEADER *mh_dest = GlobalLock16(hmf);
140 memcpy(mh_dest, mh, size);
141 GlobalUnlock16(hmf);
143 HeapFree(GetProcessHeap(), 0, mh);
144 return hmf;
147 /******************************************************************
148 * MF_GetMetaHeader
150 * Returns ptr to METAHEADER associated with HMETAFILE
152 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
154 METAHEADER *ret = NULL;
155 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
156 if (metaObj)
158 ret = metaObj->mh;
159 GDI_ReleaseObj( hmf );
161 return ret;
164 /******************************************************************
165 * MF_GetMetaHeader16
167 * Returns ptr to METAHEADER associated with HMETAFILE16
168 * Should be followed by call to MF_ReleaseMetaHeader16
170 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
172 return GlobalLock16(hmf);
175 /******************************************************************
176 * MF_ReleaseMetaHeader16
178 * Releases METAHEADER associated with HMETAFILE16
180 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
182 return GlobalUnlock16( hmf );
186 /******************************************************************
187 * convert_points
189 * Convert an array of POINT16 to an array of POINT.
190 * Result must be freed by caller.
192 static POINT *convert_points( UINT count, POINT16 *pt16 )
194 UINT i;
195 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
196 if (ret)
198 for (i = 0; i < count; i++)
200 ret[i].x = pt16[i].x;
201 ret[i].y = pt16[i].y;
204 return ret;
208 /******************************************************************
209 * DeleteMetaFile (GDI.127)
211 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
213 return !GlobalFree16( hmf );
216 /******************************************************************
217 * DeleteMetaFile (GDI32.@)
219 * Delete a memory-based metafile.
222 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
224 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
225 if (!metaObj) return FALSE;
226 HeapFree( GetProcessHeap(), 0, metaObj->mh );
227 GDI_FreeObject( hmf, metaObj );
228 return TRUE;
231 /******************************************************************
232 * MF_ReadMetaFile
234 * Returns a pointer to a memory based METAHEADER read in from file HFILE
237 static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
239 METAHEADER *mh;
240 DWORD BytesRead, size;
242 size = sizeof(METAHEADER);
243 mh = HeapAlloc( GetProcessHeap(), 0, size );
244 if(!mh) return NULL;
245 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
246 BytesRead != size) {
247 HeapFree( GetProcessHeap(), 0, mh );
248 return NULL;
250 if(mh->mtVersion != MFVERSION || mh->mtHeaderSize != size / 2) {
251 HeapFree( GetProcessHeap(), 0, mh );
252 return NULL;
254 size = mh->mtSize * 2;
255 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
256 if(!mh) return NULL;
257 size -= sizeof(METAHEADER);
258 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
259 NULL) == 0 ||
260 BytesRead != size) {
261 HeapFree( GetProcessHeap(), 0, mh );
262 return NULL;
265 if (mh->mtType != METAFILE_MEMORY) {
266 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
267 mh->mtType = METAFILE_MEMORY;
269 return mh;
272 /******************************************************************
273 * GetMetaFile (GDI.124)
275 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
277 METAHEADER *mh;
278 HANDLE hFile;
280 TRACE("%s\n", lpFilename);
282 if(!lpFilename)
283 return 0;
285 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
286 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
287 return 0;
289 mh = MF_ReadMetaFile(hFile);
290 CloseHandle(hFile);
291 if(!mh) return 0;
292 return MF_Create_HMETAFILE16( mh );
295 /******************************************************************
296 * GetMetaFileA (GDI32.@)
298 * Read a metafile from a file. Returns handle to a memory-based metafile.
300 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
302 METAHEADER *mh;
303 HANDLE hFile;
305 TRACE("%s\n", lpFilename);
307 if(!lpFilename)
308 return 0;
310 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
311 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
312 return 0;
314 mh = MF_ReadMetaFile(hFile);
315 CloseHandle(hFile);
316 if(!mh) return 0;
317 return MF_Create_HMETAFILE( mh );
322 /******************************************************************
323 * GetMetaFileW (GDI32.@)
325 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
327 METAHEADER *mh;
328 HANDLE hFile;
330 TRACE("%s\n", debugstr_w(lpFilename));
332 if(!lpFilename)
333 return 0;
335 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
336 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
337 return 0;
339 mh = MF_ReadMetaFile(hFile);
340 CloseHandle(hFile);
341 if(!mh) return 0;
342 return MF_Create_HMETAFILE( mh );
346 /******************************************************************
347 * MF_LoadDiskBasedMetaFile
349 * Creates a new memory-based metafile from a disk-based one.
351 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
353 METAHEADERDISK *mhd;
354 HANDLE hfile;
355 METAHEADER *mh2;
357 if(mh->mtType != METAFILE_DISK) {
358 ERR("Not a disk based metafile\n");
359 return NULL;
361 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
363 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
364 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
365 WARN("Can't open file of disk based metafile\n");
366 return NULL;
368 mh2 = MF_ReadMetaFile(hfile);
369 CloseHandle(hfile);
370 return mh2;
373 /******************************************************************
374 * MF_CreateMetaHeaderDisk
376 * Take a memory based METAHEADER and change it to a disk based METAHEADER
377 * assosiated with filename. Note: Trashes contents of old one.
379 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
381 METAHEADERDISK *mhd;
382 DWORD size;
384 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
385 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
386 mh->mtType = METAFILE_DISK;
387 size = HeapSize( GetProcessHeap(), 0, mh );
388 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
390 if( uni )
391 WideCharToMultiByte(CP_ACP, 0, filename, -1,
392 mhd->filename, sizeof mhd->filename, NULL, NULL);
393 else
394 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
395 return mh;
398 /******************************************************************
399 * CopyMetaFile (GDI.151)
401 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
403 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
404 METAHEADER *mh2 = NULL;
405 HANDLE hFile;
407 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
409 if(!mh) return 0;
411 if(mh->mtType == METAFILE_DISK)
412 mh2 = MF_LoadDiskBasedMetaFile(mh);
413 else {
414 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
415 memcpy( mh2, mh, mh->mtSize * 2 );
417 MF_ReleaseMetaHeader16( hSrcMetaFile );
419 if(lpFilename) { /* disk based metafile */
420 DWORD w;
421 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
422 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
423 HeapFree( GetProcessHeap(), 0, mh2 );
424 return 0;
426 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
427 CloseHandle(hFile);
428 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
431 return MF_Create_HMETAFILE16( mh2 );
435 /******************************************************************
436 * CopyMetaFileW (GDI32.@)
438 * Copies the metafile corresponding to hSrcMetaFile to either
439 * a disk file, if a filename is given, or to a new memory based
440 * metafile, if lpFileName is NULL.
442 * PARAMS
443 * hSrcMetaFile [I] handle of metafile to copy
444 * lpFilename [I] filename if copying to a file
446 * RETURNS
447 * Handle to metafile copy on success, NULL on failure.
449 * BUGS
450 * Copying to disk returns NULL even if successful.
452 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename )
454 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
455 METAHEADER *mh2 = NULL;
456 HANDLE hFile;
458 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
460 if(!mh) return 0;
462 if(mh->mtType == METAFILE_DISK)
463 mh2 = MF_LoadDiskBasedMetaFile(mh);
464 else {
465 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
466 memcpy( mh2, mh, mh->mtSize * 2 );
469 if(lpFilename) { /* disk based metafile */
470 DWORD w;
471 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
472 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
473 HeapFree( GetProcessHeap(), 0, mh2 );
474 return 0;
476 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
477 CloseHandle(hFile);
478 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, TRUE);
481 return MF_Create_HMETAFILE( mh2 );
485 /******************************************************************
486 * CopyMetaFileA (GDI32.@)
488 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
490 UNICODE_STRING lpFilenameW;
491 HMETAFILE ret = 0;
493 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
494 else lpFilenameW.Buffer = NULL;
496 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
497 if (lpFilenameW.Buffer)
498 RtlFreeUnicodeString(&lpFilenameW);
499 return ret;
503 /******************************************************************
504 * IsValidMetaFile (GDI.410)
506 * Attempts to check if a given metafile is correctly formatted.
507 * Currently, the only things verified are several properties of the
508 * header.
510 * RETURNS
511 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
513 * BUGS
514 * This is not exactly what windows does, see _Undocumented_Windows_
515 * for details.
517 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
519 BOOL16 res=FALSE;
520 METAHEADER *mh = MF_GetMetaHeader16(hmf);
521 if (mh) {
522 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
523 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
524 if (mh->mtVersion == MFVERSION)
525 res=TRUE;
526 MF_ReleaseMetaHeader16(hmf);
528 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
529 return res;
533 /*******************************************************************
534 * MF_PlayMetaFile
536 * Helper for PlayMetaFile
538 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
541 METARECORD *mr;
542 HANDLETABLE *ht;
543 unsigned int offset = 0;
544 WORD i;
545 HPEN hPen;
546 HBRUSH hBrush;
547 HFONT hFont;
548 BOOL loaded = FALSE;
550 if (!mh) return FALSE;
551 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
552 mh = MF_LoadDiskBasedMetaFile(mh);
553 if(!mh) return FALSE;
554 loaded = TRUE;
557 /* save the current pen, brush and font */
558 hPen = GetCurrentObject(hdc, OBJ_PEN);
559 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
560 hFont = GetCurrentObject(hdc, OBJ_FONT);
562 /* create the handle table */
563 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
564 sizeof(HANDLETABLE) * mh->mtNoObjects);
565 if(!ht) return FALSE;
567 /* loop through metafile playing records */
568 offset = mh->mtHeaderSize * 2;
569 while (offset < mh->mtSize * 2)
571 mr = (METARECORD *)((char *)mh + offset);
572 TRACE("offset=%04x,size=%08lx\n",
573 offset, mr->rdSize);
574 if (!mr->rdSize) {
575 TRACE(
576 "Entry got size 0 at offset %d, total mf length is %ld\n",
577 offset,mh->mtSize*2);
578 break; /* would loop endlessly otherwise */
580 offset += mr->rdSize * 2;
581 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
584 SelectObject(hdc, hBrush);
585 SelectObject(hdc, hPen);
586 SelectObject(hdc, hFont);
588 /* free objects in handle table */
589 for(i = 0; i < mh->mtNoObjects; i++)
590 if(*(ht->objectHandle + i) != 0)
591 DeleteObject(*(ht->objectHandle + i));
593 /* free handle table */
594 HeapFree( GetProcessHeap(), 0, ht );
595 if(loaded)
596 HeapFree( GetProcessHeap(), 0, mh );
597 return TRUE;
600 /******************************************************************
601 * PlayMetaFile (GDI.123)
604 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
606 BOOL16 ret;
607 METAHEADER *mh = MF_GetMetaHeader16( hmf );
608 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
609 MF_ReleaseMetaHeader16( hmf );
610 return ret;
613 /******************************************************************
614 * PlayMetaFile (GDI32.@)
616 * Renders the metafile specified by hmf in the DC specified by
617 * hdc. Returns FALSE on failure, TRUE on success.
619 * PARAMS
620 * hdc [I] handle of DC to render in
621 * hmf [I] handle of metafile to render
623 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
625 METAHEADER *mh = MF_GetMetaHeader( hmf );
626 return MF_PlayMetaFile( hdc, mh );
630 /******************************************************************
631 * EnumMetaFile (GDI.175)
634 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
635 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
637 METAHEADER *mh = MF_GetMetaHeader16(hmf);
638 METARECORD *mr;
639 HANDLETABLE16 *ht;
640 HDC hdc = HDC_32(hdc16);
641 HGLOBAL16 hHT;
642 SEGPTR spht;
643 unsigned int offset = 0;
644 WORD i, seg;
645 HPEN hPen;
646 HBRUSH hBrush;
647 HFONT hFont;
648 WORD args[8];
649 BOOL16 result = TRUE, loaded = FALSE;
651 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
653 if(!mh) return FALSE;
654 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
655 mh = MF_LoadDiskBasedMetaFile(mh);
656 if(!mh) return FALSE;
657 loaded = TRUE;
660 /* save the current pen, brush and font */
661 hPen = GetCurrentObject(hdc, OBJ_PEN);
662 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
663 hFont = GetCurrentObject(hdc, OBJ_FONT);
665 /* create the handle table */
667 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
668 sizeof(HANDLETABLE16) * mh->mtNoObjects);
669 spht = K32WOWGlobalLock16(hHT);
671 seg = hmf | 7;
672 offset = mh->mtHeaderSize * 2;
674 /* loop through metafile records */
676 args[7] = hdc16;
677 args[6] = SELECTOROF(spht);
678 args[5] = OFFSETOF(spht);
679 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
680 args[3] = LOWORD(offset);
681 args[2] = mh->mtNoObjects;
682 args[1] = HIWORD(lpData);
683 args[0] = LOWORD(lpData);
685 while (offset < (mh->mtSize * 2))
687 DWORD ret;
689 mr = (METARECORD *)((char *)mh + offset);
691 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
692 if (!LOWORD(ret))
694 result = FALSE;
695 break;
698 offset += (mr->rdSize * 2);
699 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
700 args[3] = LOWORD(offset);
703 SelectObject(hdc, hBrush);
704 SelectObject(hdc, hPen);
705 SelectObject(hdc, hFont);
707 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
709 /* free objects in handle table */
710 for(i = 0; i < mh->mtNoObjects; i++)
711 if(*(ht->objectHandle + i) != 0)
712 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
714 /* free handle table */
715 GlobalFree16(hHT);
716 if(loaded)
717 HeapFree( GetProcessHeap(), 0, mh );
718 MF_ReleaseMetaHeader16(hmf);
719 return result;
722 /******************************************************************
723 * EnumMetaFile (GDI32.@)
725 * Loop through the metafile records in hmf, calling the user-specified
726 * function for each one, stopping when the user's function returns FALSE
727 * (which is considered to be failure)
728 * or when no records are left (which is considered to be success).
730 * RETURNS
731 * TRUE on success, FALSE on failure.
733 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
735 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
736 METARECORD *mr;
737 HANDLETABLE *ht;
738 BOOL result = TRUE;
739 int i;
740 unsigned int offset = 0;
741 HPEN hPen;
742 HBRUSH hBrush;
743 HFONT hFont;
745 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
746 if (!mh) return 0;
747 if(mh->mtType == METAFILE_DISK)
749 /* Create a memory-based copy */
750 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
751 mh = mhTemp;
754 /* save the current pen, brush and font */
755 hPen = GetCurrentObject(hdc, OBJ_PEN);
756 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
757 hFont = GetCurrentObject(hdc, OBJ_FONT);
759 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
760 sizeof(HANDLETABLE) * mh->mtNoObjects);
762 /* loop through metafile records */
763 offset = mh->mtHeaderSize * 2;
765 while (offset < (mh->mtSize * 2))
767 mr = (METARECORD *)((char *)mh + offset);
768 if(mr->rdFunction == META_EOF) {
769 TRACE("Got META_EOF so stopping\n");
770 break;
772 TRACE("Calling EnumFunc with record type %x\n",
773 mr->rdFunction);
774 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
776 result = FALSE;
777 break;
780 offset += (mr->rdSize * 2);
783 /* restore pen, brush and font */
784 SelectObject(hdc, hBrush);
785 SelectObject(hdc, hPen);
786 SelectObject(hdc, hFont);
788 /* free objects in handle table */
789 for(i = 0; i < mh->mtNoObjects; i++)
790 if(*(ht->objectHandle + i) != 0)
791 DeleteObject(*(ht->objectHandle + i));
793 /* free handle table */
794 HeapFree( GetProcessHeap(), 0, ht);
795 /* free a copy of metafile */
796 HeapFree( GetProcessHeap(), 0, mhTemp );
797 return result;
800 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
801 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
802 /******************************************************************
803 * PlayMetaFileRecord (GDI32.@)
805 * Render a single metafile record specified by *mr in the DC hdc, while
806 * using the handle table *ht, of length handles,
807 * to store metafile objects.
809 * BUGS
810 * The following metafile records are unimplemented:
812 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
813 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
814 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
816 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
818 short s1;
819 POINT *pt;
820 BITMAPINFOHEADER *infohdr;
822 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
824 switch (mr->rdFunction)
826 case META_EOF:
827 break;
829 case META_DELETEOBJECT:
830 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
831 *(ht->objectHandle + mr->rdParm[0]) = 0;
832 break;
834 case META_SETBKCOLOR:
835 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
836 break;
838 case META_SETBKMODE:
839 SetBkMode(hdc, mr->rdParm[0]);
840 break;
842 case META_SETMAPMODE:
843 SetMapMode(hdc, mr->rdParm[0]);
844 break;
846 case META_SETROP2:
847 SetROP2(hdc, mr->rdParm[0]);
848 break;
850 case META_SETRELABS:
851 SetRelAbs(hdc, mr->rdParm[0]);
852 break;
854 case META_SETPOLYFILLMODE:
855 SetPolyFillMode(hdc, mr->rdParm[0]);
856 break;
858 case META_SETSTRETCHBLTMODE:
859 SetStretchBltMode(hdc, mr->rdParm[0]);
860 break;
862 case META_SETTEXTCOLOR:
863 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
864 break;
866 case META_SETWINDOWORG:
867 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
868 break;
870 case META_SETWINDOWEXT:
871 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
872 break;
874 case META_SETVIEWPORTORG:
875 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
876 break;
878 case META_SETVIEWPORTEXT:
879 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
880 break;
882 case META_OFFSETWINDOWORG:
883 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
884 break;
886 case META_SCALEWINDOWEXT:
887 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
888 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
889 break;
891 case META_OFFSETVIEWPORTORG:
892 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
893 break;
895 case META_SCALEVIEWPORTEXT:
896 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
897 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
898 break;
900 case META_LINETO:
901 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
902 break;
904 case META_MOVETO:
905 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
906 break;
908 case META_EXCLUDECLIPRECT:
909 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
910 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
911 break;
913 case META_INTERSECTCLIPRECT:
914 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
915 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
916 break;
918 case META_ARC:
919 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
920 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
921 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
922 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
923 break;
925 case META_ELLIPSE:
926 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
927 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
928 break;
930 case META_FLOODFILL:
931 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
932 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
933 break;
935 case META_PIE:
936 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
937 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
938 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
939 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
940 break;
942 case META_RECTANGLE:
943 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
944 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
945 break;
947 case META_ROUNDRECT:
948 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
949 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
950 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
951 break;
953 case META_PATBLT:
954 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
955 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
956 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
957 break;
959 case META_SAVEDC:
960 SaveDC(hdc);
961 break;
963 case META_SETPIXEL:
964 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
965 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
966 break;
968 case META_OFFSETCLIPRGN:
969 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
970 break;
972 case META_TEXTOUT:
973 s1 = mr->rdParm[0];
974 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
975 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
976 (char *)(mr->rdParm + 1), s1);
977 break;
979 case META_POLYGON:
980 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
982 Polygon(hdc, pt, mr->rdParm[0]);
983 HeapFree( GetProcessHeap(), 0, pt );
985 break;
987 case META_POLYPOLYGON:
989 UINT i, total;
990 SHORT *counts = (SHORT *)(mr->rdParm + 1);
992 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
993 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
994 if (pt)
996 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
997 if (cnt32)
999 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
1000 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
1001 HeapFree( GetProcessHeap(), 0, cnt32 );
1004 HeapFree( GetProcessHeap(), 0, pt );
1006 break;
1008 case META_POLYLINE:
1009 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1011 Polyline( hdc, pt, mr->rdParm[0] );
1012 HeapFree( GetProcessHeap(), 0, pt );
1014 break;
1016 case META_RESTOREDC:
1017 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1018 break;
1020 case META_SELECTOBJECT:
1021 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1022 break;
1024 case META_CHORD:
1025 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1026 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1027 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1028 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1029 break;
1031 case META_CREATEPATTERNBRUSH:
1032 switch (mr->rdParm[0])
1034 case BS_PATTERN:
1035 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1036 MF_AddHandle(ht, handles,
1037 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1038 infohdr->biHeight,
1039 infohdr->biPlanes,
1040 infohdr->biBitCount,
1041 (LPSTR)(mr->rdParm +
1042 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1043 break;
1045 case BS_DIBPATTERN:
1046 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1047 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1048 break;
1050 default:
1051 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1052 mr->rdParm[0]);
1053 break;
1055 break;
1057 case META_CREATEPENINDIRECT:
1059 LOGPEN pen;
1060 pen.lopnStyle = mr->rdParm[0];
1061 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1062 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1063 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1064 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1066 break;
1068 case META_CREATEFONTINDIRECT:
1070 LOGFONTA font;
1071 font.lfHeight = (SHORT)mr->rdParm[0];
1072 font.lfWidth = (SHORT)mr->rdParm[1];
1073 font.lfEscapement = (SHORT)mr->rdParm[2];
1074 font.lfOrientation = (SHORT)mr->rdParm[3];
1075 font.lfWeight = (SHORT)mr->rdParm[4];
1076 font.lfItalic = LOBYTE(mr->rdParm[5]);
1077 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1078 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1079 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1080 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1081 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1082 font.lfQuality = LOBYTE(mr->rdParm[8]);
1083 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1084 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1085 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1087 break;
1089 case META_CREATEBRUSHINDIRECT:
1091 LOGBRUSH brush;
1092 brush.lbStyle = mr->rdParm[0];
1093 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1094 brush.lbHatch = mr->rdParm[3];
1095 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1097 break;
1099 case META_CREATEPALETTE:
1100 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1101 break;
1103 case META_SETTEXTALIGN:
1104 SetTextAlign(hdc, mr->rdParm[0]);
1105 break;
1107 case META_SELECTPALETTE:
1108 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1109 break;
1111 case META_SETMAPPERFLAGS:
1112 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1113 break;
1115 case META_REALIZEPALETTE:
1116 GDIRealizePalette(hdc);
1117 break;
1119 case META_ESCAPE:
1120 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
1121 break;
1123 case META_EXTTEXTOUT:
1124 MF_Play_MetaExtTextOut( hdc, mr );
1125 break;
1127 case META_STRETCHDIB:
1129 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1130 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1131 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1132 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1133 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
1134 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1136 break;
1138 case META_DIBSTRETCHBLT:
1140 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1141 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1142 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1143 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1144 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
1145 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1147 break;
1149 case META_STRETCHBLT:
1151 HDC hdcSrc = CreateCompatibleDC(hdc);
1152 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1153 mr->rdParm[11], /*Height*/
1154 mr->rdParm[13], /*Planes*/
1155 mr->rdParm[14], /*BitsPixel*/
1156 (LPSTR)&mr->rdParm[15]); /*bits*/
1157 SelectObject(hdcSrc,hbitmap);
1158 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1159 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1160 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1161 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1162 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1163 DeleteDC(hdcSrc);
1165 break;
1167 case META_BITBLT:
1169 HDC hdcSrc = CreateCompatibleDC(hdc);
1170 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
1171 mr->rdParm[8]/*Height*/,
1172 mr->rdParm[10]/*Planes*/,
1173 mr->rdParm[11]/*BitsPixel*/,
1174 (LPSTR)&mr->rdParm[12]/*bits*/);
1175 SelectObject(hdcSrc,hbitmap);
1176 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1177 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1178 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
1179 MAKELONG(0,mr->rdParm[0]));
1180 DeleteDC(hdcSrc);
1182 break;
1184 case META_CREATEREGION:
1186 HRGN hrgn = CreateRectRgn(0,0,0,0);
1188 MF_Play_MetaCreateRegion(mr, hrgn);
1189 MF_AddHandle(ht, handles, hrgn);
1191 break;
1193 case META_FILLREGION:
1194 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1195 *(ht->objectHandle + mr->rdParm[0]));
1196 break;
1198 case META_FRAMEREGION:
1199 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1200 *(ht->objectHandle + mr->rdParm[2]),
1201 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1202 break;
1204 case META_INVERTREGION:
1205 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1206 break;
1208 case META_PAINTREGION:
1209 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1210 break;
1212 case META_SELECTCLIPREGION:
1214 HRGN hrgn = 0;
1216 if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]);
1217 SelectClipRgn(hdc, hrgn);
1219 break;
1221 case META_DIBCREATEPATTERNBRUSH:
1222 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1223 but there's no difference */
1224 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1225 break;
1227 case META_DIBBITBLT:
1228 /* In practice I've found that there are two layouts for
1229 META_DIBBITBLT, one (the first here) is the usual one when a src
1230 dc is actually passed to it, the second occurs when the src dc is
1231 passed in as NULL to the creating BitBlt. As the second case has
1232 no dib, a size check will suffice to distinguish.
1234 Caolan.McNamara@ul.ie */
1236 if (mr->rdSize > 12) {
1237 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1238 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1240 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1241 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1242 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1243 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1245 else /* equivalent to a PatBlt */
1246 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1247 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1248 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1249 break;
1251 case META_SETTEXTCHAREXTRA:
1252 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1253 break;
1255 case META_SETTEXTJUSTIFICATION:
1256 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1257 break;
1259 case META_EXTFLOODFILL:
1260 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1261 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1262 mr->rdParm[0]);
1263 break;
1265 case META_SETDIBTODEV:
1267 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1268 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1269 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1270 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1271 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1272 mr->rdParm[2], mr->rdParm[1], bits, info,
1273 mr->rdParm[0]);
1274 break;
1277 #define META_UNIMP(x) case x: \
1278 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1279 break;
1280 META_UNIMP(META_DRAWTEXT)
1281 META_UNIMP(META_ANIMATEPALETTE)
1282 META_UNIMP(META_SETPALENTRIES)
1283 META_UNIMP(META_RESIZEPALETTE)
1284 META_UNIMP(META_RESETDC)
1285 META_UNIMP(META_STARTDOC)
1286 META_UNIMP(META_STARTPAGE)
1287 META_UNIMP(META_ENDPAGE)
1288 META_UNIMP(META_ABORTDOC)
1289 META_UNIMP(META_ENDDOC)
1290 META_UNIMP(META_CREATEBRUSH)
1291 META_UNIMP(META_CREATEBITMAPINDIRECT)
1292 META_UNIMP(META_CREATEBITMAP)
1293 #undef META_UNIMP
1295 default:
1296 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1297 return FALSE;
1299 return TRUE;
1302 /******************************************************************
1303 * GetMetaFileBits (GDI.159)
1305 * Trade in a metafile object handle for a handle to the metafile memory.
1307 * PARAMS
1308 * hmf [I] metafile handle
1311 HGLOBAL16 WINAPI GetMetaFileBits16( HMETAFILE16 hmf )
1313 TRACE("hMem out: %04x\n", hmf);
1314 return hmf;
1317 /******************************************************************
1318 * SetMetaFileBits (GDI.160)
1320 * Trade in a metafile memory handle for a handle to a metafile object.
1321 * The memory region should hold a proper metafile, otherwise
1322 * problems will occur when it is used. Validity of the memory is not
1323 * checked. The function is essentially just the identity function.
1325 * PARAMS
1326 * hMem [I] handle to a memory region holding a metafile
1328 HMETAFILE16 WINAPI SetMetaFileBits16( HGLOBAL16 hMem )
1330 TRACE("hmf out: %04x\n", hMem);
1332 return hMem;
1335 /******************************************************************
1336 * SetMetaFileBitsBetter (GDI.196)
1338 * Trade in a metafile memory handle for a handle to a metafile object,
1339 * making a cursory check (using IsValidMetaFile()) that the memory
1340 * handle points to a valid metafile.
1342 * RETURNS
1343 * Handle to a metafile on success, NULL on failure..
1345 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1347 if( IsValidMetaFile16( hMeta ) )
1348 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1349 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1350 return (HMETAFILE16)0;
1353 /******************************************************************
1354 * SetMetaFileBitsEx (GDI32.@)
1356 * Create a metafile from raw data. No checking of the data is performed.
1357 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1359 * PARAMS
1360 * size [I] size of metafile, in bytes
1361 * lpData [I] pointer to metafile data
1363 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
1365 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1366 if (!mh) return 0;
1367 memcpy(mh, lpData, size);
1368 return MF_Create_HMETAFILE(mh);
1371 /*****************************************************************
1372 * GetMetaFileBitsEx (GDI32.@)
1374 * Get raw metafile data.
1376 * Copies the data from metafile _hmf_ into the buffer _buf_.
1377 * If _buf_ is zero, returns size of buffer required. Otherwise,
1378 * returns number of bytes copied.
1380 * PARAMS
1381 * hmf [I] metafile
1382 * nSize [I] size of buf
1383 * buf [O] buffer to receive raw metafile data
1385 UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
1387 METAHEADER *mh = MF_GetMetaHeader(hmf);
1388 UINT mfSize;
1390 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1391 if (!mh) return 0; /* FIXME: error code */
1392 if(mh->mtType == METAFILE_DISK)
1393 FIXME("Disk-based metafile?\n");
1394 mfSize = mh->mtSize * 2;
1395 if (!buf) {
1396 TRACE("returning size %d\n", mfSize);
1397 return mfSize;
1399 if(mfSize > nSize) mfSize = nSize;
1400 memmove(buf, mh, mfSize);
1401 return mfSize;
1404 /******************************************************************
1405 * GetWinMetaFileBits [GDI32.@]
1407 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1408 UINT cbBuffer, LPBYTE lpbBuffer,
1409 INT fnMapMode, HDC hdcRef)
1411 HDC hdcmf;
1412 HMETAFILE hmf;
1413 UINT ret;
1414 RECT rc;
1415 INT oldMapMode;
1417 GetClipBox(hdcRef, &rc);
1418 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1420 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1421 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1423 hdcmf = CreateMetaFileA(NULL);
1424 PlayEnhMetaFile(hdcmf, hemf, &rc);
1425 hmf = CloseMetaFile(hdcmf);
1426 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1427 DeleteMetaFile(hmf);
1429 SetMapMode(hdcRef, oldMapMode);
1431 return ret;
1434 /******************************************************************
1435 * MF_Play_MetaCreateRegion
1437 * Handles META_CREATEREGION for PlayMetaFileRecord().
1439 * The layout of the record looks something like this:
1441 * rdParm meaning
1442 * 0 Always 0?
1443 * 1 Always 6?
1444 * 2 Looks like a handle? - not constant
1445 * 3 0 or 1 ??
1446 * 4 Total number of bytes
1447 * 5 No. of separate bands = n [see below]
1448 * 6 Largest number of x co-ords in a band
1449 * 7-10 Bounding box x1 y1 x2 y2
1450 * 11-... n bands
1452 * Regions are divided into bands that are uniform in the
1453 * y-direction. Each band consists of pairs of on/off x-coords and is
1454 * written as
1455 * m y0 y1 x1 x2 x3 ... xm m
1456 * into successive rdParm[]s.
1458 * This is probably just a dump of the internal RGNOBJ?
1460 * HDMD - 18/12/97
1464 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1466 WORD band, pair;
1467 WORD *start, *end;
1468 INT16 y0, y1;
1469 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1471 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1472 band++, start = end + 1) {
1473 if(*start / 2 != (*start + 1) / 2) {
1474 WARN("Delimiter not even.\n");
1475 DeleteObject( hrgn2 );
1476 return FALSE;
1479 end = start + *start + 3;
1480 if(end > (WORD *)mr + mr->rdSize) {
1481 WARN("End points outside record.\n");
1482 DeleteObject( hrgn2 );
1483 return FALSE;
1486 if(*start != *end) {
1487 WARN("Mismatched delimiters.\n");
1488 DeleteObject( hrgn2 );
1489 return FALSE;
1492 y0 = *(INT16 *)(start + 1);
1493 y1 = *(INT16 *)(start + 2);
1494 for(pair = 0; pair < *start / 2; pair++) {
1495 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1496 *(INT16 *)(start + 4 + 2*pair), y1 );
1497 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1500 DeleteObject( hrgn2 );
1501 return TRUE;
1505 /******************************************************************
1506 * MF_Play_MetaExtTextOut
1508 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1511 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1513 INT *dx = NULL;
1514 int i;
1515 LPINT16 dxx;
1516 LPSTR sot;
1517 DWORD len;
1518 WORD s1;
1519 RECT rect;
1520 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1522 s1 = mr->rdParm[2]; /* String length */
1523 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1524 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1525 /* rec len without dx array */
1527 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1528 if (isrect)
1530 rect.left = (SHORT)mr->rdParm[4];
1531 rect.top = (SHORT)mr->rdParm[5];
1532 rect.right = (SHORT)mr->rdParm[6];
1533 rect.bottom = (SHORT)mr->rdParm[7];
1534 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1537 if (mr->rdSize == len / 2)
1538 dxx = NULL; /* determine if array present */
1539 else
1540 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1542 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1543 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1544 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1546 else {
1547 TRACE("%s len: %ld\n", sot, mr->rdSize);
1548 WARN("Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1549 len, s1, mr->rdSize, mr->rdParm[3]);
1550 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1552 ExtTextOutA( hdc,
1553 (SHORT)mr->rdParm[1], /* X position */
1554 (SHORT)mr->rdParm[0], /* Y position */
1555 mr->rdParm[3], /* options */
1556 &rect, /* rectangle */
1557 sot, /* string */
1558 s1, dx); /* length, dx array */
1559 if (dx)
1561 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1562 HeapFree( GetProcessHeap(), 0, dx );
1564 return TRUE;