Use Windows metrics for font scaling.
[wine/testsucceed.git] / objects / metafile.c
blobdf012a5b09747d9b2f0ea5e12d5ba7a1bef9cab0
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
128 * Should be followed by call to MF_ReleaseMetaHeader
130 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
132 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
133 return metaObj ? metaObj->mh : 0;
136 /******************************************************************
137 * MF_GetMetaHeader16
139 * Returns ptr to METAHEADER associated with HMETAFILE16
140 * Should be followed by call to MF_ReleaseMetaHeader16
142 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
144 return GlobalLock16(hmf);
147 /******************************************************************
148 * MF_ReleaseMetaHeader
150 * Releases METAHEADER associated with HMETAFILE
152 static void MF_ReleaseMetaHeader( HMETAFILE hmf )
154 GDI_ReleaseObj( hmf );
157 /******************************************************************
158 * MF_ReleaseMetaHeader16
160 * Releases METAHEADER associated with HMETAFILE16
162 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
164 return GlobalUnlock16( hmf );
168 /******************************************************************
169 * DeleteMetaFile (GDI.127)
171 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
173 return !GlobalFree16( hmf );
176 /******************************************************************
177 * DeleteMetaFile (GDI32.@)
179 * Delete a memory-based metafile.
182 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
184 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
185 if (!metaObj) return FALSE;
186 HeapFree( GetProcessHeap(), 0, metaObj->mh );
187 GDI_FreeObject( hmf, metaObj );
188 return TRUE;
191 /******************************************************************
192 * MF_ReadMetaFile
194 * Returns a pointer to a memory based METAHEADER read in from file HFILE
197 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
199 METAHEADER *mh;
200 DWORD BytesRead, size;
202 size = sizeof(METAHEADER);
203 mh = HeapAlloc( GetProcessHeap(), 0, size );
204 if(!mh) return NULL;
205 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
206 BytesRead != size) {
207 HeapFree( GetProcessHeap(), 0, mh );
208 return NULL;
210 size = mh->mtSize * 2;
211 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
212 if(!mh) return NULL;
213 size -= sizeof(METAHEADER);
214 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
215 NULL) == 0 ||
216 BytesRead != size) {
217 HeapFree( GetProcessHeap(), 0, mh );
218 return NULL;
221 if (mh->mtType != METAFILE_MEMORY) {
222 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
223 mh->mtType = METAFILE_MEMORY;
225 return mh;
228 /******************************************************************
229 * GetMetaFile (GDI.124)
231 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
233 METAHEADER *mh;
234 HANDLE hFile;
236 TRACE("%s\n", lpFilename);
238 if(!lpFilename)
239 return 0;
241 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
242 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
243 return 0;
245 mh = MF_ReadMetaFile(hFile);
246 CloseHandle(hFile);
247 if(!mh) return 0;
248 return MF_Create_HMETAFILE16( mh );
251 /******************************************************************
252 * GetMetaFileA (GDI32.@)
254 * Read a metafile from a file. Returns handle to a memory-based metafile.
256 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
258 METAHEADER *mh;
259 HANDLE hFile;
261 TRACE("%s\n", lpFilename);
263 if(!lpFilename)
264 return 0;
266 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
267 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
268 return 0;
270 mh = MF_ReadMetaFile(hFile);
271 CloseHandle(hFile);
272 if(!mh) return 0;
273 return MF_Create_HMETAFILE( mh );
278 /******************************************************************
279 * GetMetaFileW (GDI32.@)
281 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
283 METAHEADER *mh;
284 HANDLE hFile;
286 TRACE("%s\n", debugstr_w(lpFilename));
288 if(!lpFilename)
289 return 0;
291 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
292 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
293 return 0;
295 mh = MF_ReadMetaFile(hFile);
296 CloseHandle(hFile);
297 if(!mh) return 0;
298 return MF_Create_HMETAFILE( mh );
302 /******************************************************************
303 * MF_LoadDiskBasedMetaFile
305 * Creates a new memory-based metafile from a disk-based one.
307 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
309 METAHEADERDISK *mhd;
310 HANDLE hfile;
311 METAHEADER *mh2;
313 if(mh->mtType != METAFILE_DISK) {
314 ERR("Not a disk based metafile\n");
315 return NULL;
317 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
319 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
320 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
321 WARN("Can't open file of disk based metafile\n");
322 return NULL;
324 mh2 = MF_ReadMetaFile(hfile);
325 CloseHandle(hfile);
326 return mh2;
329 /******************************************************************
330 * MF_CreateMetaHeaderDisk
332 * Take a memory based METAHEADER and change it to a disk based METAHEADER
333 * assosiated with filename. Note: Trashes contents of old one.
335 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
337 METAHEADERDISK *mhd;
338 DWORD size;
340 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
341 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
342 mh->mtType = METAFILE_DISK;
343 size = HeapSize( GetProcessHeap(), 0, mh );
344 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
345 strcpy(mhd->filename, filename);
346 return mh;
349 /******************************************************************
350 * CopyMetaFile (GDI.151)
352 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
354 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
355 METAHEADER *mh2 = NULL;
356 HANDLE hFile;
358 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
360 if(!mh) return 0;
362 if(mh->mtType == METAFILE_DISK)
363 mh2 = MF_LoadDiskBasedMetaFile(mh);
364 else {
365 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
366 memcpy( mh2, mh, mh->mtSize * 2 );
368 MF_ReleaseMetaHeader16( hSrcMetaFile );
370 if(lpFilename) { /* disk based metafile */
371 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
372 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
373 HeapFree( GetProcessHeap(), 0, mh2 );
374 return 0;
376 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
377 CloseHandle(hFile);
378 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
381 return MF_Create_HMETAFILE16( mh2 );
385 /******************************************************************
386 * CopyMetaFileA (GDI32.@)
388 * Copies the metafile corresponding to hSrcMetaFile to either
389 * a disk file, if a filename is given, or to a new memory based
390 * metafile, if lpFileName is NULL.
392 * RETURNS
394 * Handle to metafile copy on success, NULL on failure.
396 * BUGS
398 * Copying to disk returns NULL even if successful.
400 HMETAFILE WINAPI CopyMetaFileA(
401 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
402 LPCSTR lpFilename /* [in] filename if copying to a file */
404 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
405 METAHEADER *mh2 = NULL;
406 HANDLE hFile;
408 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
410 if(!mh) return 0;
412 if(mh->mtType == METAFILE_DISK)
413 mh2 = MF_LoadDiskBasedMetaFile(mh);
414 else {
415 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
416 memcpy( mh2, mh, mh->mtSize * 2 );
418 MF_ReleaseMetaHeader( hSrcMetaFile );
420 if(lpFilename) { /* disk based metafile */
421 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
422 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
423 HeapFree( GetProcessHeap(), 0, mh2 );
424 return 0;
426 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
427 CloseHandle(hFile);
428 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
431 return MF_Create_HMETAFILE( mh2 );
435 /******************************************************************
436 * CopyMetaFileW (GDI32.@)
438 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
439 LPCWSTR lpFilename )
441 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
442 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
443 HeapFree( GetProcessHeap(), 0, p );
444 return ret;
448 /******************************************************************
449 * IsValidMetaFile (GDI.410)
451 * Attempts to check if a given metafile is correctly formatted.
452 * Currently, the only things verified are several properties of the
453 * header.
455 * RETURNS
456 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
458 * BUGS
459 * This is not exactly what windows does, see _Undocumented_Windows_
460 * for details.
462 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
464 BOOL16 res=FALSE;
465 METAHEADER *mh = MF_GetMetaHeader16(hmf);
466 if (mh) {
467 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
468 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
469 if (mh->mtVersion == MFVERSION)
470 res=TRUE;
471 MF_ReleaseMetaHeader16(hmf);
473 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
474 return res;
478 /*******************************************************************
479 * MF_PlayMetaFile
481 * Helper for PlayMetaFile
483 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
486 METARECORD *mr;
487 HANDLETABLE16 *ht;
488 unsigned int offset = 0;
489 WORD i;
490 HPEN hPen;
491 HBRUSH hBrush;
492 HFONT hFont;
493 BOOL loaded = FALSE;
495 if (!mh) return FALSE;
496 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
497 mh = MF_LoadDiskBasedMetaFile(mh);
498 if(!mh) return FALSE;
499 loaded = TRUE;
502 /* save the current pen, brush and font */
503 hPen = GetCurrentObject(hdc, OBJ_PEN);
504 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
505 hFont = GetCurrentObject(hdc, OBJ_FONT);
507 /* create the handle table */
508 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
509 sizeof(HANDLETABLE16) * mh->mtNoObjects);
510 if(!ht) return FALSE;
512 /* loop through metafile playing records */
513 offset = mh->mtHeaderSize * 2;
514 while (offset < mh->mtSize * 2)
516 mr = (METARECORD *)((char *)mh + offset);
517 TRACE("offset=%04x,size=%08lx\n",
518 offset, mr->rdSize);
519 if (!mr->rdSize) {
520 TRACE(
521 "Entry got size 0 at offset %d, total mf length is %ld\n",
522 offset,mh->mtSize*2);
523 break; /* would loop endlessly otherwise */
525 offset += mr->rdSize * 2;
526 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
529 SelectObject(hdc, hBrush);
530 SelectObject(hdc, hPen);
531 SelectObject(hdc, hFont);
533 /* free objects in handle table */
534 for(i = 0; i < mh->mtNoObjects; i++)
535 if(*(ht->objectHandle + i) != 0)
536 DeleteObject(*(ht->objectHandle + i));
538 /* free handle table */
539 HeapFree( GetProcessHeap(), 0, ht );
540 if(loaded)
541 HeapFree( GetProcessHeap(), 0, mh );
542 return TRUE;
545 /******************************************************************
546 * PlayMetaFile (GDI.123)
549 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
551 BOOL16 ret;
552 METAHEADER *mh = MF_GetMetaHeader16( hmf );
553 ret = MF_PlayMetaFile( hdc, mh );
554 MF_ReleaseMetaHeader16( hmf );
555 return ret;
558 /******************************************************************
559 * PlayMetaFile (GDI32.@)
561 * Renders the metafile specified by hmf in the DC specified by
562 * hdc. Returns FALSE on failure, TRUE on success.
564 BOOL WINAPI PlayMetaFile(
565 HDC hdc, /* [in] handle of DC to render in */
566 HMETAFILE hmf /* [in] handle of metafile to render */
569 BOOL ret;
570 METAHEADER *mh = MF_GetMetaHeader( hmf );
571 ret = MF_PlayMetaFile( hdc, mh );
572 MF_ReleaseMetaHeader( hmf );
573 return ret;
577 /******************************************************************
578 * EnumMetaFile16 (GDI.175)
581 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
582 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
584 METAHEADER *mh = MF_GetMetaHeader16(hmf);
585 METARECORD *mr;
586 HANDLETABLE16 *ht;
587 HGLOBAL16 hHT;
588 SEGPTR spht;
589 unsigned int offset = 0;
590 WORD i, seg;
591 HPEN hPen;
592 HBRUSH hBrush;
593 HFONT hFont;
594 BOOL16 result = TRUE, loaded = FALSE;
596 TRACE("(%04x, %04x, %08lx, %08lx)\n",
597 hdc, hmf, (DWORD)lpEnumFunc, lpData);
600 if(!mh) return FALSE;
601 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
602 mh = MF_LoadDiskBasedMetaFile(mh);
603 if(!mh) return FALSE;
604 loaded = TRUE;
607 /* save the current pen, brush and font */
608 hPen = GetCurrentObject(hdc, OBJ_PEN);
609 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
610 hFont = GetCurrentObject(hdc, OBJ_FONT);
612 /* create the handle table */
614 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
615 sizeof(HANDLETABLE16) * mh->mtNoObjects);
616 spht = K32WOWGlobalLock16(hHT);
618 seg = hmf | 7;
619 offset = mh->mtHeaderSize * 2;
621 /* loop through metafile records */
623 while (offset < (mh->mtSize * 2))
625 mr = (METARECORD *)((char *)mh + offset);
626 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
627 (METARECORD *)MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
628 mh->mtNoObjects, (LONG)lpData ))
630 result = FALSE;
631 break;
635 offset += (mr->rdSize * 2);
638 SelectObject(hdc, hBrush);
639 SelectObject(hdc, hPen);
640 SelectObject(hdc, hFont);
642 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
644 /* free objects in handle table */
645 for(i = 0; i < mh->mtNoObjects; i++)
646 if(*(ht->objectHandle + i) != 0)
647 DeleteObject(*(ht->objectHandle + i));
649 /* free handle table */
650 GlobalFree16(hHT);
651 if(loaded)
652 HeapFree( GetProcessHeap(), 0, mh );
653 MF_ReleaseMetaHeader16(hmf);
654 return result;
657 /******************************************************************
658 * EnumMetaFile (GDI32.@)
660 * Loop through the metafile records in hmf, calling the user-specified
661 * function for each one, stopping when the user's function returns FALSE
662 * (which is considered to be failure)
663 * or when no records are left (which is considered to be success).
665 * RETURNS
666 * TRUE on success, FALSE on failure.
668 * HISTORY
669 * Niels de carpentier, april 1996
671 BOOL WINAPI EnumMetaFile(
672 HDC hdc,
673 HMETAFILE hmf,
674 MFENUMPROC lpEnumFunc,
675 LPARAM lpData
677 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
678 METARECORD *mr;
679 HANDLETABLE *ht;
680 BOOL result = TRUE;
681 int i;
682 unsigned int offset = 0;
683 HPEN hPen;
684 HBRUSH hBrush;
685 HFONT hFont;
687 TRACE("(%08x,%08x,%p,%p)\n",
688 hdc, hmf, lpEnumFunc, (void*)lpData);
689 if (!mh) return 0;
690 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
691 mhTemp = MF_LoadDiskBasedMetaFile(mh);
692 if(!mhTemp)
694 MF_ReleaseMetaHeader(hmf);
695 return FALSE;
697 mh = mhTemp;
699 else
701 /* We need to copy this thing instead of use it directly because we
702 * have to close the hmf handle for the purpose of avoiding deadlock.
704 mhTemp = HeapAlloc( GetProcessHeap(), 0, mh->mtHeaderSize + mh->mtSize*2 );
705 if(!mhTemp)
707 MF_ReleaseMetaHeader(hmf);
708 return FALSE;
710 memcpy( mhTemp, mh, mh->mtHeaderSize + mh->mtSize*2 );
711 mh = mhTemp;
713 MF_ReleaseMetaHeader(hmf);
714 hmf = 0; /* just in case */
716 /* save the current pen, brush and font */
717 hPen = GetCurrentObject(hdc, OBJ_PEN);
718 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
719 hFont = GetCurrentObject(hdc, OBJ_FONT);
721 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
722 sizeof(HANDLETABLE) * mh->mtNoObjects);
724 /* loop through metafile records */
725 offset = mh->mtHeaderSize * 2;
727 while (offset < (mh->mtSize * 2))
729 mr = (METARECORD *)((char *)mh + offset);
730 TRACE("Calling EnumFunc with record type %x\n",
731 mr->rdFunction);
732 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
734 result = FALSE;
735 break;
738 offset += (mr->rdSize * 2);
741 /* restore pen, brush and font */
742 SelectObject(hdc, hBrush);
743 SelectObject(hdc, hPen);
744 SelectObject(hdc, hFont);
746 /* free objects in handle table */
747 for(i = 0; i < mh->mtNoObjects; i++)
748 if(*(ht->objectHandle + i) != 0)
749 DeleteObject(*(ht->objectHandle + i));
751 /* free handle table */
752 HeapFree( GetProcessHeap(), 0, ht);
753 /* free a copy of metafile */
754 HeapFree( GetProcessHeap(), 0, mh );
755 return result;
758 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
759 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
760 /******************************************************************
761 * PlayMetaFileRecord (GDI.176)
763 * Render a single metafile record specified by *mr in the DC hdc, while
764 * using the handle table *ht, of length nHandles,
765 * to store metafile objects.
767 * BUGS
768 * The following metafile records are unimplemented:
770 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
771 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
772 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
775 void WINAPI PlayMetaFileRecord16(
776 HDC16 hdc, /* [in] DC to render metafile into */
777 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
778 METARECORD *mr, /* [in] pointer to metafile record to render */
779 UINT16 nHandles /* [in] size of handle table */
781 short s1;
782 HANDLE16 hndl;
783 char *ptr;
784 BITMAPINFOHEADER *infohdr;
786 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
787 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
789 switch (mr->rdFunction)
791 case META_EOF:
792 break;
794 case META_DELETEOBJECT:
795 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
796 *(ht->objectHandle + *(mr->rdParm)) = 0;
797 break;
799 case META_SETBKCOLOR:
800 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
801 break;
803 case META_SETBKMODE:
804 SetBkMode16(hdc, *(mr->rdParm));
805 break;
807 case META_SETMAPMODE:
808 SetMapMode16(hdc, *(mr->rdParm));
809 break;
811 case META_SETROP2:
812 SetROP216(hdc, *(mr->rdParm));
813 break;
815 case META_SETRELABS:
816 SetRelAbs16(hdc, *(mr->rdParm));
817 break;
819 case META_SETPOLYFILLMODE:
820 SetPolyFillMode16(hdc, *(mr->rdParm));
821 break;
823 case META_SETSTRETCHBLTMODE:
824 SetStretchBltMode16(hdc, *(mr->rdParm));
825 break;
827 case META_SETTEXTCOLOR:
828 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
829 break;
831 case META_SETWINDOWORG:
832 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
833 break;
835 case META_SETWINDOWEXT:
836 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
837 break;
839 case META_SETVIEWPORTORG:
840 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
841 break;
843 case META_SETVIEWPORTEXT:
844 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
845 break;
847 case META_OFFSETWINDOWORG:
848 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
849 break;
851 case META_SCALEWINDOWEXT:
852 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
853 *(mr->rdParm + 1), *(mr->rdParm));
854 break;
856 case META_OFFSETVIEWPORTORG:
857 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
858 break;
860 case META_SCALEVIEWPORTEXT:
861 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
862 *(mr->rdParm + 1), *(mr->rdParm));
863 break;
865 case META_LINETO:
866 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
867 break;
869 case META_MOVETO:
870 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
871 break;
873 case META_EXCLUDECLIPRECT:
874 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
875 *(mr->rdParm + 1), *(mr->rdParm) );
876 break;
878 case META_INTERSECTCLIPRECT:
879 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
880 *(mr->rdParm + 1), *(mr->rdParm) );
881 break;
883 case META_ARC:
884 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
885 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
886 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
887 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
888 break;
890 case META_ELLIPSE:
891 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
893 break;
895 case META_FLOODFILL:
896 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
897 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
898 break;
900 case META_PIE:
901 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
902 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
903 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
904 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
905 break;
907 case META_RECTANGLE:
908 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
909 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
910 break;
912 case META_ROUNDRECT:
913 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
914 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
915 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
916 break;
918 case META_PATBLT:
919 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
920 *(mr->rdParm + 3), *(mr->rdParm + 2),
921 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
922 break;
924 case META_SAVEDC:
925 SaveDC(hdc);
926 break;
928 case META_SETPIXEL:
929 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
930 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
931 break;
933 case META_OFFSETCLIPRGN:
934 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
935 break;
937 case META_TEXTOUT:
938 s1 = *(mr->rdParm);
939 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
940 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
941 (char *)(mr->rdParm + 1), s1);
942 break;
944 case META_POLYGON:
945 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
946 break;
948 case META_POLYPOLYGON:
949 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
950 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
951 break;
953 case META_POLYLINE:
954 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
955 break;
957 case META_RESTOREDC:
958 RestoreDC(hdc, (INT16)*(mr->rdParm));
959 break;
961 case META_SELECTOBJECT:
962 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
963 break;
965 case META_CHORD:
966 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
967 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
968 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
969 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
970 break;
972 case META_CREATEPATTERNBRUSH:
973 switch (*(mr->rdParm))
975 case BS_PATTERN:
976 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
977 MF_AddHandle(ht, nHandles,
978 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
979 infohdr->biHeight,
980 infohdr->biPlanes,
981 infohdr->biBitCount,
982 (LPSTR)(mr->rdParm +
983 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
984 break;
986 case BS_DIBPATTERN:
987 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
988 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
989 ptr = GlobalLock16(hndl);
990 memcpy(ptr, mr->rdParm + 2, s1);
991 GlobalUnlock16(hndl);
992 MF_AddHandle(ht, nHandles,
993 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
994 GlobalFree16(hndl);
995 break;
997 default:
998 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
999 mr->rdParm[0]);
1000 break;
1002 break;
1004 case META_CREATEPENINDIRECT:
1005 MF_AddHandle(ht, nHandles,
1006 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
1007 break;
1009 case META_CREATEFONTINDIRECT:
1010 MF_AddHandle(ht, nHandles,
1011 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
1012 break;
1014 case META_CREATEBRUSHINDIRECT:
1015 MF_AddHandle(ht, nHandles,
1016 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1017 break;
1019 case META_CREATEPALETTE:
1020 MF_AddHandle(ht, nHandles,
1021 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1022 break;
1024 case META_SETTEXTALIGN:
1025 SetTextAlign16(hdc, *(mr->rdParm));
1026 break;
1028 case META_SELECTPALETTE:
1029 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1030 *(mr->rdParm));
1031 break;
1033 case META_SETMAPPERFLAGS:
1034 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1035 break;
1037 case META_REALIZEPALETTE:
1038 GDIRealizePalette16(hdc);
1039 break;
1041 case META_ESCAPE:
1042 FIXME("META_ESCAPE unimplemented.\n");
1043 break;
1045 case META_EXTTEXTOUT:
1046 MF_Play_MetaExtTextOut( hdc, mr );
1047 break;
1049 case META_STRETCHDIB:
1051 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1052 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1053 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1054 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1055 mr->rdParm[4],mr->rdParm[3],bits,info,
1056 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1058 break;
1060 case META_DIBSTRETCHBLT:
1062 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1063 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1064 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1065 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1066 mr->rdParm[3],mr->rdParm[2],bits,info,
1067 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1069 break;
1071 case META_STRETCHBLT:
1073 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1074 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1075 mr->rdParm[11], /*Height*/
1076 mr->rdParm[13], /*Planes*/
1077 mr->rdParm[14], /*BitsPixel*/
1078 (LPSTR)&mr->rdParm[15]); /*bits*/
1079 SelectObject(hdcSrc,hbitmap);
1080 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1081 mr->rdParm[7],mr->rdParm[6],
1082 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1083 mr->rdParm[3],mr->rdParm[2],
1084 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1085 DeleteDC(hdcSrc);
1087 break;
1089 case META_BITBLT:
1091 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1092 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1093 mr->rdParm[8]/*Height*/,
1094 mr->rdParm[10]/*Planes*/,
1095 mr->rdParm[11]/*BitsPixel*/,
1096 (LPSTR)&mr->rdParm[12]/*bits*/);
1097 SelectObject(hdcSrc,hbitmap);
1098 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1099 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1100 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1101 MAKELONG(0,mr->rdParm[0]));
1102 DeleteDC(hdcSrc);
1104 break;
1106 case META_CREATEREGION:
1108 HRGN hrgn = CreateRectRgn(0,0,0,0);
1110 MF_Play_MetaCreateRegion(mr, hrgn);
1111 MF_AddHandle(ht, nHandles, hrgn);
1113 break;
1115 case META_FILLREGION:
1116 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1117 *(ht->objectHandle + *(mr->rdParm)));
1118 break;
1120 case META_FRAMEREGION:
1121 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1122 *(ht->objectHandle + *(mr->rdParm+2)),
1123 *(mr->rdParm+1), *(mr->rdParm));
1124 break;
1126 case META_INVERTREGION:
1127 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1128 break;
1130 case META_PAINTREGION:
1131 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1132 break;
1134 case META_SELECTCLIPREGION:
1135 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1136 break;
1138 case META_DIBCREATEPATTERNBRUSH:
1139 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1140 but there's no difference */
1142 TRACE("%d\n",*(mr->rdParm));
1143 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1144 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1145 ptr = GlobalLock16(hndl);
1146 memcpy(ptr, mr->rdParm + 2, s1);
1147 GlobalUnlock16(hndl);
1148 MF_AddHandle(ht, nHandles,
1149 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1150 GlobalFree16(hndl);
1151 break;
1153 case META_DIBBITBLT:
1154 /* In practice I've found that there are two layouts for
1155 META_DIBBITBLT, one (the first here) is the usual one when a src
1156 dc is actually passed to it, the second occurs when the src dc is
1157 passed in as NULL to the creating BitBlt. As the second case has
1158 no dib, a size check will suffice to distinguish.
1160 Caolan.McNamara@ul.ie */
1162 if (mr->rdSize > 12) {
1163 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1164 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1166 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1167 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1168 mr->rdParm[5], mr->rdParm[4], bits, info,
1169 DIB_RGB_COLORS,
1170 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1171 } else { /* equivalent to a PatBlt */
1172 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1173 mr->rdParm[6], mr->rdParm[5],
1174 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1176 break;
1178 case META_SETTEXTCHAREXTRA:
1179 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1180 break;
1182 case META_SETTEXTJUSTIFICATION:
1183 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1184 break;
1186 case META_EXTFLOODFILL:
1187 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1188 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1189 *(mr->rdParm));
1190 break;
1192 case META_SETDIBTODEV:
1194 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1195 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1196 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1197 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1198 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1199 mr->rdParm[2], mr->rdParm[1], bits, info,
1200 mr->rdParm[0]);
1201 break;
1204 #define META_UNIMP(x) case x: \
1205 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1206 break;
1207 META_UNIMP(META_DRAWTEXT)
1208 META_UNIMP(META_ANIMATEPALETTE)
1209 META_UNIMP(META_SETPALENTRIES)
1210 META_UNIMP(META_RESIZEPALETTE)
1211 META_UNIMP(META_RESETDC)
1212 META_UNIMP(META_STARTDOC)
1213 META_UNIMP(META_STARTPAGE)
1214 META_UNIMP(META_ENDPAGE)
1215 META_UNIMP(META_ABORTDOC)
1216 META_UNIMP(META_ENDDOC)
1217 META_UNIMP(META_CREATEBRUSH)
1218 META_UNIMP(META_CREATEBITMAPINDIRECT)
1219 META_UNIMP(META_CREATEBITMAP)
1220 #undef META_UNIMP
1222 default:
1223 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1224 mr->rdFunction);
1228 /******************************************************************
1229 * PlayMetaFileRecord (GDI32.@)
1231 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1232 METARECORD *metarecord, UINT handles )
1234 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1235 handles*sizeof(HANDLETABLE16));
1236 unsigned int i = 0;
1237 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1238 handles);
1239 for (i=0; i<handles; i++)
1240 ht->objectHandle[i] = handletable->objectHandle[i];
1241 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1242 for (i=0; i<handles; i++)
1243 handletable->objectHandle[i] = ht->objectHandle[i];
1244 GlobalFree((HGLOBAL)ht);
1245 return TRUE;
1248 /******************************************************************
1249 * GetMetaFileBits (GDI.159)
1251 * Trade in a metafile object handle for a handle to the metafile memory.
1255 HGLOBAL16 WINAPI GetMetaFileBits16(
1256 HMETAFILE16 hmf /* [in] metafile handle */
1259 TRACE("hMem out: %04x\n", hmf);
1260 return hmf;
1263 /******************************************************************
1264 * SetMetaFileBits (GDI.160)
1266 * Trade in a metafile memory handle for a handle to a metafile object.
1267 * The memory region should hold a proper metafile, otherwise
1268 * problems will occur when it is used. Validity of the memory is not
1269 * checked. The function is essentially just the identity function.
1271 HMETAFILE16 WINAPI SetMetaFileBits16(
1272 HGLOBAL16 hMem
1273 /* [in] handle to a memory region holding a metafile */
1276 TRACE("hmf out: %04x\n", hMem);
1278 return hMem;
1281 /******************************************************************
1282 * SetMetaFileBitsBetter (GDI.196)
1284 * Trade in a metafile memory handle for a handle to a metafile object,
1285 * making a cursory check (using IsValidMetaFile()) that the memory
1286 * handle points to a valid metafile.
1288 * RETURNS
1289 * Handle to a metafile on success, NULL on failure..
1291 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1293 if( IsValidMetaFile16( hMeta ) )
1294 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1295 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1296 return (HMETAFILE16)0;
1299 /******************************************************************
1300 * SetMetaFileBitsEx (GDI32.@)
1302 * Create a metafile from raw data. No checking of the data is performed.
1303 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1305 HMETAFILE WINAPI SetMetaFileBitsEx(
1306 UINT size, /* [in] size of metafile, in bytes */
1307 const BYTE *lpData /* [in] pointer to metafile data */
1310 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1311 if (!mh) return 0;
1312 memcpy(mh, lpData, size);
1313 return MF_Create_HMETAFILE(mh);
1316 /*****************************************************************
1317 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1319 * Copies the data from metafile _hmf_ into the buffer _buf_.
1320 * If _buf_ is zero, returns size of buffer required. Otherwise,
1321 * returns number of bytes copied.
1323 UINT WINAPI GetMetaFileBitsEx(
1324 HMETAFILE hmf, /* [in] metafile */
1325 UINT nSize, /* [in] size of buf */
1326 LPVOID buf /* [out] buffer to receive raw metafile data */
1328 METAHEADER *mh = MF_GetMetaHeader(hmf);
1329 UINT mfSize;
1331 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1332 if (!mh) return 0; /* FIXME: error code */
1333 if(mh->mtType == METAFILE_DISK)
1334 FIXME("Disk-based metafile?\n");
1335 mfSize = mh->mtSize * 2;
1336 if (!buf) {
1337 MF_ReleaseMetaHeader(hmf);
1338 TRACE("returning size %d\n", mfSize);
1339 return mfSize;
1341 if(mfSize > nSize) mfSize = nSize;
1342 memmove(buf, mh, mfSize);
1343 MF_ReleaseMetaHeader(hmf);
1344 return mfSize;
1347 /******************************************************************
1348 * GetWinMetaFileBits [GDI32.@]
1350 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1351 UINT cbBuffer, LPBYTE lpbBuffer,
1352 INT fnMapMode, HDC hdcRef)
1354 FIXME("(%d,%d,%p,%d,%d): stub\n",
1355 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1356 return 0;
1359 /******************************************************************
1360 * MF_Play_MetaCreateRegion
1362 * Handles META_CREATEREGION for PlayMetaFileRecord().
1366 * The layout of the record looks something like this:
1368 * rdParm meaning
1369 * 0 Always 0?
1370 * 1 Always 6?
1371 * 2 Looks like a handle? - not constant
1372 * 3 0 or 1 ??
1373 * 4 Total number of bytes
1374 * 5 No. of separate bands = n [see below]
1375 * 6 Largest number of x co-ords in a band
1376 * 7-10 Bounding box x1 y1 x2 y2
1377 * 11-... n bands
1379 * Regions are divided into bands that are uniform in the
1380 * y-direction. Each band consists of pairs of on/off x-coords and is
1381 * written as
1382 * m y0 y1 x1 x2 x3 ... xm m
1383 * into successive rdParm[]s.
1385 * This is probably just a dump of the internal RGNOBJ?
1387 * HDMD - 18/12/97
1391 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1393 WORD band, pair;
1394 WORD *start, *end;
1395 INT16 y0, y1;
1396 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1398 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1399 band++, start = end + 1) {
1400 if(*start / 2 != (*start + 1) / 2) {
1401 WARN("Delimiter not even.\n");
1402 DeleteObject( hrgn2 );
1403 return FALSE;
1406 end = start + *start + 3;
1407 if(end > (WORD *)mr + mr->rdSize) {
1408 WARN("End points outside record.\n");
1409 DeleteObject( hrgn2 );
1410 return FALSE;
1413 if(*start != *end) {
1414 WARN("Mismatched delimiters.\n");
1415 DeleteObject( hrgn2 );
1416 return FALSE;
1419 y0 = *(INT16 *)(start + 1);
1420 y1 = *(INT16 *)(start + 2);
1421 for(pair = 0; pair < *start / 2; pair++) {
1422 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1423 *(INT16 *)(start + 4 + 2*pair), y1 );
1424 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1427 DeleteObject( hrgn2 );
1428 return TRUE;
1432 /******************************************************************
1433 * MF_Play_MetaExtTextOut
1435 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1438 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1440 LPINT16 dxx;
1441 LPSTR sot;
1442 DWORD len;
1443 WORD s1;
1445 s1 = mr->rdParm[2]; /* String length */
1446 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1447 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1448 /* rec len without dx array */
1450 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1451 if (mr->rdParm[3])
1452 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1454 if (mr->rdSize == len / 2)
1455 dxx = NULL; /* determine if array present */
1456 else
1457 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1458 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1459 else {
1460 TRACE("%s len: %ld\n", sot, mr->rdSize);
1461 WARN(
1462 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1463 len, s1, mr->rdSize, mr->rdParm[3]);
1464 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1466 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1467 mr->rdParm[0], /* Y position */
1468 mr->rdParm[3], /* options */
1469 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1470 /* rectangle */
1471 sot, /* string */
1472 s1, dxx); /* length, dx array */
1473 if (dxx)
1474 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1475 return TRUE;