Fixed font enumeration.
[wine.git] / objects / metafile.c
blobc6ac28aac4e92dd158ac5cd2de820a86d9fd8553
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
44 */
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 "metafile.h"
57 #include "wine/debug.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
61 #include "pshpack1.h"
62 typedef struct
64 DWORD dw1, dw2, dw3;
65 WORD w4;
66 CHAR filename[0x100];
67 } METAHEADERDISK;
68 #include "poppack.h"
70 #define MFHEADERSIZE (sizeof(METAHEADER))
71 #define MFVERSION 0x300
73 /* ### start build ### */
74 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
75 /* ### stop build ### */
77 /******************************************************************
78 * MF_AddHandle
80 * Add a handle to an external handle table and return the index
82 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
84 int i;
86 for (i = 0; i < htlen; i++)
88 if (*(ht->objectHandle + i) == 0)
90 *(ht->objectHandle + i) = hobj;
91 return i;
94 return -1;
98 /******************************************************************
99 * MF_Create_HMETATFILE
101 * Creates a (32 bit) HMETAFILE object from a METAHEADER
103 * HMETAFILEs are GDI objects.
105 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
107 HMETAFILE hmf = 0;
108 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
109 if (metaObj)
111 metaObj->mh = mh;
112 GDI_ReleaseObj( hmf );
114 return hmf;
117 /******************************************************************
118 * MF_Create_HMETATFILE16
120 * Creates a HMETAFILE16 object from a METAHEADER
122 * HMETAFILE16s are Global memory handles.
124 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
126 HMETAFILE16 hmf;
127 DWORD size = mh->mtSize * sizeof(WORD);
129 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
130 if(hmf)
132 METAHEADER *mh_dest = GlobalLock16(hmf);
133 memcpy(mh_dest, mh, size);
134 GlobalUnlock16(hmf);
136 HeapFree(GetProcessHeap(), 0, mh);
137 return hmf;
140 /******************************************************************
141 * MF_GetMetaHeader
143 * Returns ptr to METAHEADER associated with HMETAFILE
145 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
147 METAHEADER *ret = NULL;
148 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
149 if (metaObj)
151 ret = metaObj->mh;
152 GDI_ReleaseObj( hmf );
154 return ret;
157 /******************************************************************
158 * MF_GetMetaHeader16
160 * Returns ptr to METAHEADER associated with HMETAFILE16
161 * Should be followed by call to MF_ReleaseMetaHeader16
163 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
165 return GlobalLock16(hmf);
168 /******************************************************************
169 * MF_ReleaseMetaHeader16
171 * Releases METAHEADER associated with HMETAFILE16
173 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
175 return GlobalUnlock16( hmf );
179 /******************************************************************
180 * DeleteMetaFile (GDI.127)
182 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
184 return !GlobalFree16( hmf );
187 /******************************************************************
188 * DeleteMetaFile (GDI32.@)
190 * Delete a memory-based metafile.
193 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
195 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
196 if (!metaObj) return FALSE;
197 HeapFree( GetProcessHeap(), 0, metaObj->mh );
198 GDI_FreeObject( hmf, metaObj );
199 return TRUE;
202 /******************************************************************
203 * MF_ReadMetaFile
205 * Returns a pointer to a memory based METAHEADER read in from file HFILE
208 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
210 METAHEADER *mh;
211 DWORD BytesRead, size;
213 size = sizeof(METAHEADER);
214 mh = HeapAlloc( GetProcessHeap(), 0, size );
215 if(!mh) return NULL;
216 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
217 BytesRead != size) {
218 HeapFree( GetProcessHeap(), 0, mh );
219 return NULL;
221 size = mh->mtSize * 2;
222 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
223 if(!mh) return NULL;
224 size -= sizeof(METAHEADER);
225 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
226 NULL) == 0 ||
227 BytesRead != size) {
228 HeapFree( GetProcessHeap(), 0, mh );
229 return NULL;
232 if (mh->mtType != METAFILE_MEMORY) {
233 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
234 mh->mtType = METAFILE_MEMORY;
236 return mh;
239 /******************************************************************
240 * GetMetaFile (GDI.124)
242 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
244 METAHEADER *mh;
245 HANDLE hFile;
247 TRACE("%s\n", lpFilename);
249 if(!lpFilename)
250 return 0;
252 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
253 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
254 return 0;
256 mh = MF_ReadMetaFile(hFile);
257 CloseHandle(hFile);
258 if(!mh) return 0;
259 return MF_Create_HMETAFILE16( mh );
262 /******************************************************************
263 * GetMetaFileA (GDI32.@)
265 * Read a metafile from a file. Returns handle to a memory-based metafile.
267 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
269 METAHEADER *mh;
270 HANDLE hFile;
272 TRACE("%s\n", lpFilename);
274 if(!lpFilename)
275 return 0;
277 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
278 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
279 return 0;
281 mh = MF_ReadMetaFile(hFile);
282 CloseHandle(hFile);
283 if(!mh) return 0;
284 return MF_Create_HMETAFILE( mh );
289 /******************************************************************
290 * GetMetaFileW (GDI32.@)
292 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
294 METAHEADER *mh;
295 HANDLE hFile;
297 TRACE("%s\n", debugstr_w(lpFilename));
299 if(!lpFilename)
300 return 0;
302 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
303 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
304 return 0;
306 mh = MF_ReadMetaFile(hFile);
307 CloseHandle(hFile);
308 if(!mh) return 0;
309 return MF_Create_HMETAFILE( mh );
313 /******************************************************************
314 * MF_LoadDiskBasedMetaFile
316 * Creates a new memory-based metafile from a disk-based one.
318 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
320 METAHEADERDISK *mhd;
321 HANDLE hfile;
322 METAHEADER *mh2;
324 if(mh->mtType != METAFILE_DISK) {
325 ERR("Not a disk based metafile\n");
326 return NULL;
328 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
330 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
331 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
332 WARN("Can't open file of disk based metafile\n");
333 return NULL;
335 mh2 = MF_ReadMetaFile(hfile);
336 CloseHandle(hfile);
337 return mh2;
340 /******************************************************************
341 * MF_CreateMetaHeaderDisk
343 * Take a memory based METAHEADER and change it to a disk based METAHEADER
344 * assosiated with filename. Note: Trashes contents of old one.
346 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
348 METAHEADERDISK *mhd;
349 DWORD size;
351 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
352 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
353 mh->mtType = METAFILE_DISK;
354 size = HeapSize( GetProcessHeap(), 0, mh );
355 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
356 strcpy(mhd->filename, filename);
357 return mh;
360 /******************************************************************
361 * CopyMetaFile (GDI.151)
363 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
365 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
366 METAHEADER *mh2 = NULL;
367 HANDLE hFile;
369 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
371 if(!mh) return 0;
373 if(mh->mtType == METAFILE_DISK)
374 mh2 = MF_LoadDiskBasedMetaFile(mh);
375 else {
376 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
377 memcpy( mh2, mh, mh->mtSize * 2 );
379 MF_ReleaseMetaHeader16( hSrcMetaFile );
381 if(lpFilename) { /* disk based metafile */
382 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
383 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
384 HeapFree( GetProcessHeap(), 0, mh2 );
385 return 0;
387 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
388 CloseHandle(hFile);
389 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
392 return MF_Create_HMETAFILE16( mh2 );
396 /******************************************************************
397 * CopyMetaFileA (GDI32.@)
399 * Copies the metafile corresponding to hSrcMetaFile to either
400 * a disk file, if a filename is given, or to a new memory based
401 * metafile, if lpFileName is NULL.
403 * RETURNS
405 * Handle to metafile copy on success, NULL on failure.
407 * BUGS
409 * Copying to disk returns NULL even if successful.
411 HMETAFILE WINAPI CopyMetaFileA(
412 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
413 LPCSTR lpFilename /* [in] filename if copying to a file */
415 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
416 METAHEADER *mh2 = NULL;
417 HANDLE hFile;
419 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
421 if(!mh) return 0;
423 if(mh->mtType == METAFILE_DISK)
424 mh2 = MF_LoadDiskBasedMetaFile(mh);
425 else {
426 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
427 memcpy( mh2, mh, mh->mtSize * 2 );
430 if(lpFilename) { /* disk based metafile */
431 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
432 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
433 HeapFree( GetProcessHeap(), 0, mh2 );
434 return 0;
436 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
437 CloseHandle(hFile);
438 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
441 return MF_Create_HMETAFILE( mh2 );
445 /******************************************************************
446 * CopyMetaFileW (GDI32.@)
448 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
449 LPCWSTR lpFilename )
451 HMETAFILE ret = 0;
452 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
453 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
455 if (p)
457 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
458 ret = CopyMetaFileA( hSrcMetaFile, p );
459 HeapFree( GetProcessHeap(), 0, p );
461 return ret;
465 /******************************************************************
466 * IsValidMetaFile (GDI.410)
468 * Attempts to check if a given metafile is correctly formatted.
469 * Currently, the only things verified are several properties of the
470 * header.
472 * RETURNS
473 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
475 * BUGS
476 * This is not exactly what windows does, see _Undocumented_Windows_
477 * for details.
479 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
481 BOOL16 res=FALSE;
482 METAHEADER *mh = MF_GetMetaHeader16(hmf);
483 if (mh) {
484 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
485 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
486 if (mh->mtVersion == MFVERSION)
487 res=TRUE;
488 MF_ReleaseMetaHeader16(hmf);
490 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
491 return res;
495 /*******************************************************************
496 * MF_PlayMetaFile
498 * Helper for PlayMetaFile
500 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
503 METARECORD *mr;
504 HANDLETABLE16 *ht;
505 unsigned int offset = 0;
506 WORD i;
507 HPEN hPen;
508 HBRUSH hBrush;
509 HFONT hFont;
510 BOOL loaded = FALSE;
512 if (!mh) return FALSE;
513 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
514 mh = MF_LoadDiskBasedMetaFile(mh);
515 if(!mh) return FALSE;
516 loaded = TRUE;
519 /* save the current pen, brush and font */
520 hPen = GetCurrentObject(hdc, OBJ_PEN);
521 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
522 hFont = GetCurrentObject(hdc, OBJ_FONT);
524 /* create the handle table */
525 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
526 sizeof(HANDLETABLE16) * mh->mtNoObjects);
527 if(!ht) return FALSE;
529 /* loop through metafile playing records */
530 offset = mh->mtHeaderSize * 2;
531 while (offset < mh->mtSize * 2)
533 mr = (METARECORD *)((char *)mh + offset);
534 TRACE("offset=%04x,size=%08lx\n",
535 offset, mr->rdSize);
536 if (!mr->rdSize) {
537 TRACE(
538 "Entry got size 0 at offset %d, total mf length is %ld\n",
539 offset,mh->mtSize*2);
540 break; /* would loop endlessly otherwise */
542 offset += mr->rdSize * 2;
543 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
546 SelectObject(hdc, hBrush);
547 SelectObject(hdc, hPen);
548 SelectObject(hdc, hFont);
550 /* free objects in handle table */
551 for(i = 0; i < mh->mtNoObjects; i++)
552 if(*(ht->objectHandle + i) != 0)
553 DeleteObject(*(ht->objectHandle + i));
555 /* free handle table */
556 HeapFree( GetProcessHeap(), 0, ht );
557 if(loaded)
558 HeapFree( GetProcessHeap(), 0, mh );
559 return TRUE;
562 /******************************************************************
563 * PlayMetaFile (GDI.123)
566 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
568 BOOL16 ret;
569 METAHEADER *mh = MF_GetMetaHeader16( hmf );
570 ret = MF_PlayMetaFile( hdc, mh );
571 MF_ReleaseMetaHeader16( hmf );
572 return ret;
575 /******************************************************************
576 * PlayMetaFile (GDI32.@)
578 * Renders the metafile specified by hmf in the DC specified by
579 * hdc. Returns FALSE on failure, TRUE on success.
581 BOOL WINAPI PlayMetaFile(
582 HDC hdc, /* [in] handle of DC to render in */
583 HMETAFILE hmf /* [in] handle of metafile to render */
586 METAHEADER *mh = MF_GetMetaHeader( hmf );
587 return MF_PlayMetaFile( hdc, mh );
591 /******************************************************************
592 * EnumMetaFile (GDI.175)
595 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
596 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
598 METAHEADER *mh = MF_GetMetaHeader16(hmf);
599 METARECORD *mr;
600 HANDLETABLE16 *ht;
601 HGLOBAL16 hHT;
602 SEGPTR spht;
603 unsigned int offset = 0;
604 WORD i, seg;
605 HPEN hPen;
606 HBRUSH hBrush;
607 HFONT hFont;
608 BOOL16 result = TRUE, loaded = FALSE;
610 TRACE("(%04x, %04x, %08lx, %08lx)\n",
611 hdc, hmf, (DWORD)lpEnumFunc, lpData);
614 if(!mh) return FALSE;
615 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
616 mh = MF_LoadDiskBasedMetaFile(mh);
617 if(!mh) return FALSE;
618 loaded = TRUE;
621 /* save the current pen, brush and font */
622 hPen = GetCurrentObject(hdc, OBJ_PEN);
623 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
624 hFont = GetCurrentObject(hdc, OBJ_FONT);
626 /* create the handle table */
628 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
629 sizeof(HANDLETABLE16) * mh->mtNoObjects);
630 spht = K32WOWGlobalLock16(hHT);
632 seg = hmf | 7;
633 offset = mh->mtHeaderSize * 2;
635 /* loop through metafile records */
637 while (offset < (mh->mtSize * 2))
639 mr = (METARECORD *)((char *)mh + offset);
641 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
642 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
643 mh->mtNoObjects, (LONG)lpData ))
645 result = FALSE;
646 break;
650 offset += (mr->rdSize * 2);
653 SelectObject(hdc, hBrush);
654 SelectObject(hdc, hPen);
655 SelectObject(hdc, hFont);
657 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
659 /* free objects in handle table */
660 for(i = 0; i < mh->mtNoObjects; i++)
661 if(*(ht->objectHandle + i) != 0)
662 DeleteObject(*(ht->objectHandle + i));
664 /* free handle table */
665 GlobalFree16(hHT);
666 if(loaded)
667 HeapFree( GetProcessHeap(), 0, mh );
668 MF_ReleaseMetaHeader16(hmf);
669 return result;
672 /******************************************************************
673 * EnumMetaFile (GDI32.@)
675 * Loop through the metafile records in hmf, calling the user-specified
676 * function for each one, stopping when the user's function returns FALSE
677 * (which is considered to be failure)
678 * or when no records are left (which is considered to be success).
680 * RETURNS
681 * TRUE on success, FALSE on failure.
683 * HISTORY
684 * Niels de carpentier, april 1996
686 BOOL WINAPI EnumMetaFile(
687 HDC hdc,
688 HMETAFILE hmf,
689 MFENUMPROC lpEnumFunc,
690 LPARAM lpData
692 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
693 METARECORD *mr;
694 HANDLETABLE *ht;
695 BOOL result = TRUE;
696 int i;
697 unsigned int offset = 0;
698 HPEN hPen;
699 HBRUSH hBrush;
700 HFONT hFont;
702 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
703 if (!mh) return 0;
704 if(mh->mtType == METAFILE_DISK)
706 /* Create a memory-based copy */
707 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
708 mh = mhTemp;
711 /* save the current pen, brush and font */
712 hPen = GetCurrentObject(hdc, OBJ_PEN);
713 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
714 hFont = GetCurrentObject(hdc, OBJ_FONT);
716 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
717 sizeof(HANDLETABLE) * mh->mtNoObjects);
719 /* loop through metafile records */
720 offset = mh->mtHeaderSize * 2;
722 while (offset < (mh->mtSize * 2))
724 mr = (METARECORD *)((char *)mh + offset);
725 TRACE("Calling EnumFunc with record type %x\n",
726 mr->rdFunction);
727 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
729 result = FALSE;
730 break;
733 offset += (mr->rdSize * 2);
736 /* restore pen, brush and font */
737 SelectObject(hdc, hBrush);
738 SelectObject(hdc, hPen);
739 SelectObject(hdc, hFont);
741 /* free objects in handle table */
742 for(i = 0; i < mh->mtNoObjects; i++)
743 if(*(ht->objectHandle + i) != 0)
744 DeleteObject(*(ht->objectHandle + i));
746 /* free handle table */
747 HeapFree( GetProcessHeap(), 0, ht);
748 /* free a copy of metafile */
749 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
750 return result;
753 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
754 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
755 /******************************************************************
756 * PlayMetaFileRecord (GDI.176)
758 * Render a single metafile record specified by *mr in the DC hdc, while
759 * using the handle table *ht, of length nHandles,
760 * to store metafile objects.
762 * BUGS
763 * The following metafile records are unimplemented:
765 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
766 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
767 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
770 void WINAPI PlayMetaFileRecord16(
771 HDC16 hdc, /* [in] DC to render metafile into */
772 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
773 METARECORD *mr, /* [in] pointer to metafile record to render */
774 UINT16 nHandles /* [in] size of handle table */
776 short s1;
777 HANDLE16 hndl;
778 char *ptr;
779 BITMAPINFOHEADER *infohdr;
781 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
782 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
784 switch (mr->rdFunction)
786 case META_EOF:
787 break;
789 case META_DELETEOBJECT:
790 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
791 *(ht->objectHandle + *(mr->rdParm)) = 0;
792 break;
794 case META_SETBKCOLOR:
795 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
796 break;
798 case META_SETBKMODE:
799 SetBkMode16(hdc, *(mr->rdParm));
800 break;
802 case META_SETMAPMODE:
803 SetMapMode16(hdc, *(mr->rdParm));
804 break;
806 case META_SETROP2:
807 SetROP216(hdc, *(mr->rdParm));
808 break;
810 case META_SETRELABS:
811 SetRelAbs16(hdc, *(mr->rdParm));
812 break;
814 case META_SETPOLYFILLMODE:
815 SetPolyFillMode16(hdc, *(mr->rdParm));
816 break;
818 case META_SETSTRETCHBLTMODE:
819 SetStretchBltMode16(hdc, *(mr->rdParm));
820 break;
822 case META_SETTEXTCOLOR:
823 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
824 break;
826 case META_SETWINDOWORG:
827 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
828 break;
830 case META_SETWINDOWEXT:
831 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
832 break;
834 case META_SETVIEWPORTORG:
835 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
836 break;
838 case META_SETVIEWPORTEXT:
839 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
840 break;
842 case META_OFFSETWINDOWORG:
843 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
844 break;
846 case META_SCALEWINDOWEXT:
847 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
848 *(mr->rdParm + 1), *(mr->rdParm));
849 break;
851 case META_OFFSETVIEWPORTORG:
852 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
853 break;
855 case META_SCALEVIEWPORTEXT:
856 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
857 *(mr->rdParm + 1), *(mr->rdParm));
858 break;
860 case META_LINETO:
861 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
862 break;
864 case META_MOVETO:
865 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
866 break;
868 case META_EXCLUDECLIPRECT:
869 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
870 *(mr->rdParm + 1), *(mr->rdParm) );
871 break;
873 case META_INTERSECTCLIPRECT:
874 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
875 *(mr->rdParm + 1), *(mr->rdParm) );
876 break;
878 case META_ARC:
879 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
880 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
881 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
882 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
883 break;
885 case META_ELLIPSE:
886 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
887 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
888 break;
890 case META_FLOODFILL:
891 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
893 break;
895 case META_PIE:
896 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
897 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
898 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
899 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
900 break;
902 case META_RECTANGLE:
903 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
904 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
905 break;
907 case META_ROUNDRECT:
908 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
909 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
910 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
911 break;
913 case META_PATBLT:
914 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
915 *(mr->rdParm + 3), *(mr->rdParm + 2),
916 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
917 break;
919 case META_SAVEDC:
920 SaveDC(hdc);
921 break;
923 case META_SETPIXEL:
924 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
925 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
926 break;
928 case META_OFFSETCLIPRGN:
929 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
930 break;
932 case META_TEXTOUT:
933 s1 = *(mr->rdParm);
934 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
935 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
936 (char *)(mr->rdParm + 1), s1);
937 break;
939 case META_POLYGON:
940 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
941 break;
943 case META_POLYPOLYGON:
944 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
945 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
946 break;
948 case META_POLYLINE:
949 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
950 break;
952 case META_RESTOREDC:
953 RestoreDC(hdc, (INT16)*(mr->rdParm));
954 break;
956 case META_SELECTOBJECT:
957 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
958 break;
960 case META_CHORD:
961 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
962 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
963 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
964 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
965 break;
967 case META_CREATEPATTERNBRUSH:
968 switch (*(mr->rdParm))
970 case BS_PATTERN:
971 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
972 MF_AddHandle(ht, nHandles,
973 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
974 infohdr->biHeight,
975 infohdr->biPlanes,
976 infohdr->biBitCount,
977 (LPSTR)(mr->rdParm +
978 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
979 break;
981 case BS_DIBPATTERN:
982 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
983 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
984 ptr = GlobalLock16(hndl);
985 memcpy(ptr, mr->rdParm + 2, s1);
986 GlobalUnlock16(hndl);
987 MF_AddHandle(ht, nHandles,
988 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
989 GlobalFree16(hndl);
990 break;
992 default:
993 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
994 mr->rdParm[0]);
995 break;
997 break;
999 case META_CREATEPENINDIRECT:
1000 MF_AddHandle(ht, nHandles,
1001 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1002 break;
1004 case META_CREATEFONTINDIRECT:
1005 MF_AddHandle(ht, nHandles,
1006 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1007 break;
1009 case META_CREATEBRUSHINDIRECT:
1010 MF_AddHandle(ht, nHandles,
1011 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1012 break;
1014 case META_CREATEPALETTE:
1015 MF_AddHandle(ht, nHandles,
1016 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1017 break;
1019 case META_SETTEXTALIGN:
1020 SetTextAlign16(hdc, *(mr->rdParm));
1021 break;
1023 case META_SELECTPALETTE:
1024 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1025 *(mr->rdParm));
1026 break;
1028 case META_SETMAPPERFLAGS:
1029 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1030 break;
1032 case META_REALIZEPALETTE:
1033 GDIRealizePalette16(hdc);
1034 break;
1036 case META_ESCAPE:
1037 FIXME("META_ESCAPE unimplemented.\n");
1038 break;
1040 case META_EXTTEXTOUT:
1041 MF_Play_MetaExtTextOut( hdc, mr );
1042 break;
1044 case META_STRETCHDIB:
1046 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1047 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1048 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1049 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1050 mr->rdParm[4],mr->rdParm[3],bits,info,
1051 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1053 break;
1055 case META_DIBSTRETCHBLT:
1057 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1058 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1059 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1060 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1061 mr->rdParm[3],mr->rdParm[2],bits,info,
1062 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1064 break;
1066 case META_STRETCHBLT:
1068 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1069 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1070 mr->rdParm[11], /*Height*/
1071 mr->rdParm[13], /*Planes*/
1072 mr->rdParm[14], /*BitsPixel*/
1073 (LPSTR)&mr->rdParm[15]); /*bits*/
1074 SelectObject(hdcSrc,hbitmap);
1075 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1076 mr->rdParm[7],mr->rdParm[6],
1077 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1078 mr->rdParm[3],mr->rdParm[2],
1079 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1080 DeleteDC(hdcSrc);
1082 break;
1084 case META_BITBLT:
1086 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1087 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1088 mr->rdParm[8]/*Height*/,
1089 mr->rdParm[10]/*Planes*/,
1090 mr->rdParm[11]/*BitsPixel*/,
1091 (LPSTR)&mr->rdParm[12]/*bits*/);
1092 SelectObject(hdcSrc,hbitmap);
1093 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1094 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1095 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1096 MAKELONG(0,mr->rdParm[0]));
1097 DeleteDC(hdcSrc);
1099 break;
1101 case META_CREATEREGION:
1103 HRGN hrgn = CreateRectRgn(0,0,0,0);
1105 MF_Play_MetaCreateRegion(mr, hrgn);
1106 MF_AddHandle(ht, nHandles, hrgn);
1108 break;
1110 case META_FILLREGION:
1111 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1112 *(ht->objectHandle + *(mr->rdParm)));
1113 break;
1115 case META_FRAMEREGION:
1116 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1117 *(ht->objectHandle + *(mr->rdParm+2)),
1118 *(mr->rdParm+1), *(mr->rdParm));
1119 break;
1121 case META_INVERTREGION:
1122 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1123 break;
1125 case META_PAINTREGION:
1126 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1127 break;
1129 case META_SELECTCLIPREGION:
1130 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1131 break;
1133 case META_DIBCREATEPATTERNBRUSH:
1134 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1135 but there's no difference */
1137 TRACE("%d\n",*(mr->rdParm));
1138 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1139 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1140 ptr = GlobalLock16(hndl);
1141 memcpy(ptr, mr->rdParm + 2, s1);
1142 GlobalUnlock16(hndl);
1143 MF_AddHandle(ht, nHandles,
1144 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1145 GlobalFree16(hndl);
1146 break;
1148 case META_DIBBITBLT:
1149 /* In practice I've found that there are two layouts for
1150 META_DIBBITBLT, one (the first here) is the usual one when a src
1151 dc is actually passed to it, the second occurs when the src dc is
1152 passed in as NULL to the creating BitBlt. As the second case has
1153 no dib, a size check will suffice to distinguish.
1155 Caolan.McNamara@ul.ie */
1157 if (mr->rdSize > 12) {
1158 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1159 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1161 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1162 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1163 mr->rdParm[5], mr->rdParm[4], bits, info,
1164 DIB_RGB_COLORS,
1165 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1166 } else { /* equivalent to a PatBlt */
1167 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1168 mr->rdParm[6], mr->rdParm[5],
1169 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1171 break;
1173 case META_SETTEXTCHAREXTRA:
1174 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1175 break;
1177 case META_SETTEXTJUSTIFICATION:
1178 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1179 break;
1181 case META_EXTFLOODFILL:
1182 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1183 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1184 *(mr->rdParm));
1185 break;
1187 case META_SETDIBTODEV:
1189 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1190 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1191 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1192 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1193 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1194 mr->rdParm[2], mr->rdParm[1], bits, info,
1195 mr->rdParm[0]);
1196 break;
1199 #define META_UNIMP(x) case x: \
1200 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1201 break;
1202 META_UNIMP(META_DRAWTEXT)
1203 META_UNIMP(META_ANIMATEPALETTE)
1204 META_UNIMP(META_SETPALENTRIES)
1205 META_UNIMP(META_RESIZEPALETTE)
1206 META_UNIMP(META_RESETDC)
1207 META_UNIMP(META_STARTDOC)
1208 META_UNIMP(META_STARTPAGE)
1209 META_UNIMP(META_ENDPAGE)
1210 META_UNIMP(META_ABORTDOC)
1211 META_UNIMP(META_ENDDOC)
1212 META_UNIMP(META_CREATEBRUSH)
1213 META_UNIMP(META_CREATEBITMAPINDIRECT)
1214 META_UNIMP(META_CREATEBITMAP)
1215 #undef META_UNIMP
1217 default:
1218 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1219 mr->rdFunction);
1223 /******************************************************************
1224 * PlayMetaFileRecord (GDI32.@)
1226 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1227 METARECORD *metarecord, UINT handles )
1229 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1230 handles*sizeof(HANDLETABLE16));
1231 unsigned int i = 0;
1232 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1233 handles);
1234 for (i=0; i<handles; i++)
1235 ht->objectHandle[i] = handletable->objectHandle[i];
1236 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1237 for (i=0; i<handles; i++)
1238 handletable->objectHandle[i] = ht->objectHandle[i];
1239 GlobalFree((HGLOBAL)ht);
1240 return TRUE;
1243 /******************************************************************
1244 * GetMetaFileBits (GDI.159)
1246 * Trade in a metafile object handle for a handle to the metafile memory.
1250 HGLOBAL16 WINAPI GetMetaFileBits16(
1251 HMETAFILE16 hmf /* [in] metafile handle */
1254 TRACE("hMem out: %04x\n", hmf);
1255 return hmf;
1258 /******************************************************************
1259 * SetMetaFileBits (GDI.160)
1261 * Trade in a metafile memory handle for a handle to a metafile object.
1262 * The memory region should hold a proper metafile, otherwise
1263 * problems will occur when it is used. Validity of the memory is not
1264 * checked. The function is essentially just the identity function.
1266 HMETAFILE16 WINAPI SetMetaFileBits16(
1267 HGLOBAL16 hMem
1268 /* [in] handle to a memory region holding a metafile */
1271 TRACE("hmf out: %04x\n", hMem);
1273 return hMem;
1276 /******************************************************************
1277 * SetMetaFileBitsBetter (GDI.196)
1279 * Trade in a metafile memory handle for a handle to a metafile object,
1280 * making a cursory check (using IsValidMetaFile()) that the memory
1281 * handle points to a valid metafile.
1283 * RETURNS
1284 * Handle to a metafile on success, NULL on failure..
1286 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1288 if( IsValidMetaFile16( hMeta ) )
1289 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1290 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1291 return (HMETAFILE16)0;
1294 /******************************************************************
1295 * SetMetaFileBitsEx (GDI32.@)
1297 * Create a metafile from raw data. No checking of the data is performed.
1298 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1300 HMETAFILE WINAPI SetMetaFileBitsEx(
1301 UINT size, /* [in] size of metafile, in bytes */
1302 const BYTE *lpData /* [in] pointer to metafile data */
1305 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1306 if (!mh) return 0;
1307 memcpy(mh, lpData, size);
1308 return MF_Create_HMETAFILE(mh);
1311 /*****************************************************************
1312 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1314 * Copies the data from metafile _hmf_ into the buffer _buf_.
1315 * If _buf_ is zero, returns size of buffer required. Otherwise,
1316 * returns number of bytes copied.
1318 UINT WINAPI GetMetaFileBitsEx(
1319 HMETAFILE hmf, /* [in] metafile */
1320 UINT nSize, /* [in] size of buf */
1321 LPVOID buf /* [out] buffer to receive raw metafile data */
1323 METAHEADER *mh = MF_GetMetaHeader(hmf);
1324 UINT mfSize;
1326 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1327 if (!mh) return 0; /* FIXME: error code */
1328 if(mh->mtType == METAFILE_DISK)
1329 FIXME("Disk-based metafile?\n");
1330 mfSize = mh->mtSize * 2;
1331 if (!buf) {
1332 TRACE("returning size %d\n", mfSize);
1333 return mfSize;
1335 if(mfSize > nSize) mfSize = nSize;
1336 memmove(buf, mh, mfSize);
1337 return mfSize;
1340 /******************************************************************
1341 * GetWinMetaFileBits [GDI32.@]
1343 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1344 UINT cbBuffer, LPBYTE lpbBuffer,
1345 INT fnMapMode, HDC hdcRef)
1347 FIXME("(%d,%d,%p,%d,%d): stub\n",
1348 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1349 return 0;
1352 /******************************************************************
1353 * MF_Play_MetaCreateRegion
1355 * Handles META_CREATEREGION for PlayMetaFileRecord().
1359 * The layout of the record looks something like this:
1361 * rdParm meaning
1362 * 0 Always 0?
1363 * 1 Always 6?
1364 * 2 Looks like a handle? - not constant
1365 * 3 0 or 1 ??
1366 * 4 Total number of bytes
1367 * 5 No. of separate bands = n [see below]
1368 * 6 Largest number of x co-ords in a band
1369 * 7-10 Bounding box x1 y1 x2 y2
1370 * 11-... n bands
1372 * Regions are divided into bands that are uniform in the
1373 * y-direction. Each band consists of pairs of on/off x-coords and is
1374 * written as
1375 * m y0 y1 x1 x2 x3 ... xm m
1376 * into successive rdParm[]s.
1378 * This is probably just a dump of the internal RGNOBJ?
1380 * HDMD - 18/12/97
1384 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1386 WORD band, pair;
1387 WORD *start, *end;
1388 INT16 y0, y1;
1389 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1391 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1392 band++, start = end + 1) {
1393 if(*start / 2 != (*start + 1) / 2) {
1394 WARN("Delimiter not even.\n");
1395 DeleteObject( hrgn2 );
1396 return FALSE;
1399 end = start + *start + 3;
1400 if(end > (WORD *)mr + mr->rdSize) {
1401 WARN("End points outside record.\n");
1402 DeleteObject( hrgn2 );
1403 return FALSE;
1406 if(*start != *end) {
1407 WARN("Mismatched delimiters.\n");
1408 DeleteObject( hrgn2 );
1409 return FALSE;
1412 y0 = *(INT16 *)(start + 1);
1413 y1 = *(INT16 *)(start + 2);
1414 for(pair = 0; pair < *start / 2; pair++) {
1415 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1416 *(INT16 *)(start + 4 + 2*pair), y1 );
1417 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1420 DeleteObject( hrgn2 );
1421 return TRUE;
1425 /******************************************************************
1426 * MF_Play_MetaExtTextOut
1428 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1431 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1433 LPINT16 dxx;
1434 LPSTR sot;
1435 DWORD len;
1436 WORD s1;
1438 s1 = mr->rdParm[2]; /* String length */
1439 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1440 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1441 /* rec len without dx array */
1443 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1444 if (mr->rdParm[3])
1445 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1447 if (mr->rdSize == len / 2)
1448 dxx = NULL; /* determine if array present */
1449 else
1450 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1451 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1452 else {
1453 TRACE("%s len: %ld\n", sot, mr->rdSize);
1454 WARN(
1455 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1456 len, s1, mr->rdSize, mr->rdParm[3]);
1457 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1459 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1460 mr->rdParm[0], /* Y position */
1461 mr->rdParm[3], /* options */
1462 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1463 /* rectangle */
1464 sot, /* string */
1465 s1, dxx); /* length, dx array */
1466 if (dxx)
1467 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1468 return TRUE;