Fixed some issues found by winapi_check.
[wine.git] / objects / metafile.c
blobdfa5e300c153f7cc2cbeffe885c5120b144fec58
1 /*
2 * Metafile functions
4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 */
9 /*
10 * These functions are primarily involved with metafile playback or anything
11 * that touches a HMETAFILE.
12 * For recording of metafiles look in graphics/metafiledrv/
14 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
15 * global memory handles so these cannot be interchanged.
17 * Memory-based metafiles are just stored as a continuous block of memory with
18 * a METAHEADER at the head with METARECORDs appended to it. mtType is
19 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
20 * disk-based metafile - even mtType is METAFILE_MEMORY.
21 * 16bit HMETAFILE16s are global handles to this block
22 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
23 * the memory.
24 * Disk-based metafiles are rather different. HMETAFILE16s point to a
25 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
26 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27 * more 0, then 2 which may be a time stamp of the file and then the path of
28 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
30 * HDMD - 14/4/1999
31 */
33 #include "config.h"
35 #include <string.h>
36 #include <fcntl.h>
38 #include "wine/winbase16.h"
39 #include "wine/wingdi16.h"
40 #include "bitmap.h"
41 #include "global.h"
42 #include "metafile.h"
44 #include "debugtools.h"
46 DEFAULT_DEBUG_CHANNEL(metafile);
48 #include "pshpack1.h"
49 typedef struct
51 DWORD dw1, dw2, dw3;
52 WORD w4;
53 CHAR filename[0x100];
54 } METAHEADERDISK;
55 #include "poppack.h"
57 #define MFHEADERSIZE (sizeof(METAHEADER))
58 #define MFVERSION 0x300
60 /* ### start build ### */
61 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
62 /* ### stop build ### */
64 /******************************************************************
65 * MF_AddHandle
67 * Add a handle to an external handle table and return the index
69 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
71 int i;
73 for (i = 0; i < htlen; i++)
75 if (*(ht->objectHandle + i) == 0)
77 *(ht->objectHandle + i) = hobj;
78 return i;
81 return -1;
85 /******************************************************************
86 * MF_Create_HMETATFILE
88 * Creates a (32 bit) HMETAFILE object from a METAHEADER
90 * HMETAFILEs are GDI objects.
92 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
94 HMETAFILE hmf = 0;
95 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
96 if (metaObj)
98 metaObj->mh = mh;
99 GDI_ReleaseObj( hmf );
101 return hmf;
104 /******************************************************************
105 * MF_Create_HMETATFILE16
107 * Creates a HMETAFILE16 object from a METAHEADER
109 * HMETAFILE16s are Global memory handles.
111 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
113 HMETAFILE16 hmf;
114 DWORD size = mh->mtSize * sizeof(WORD);
116 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
117 if(hmf)
119 METAHEADER *mh_dest = GlobalLock16(hmf);
120 memcpy(mh_dest, mh, size);
121 GlobalUnlock16(hmf);
123 HeapFree(GetProcessHeap(), 0, mh);
124 return hmf;
127 /******************************************************************
128 * MF_GetMetaHeader
130 * Returns ptr to METAHEADER associated with HMETAFILE
132 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
134 METAHEADER *ret = NULL;
135 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
136 if (metaObj)
138 ret = metaObj->mh;
139 GDI_ReleaseObj( hmf );
141 return ret;
144 /******************************************************************
145 * MF_GetMetaHeader16
147 * Returns ptr to METAHEADER associated with HMETAFILE16
148 * Should be followed by call to MF_ReleaseMetaHeader16
150 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
152 return GlobalLock16(hmf);
155 /******************************************************************
156 * MF_ReleaseMetaHeader16
158 * Releases METAHEADER associated with HMETAFILE16
160 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
162 return GlobalUnlock16( hmf );
166 /******************************************************************
167 * DeleteMetaFile (GDI.127)
169 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
171 return !GlobalFree16( hmf );
174 /******************************************************************
175 * DeleteMetaFile (GDI32.@)
177 * Delete a memory-based metafile.
180 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
182 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
183 if (!metaObj) return FALSE;
184 HeapFree( GetProcessHeap(), 0, metaObj->mh );
185 GDI_FreeObject( hmf, metaObj );
186 return TRUE;
189 /******************************************************************
190 * MF_ReadMetaFile
192 * Returns a pointer to a memory based METAHEADER read in from file HFILE
195 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
197 METAHEADER *mh;
198 DWORD BytesRead, size;
200 size = sizeof(METAHEADER);
201 mh = HeapAlloc( GetProcessHeap(), 0, size );
202 if(!mh) return NULL;
203 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
204 BytesRead != size) {
205 HeapFree( GetProcessHeap(), 0, mh );
206 return NULL;
208 size = mh->mtSize * 2;
209 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
210 if(!mh) return NULL;
211 size -= sizeof(METAHEADER);
212 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
213 NULL) == 0 ||
214 BytesRead != size) {
215 HeapFree( GetProcessHeap(), 0, mh );
216 return NULL;
219 if (mh->mtType != METAFILE_MEMORY) {
220 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
221 mh->mtType = METAFILE_MEMORY;
223 return mh;
226 /******************************************************************
227 * GetMetaFile (GDI.124)
229 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
231 METAHEADER *mh;
232 HANDLE hFile;
234 TRACE("%s\n", lpFilename);
236 if(!lpFilename)
237 return 0;
239 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
240 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
241 return 0;
243 mh = MF_ReadMetaFile(hFile);
244 CloseHandle(hFile);
245 if(!mh) return 0;
246 return MF_Create_HMETAFILE16( mh );
249 /******************************************************************
250 * GetMetaFileA (GDI32.@)
252 * Read a metafile from a file. Returns handle to a memory-based metafile.
254 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
256 METAHEADER *mh;
257 HANDLE hFile;
259 TRACE("%s\n", lpFilename);
261 if(!lpFilename)
262 return 0;
264 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
265 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
266 return 0;
268 mh = MF_ReadMetaFile(hFile);
269 CloseHandle(hFile);
270 if(!mh) return 0;
271 return MF_Create_HMETAFILE( mh );
276 /******************************************************************
277 * GetMetaFileW (GDI32.@)
279 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
281 METAHEADER *mh;
282 HANDLE hFile;
284 TRACE("%s\n", debugstr_w(lpFilename));
286 if(!lpFilename)
287 return 0;
289 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
290 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
291 return 0;
293 mh = MF_ReadMetaFile(hFile);
294 CloseHandle(hFile);
295 if(!mh) return 0;
296 return MF_Create_HMETAFILE( mh );
300 /******************************************************************
301 * MF_LoadDiskBasedMetaFile
303 * Creates a new memory-based metafile from a disk-based one.
305 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
307 METAHEADERDISK *mhd;
308 HANDLE hfile;
309 METAHEADER *mh2;
311 if(mh->mtType != METAFILE_DISK) {
312 ERR("Not a disk based metafile\n");
313 return NULL;
315 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
317 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
318 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
319 WARN("Can't open file of disk based metafile\n");
320 return NULL;
322 mh2 = MF_ReadMetaFile(hfile);
323 CloseHandle(hfile);
324 return mh2;
327 /******************************************************************
328 * MF_CreateMetaHeaderDisk
330 * Take a memory based METAHEADER and change it to a disk based METAHEADER
331 * assosiated with filename. Note: Trashes contents of old one.
333 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
335 METAHEADERDISK *mhd;
336 DWORD size;
338 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
339 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
340 mh->mtType = METAFILE_DISK;
341 size = HeapSize( GetProcessHeap(), 0, mh );
342 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
343 strcpy(mhd->filename, filename);
344 return mh;
347 /******************************************************************
348 * CopyMetaFile (GDI.151)
350 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
352 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
353 METAHEADER *mh2 = NULL;
354 HANDLE hFile;
356 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
358 if(!mh) return 0;
360 if(mh->mtType == METAFILE_DISK)
361 mh2 = MF_LoadDiskBasedMetaFile(mh);
362 else {
363 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
364 memcpy( mh2, mh, mh->mtSize * 2 );
366 MF_ReleaseMetaHeader16( hSrcMetaFile );
368 if(lpFilename) { /* disk based metafile */
369 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
370 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
371 HeapFree( GetProcessHeap(), 0, mh2 );
372 return 0;
374 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
375 CloseHandle(hFile);
376 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
379 return MF_Create_HMETAFILE16( mh2 );
383 /******************************************************************
384 * CopyMetaFileA (GDI32.@)
386 * Copies the metafile corresponding to hSrcMetaFile to either
387 * a disk file, if a filename is given, or to a new memory based
388 * metafile, if lpFileName is NULL.
390 * RETURNS
392 * Handle to metafile copy on success, NULL on failure.
394 * BUGS
396 * Copying to disk returns NULL even if successful.
398 HMETAFILE WINAPI CopyMetaFileA(
399 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
400 LPCSTR lpFilename /* [in] filename if copying to a file */
402 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
403 METAHEADER *mh2 = NULL;
404 HANDLE hFile;
406 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
408 if(!mh) return 0;
410 if(mh->mtType == METAFILE_DISK)
411 mh2 = MF_LoadDiskBasedMetaFile(mh);
412 else {
413 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
414 memcpy( mh2, mh, mh->mtSize * 2 );
417 if(lpFilename) { /* disk based metafile */
418 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
419 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
420 HeapFree( GetProcessHeap(), 0, mh2 );
421 return 0;
423 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
424 CloseHandle(hFile);
425 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
428 return MF_Create_HMETAFILE( mh2 );
432 /******************************************************************
433 * CopyMetaFileW (GDI32.@)
435 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
436 LPCWSTR lpFilename )
438 HMETAFILE ret = 0;
439 DWORD len = WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, NULL, 0, NULL, NULL );
440 LPSTR p = HeapAlloc( GetProcessHeap(), 0, len );
442 if (p)
444 WideCharToMultiByte( CP_ACP, 0, lpFilename, -1, p, len, NULL, NULL );
445 ret = CopyMetaFileA( hSrcMetaFile, p );
446 HeapFree( GetProcessHeap(), 0, p );
448 return ret;
452 /******************************************************************
453 * IsValidMetaFile (GDI.410)
455 * Attempts to check if a given metafile is correctly formatted.
456 * Currently, the only things verified are several properties of the
457 * header.
459 * RETURNS
460 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
462 * BUGS
463 * This is not exactly what windows does, see _Undocumented_Windows_
464 * for details.
466 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
468 BOOL16 res=FALSE;
469 METAHEADER *mh = MF_GetMetaHeader16(hmf);
470 if (mh) {
471 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
472 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
473 if (mh->mtVersion == MFVERSION)
474 res=TRUE;
475 MF_ReleaseMetaHeader16(hmf);
477 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
478 return res;
482 /*******************************************************************
483 * MF_PlayMetaFile
485 * Helper for PlayMetaFile
487 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
490 METARECORD *mr;
491 HANDLETABLE16 *ht;
492 unsigned int offset = 0;
493 WORD i;
494 HPEN hPen;
495 HBRUSH hBrush;
496 HFONT hFont;
497 BOOL loaded = FALSE;
499 if (!mh) return FALSE;
500 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
501 mh = MF_LoadDiskBasedMetaFile(mh);
502 if(!mh) return FALSE;
503 loaded = TRUE;
506 /* save the current pen, brush and font */
507 hPen = GetCurrentObject(hdc, OBJ_PEN);
508 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
509 hFont = GetCurrentObject(hdc, OBJ_FONT);
511 /* create the handle table */
512 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
513 sizeof(HANDLETABLE16) * mh->mtNoObjects);
514 if(!ht) return FALSE;
516 /* loop through metafile playing records */
517 offset = mh->mtHeaderSize * 2;
518 while (offset < mh->mtSize * 2)
520 mr = (METARECORD *)((char *)mh + offset);
521 TRACE("offset=%04x,size=%08lx\n",
522 offset, mr->rdSize);
523 if (!mr->rdSize) {
524 TRACE(
525 "Entry got size 0 at offset %d, total mf length is %ld\n",
526 offset,mh->mtSize*2);
527 break; /* would loop endlessly otherwise */
529 offset += mr->rdSize * 2;
530 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
533 SelectObject(hdc, hBrush);
534 SelectObject(hdc, hPen);
535 SelectObject(hdc, hFont);
537 /* free objects in handle table */
538 for(i = 0; i < mh->mtNoObjects; i++)
539 if(*(ht->objectHandle + i) != 0)
540 DeleteObject(*(ht->objectHandle + i));
542 /* free handle table */
543 HeapFree( GetProcessHeap(), 0, ht );
544 if(loaded)
545 HeapFree( GetProcessHeap(), 0, mh );
546 return TRUE;
549 /******************************************************************
550 * PlayMetaFile (GDI.123)
553 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
555 BOOL16 ret;
556 METAHEADER *mh = MF_GetMetaHeader16( hmf );
557 ret = MF_PlayMetaFile( hdc, mh );
558 MF_ReleaseMetaHeader16( hmf );
559 return ret;
562 /******************************************************************
563 * PlayMetaFile (GDI32.@)
565 * Renders the metafile specified by hmf in the DC specified by
566 * hdc. Returns FALSE on failure, TRUE on success.
568 BOOL WINAPI PlayMetaFile(
569 HDC hdc, /* [in] handle of DC to render in */
570 HMETAFILE hmf /* [in] handle of metafile to render */
573 METAHEADER *mh = MF_GetMetaHeader( hmf );
574 return MF_PlayMetaFile( hdc, mh );
578 /******************************************************************
579 * EnumMetaFile (GDI.175)
582 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
583 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
585 METAHEADER *mh = MF_GetMetaHeader16(hmf);
586 METARECORD *mr;
587 HANDLETABLE16 *ht;
588 HGLOBAL16 hHT;
589 SEGPTR spht;
590 unsigned int offset = 0;
591 WORD i, seg;
592 HPEN hPen;
593 HBRUSH hBrush;
594 HFONT hFont;
595 BOOL16 result = TRUE, loaded = FALSE;
597 TRACE("(%04x, %04x, %08lx, %08lx)\n",
598 hdc, hmf, (DWORD)lpEnumFunc, lpData);
601 if(!mh) return FALSE;
602 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
603 mh = MF_LoadDiskBasedMetaFile(mh);
604 if(!mh) return FALSE;
605 loaded = TRUE;
608 /* save the current pen, brush and font */
609 hPen = GetCurrentObject(hdc, OBJ_PEN);
610 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
611 hFont = GetCurrentObject(hdc, OBJ_FONT);
613 /* create the handle table */
615 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
616 sizeof(HANDLETABLE16) * mh->mtNoObjects);
617 spht = K32WOWGlobalLock16(hHT);
619 seg = hmf | 7;
620 offset = mh->mtHeaderSize * 2;
622 /* loop through metafile records */
624 while (offset < (mh->mtSize * 2))
626 mr = (METARECORD *)((char *)mh + offset);
628 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
629 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
630 mh->mtNoObjects, (LONG)lpData ))
632 result = FALSE;
633 break;
637 offset += (mr->rdSize * 2);
640 SelectObject(hdc, hBrush);
641 SelectObject(hdc, hPen);
642 SelectObject(hdc, hFont);
644 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
646 /* free objects in handle table */
647 for(i = 0; i < mh->mtNoObjects; i++)
648 if(*(ht->objectHandle + i) != 0)
649 DeleteObject(*(ht->objectHandle + i));
651 /* free handle table */
652 GlobalFree16(hHT);
653 if(loaded)
654 HeapFree( GetProcessHeap(), 0, mh );
655 MF_ReleaseMetaHeader16(hmf);
656 return result;
659 /******************************************************************
660 * EnumMetaFile (GDI32.@)
662 * Loop through the metafile records in hmf, calling the user-specified
663 * function for each one, stopping when the user's function returns FALSE
664 * (which is considered to be failure)
665 * or when no records are left (which is considered to be success).
667 * RETURNS
668 * TRUE on success, FALSE on failure.
670 * HISTORY
671 * Niels de carpentier, april 1996
673 BOOL WINAPI EnumMetaFile(
674 HDC hdc,
675 HMETAFILE hmf,
676 MFENUMPROC lpEnumFunc,
677 LPARAM lpData
679 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
680 METARECORD *mr;
681 HANDLETABLE *ht;
682 BOOL result = TRUE;
683 int i;
684 unsigned int offset = 0;
685 HPEN hPen;
686 HBRUSH hBrush;
687 HFONT hFont;
689 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
690 if (!mh) return 0;
691 if(mh->mtType == METAFILE_DISK)
693 /* Create a memory-based copy */
694 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
695 mh = mhTemp;
698 /* save the current pen, brush and font */
699 hPen = GetCurrentObject(hdc, OBJ_PEN);
700 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
701 hFont = GetCurrentObject(hdc, OBJ_FONT);
703 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
704 sizeof(HANDLETABLE) * mh->mtNoObjects);
706 /* loop through metafile records */
707 offset = mh->mtHeaderSize * 2;
709 while (offset < (mh->mtSize * 2))
711 mr = (METARECORD *)((char *)mh + offset);
712 TRACE("Calling EnumFunc with record type %x\n",
713 mr->rdFunction);
714 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
716 result = FALSE;
717 break;
720 offset += (mr->rdSize * 2);
723 /* restore pen, brush and font */
724 SelectObject(hdc, hBrush);
725 SelectObject(hdc, hPen);
726 SelectObject(hdc, hFont);
728 /* free objects in handle table */
729 for(i = 0; i < mh->mtNoObjects; i++)
730 if(*(ht->objectHandle + i) != 0)
731 DeleteObject(*(ht->objectHandle + i));
733 /* free handle table */
734 HeapFree( GetProcessHeap(), 0, ht);
735 /* free a copy of metafile */
736 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
737 return result;
740 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
741 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
742 /******************************************************************
743 * PlayMetaFileRecord (GDI.176)
745 * Render a single metafile record specified by *mr in the DC hdc, while
746 * using the handle table *ht, of length nHandles,
747 * to store metafile objects.
749 * BUGS
750 * The following metafile records are unimplemented:
752 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
753 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
754 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
757 void WINAPI PlayMetaFileRecord16(
758 HDC16 hdc, /* [in] DC to render metafile into */
759 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
760 METARECORD *mr, /* [in] pointer to metafile record to render */
761 UINT16 nHandles /* [in] size of handle table */
763 short s1;
764 HANDLE16 hndl;
765 char *ptr;
766 BITMAPINFOHEADER *infohdr;
768 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
769 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
771 switch (mr->rdFunction)
773 case META_EOF:
774 break;
776 case META_DELETEOBJECT:
777 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
778 *(ht->objectHandle + *(mr->rdParm)) = 0;
779 break;
781 case META_SETBKCOLOR:
782 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
783 break;
785 case META_SETBKMODE:
786 SetBkMode16(hdc, *(mr->rdParm));
787 break;
789 case META_SETMAPMODE:
790 SetMapMode16(hdc, *(mr->rdParm));
791 break;
793 case META_SETROP2:
794 SetROP216(hdc, *(mr->rdParm));
795 break;
797 case META_SETRELABS:
798 SetRelAbs16(hdc, *(mr->rdParm));
799 break;
801 case META_SETPOLYFILLMODE:
802 SetPolyFillMode16(hdc, *(mr->rdParm));
803 break;
805 case META_SETSTRETCHBLTMODE:
806 SetStretchBltMode16(hdc, *(mr->rdParm));
807 break;
809 case META_SETTEXTCOLOR:
810 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
811 break;
813 case META_SETWINDOWORG:
814 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
815 break;
817 case META_SETWINDOWEXT:
818 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
819 break;
821 case META_SETVIEWPORTORG:
822 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
823 break;
825 case META_SETVIEWPORTEXT:
826 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
827 break;
829 case META_OFFSETWINDOWORG:
830 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
831 break;
833 case META_SCALEWINDOWEXT:
834 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
835 *(mr->rdParm + 1), *(mr->rdParm));
836 break;
838 case META_OFFSETVIEWPORTORG:
839 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
840 break;
842 case META_SCALEVIEWPORTEXT:
843 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
844 *(mr->rdParm + 1), *(mr->rdParm));
845 break;
847 case META_LINETO:
848 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
849 break;
851 case META_MOVETO:
852 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
853 break;
855 case META_EXCLUDECLIPRECT:
856 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
857 *(mr->rdParm + 1), *(mr->rdParm) );
858 break;
860 case META_INTERSECTCLIPRECT:
861 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
862 *(mr->rdParm + 1), *(mr->rdParm) );
863 break;
865 case META_ARC:
866 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
867 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
868 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
869 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
870 break;
872 case META_ELLIPSE:
873 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
874 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
875 break;
877 case META_FLOODFILL:
878 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
879 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
880 break;
882 case META_PIE:
883 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
884 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
885 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
886 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
887 break;
889 case META_RECTANGLE:
890 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
891 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
892 break;
894 case META_ROUNDRECT:
895 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
896 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
897 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
898 break;
900 case META_PATBLT:
901 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
902 *(mr->rdParm + 3), *(mr->rdParm + 2),
903 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
904 break;
906 case META_SAVEDC:
907 SaveDC(hdc);
908 break;
910 case META_SETPIXEL:
911 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
912 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
913 break;
915 case META_OFFSETCLIPRGN:
916 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
917 break;
919 case META_TEXTOUT:
920 s1 = *(mr->rdParm);
921 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
922 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
923 (char *)(mr->rdParm + 1), s1);
924 break;
926 case META_POLYGON:
927 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
928 break;
930 case META_POLYPOLYGON:
931 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
932 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
933 break;
935 case META_POLYLINE:
936 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
937 break;
939 case META_RESTOREDC:
940 RestoreDC(hdc, (INT16)*(mr->rdParm));
941 break;
943 case META_SELECTOBJECT:
944 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
945 break;
947 case META_CHORD:
948 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
949 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
950 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
951 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
952 break;
954 case META_CREATEPATTERNBRUSH:
955 switch (*(mr->rdParm))
957 case BS_PATTERN:
958 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
959 MF_AddHandle(ht, nHandles,
960 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
961 infohdr->biHeight,
962 infohdr->biPlanes,
963 infohdr->biBitCount,
964 (LPSTR)(mr->rdParm +
965 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
966 break;
968 case BS_DIBPATTERN:
969 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
970 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
971 ptr = GlobalLock16(hndl);
972 memcpy(ptr, mr->rdParm + 2, s1);
973 GlobalUnlock16(hndl);
974 MF_AddHandle(ht, nHandles,
975 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
976 GlobalFree16(hndl);
977 break;
979 default:
980 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
981 mr->rdParm[0]);
982 break;
984 break;
986 case META_CREATEPENINDIRECT:
987 MF_AddHandle(ht, nHandles,
988 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
989 break;
991 case META_CREATEFONTINDIRECT:
992 MF_AddHandle(ht, nHandles,
993 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
994 break;
996 case META_CREATEBRUSHINDIRECT:
997 MF_AddHandle(ht, nHandles,
998 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
999 break;
1001 case META_CREATEPALETTE:
1002 MF_AddHandle(ht, nHandles,
1003 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1004 break;
1006 case META_SETTEXTALIGN:
1007 SetTextAlign16(hdc, *(mr->rdParm));
1008 break;
1010 case META_SELECTPALETTE:
1011 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1012 *(mr->rdParm));
1013 break;
1015 case META_SETMAPPERFLAGS:
1016 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1017 break;
1019 case META_REALIZEPALETTE:
1020 GDIRealizePalette16(hdc);
1021 break;
1023 case META_ESCAPE:
1024 FIXME("META_ESCAPE unimplemented.\n");
1025 break;
1027 case META_EXTTEXTOUT:
1028 MF_Play_MetaExtTextOut( hdc, mr );
1029 break;
1031 case META_STRETCHDIB:
1033 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1034 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1035 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1036 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1037 mr->rdParm[4],mr->rdParm[3],bits,info,
1038 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1040 break;
1042 case META_DIBSTRETCHBLT:
1044 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1045 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1046 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1047 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1048 mr->rdParm[3],mr->rdParm[2],bits,info,
1049 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1051 break;
1053 case META_STRETCHBLT:
1055 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1056 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1057 mr->rdParm[11], /*Height*/
1058 mr->rdParm[13], /*Planes*/
1059 mr->rdParm[14], /*BitsPixel*/
1060 (LPSTR)&mr->rdParm[15]); /*bits*/
1061 SelectObject(hdcSrc,hbitmap);
1062 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1063 mr->rdParm[7],mr->rdParm[6],
1064 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1065 mr->rdParm[3],mr->rdParm[2],
1066 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1067 DeleteDC(hdcSrc);
1069 break;
1071 case META_BITBLT:
1073 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1074 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1075 mr->rdParm[8]/*Height*/,
1076 mr->rdParm[10]/*Planes*/,
1077 mr->rdParm[11]/*BitsPixel*/,
1078 (LPSTR)&mr->rdParm[12]/*bits*/);
1079 SelectObject(hdcSrc,hbitmap);
1080 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1081 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1082 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1083 MAKELONG(0,mr->rdParm[0]));
1084 DeleteDC(hdcSrc);
1086 break;
1088 case META_CREATEREGION:
1090 HRGN hrgn = CreateRectRgn(0,0,0,0);
1092 MF_Play_MetaCreateRegion(mr, hrgn);
1093 MF_AddHandle(ht, nHandles, hrgn);
1095 break;
1097 case META_FILLREGION:
1098 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1099 *(ht->objectHandle + *(mr->rdParm)));
1100 break;
1102 case META_FRAMEREGION:
1103 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1104 *(ht->objectHandle + *(mr->rdParm+2)),
1105 *(mr->rdParm+1), *(mr->rdParm));
1106 break;
1108 case META_INVERTREGION:
1109 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1110 break;
1112 case META_PAINTREGION:
1113 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1114 break;
1116 case META_SELECTCLIPREGION:
1117 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1118 break;
1120 case META_DIBCREATEPATTERNBRUSH:
1121 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1122 but there's no difference */
1124 TRACE("%d\n",*(mr->rdParm));
1125 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1126 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1127 ptr = GlobalLock16(hndl);
1128 memcpy(ptr, mr->rdParm + 2, s1);
1129 GlobalUnlock16(hndl);
1130 MF_AddHandle(ht, nHandles,
1131 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1132 GlobalFree16(hndl);
1133 break;
1135 case META_DIBBITBLT:
1136 /* In practice I've found that there are two layouts for
1137 META_DIBBITBLT, one (the first here) is the usual one when a src
1138 dc is actually passed to it, the second occurs when the src dc is
1139 passed in as NULL to the creating BitBlt. As the second case has
1140 no dib, a size check will suffice to distinguish.
1142 Caolan.McNamara@ul.ie */
1144 if (mr->rdSize > 12) {
1145 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1146 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1148 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1149 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1150 mr->rdParm[5], mr->rdParm[4], bits, info,
1151 DIB_RGB_COLORS,
1152 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1153 } else { /* equivalent to a PatBlt */
1154 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1155 mr->rdParm[6], mr->rdParm[5],
1156 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1158 break;
1160 case META_SETTEXTCHAREXTRA:
1161 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1162 break;
1164 case META_SETTEXTJUSTIFICATION:
1165 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1166 break;
1168 case META_EXTFLOODFILL:
1169 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1170 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1171 *(mr->rdParm));
1172 break;
1174 case META_SETDIBTODEV:
1176 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1177 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1178 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1179 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1180 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1181 mr->rdParm[2], mr->rdParm[1], bits, info,
1182 mr->rdParm[0]);
1183 break;
1186 #define META_UNIMP(x) case x: \
1187 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1188 break;
1189 META_UNIMP(META_DRAWTEXT)
1190 META_UNIMP(META_ANIMATEPALETTE)
1191 META_UNIMP(META_SETPALENTRIES)
1192 META_UNIMP(META_RESIZEPALETTE)
1193 META_UNIMP(META_RESETDC)
1194 META_UNIMP(META_STARTDOC)
1195 META_UNIMP(META_STARTPAGE)
1196 META_UNIMP(META_ENDPAGE)
1197 META_UNIMP(META_ABORTDOC)
1198 META_UNIMP(META_ENDDOC)
1199 META_UNIMP(META_CREATEBRUSH)
1200 META_UNIMP(META_CREATEBITMAPINDIRECT)
1201 META_UNIMP(META_CREATEBITMAP)
1202 #undef META_UNIMP
1204 default:
1205 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1206 mr->rdFunction);
1210 /******************************************************************
1211 * PlayMetaFileRecord (GDI32.@)
1213 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1214 METARECORD *metarecord, UINT handles )
1216 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1217 handles*sizeof(HANDLETABLE16));
1218 unsigned int i = 0;
1219 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1220 handles);
1221 for (i=0; i<handles; i++)
1222 ht->objectHandle[i] = handletable->objectHandle[i];
1223 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1224 for (i=0; i<handles; i++)
1225 handletable->objectHandle[i] = ht->objectHandle[i];
1226 GlobalFree((HGLOBAL)ht);
1227 return TRUE;
1230 /******************************************************************
1231 * GetMetaFileBits (GDI.159)
1233 * Trade in a metafile object handle for a handle to the metafile memory.
1237 HGLOBAL16 WINAPI GetMetaFileBits16(
1238 HMETAFILE16 hmf /* [in] metafile handle */
1241 TRACE("hMem out: %04x\n", hmf);
1242 return hmf;
1245 /******************************************************************
1246 * SetMetaFileBits (GDI.160)
1248 * Trade in a metafile memory handle for a handle to a metafile object.
1249 * The memory region should hold a proper metafile, otherwise
1250 * problems will occur when it is used. Validity of the memory is not
1251 * checked. The function is essentially just the identity function.
1253 HMETAFILE16 WINAPI SetMetaFileBits16(
1254 HGLOBAL16 hMem
1255 /* [in] handle to a memory region holding a metafile */
1258 TRACE("hmf out: %04x\n", hMem);
1260 return hMem;
1263 /******************************************************************
1264 * SetMetaFileBitsBetter (GDI.196)
1266 * Trade in a metafile memory handle for a handle to a metafile object,
1267 * making a cursory check (using IsValidMetaFile()) that the memory
1268 * handle points to a valid metafile.
1270 * RETURNS
1271 * Handle to a metafile on success, NULL on failure..
1273 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1275 if( IsValidMetaFile16( hMeta ) )
1276 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1277 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1278 return (HMETAFILE16)0;
1281 /******************************************************************
1282 * SetMetaFileBitsEx (GDI32.@)
1284 * Create a metafile from raw data. No checking of the data is performed.
1285 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1287 HMETAFILE WINAPI SetMetaFileBitsEx(
1288 UINT size, /* [in] size of metafile, in bytes */
1289 const BYTE *lpData /* [in] pointer to metafile data */
1292 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1293 if (!mh) return 0;
1294 memcpy(mh, lpData, size);
1295 return MF_Create_HMETAFILE(mh);
1298 /*****************************************************************
1299 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1301 * Copies the data from metafile _hmf_ into the buffer _buf_.
1302 * If _buf_ is zero, returns size of buffer required. Otherwise,
1303 * returns number of bytes copied.
1305 UINT WINAPI GetMetaFileBitsEx(
1306 HMETAFILE hmf, /* [in] metafile */
1307 UINT nSize, /* [in] size of buf */
1308 LPVOID buf /* [out] buffer to receive raw metafile data */
1310 METAHEADER *mh = MF_GetMetaHeader(hmf);
1311 UINT mfSize;
1313 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1314 if (!mh) return 0; /* FIXME: error code */
1315 if(mh->mtType == METAFILE_DISK)
1316 FIXME("Disk-based metafile?\n");
1317 mfSize = mh->mtSize * 2;
1318 if (!buf) {
1319 TRACE("returning size %d\n", mfSize);
1320 return mfSize;
1322 if(mfSize > nSize) mfSize = nSize;
1323 memmove(buf, mh, mfSize);
1324 return mfSize;
1327 /******************************************************************
1328 * GetWinMetaFileBits [GDI32.@]
1330 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1331 UINT cbBuffer, LPBYTE lpbBuffer,
1332 INT fnMapMode, HDC hdcRef)
1334 FIXME("(%d,%d,%p,%d,%d): stub\n",
1335 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1336 return 0;
1339 /******************************************************************
1340 * MF_Play_MetaCreateRegion
1342 * Handles META_CREATEREGION for PlayMetaFileRecord().
1346 * The layout of the record looks something like this:
1348 * rdParm meaning
1349 * 0 Always 0?
1350 * 1 Always 6?
1351 * 2 Looks like a handle? - not constant
1352 * 3 0 or 1 ??
1353 * 4 Total number of bytes
1354 * 5 No. of separate bands = n [see below]
1355 * 6 Largest number of x co-ords in a band
1356 * 7-10 Bounding box x1 y1 x2 y2
1357 * 11-... n bands
1359 * Regions are divided into bands that are uniform in the
1360 * y-direction. Each band consists of pairs of on/off x-coords and is
1361 * written as
1362 * m y0 y1 x1 x2 x3 ... xm m
1363 * into successive rdParm[]s.
1365 * This is probably just a dump of the internal RGNOBJ?
1367 * HDMD - 18/12/97
1371 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1373 WORD band, pair;
1374 WORD *start, *end;
1375 INT16 y0, y1;
1376 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1378 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1379 band++, start = end + 1) {
1380 if(*start / 2 != (*start + 1) / 2) {
1381 WARN("Delimiter not even.\n");
1382 DeleteObject( hrgn2 );
1383 return FALSE;
1386 end = start + *start + 3;
1387 if(end > (WORD *)mr + mr->rdSize) {
1388 WARN("End points outside record.\n");
1389 DeleteObject( hrgn2 );
1390 return FALSE;
1393 if(*start != *end) {
1394 WARN("Mismatched delimiters.\n");
1395 DeleteObject( hrgn2 );
1396 return FALSE;
1399 y0 = *(INT16 *)(start + 1);
1400 y1 = *(INT16 *)(start + 2);
1401 for(pair = 0; pair < *start / 2; pair++) {
1402 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1403 *(INT16 *)(start + 4 + 2*pair), y1 );
1404 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1407 DeleteObject( hrgn2 );
1408 return TRUE;
1412 /******************************************************************
1413 * MF_Play_MetaExtTextOut
1415 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1418 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1420 LPINT16 dxx;
1421 LPSTR sot;
1422 DWORD len;
1423 WORD s1;
1425 s1 = mr->rdParm[2]; /* String length */
1426 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1427 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1428 /* rec len without dx array */
1430 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1431 if (mr->rdParm[3])
1432 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1434 if (mr->rdSize == len / 2)
1435 dxx = NULL; /* determine if array present */
1436 else
1437 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1438 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1439 else {
1440 TRACE("%s len: %ld\n", sot, mr->rdSize);
1441 WARN(
1442 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1443 len, s1, mr->rdSize, mr->rdParm[3]);
1444 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1446 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1447 mr->rdParm[0], /* Y position */
1448 mr->rdParm[3], /* options */
1449 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1450 /* rectangle */
1451 sot, /* string */
1452 s1, dxx); /* length, dx array */
1453 if (dxx)
1454 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1455 return TRUE;