Don't hold the GDI lock during accesses to the metafile data.
[wine/multimedia.git] / objects / metafile.c
blob614953fd9e5aad893bea961102383861258a66d8
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 "heap.h"
43 #include "metafile.h"
45 #include "debugtools.h"
47 DEFAULT_DEBUG_CHANNEL(metafile);
49 #include "pshpack1.h"
50 typedef struct
52 DWORD dw1, dw2, dw3;
53 WORD w4;
54 CHAR filename[0x100];
55 } METAHEADERDISK;
56 #include "poppack.h"
58 #define MFHEADERSIZE (sizeof(METAHEADER))
59 #define MFVERSION 0x300
61 /******************************************************************
62 * MF_AddHandle
64 * Add a handle to an external handle table and return the index
66 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
68 int i;
70 for (i = 0; i < htlen; i++)
72 if (*(ht->objectHandle + i) == 0)
74 *(ht->objectHandle + i) = hobj;
75 return i;
78 return -1;
82 /******************************************************************
83 * MF_Create_HMETATFILE
85 * Creates a (32 bit) HMETAFILE object from a METAHEADER
87 * HMETAFILEs are GDI objects.
89 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
91 HMETAFILE hmf = 0;
92 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
93 if (metaObj)
95 metaObj->mh = mh;
96 GDI_ReleaseObj( hmf );
98 return hmf;
101 /******************************************************************
102 * MF_Create_HMETATFILE16
104 * Creates a HMETAFILE16 object from a METAHEADER
106 * HMETAFILE16s are Global memory handles.
108 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
110 HMETAFILE16 hmf;
111 DWORD size = mh->mtSize * sizeof(WORD);
113 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
114 if(hmf)
116 METAHEADER *mh_dest = GlobalLock16(hmf);
117 memcpy(mh_dest, mh, size);
118 GlobalUnlock16(hmf);
120 HeapFree(GetProcessHeap(), 0, mh);
121 return hmf;
124 /******************************************************************
125 * MF_GetMetaHeader
127 * Returns ptr to METAHEADER associated with HMETAFILE
129 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
131 METAHEADER *ret = NULL;
132 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
133 if (metaObj)
135 ret = metaObj->mh;
136 GDI_ReleaseObj( hmf );
138 return ret;
141 /******************************************************************
142 * MF_GetMetaHeader16
144 * Returns ptr to METAHEADER associated with HMETAFILE16
145 * Should be followed by call to MF_ReleaseMetaHeader16
147 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
149 return GlobalLock16(hmf);
152 /******************************************************************
153 * MF_ReleaseMetaHeader16
155 * Releases METAHEADER associated with HMETAFILE16
157 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
159 return GlobalUnlock16( hmf );
163 /******************************************************************
164 * DeleteMetaFile (GDI.127)
166 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
168 return !GlobalFree16( hmf );
171 /******************************************************************
172 * DeleteMetaFile (GDI32.@)
174 * Delete a memory-based metafile.
177 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
179 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
180 if (!metaObj) return FALSE;
181 HeapFree( GetProcessHeap(), 0, metaObj->mh );
182 GDI_FreeObject( hmf, metaObj );
183 return TRUE;
186 /******************************************************************
187 * MF_ReadMetaFile
189 * Returns a pointer to a memory based METAHEADER read in from file HFILE
192 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
194 METAHEADER *mh;
195 DWORD BytesRead, size;
197 size = sizeof(METAHEADER);
198 mh = HeapAlloc( GetProcessHeap(), 0, size );
199 if(!mh) return NULL;
200 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
201 BytesRead != size) {
202 HeapFree( GetProcessHeap(), 0, mh );
203 return NULL;
205 size = mh->mtSize * 2;
206 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
207 if(!mh) return NULL;
208 size -= sizeof(METAHEADER);
209 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
210 NULL) == 0 ||
211 BytesRead != size) {
212 HeapFree( GetProcessHeap(), 0, mh );
213 return NULL;
216 if (mh->mtType != METAFILE_MEMORY) {
217 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
218 mh->mtType = METAFILE_MEMORY;
220 return mh;
223 /******************************************************************
224 * GetMetaFile (GDI.124)
226 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
228 METAHEADER *mh;
229 HANDLE hFile;
231 TRACE("%s\n", lpFilename);
233 if(!lpFilename)
234 return 0;
236 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
237 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
238 return 0;
240 mh = MF_ReadMetaFile(hFile);
241 CloseHandle(hFile);
242 if(!mh) return 0;
243 return MF_Create_HMETAFILE16( mh );
246 /******************************************************************
247 * GetMetaFileA (GDI32.@)
249 * Read a metafile from a file. Returns handle to a memory-based metafile.
251 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
253 METAHEADER *mh;
254 HANDLE hFile;
256 TRACE("%s\n", lpFilename);
258 if(!lpFilename)
259 return 0;
261 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
262 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
263 return 0;
265 mh = MF_ReadMetaFile(hFile);
266 CloseHandle(hFile);
267 if(!mh) return 0;
268 return MF_Create_HMETAFILE( mh );
273 /******************************************************************
274 * GetMetaFileW (GDI32.@)
276 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
278 METAHEADER *mh;
279 HANDLE hFile;
281 TRACE("%s\n", debugstr_w(lpFilename));
283 if(!lpFilename)
284 return 0;
286 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
287 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
288 return 0;
290 mh = MF_ReadMetaFile(hFile);
291 CloseHandle(hFile);
292 if(!mh) return 0;
293 return MF_Create_HMETAFILE( mh );
297 /******************************************************************
298 * MF_LoadDiskBasedMetaFile
300 * Creates a new memory-based metafile from a disk-based one.
302 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
304 METAHEADERDISK *mhd;
305 HANDLE hfile;
306 METAHEADER *mh2;
308 if(mh->mtType != METAFILE_DISK) {
309 ERR("Not a disk based metafile\n");
310 return NULL;
312 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
314 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
315 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
316 WARN("Can't open file of disk based metafile\n");
317 return NULL;
319 mh2 = MF_ReadMetaFile(hfile);
320 CloseHandle(hfile);
321 return mh2;
324 /******************************************************************
325 * MF_CreateMetaHeaderDisk
327 * Take a memory based METAHEADER and change it to a disk based METAHEADER
328 * assosiated with filename. Note: Trashes contents of old one.
330 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
332 METAHEADERDISK *mhd;
333 DWORD size;
335 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
336 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
337 mh->mtType = METAFILE_DISK;
338 size = HeapSize( GetProcessHeap(), 0, mh );
339 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
340 strcpy(mhd->filename, filename);
341 return mh;
344 /******************************************************************
345 * CopyMetaFile (GDI.151)
347 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
349 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
350 METAHEADER *mh2 = NULL;
351 HANDLE hFile;
353 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
355 if(!mh) return 0;
357 if(mh->mtType == METAFILE_DISK)
358 mh2 = MF_LoadDiskBasedMetaFile(mh);
359 else {
360 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
361 memcpy( mh2, mh, mh->mtSize * 2 );
363 MF_ReleaseMetaHeader16( hSrcMetaFile );
365 if(lpFilename) { /* disk based metafile */
366 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
367 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
368 HeapFree( GetProcessHeap(), 0, mh2 );
369 return 0;
371 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
372 CloseHandle(hFile);
373 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
376 return MF_Create_HMETAFILE16( mh2 );
380 /******************************************************************
381 * CopyMetaFileA (GDI32.@)
383 * Copies the metafile corresponding to hSrcMetaFile to either
384 * a disk file, if a filename is given, or to a new memory based
385 * metafile, if lpFileName is NULL.
387 * RETURNS
389 * Handle to metafile copy on success, NULL on failure.
391 * BUGS
393 * Copying to disk returns NULL even if successful.
395 HMETAFILE WINAPI CopyMetaFileA(
396 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
397 LPCSTR lpFilename /* [in] filename if copying to a file */
399 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
400 METAHEADER *mh2 = NULL;
401 HANDLE hFile;
403 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
405 if(!mh) return 0;
407 if(mh->mtType == METAFILE_DISK)
408 mh2 = MF_LoadDiskBasedMetaFile(mh);
409 else {
410 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
411 memcpy( mh2, mh, mh->mtSize * 2 );
414 if(lpFilename) { /* disk based metafile */
415 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
416 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
417 HeapFree( GetProcessHeap(), 0, mh2 );
418 return 0;
420 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
421 CloseHandle(hFile);
422 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
425 return MF_Create_HMETAFILE( mh2 );
429 /******************************************************************
430 * CopyMetaFileW (GDI32.@)
432 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
433 LPCWSTR lpFilename )
435 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
436 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
437 HeapFree( GetProcessHeap(), 0, p );
438 return ret;
442 /******************************************************************
443 * IsValidMetaFile (GDI.410)
445 * Attempts to check if a given metafile is correctly formatted.
446 * Currently, the only things verified are several properties of the
447 * header.
449 * RETURNS
450 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
452 * BUGS
453 * This is not exactly what windows does, see _Undocumented_Windows_
454 * for details.
456 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
458 BOOL16 res=FALSE;
459 METAHEADER *mh = MF_GetMetaHeader16(hmf);
460 if (mh) {
461 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
462 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
463 if (mh->mtVersion == MFVERSION)
464 res=TRUE;
465 MF_ReleaseMetaHeader16(hmf);
467 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
468 return res;
472 /*******************************************************************
473 * MF_PlayMetaFile
475 * Helper for PlayMetaFile
477 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
480 METARECORD *mr;
481 HANDLETABLE16 *ht;
482 unsigned int offset = 0;
483 WORD i;
484 HPEN hPen;
485 HBRUSH hBrush;
486 HFONT hFont;
487 BOOL loaded = FALSE;
489 if (!mh) return FALSE;
490 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
491 mh = MF_LoadDiskBasedMetaFile(mh);
492 if(!mh) return FALSE;
493 loaded = TRUE;
496 /* save the current pen, brush and font */
497 hPen = GetCurrentObject(hdc, OBJ_PEN);
498 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
499 hFont = GetCurrentObject(hdc, OBJ_FONT);
501 /* create the handle table */
502 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
503 sizeof(HANDLETABLE16) * mh->mtNoObjects);
504 if(!ht) return FALSE;
506 /* loop through metafile playing records */
507 offset = mh->mtHeaderSize * 2;
508 while (offset < mh->mtSize * 2)
510 mr = (METARECORD *)((char *)mh + offset);
511 TRACE("offset=%04x,size=%08lx\n",
512 offset, mr->rdSize);
513 if (!mr->rdSize) {
514 TRACE(
515 "Entry got size 0 at offset %d, total mf length is %ld\n",
516 offset,mh->mtSize*2);
517 break; /* would loop endlessly otherwise */
519 offset += mr->rdSize * 2;
520 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
523 SelectObject(hdc, hBrush);
524 SelectObject(hdc, hPen);
525 SelectObject(hdc, hFont);
527 /* free objects in handle table */
528 for(i = 0; i < mh->mtNoObjects; i++)
529 if(*(ht->objectHandle + i) != 0)
530 DeleteObject(*(ht->objectHandle + i));
532 /* free handle table */
533 HeapFree( GetProcessHeap(), 0, ht );
534 if(loaded)
535 HeapFree( GetProcessHeap(), 0, mh );
536 return TRUE;
539 /******************************************************************
540 * PlayMetaFile (GDI.123)
543 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
545 BOOL16 ret;
546 METAHEADER *mh = MF_GetMetaHeader16( hmf );
547 ret = MF_PlayMetaFile( hdc, mh );
548 MF_ReleaseMetaHeader16( hmf );
549 return ret;
552 /******************************************************************
553 * PlayMetaFile (GDI32.@)
555 * Renders the metafile specified by hmf in the DC specified by
556 * hdc. Returns FALSE on failure, TRUE on success.
558 BOOL WINAPI PlayMetaFile(
559 HDC hdc, /* [in] handle of DC to render in */
560 HMETAFILE hmf /* [in] handle of metafile to render */
563 METAHEADER *mh = MF_GetMetaHeader( hmf );
564 return MF_PlayMetaFile( hdc, mh );
568 /******************************************************************
569 * EnumMetaFile16 (GDI.175)
572 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
573 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
575 METAHEADER *mh = MF_GetMetaHeader16(hmf);
576 METARECORD *mr;
577 HANDLETABLE16 *ht;
578 HGLOBAL16 hHT;
579 SEGPTR spht;
580 unsigned int offset = 0;
581 WORD i, seg;
582 HPEN hPen;
583 HBRUSH hBrush;
584 HFONT hFont;
585 BOOL16 result = TRUE, loaded = FALSE;
587 TRACE("(%04x, %04x, %08lx, %08lx)\n",
588 hdc, hmf, (DWORD)lpEnumFunc, lpData);
591 if(!mh) return FALSE;
592 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
593 mh = MF_LoadDiskBasedMetaFile(mh);
594 if(!mh) return FALSE;
595 loaded = TRUE;
598 /* save the current pen, brush and font */
599 hPen = GetCurrentObject(hdc, OBJ_PEN);
600 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
601 hFont = GetCurrentObject(hdc, OBJ_FONT);
603 /* create the handle table */
605 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
606 sizeof(HANDLETABLE16) * mh->mtNoObjects);
607 spht = K32WOWGlobalLock16(hHT);
609 seg = hmf | 7;
610 offset = mh->mtHeaderSize * 2;
612 /* loop through metafile records */
614 while (offset < (mh->mtSize * 2))
616 mr = (METARECORD *)((char *)mh + offset);
617 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
618 (METARECORD *)MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
619 mh->mtNoObjects, (LONG)lpData ))
621 result = FALSE;
622 break;
626 offset += (mr->rdSize * 2);
629 SelectObject(hdc, hBrush);
630 SelectObject(hdc, hPen);
631 SelectObject(hdc, hFont);
633 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
635 /* free objects in handle table */
636 for(i = 0; i < mh->mtNoObjects; i++)
637 if(*(ht->objectHandle + i) != 0)
638 DeleteObject(*(ht->objectHandle + i));
640 /* free handle table */
641 GlobalFree16(hHT);
642 if(loaded)
643 HeapFree( GetProcessHeap(), 0, mh );
644 MF_ReleaseMetaHeader16(hmf);
645 return result;
648 /******************************************************************
649 * EnumMetaFile (GDI32.@)
651 * Loop through the metafile records in hmf, calling the user-specified
652 * function for each one, stopping when the user's function returns FALSE
653 * (which is considered to be failure)
654 * or when no records are left (which is considered to be success).
656 * RETURNS
657 * TRUE on success, FALSE on failure.
659 * HISTORY
660 * Niels de carpentier, april 1996
662 BOOL WINAPI EnumMetaFile(
663 HDC hdc,
664 HMETAFILE hmf,
665 MFENUMPROC lpEnumFunc,
666 LPARAM lpData
668 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
669 METARECORD *mr;
670 HANDLETABLE *ht;
671 BOOL result = TRUE;
672 int i;
673 unsigned int offset = 0;
674 HPEN hPen;
675 HBRUSH hBrush;
676 HFONT hFont;
678 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
679 if (!mh) return 0;
680 if(mh->mtType == METAFILE_DISK)
682 /* Create a memory-based copy */
683 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
684 mh = mhTemp;
687 /* save the current pen, brush and font */
688 hPen = GetCurrentObject(hdc, OBJ_PEN);
689 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
690 hFont = GetCurrentObject(hdc, OBJ_FONT);
692 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
693 sizeof(HANDLETABLE) * mh->mtNoObjects);
695 /* loop through metafile records */
696 offset = mh->mtHeaderSize * 2;
698 while (offset < (mh->mtSize * 2))
700 mr = (METARECORD *)((char *)mh + offset);
701 TRACE("Calling EnumFunc with record type %x\n",
702 mr->rdFunction);
703 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
705 result = FALSE;
706 break;
709 offset += (mr->rdSize * 2);
712 /* restore pen, brush and font */
713 SelectObject(hdc, hBrush);
714 SelectObject(hdc, hPen);
715 SelectObject(hdc, hFont);
717 /* free objects in handle table */
718 for(i = 0; i < mh->mtNoObjects; i++)
719 if(*(ht->objectHandle + i) != 0)
720 DeleteObject(*(ht->objectHandle + i));
722 /* free handle table */
723 HeapFree( GetProcessHeap(), 0, ht);
724 /* free a copy of metafile */
725 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
726 return result;
729 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
730 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
731 /******************************************************************
732 * PlayMetaFileRecord (GDI.176)
734 * Render a single metafile record specified by *mr in the DC hdc, while
735 * using the handle table *ht, of length nHandles,
736 * to store metafile objects.
738 * BUGS
739 * The following metafile records are unimplemented:
741 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
742 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
743 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
746 void WINAPI PlayMetaFileRecord16(
747 HDC16 hdc, /* [in] DC to render metafile into */
748 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
749 METARECORD *mr, /* [in] pointer to metafile record to render */
750 UINT16 nHandles /* [in] size of handle table */
752 short s1;
753 HANDLE16 hndl;
754 char *ptr;
755 BITMAPINFOHEADER *infohdr;
757 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
758 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
760 switch (mr->rdFunction)
762 case META_EOF:
763 break;
765 case META_DELETEOBJECT:
766 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
767 *(ht->objectHandle + *(mr->rdParm)) = 0;
768 break;
770 case META_SETBKCOLOR:
771 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
772 break;
774 case META_SETBKMODE:
775 SetBkMode16(hdc, *(mr->rdParm));
776 break;
778 case META_SETMAPMODE:
779 SetMapMode16(hdc, *(mr->rdParm));
780 break;
782 case META_SETROP2:
783 SetROP216(hdc, *(mr->rdParm));
784 break;
786 case META_SETRELABS:
787 SetRelAbs16(hdc, *(mr->rdParm));
788 break;
790 case META_SETPOLYFILLMODE:
791 SetPolyFillMode16(hdc, *(mr->rdParm));
792 break;
794 case META_SETSTRETCHBLTMODE:
795 SetStretchBltMode16(hdc, *(mr->rdParm));
796 break;
798 case META_SETTEXTCOLOR:
799 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
800 break;
802 case META_SETWINDOWORG:
803 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
804 break;
806 case META_SETWINDOWEXT:
807 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
808 break;
810 case META_SETVIEWPORTORG:
811 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
812 break;
814 case META_SETVIEWPORTEXT:
815 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
816 break;
818 case META_OFFSETWINDOWORG:
819 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
820 break;
822 case META_SCALEWINDOWEXT:
823 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
824 *(mr->rdParm + 1), *(mr->rdParm));
825 break;
827 case META_OFFSETVIEWPORTORG:
828 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
829 break;
831 case META_SCALEVIEWPORTEXT:
832 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
833 *(mr->rdParm + 1), *(mr->rdParm));
834 break;
836 case META_LINETO:
837 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
838 break;
840 case META_MOVETO:
841 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
842 break;
844 case META_EXCLUDECLIPRECT:
845 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
846 *(mr->rdParm + 1), *(mr->rdParm) );
847 break;
849 case META_INTERSECTCLIPRECT:
850 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
851 *(mr->rdParm + 1), *(mr->rdParm) );
852 break;
854 case META_ARC:
855 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
856 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
857 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
858 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
859 break;
861 case META_ELLIPSE:
862 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
863 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
864 break;
866 case META_FLOODFILL:
867 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
868 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
869 break;
871 case META_PIE:
872 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
873 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
874 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
875 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
876 break;
878 case META_RECTANGLE:
879 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
880 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
881 break;
883 case META_ROUNDRECT:
884 RoundRect(hdc, (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_PATBLT:
890 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
891 *(mr->rdParm + 3), *(mr->rdParm + 2),
892 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
893 break;
895 case META_SAVEDC:
896 SaveDC(hdc);
897 break;
899 case META_SETPIXEL:
900 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
901 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
902 break;
904 case META_OFFSETCLIPRGN:
905 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
906 break;
908 case META_TEXTOUT:
909 s1 = *(mr->rdParm);
910 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
911 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
912 (char *)(mr->rdParm + 1), s1);
913 break;
915 case META_POLYGON:
916 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
917 break;
919 case META_POLYPOLYGON:
920 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
921 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
922 break;
924 case META_POLYLINE:
925 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
926 break;
928 case META_RESTOREDC:
929 RestoreDC(hdc, (INT16)*(mr->rdParm));
930 break;
932 case META_SELECTOBJECT:
933 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
934 break;
936 case META_CHORD:
937 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
938 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
939 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
940 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
941 break;
943 case META_CREATEPATTERNBRUSH:
944 switch (*(mr->rdParm))
946 case BS_PATTERN:
947 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
948 MF_AddHandle(ht, nHandles,
949 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
950 infohdr->biHeight,
951 infohdr->biPlanes,
952 infohdr->biBitCount,
953 (LPSTR)(mr->rdParm +
954 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
955 break;
957 case BS_DIBPATTERN:
958 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
959 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
960 ptr = GlobalLock16(hndl);
961 memcpy(ptr, mr->rdParm + 2, s1);
962 GlobalUnlock16(hndl);
963 MF_AddHandle(ht, nHandles,
964 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
965 GlobalFree16(hndl);
966 break;
968 default:
969 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
970 mr->rdParm[0]);
971 break;
973 break;
975 case META_CREATEPENINDIRECT:
976 MF_AddHandle(ht, nHandles,
977 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
978 break;
980 case META_CREATEFONTINDIRECT:
981 MF_AddHandle(ht, nHandles,
982 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
983 break;
985 case META_CREATEBRUSHINDIRECT:
986 MF_AddHandle(ht, nHandles,
987 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
988 break;
990 case META_CREATEPALETTE:
991 MF_AddHandle(ht, nHandles,
992 CreatePalette16((LPLOGPALETTE)mr->rdParm));
993 break;
995 case META_SETTEXTALIGN:
996 SetTextAlign16(hdc, *(mr->rdParm));
997 break;
999 case META_SELECTPALETTE:
1000 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1001 *(mr->rdParm));
1002 break;
1004 case META_SETMAPPERFLAGS:
1005 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1006 break;
1008 case META_REALIZEPALETTE:
1009 GDIRealizePalette16(hdc);
1010 break;
1012 case META_ESCAPE:
1013 FIXME("META_ESCAPE unimplemented.\n");
1014 break;
1016 case META_EXTTEXTOUT:
1017 MF_Play_MetaExtTextOut( hdc, mr );
1018 break;
1020 case META_STRETCHDIB:
1022 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1023 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1024 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1025 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1026 mr->rdParm[4],mr->rdParm[3],bits,info,
1027 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1029 break;
1031 case META_DIBSTRETCHBLT:
1033 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1034 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1035 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1036 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1037 mr->rdParm[3],mr->rdParm[2],bits,info,
1038 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1040 break;
1042 case META_STRETCHBLT:
1044 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1045 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1046 mr->rdParm[11], /*Height*/
1047 mr->rdParm[13], /*Planes*/
1048 mr->rdParm[14], /*BitsPixel*/
1049 (LPSTR)&mr->rdParm[15]); /*bits*/
1050 SelectObject(hdcSrc,hbitmap);
1051 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1052 mr->rdParm[7],mr->rdParm[6],
1053 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1054 mr->rdParm[3],mr->rdParm[2],
1055 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1056 DeleteDC(hdcSrc);
1058 break;
1060 case META_BITBLT:
1062 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1063 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1064 mr->rdParm[8]/*Height*/,
1065 mr->rdParm[10]/*Planes*/,
1066 mr->rdParm[11]/*BitsPixel*/,
1067 (LPSTR)&mr->rdParm[12]/*bits*/);
1068 SelectObject(hdcSrc,hbitmap);
1069 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1070 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1071 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1072 MAKELONG(0,mr->rdParm[0]));
1073 DeleteDC(hdcSrc);
1075 break;
1077 case META_CREATEREGION:
1079 HRGN hrgn = CreateRectRgn(0,0,0,0);
1081 MF_Play_MetaCreateRegion(mr, hrgn);
1082 MF_AddHandle(ht, nHandles, hrgn);
1084 break;
1086 case META_FILLREGION:
1087 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1088 *(ht->objectHandle + *(mr->rdParm)));
1089 break;
1091 case META_FRAMEREGION:
1092 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1093 *(ht->objectHandle + *(mr->rdParm+2)),
1094 *(mr->rdParm+1), *(mr->rdParm));
1095 break;
1097 case META_INVERTREGION:
1098 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1099 break;
1101 case META_PAINTREGION:
1102 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1103 break;
1105 case META_SELECTCLIPREGION:
1106 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1107 break;
1109 case META_DIBCREATEPATTERNBRUSH:
1110 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1111 but there's no difference */
1113 TRACE("%d\n",*(mr->rdParm));
1114 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1115 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1116 ptr = GlobalLock16(hndl);
1117 memcpy(ptr, mr->rdParm + 2, s1);
1118 GlobalUnlock16(hndl);
1119 MF_AddHandle(ht, nHandles,
1120 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1121 GlobalFree16(hndl);
1122 break;
1124 case META_DIBBITBLT:
1125 /* In practice I've found that there are two layouts for
1126 META_DIBBITBLT, one (the first here) is the usual one when a src
1127 dc is actually passed to it, the second occurs when the src dc is
1128 passed in as NULL to the creating BitBlt. As the second case has
1129 no dib, a size check will suffice to distinguish.
1131 Caolan.McNamara@ul.ie */
1133 if (mr->rdSize > 12) {
1134 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1135 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1137 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1138 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1139 mr->rdParm[5], mr->rdParm[4], bits, info,
1140 DIB_RGB_COLORS,
1141 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1142 } else { /* equivalent to a PatBlt */
1143 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1144 mr->rdParm[6], mr->rdParm[5],
1145 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1147 break;
1149 case META_SETTEXTCHAREXTRA:
1150 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1151 break;
1153 case META_SETTEXTJUSTIFICATION:
1154 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1155 break;
1157 case META_EXTFLOODFILL:
1158 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1159 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1160 *(mr->rdParm));
1161 break;
1163 case META_SETDIBTODEV:
1165 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1166 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1167 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1168 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1169 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1170 mr->rdParm[2], mr->rdParm[1], bits, info,
1171 mr->rdParm[0]);
1172 break;
1175 #define META_UNIMP(x) case x: \
1176 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1177 break;
1178 META_UNIMP(META_DRAWTEXT)
1179 META_UNIMP(META_ANIMATEPALETTE)
1180 META_UNIMP(META_SETPALENTRIES)
1181 META_UNIMP(META_RESIZEPALETTE)
1182 META_UNIMP(META_RESETDC)
1183 META_UNIMP(META_STARTDOC)
1184 META_UNIMP(META_STARTPAGE)
1185 META_UNIMP(META_ENDPAGE)
1186 META_UNIMP(META_ABORTDOC)
1187 META_UNIMP(META_ENDDOC)
1188 META_UNIMP(META_CREATEBRUSH)
1189 META_UNIMP(META_CREATEBITMAPINDIRECT)
1190 META_UNIMP(META_CREATEBITMAP)
1191 #undef META_UNIMP
1193 default:
1194 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1195 mr->rdFunction);
1199 /******************************************************************
1200 * PlayMetaFileRecord (GDI32.@)
1202 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1203 METARECORD *metarecord, UINT handles )
1205 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1206 handles*sizeof(HANDLETABLE16));
1207 unsigned int i = 0;
1208 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1209 handles);
1210 for (i=0; i<handles; i++)
1211 ht->objectHandle[i] = handletable->objectHandle[i];
1212 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1213 for (i=0; i<handles; i++)
1214 handletable->objectHandle[i] = ht->objectHandle[i];
1215 GlobalFree((HGLOBAL)ht);
1216 return TRUE;
1219 /******************************************************************
1220 * GetMetaFileBits (GDI.159)
1222 * Trade in a metafile object handle for a handle to the metafile memory.
1226 HGLOBAL16 WINAPI GetMetaFileBits16(
1227 HMETAFILE16 hmf /* [in] metafile handle */
1230 TRACE("hMem out: %04x\n", hmf);
1231 return hmf;
1234 /******************************************************************
1235 * SetMetaFileBits (GDI.160)
1237 * Trade in a metafile memory handle for a handle to a metafile object.
1238 * The memory region should hold a proper metafile, otherwise
1239 * problems will occur when it is used. Validity of the memory is not
1240 * checked. The function is essentially just the identity function.
1242 HMETAFILE16 WINAPI SetMetaFileBits16(
1243 HGLOBAL16 hMem
1244 /* [in] handle to a memory region holding a metafile */
1247 TRACE("hmf out: %04x\n", hMem);
1249 return hMem;
1252 /******************************************************************
1253 * SetMetaFileBitsBetter (GDI.196)
1255 * Trade in a metafile memory handle for a handle to a metafile object,
1256 * making a cursory check (using IsValidMetaFile()) that the memory
1257 * handle points to a valid metafile.
1259 * RETURNS
1260 * Handle to a metafile on success, NULL on failure..
1262 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1264 if( IsValidMetaFile16( hMeta ) )
1265 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1266 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1267 return (HMETAFILE16)0;
1270 /******************************************************************
1271 * SetMetaFileBitsEx (GDI32.@)
1273 * Create a metafile from raw data. No checking of the data is performed.
1274 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1276 HMETAFILE WINAPI SetMetaFileBitsEx(
1277 UINT size, /* [in] size of metafile, in bytes */
1278 const BYTE *lpData /* [in] pointer to metafile data */
1281 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1282 if (!mh) return 0;
1283 memcpy(mh, lpData, size);
1284 return MF_Create_HMETAFILE(mh);
1287 /*****************************************************************
1288 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1290 * Copies the data from metafile _hmf_ into the buffer _buf_.
1291 * If _buf_ is zero, returns size of buffer required. Otherwise,
1292 * returns number of bytes copied.
1294 UINT WINAPI GetMetaFileBitsEx(
1295 HMETAFILE hmf, /* [in] metafile */
1296 UINT nSize, /* [in] size of buf */
1297 LPVOID buf /* [out] buffer to receive raw metafile data */
1299 METAHEADER *mh = MF_GetMetaHeader(hmf);
1300 UINT mfSize;
1302 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1303 if (!mh) return 0; /* FIXME: error code */
1304 if(mh->mtType == METAFILE_DISK)
1305 FIXME("Disk-based metafile?\n");
1306 mfSize = mh->mtSize * 2;
1307 if (!buf) {
1308 TRACE("returning size %d\n", mfSize);
1309 return mfSize;
1311 if(mfSize > nSize) mfSize = nSize;
1312 memmove(buf, mh, mfSize);
1313 return mfSize;
1316 /******************************************************************
1317 * GetWinMetaFileBits [GDI32.@]
1319 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1320 UINT cbBuffer, LPBYTE lpbBuffer,
1321 INT fnMapMode, HDC hdcRef)
1323 FIXME("(%d,%d,%p,%d,%d): stub\n",
1324 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1325 return 0;
1328 /******************************************************************
1329 * MF_Play_MetaCreateRegion
1331 * Handles META_CREATEREGION for PlayMetaFileRecord().
1335 * The layout of the record looks something like this:
1337 * rdParm meaning
1338 * 0 Always 0?
1339 * 1 Always 6?
1340 * 2 Looks like a handle? - not constant
1341 * 3 0 or 1 ??
1342 * 4 Total number of bytes
1343 * 5 No. of separate bands = n [see below]
1344 * 6 Largest number of x co-ords in a band
1345 * 7-10 Bounding box x1 y1 x2 y2
1346 * 11-... n bands
1348 * Regions are divided into bands that are uniform in the
1349 * y-direction. Each band consists of pairs of on/off x-coords and is
1350 * written as
1351 * m y0 y1 x1 x2 x3 ... xm m
1352 * into successive rdParm[]s.
1354 * This is probably just a dump of the internal RGNOBJ?
1356 * HDMD - 18/12/97
1360 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1362 WORD band, pair;
1363 WORD *start, *end;
1364 INT16 y0, y1;
1365 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1367 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1368 band++, start = end + 1) {
1369 if(*start / 2 != (*start + 1) / 2) {
1370 WARN("Delimiter not even.\n");
1371 DeleteObject( hrgn2 );
1372 return FALSE;
1375 end = start + *start + 3;
1376 if(end > (WORD *)mr + mr->rdSize) {
1377 WARN("End points outside record.\n");
1378 DeleteObject( hrgn2 );
1379 return FALSE;
1382 if(*start != *end) {
1383 WARN("Mismatched delimiters.\n");
1384 DeleteObject( hrgn2 );
1385 return FALSE;
1388 y0 = *(INT16 *)(start + 1);
1389 y1 = *(INT16 *)(start + 2);
1390 for(pair = 0; pair < *start / 2; pair++) {
1391 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1392 *(INT16 *)(start + 4 + 2*pair), y1 );
1393 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1396 DeleteObject( hrgn2 );
1397 return TRUE;
1401 /******************************************************************
1402 * MF_Play_MetaExtTextOut
1404 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1407 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1409 LPINT16 dxx;
1410 LPSTR sot;
1411 DWORD len;
1412 WORD s1;
1414 s1 = mr->rdParm[2]; /* String length */
1415 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1416 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1417 /* rec len without dx array */
1419 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1420 if (mr->rdParm[3])
1421 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1423 if (mr->rdSize == len / 2)
1424 dxx = NULL; /* determine if array present */
1425 else
1426 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1427 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1428 else {
1429 TRACE("%s len: %ld\n", sot, mr->rdSize);
1430 WARN(
1431 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1432 len, s1, mr->rdSize, mr->rdParm[3]);
1433 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1435 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1436 mr->rdParm[0], /* Y position */
1437 mr->rdParm[3], /* options */
1438 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1439 /* rectangle */
1440 sot, /* string */
1441 s1, dxx); /* length, dx array */
1442 if (dxx)
1443 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1444 return TRUE;