Fixed some HFILE vs. HANDLE mismatches.
[wine/dcerpc.git] / objects / metafile.c
blob20ef65ce3057cae1cbb45e36ac4ea5ea2583a586
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 */
34 #include <string.h>
35 #include <fcntl.h>
36 #include "wine/winbase16.h"
37 #include "metafile.h"
38 #include "bitmap.h"
39 #include "heap.h"
40 #include "toolhelp.h"
41 #include "debugtools.h"
42 #include "global.h"
44 DEFAULT_DEBUG_CHANNEL(metafile);
46 /******************************************************************
47 * MF_AddHandle
49 * Add a handle to an external handle table and return the index
51 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
53 int i;
55 for (i = 0; i < htlen; i++)
57 if (*(ht->objectHandle + i) == 0)
59 *(ht->objectHandle + i) = hobj;
60 return i;
63 return -1;
67 /******************************************************************
68 * MF_Create_HMETATFILE
70 * Creates a (32 bit) HMETAFILE object from a METAHEADER
72 * HMETAFILEs are GDI objects.
74 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
76 HMETAFILE hmf = 0;
77 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
78 if (metaObj)
80 metaObj->mh = mh;
81 GDI_ReleaseObj( hmf );
83 return hmf;
86 /******************************************************************
87 * MF_Create_HMETATFILE16
89 * Creates a HMETAFILE16 object from a METAHEADER
91 * HMETAFILE16s are Global memory handles.
93 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
95 HMETAFILE16 hmf;
96 DWORD size;
98 if(mh->mtType == METAFILE_MEMORY)
99 size = mh->mtSize * sizeof(WORD);
100 else
101 size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
103 hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
104 GetCurrentPDB16(), WINE_LDT_FLAGS_DATA );
105 return hmf;
108 /******************************************************************
109 * MF_GetMetaHeader
111 * Returns ptr to METAHEADER associated with HMETAFILE
112 * Should be followed by call to MF_ReleaseMetaHeader
114 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
116 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
117 return metaObj ? metaObj->mh : 0;
120 /******************************************************************
121 * MF_GetMetaHeader16
123 * Returns ptr to METAHEADER associated with HMETAFILE16
124 * Should be followed by call to MF_ReleaseMetaHeader16
126 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
128 return GlobalLock16(hmf);
131 /******************************************************************
132 * MF_ReleaseMetaHeader
134 * Releases METAHEADER associated with HMETAFILE
136 static void MF_ReleaseMetaHeader( HMETAFILE hmf )
138 GDI_ReleaseObj( hmf );
141 /******************************************************************
142 * MF_ReleaseMetaHeader16
144 * Releases METAHEADER associated with HMETAFILE16
146 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
148 return GlobalUnlock16( hmf );
152 /******************************************************************
153 * DeleteMetaFile16 (GDI.127)
155 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
157 return !GlobalFree16( hmf );
160 /******************************************************************
161 * DeleteMetaFile (GDI32.69)
163 * Delete a memory-based metafile.
166 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
168 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
169 if (!metaObj) return FALSE;
170 HeapFree( GetProcessHeap(), 0, metaObj->mh );
171 GDI_FreeObject( hmf, metaObj );
172 return TRUE;
175 /******************************************************************
176 * MF_ReadMetaFile
178 * Returns a pointer to a memory based METAHEADER read in from file HFILE
181 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
183 METAHEADER *mh;
184 DWORD BytesRead, size;
186 size = sizeof(METAHEADER);
187 mh = HeapAlloc( GetProcessHeap(), 0, size );
188 if(!mh) return NULL;
189 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
190 BytesRead != size) {
191 HeapFree( GetProcessHeap(), 0, mh );
192 return NULL;
194 size = mh->mtSize * 2;
195 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
196 if(!mh) return NULL;
197 size -= sizeof(METAHEADER);
198 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
199 NULL) == 0 ||
200 BytesRead != size) {
201 HeapFree( GetProcessHeap(), 0, mh );
202 return NULL;
205 if (mh->mtType != METAFILE_MEMORY) {
206 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
207 mh->mtType = METAFILE_MEMORY;
209 return mh;
212 /******************************************************************
213 * GetMetaFile16 (GDI.124)
215 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
217 METAHEADER *mh;
218 HANDLE hFile;
220 TRACE("%s\n", lpFilename);
222 if(!lpFilename)
223 return 0;
225 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
226 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
227 return 0;
229 mh = MF_ReadMetaFile(hFile);
230 CloseHandle(hFile);
231 if(!mh) return 0;
232 return MF_Create_HMETAFILE16( mh );
235 /******************************************************************
236 * GetMetaFileA (GDI32.197)
238 * Read a metafile from a file. Returns handle to a memory-based metafile.
240 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
242 METAHEADER *mh;
243 HANDLE hFile;
245 TRACE("%s\n", lpFilename);
247 if(!lpFilename)
248 return 0;
250 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
251 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
252 return 0;
254 mh = MF_ReadMetaFile(hFile);
255 CloseHandle(hFile);
256 if(!mh) return 0;
257 return MF_Create_HMETAFILE( mh );
262 /******************************************************************
263 * GetMetaFileW (GDI32.199)
265 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
267 METAHEADER *mh;
268 HANDLE hFile;
270 TRACE("%s\n", debugstr_w(lpFilename));
272 if(!lpFilename)
273 return 0;
275 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
276 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
277 return 0;
279 mh = MF_ReadMetaFile(hFile);
280 CloseHandle(hFile);
281 if(!mh) return 0;
282 return MF_Create_HMETAFILE( mh );
286 /******************************************************************
287 * MF_LoadDiskBasedMetaFile
289 * Creates a new memory-based metafile from a disk-based one.
291 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
293 METAHEADERDISK *mhd;
294 HANDLE hfile;
295 METAHEADER *mh2;
297 if(mh->mtType != METAFILE_DISK) {
298 ERR("Not a disk based metafile\n");
299 return NULL;
301 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
303 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
304 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
305 WARN("Can't open file of disk based metafile\n");
306 return NULL;
308 mh2 = MF_ReadMetaFile(hfile);
309 CloseHandle(hfile);
310 return mh2;
313 /******************************************************************
314 * MF_CreateMetaHeaderDisk
316 * Take a memory based METAHEADER and change it to a disk based METAHEADER
317 * assosiated with filename. Note: Trashes contents of old one.
319 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
321 METAHEADERDISK *mhd;
322 DWORD size;
324 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
325 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
326 mh->mtType = METAFILE_DISK;
327 size = HeapSize( GetProcessHeap(), 0, mh );
328 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
329 strcpy(mhd->filename, filename);
330 return mh;
333 /******************************************************************
334 * CopyMetaFile16 (GDI.151)
336 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
338 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
339 METAHEADER *mh2 = NULL;
340 HANDLE hFile;
342 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
344 if(!mh) return 0;
346 if(mh->mtType == METAFILE_DISK)
347 mh2 = MF_LoadDiskBasedMetaFile(mh);
348 else {
349 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
350 memcpy( mh2, mh, mh->mtSize * 2 );
352 MF_ReleaseMetaHeader16( hSrcMetaFile );
354 if(lpFilename) { /* disk based metafile */
355 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
356 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
357 HeapFree( GetProcessHeap(), 0, mh2 );
358 return 0;
360 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
361 CloseHandle(hFile);
362 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
365 return MF_Create_HMETAFILE16( mh2 );
369 /******************************************************************
370 * CopyMetaFileA (GDI32.23)
372 * Copies the metafile corresponding to hSrcMetaFile to either
373 * a disk file, if a filename is given, or to a new memory based
374 * metafile, if lpFileName is NULL.
376 * RETURNS
378 * Handle to metafile copy on success, NULL on failure.
380 * BUGS
382 * Copying to disk returns NULL even if successful.
384 HMETAFILE WINAPI CopyMetaFileA(
385 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
386 LPCSTR lpFilename /* [in] filename if copying to a file */
388 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
389 METAHEADER *mh2 = NULL;
390 HANDLE hFile;
392 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
394 if(!mh) return 0;
396 if(mh->mtType == METAFILE_DISK)
397 mh2 = MF_LoadDiskBasedMetaFile(mh);
398 else {
399 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
400 memcpy( mh2, mh, mh->mtSize * 2 );
402 MF_ReleaseMetaHeader( hSrcMetaFile );
404 if(lpFilename) { /* disk based metafile */
405 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
406 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
407 HeapFree( GetProcessHeap(), 0, mh2 );
408 return 0;
410 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
411 CloseHandle(hFile);
412 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
415 return MF_Create_HMETAFILE( mh2 );
419 /******************************************************************
420 * CopyMetaFileW (GDI32.24)
422 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
423 LPCWSTR lpFilename )
425 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
426 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
427 HeapFree( GetProcessHeap(), 0, p );
428 return ret;
432 /******************************************************************
433 * IsValidMetaFile (GDI.410)
435 * Attempts to check if a given metafile is correctly formatted.
436 * Currently, the only things verified are several properties of the
437 * header.
439 * RETURNS
440 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
442 * BUGS
443 * This is not exactly what windows does, see _Undocumented_Windows_
444 * for details.
446 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
448 BOOL16 res=FALSE;
449 METAHEADER *mh = MF_GetMetaHeader16(hmf);
450 if (mh) {
451 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
452 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
453 if (mh->mtVersion == MFVERSION)
454 res=TRUE;
455 MF_ReleaseMetaHeader16(hmf);
457 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
458 return res;
462 /*******************************************************************
463 * MF_PlayMetaFile
465 * Helper for PlayMetaFile
467 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
470 METARECORD *mr;
471 HANDLETABLE16 *ht;
472 int offset = 0;
473 WORD i;
474 HPEN hPen;
475 HBRUSH hBrush;
476 HFONT hFont;
477 BOOL loaded = FALSE;
479 if (!mh) return FALSE;
480 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
481 mh = MF_LoadDiskBasedMetaFile(mh);
482 if(!mh) return FALSE;
483 loaded = TRUE;
486 /* save the current pen, brush and font */
487 hPen = GetCurrentObject(hdc, OBJ_PEN);
488 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
489 hFont = GetCurrentObject(hdc, OBJ_FONT);
491 /* create the handle table */
492 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
493 sizeof(HANDLETABLE16) * mh->mtNoObjects);
494 if(!ht) return FALSE;
496 /* loop through metafile playing records */
497 offset = mh->mtHeaderSize * 2;
498 while (offset < mh->mtSize * 2)
500 mr = (METARECORD *)((char *)mh + offset);
501 TRACE("offset=%04x,size=%08lx\n",
502 offset, mr->rdSize);
503 if (!mr->rdSize) {
504 TRACE(
505 "Entry got size 0 at offset %d, total mf length is %ld\n",
506 offset,mh->mtSize*2);
507 break; /* would loop endlessly otherwise */
509 offset += mr->rdSize * 2;
510 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
513 SelectObject(hdc, hBrush);
514 SelectObject(hdc, hPen);
515 SelectObject(hdc, hFont);
517 /* free objects in handle table */
518 for(i = 0; i < mh->mtNoObjects; i++)
519 if(*(ht->objectHandle + i) != 0)
520 DeleteObject(*(ht->objectHandle + i));
522 /* free handle table */
523 HeapFree( GetProcessHeap(), 0, ht );
524 if(loaded)
525 HeapFree( GetProcessHeap(), 0, mh );
526 return TRUE;
529 /******************************************************************
530 * PlayMetaFile16 (GDI.123)
533 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
535 BOOL16 ret;
536 METAHEADER *mh = MF_GetMetaHeader16( hmf );
537 ret = MF_PlayMetaFile( hdc, mh );
538 MF_ReleaseMetaHeader16( hmf );
539 return ret;
542 /******************************************************************
543 * PlayMetaFile (GDI32.265)
545 * Renders the metafile specified by hmf in the DC specified by
546 * hdc. Returns FALSE on failure, TRUE on success.
548 BOOL WINAPI PlayMetaFile(
549 HDC hdc, /* [in] handle of DC to render in */
550 HMETAFILE hmf /* [in] handle of metafile to render */
553 BOOL ret;
554 METAHEADER *mh = MF_GetMetaHeader( hmf );
555 ret = MF_PlayMetaFile( hdc, mh );
556 MF_ReleaseMetaHeader( hmf );
557 return ret;
561 /******************************************************************
562 * EnumMetaFile16 (GDI.175)
565 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
566 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
568 METAHEADER *mh = MF_GetMetaHeader16(hmf);
569 METARECORD *mr;
570 HANDLETABLE16 *ht;
571 HGLOBAL16 hHT;
572 SEGPTR spht;
573 int offset = 0;
574 WORD i, seg;
575 HPEN hPen;
576 HBRUSH hBrush;
577 HFONT hFont;
578 BOOL16 result = TRUE, loaded = FALSE;
580 TRACE("(%04x, %04x, %08lx, %08lx)\n",
581 hdc, hmf, (DWORD)lpEnumFunc, lpData);
584 if(!mh) return FALSE;
585 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
586 mh = MF_LoadDiskBasedMetaFile(mh);
587 if(!mh) return FALSE;
588 loaded = TRUE;
591 /* save the current pen, brush and font */
592 hPen = GetCurrentObject(hdc, OBJ_PEN);
593 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
594 hFont = GetCurrentObject(hdc, OBJ_FONT);
596 /* create the handle table */
598 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
599 sizeof(HANDLETABLE16) * mh->mtNoObjects);
600 spht = K32WOWGlobalLock16(hHT);
602 seg = GlobalHandleToSel16(hmf);
603 offset = mh->mtHeaderSize * 2;
605 /* loop through metafile records */
607 while (offset < (mh->mtSize * 2))
609 mr = (METARECORD *)((char *)mh + offset);
610 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
611 (METARECORD *)MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
612 mh->mtNoObjects, (LONG)lpData ))
614 result = FALSE;
615 break;
619 offset += (mr->rdSize * 2);
622 SelectObject(hdc, hBrush);
623 SelectObject(hdc, hPen);
624 SelectObject(hdc, hFont);
626 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
628 /* free objects in handle table */
629 for(i = 0; i < mh->mtNoObjects; i++)
630 if(*(ht->objectHandle + i) != 0)
631 DeleteObject(*(ht->objectHandle + i));
633 /* free handle table */
634 GlobalFree16(hHT);
635 if(loaded)
636 HeapFree( GetProcessHeap(), 0, mh );
637 MF_ReleaseMetaHeader16(hmf);
638 return result;
641 /******************************************************************
642 * EnumMetaFile (GDI32.88)
644 * Loop through the metafile records in hmf, calling the user-specified
645 * function for each one, stopping when the user's function returns FALSE
646 * (which is considered to be failure)
647 * or when no records are left (which is considered to be success).
649 * RETURNS
650 * TRUE on success, FALSE on failure.
652 * HISTORY
653 * Niels de carpentier, april 1996
655 BOOL WINAPI EnumMetaFile(
656 HDC hdc,
657 HMETAFILE hmf,
658 MFENUMPROC lpEnumFunc,
659 LPARAM lpData
661 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
662 METARECORD *mr;
663 HANDLETABLE *ht;
664 BOOL result = TRUE;
665 int i, offset = 0;
666 HPEN hPen;
667 HBRUSH hBrush;
668 HFONT hFont;
670 TRACE("(%08x,%08x,%p,%p)\n",
671 hdc, hmf, lpEnumFunc, (void*)lpData);
672 if (!mh) return 0;
673 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
674 mhTemp = MF_LoadDiskBasedMetaFile(mh);
675 if(!mhTemp)
677 MF_ReleaseMetaHeader(hmf);
678 return FALSE;
680 mh = mhTemp;
682 else
684 /* We need to copy this thing instead of use it directly because we
685 * have to close the hmf handle for the purpose of avoiding deadlock.
687 mhTemp = HeapAlloc( GetProcessHeap(), 0, mh->mtHeaderSize + mh->mtSize*2 );
688 if(!mhTemp)
690 MF_ReleaseMetaHeader(hmf);
691 return FALSE;
693 memcpy( mhTemp, mh, mh->mtHeaderSize + mh->mtSize*2 );
694 mh = mhTemp;
696 MF_ReleaseMetaHeader(hmf);
697 hmf = 0; /* just in case */
699 /* save the current pen, brush and font */
700 hPen = GetCurrentObject(hdc, OBJ_PEN);
701 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
702 hFont = GetCurrentObject(hdc, OBJ_FONT);
704 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
705 sizeof(HANDLETABLE) * mh->mtNoObjects);
707 /* loop through metafile records */
708 offset = mh->mtHeaderSize * 2;
710 while (offset < (mh->mtSize * 2))
712 mr = (METARECORD *)((char *)mh + offset);
713 TRACE("Calling EnumFunc with record type %x\n",
714 mr->rdFunction);
715 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
717 result = FALSE;
718 break;
721 offset += (mr->rdSize * 2);
724 /* restore pen, brush and font */
725 SelectObject(hdc, hBrush);
726 SelectObject(hdc, hPen);
727 SelectObject(hdc, hFont);
729 /* free objects in handle table */
730 for(i = 0; i < mh->mtNoObjects; i++)
731 if(*(ht->objectHandle + i) != 0)
732 DeleteObject(*(ht->objectHandle + i));
734 /* free handle table */
735 HeapFree( GetProcessHeap(), 0, ht);
736 /* free a copy of metafile */
737 HeapFree( GetProcessHeap(), 0, mh );
738 return result;
741 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
742 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
743 /******************************************************************
744 * PlayMetaFileRecord16 (GDI.176)
746 * Render a single metafile record specified by *mr in the DC hdc, while
747 * using the handle table *ht, of length nHandles,
748 * to store metafile objects.
750 * BUGS
751 * The following metafile records are unimplemented:
753 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
754 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
755 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
758 void WINAPI PlayMetaFileRecord16(
759 HDC16 hdc, /* [in] DC to render metafile into */
760 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
761 METARECORD *mr, /* [in] pointer to metafile record to render */
762 UINT16 nHandles /* [in] size of handle table */
764 short s1;
765 HANDLE16 hndl;
766 char *ptr;
767 BITMAPINFOHEADER *infohdr;
769 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
770 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
772 switch (mr->rdFunction)
774 case META_EOF:
775 break;
777 case META_DELETEOBJECT:
778 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
779 *(ht->objectHandle + *(mr->rdParm)) = 0;
780 break;
782 case META_SETBKCOLOR:
783 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
784 break;
786 case META_SETBKMODE:
787 SetBkMode16(hdc, *(mr->rdParm));
788 break;
790 case META_SETMAPMODE:
791 SetMapMode16(hdc, *(mr->rdParm));
792 break;
794 case META_SETROP2:
795 SetROP216(hdc, *(mr->rdParm));
796 break;
798 case META_SETRELABS:
799 SetRelAbs16(hdc, *(mr->rdParm));
800 break;
802 case META_SETPOLYFILLMODE:
803 SetPolyFillMode16(hdc, *(mr->rdParm));
804 break;
806 case META_SETSTRETCHBLTMODE:
807 SetStretchBltMode16(hdc, *(mr->rdParm));
808 break;
810 case META_SETTEXTCOLOR:
811 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
812 break;
814 case META_SETWINDOWORG:
815 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
816 break;
818 case META_SETWINDOWEXT:
819 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
820 break;
822 case META_SETVIEWPORTORG:
823 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
824 break;
826 case META_SETVIEWPORTEXT:
827 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
828 break;
830 case META_OFFSETWINDOWORG:
831 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
832 break;
834 case META_SCALEWINDOWEXT:
835 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
836 *(mr->rdParm + 1), *(mr->rdParm));
837 break;
839 case META_OFFSETVIEWPORTORG:
840 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
841 break;
843 case META_SCALEVIEWPORTEXT:
844 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
845 *(mr->rdParm + 1), *(mr->rdParm));
846 break;
848 case META_LINETO:
849 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
850 break;
852 case META_MOVETO:
853 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
854 break;
856 case META_EXCLUDECLIPRECT:
857 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
858 *(mr->rdParm + 1), *(mr->rdParm) );
859 break;
861 case META_INTERSECTCLIPRECT:
862 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
863 *(mr->rdParm + 1), *(mr->rdParm) );
864 break;
866 case META_ARC:
867 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
868 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
869 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
870 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
871 break;
873 case META_ELLIPSE:
874 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
875 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
876 break;
878 case META_FLOODFILL:
879 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
880 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
881 break;
883 case META_PIE:
884 Pie(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_RECTANGLE:
891 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
893 break;
895 case META_ROUNDRECT:
896 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
897 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
898 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
899 break;
901 case META_PATBLT:
902 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
903 *(mr->rdParm + 3), *(mr->rdParm + 2),
904 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
905 break;
907 case META_SAVEDC:
908 SaveDC(hdc);
909 break;
911 case META_SETPIXEL:
912 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
913 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
914 break;
916 case META_OFFSETCLIPRGN:
917 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
918 break;
920 case META_TEXTOUT:
921 s1 = *(mr->rdParm);
922 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
923 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
924 (char *)(mr->rdParm + 1), s1);
925 break;
927 case META_POLYGON:
928 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
929 break;
931 case META_POLYPOLYGON:
932 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
933 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
934 break;
936 case META_POLYLINE:
937 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
938 break;
940 case META_RESTOREDC:
941 RestoreDC(hdc, (INT16)*(mr->rdParm));
942 break;
944 case META_SELECTOBJECT:
945 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
946 break;
948 case META_CHORD:
949 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
950 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
951 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
952 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
953 break;
955 case META_CREATEPATTERNBRUSH:
956 switch (*(mr->rdParm))
958 case BS_PATTERN:
959 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
960 MF_AddHandle(ht, nHandles,
961 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
962 infohdr->biHeight,
963 infohdr->biPlanes,
964 infohdr->biBitCount,
965 (LPSTR)(mr->rdParm +
966 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
967 break;
969 case BS_DIBPATTERN:
970 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
971 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
972 ptr = GlobalLock16(hndl);
973 memcpy(ptr, mr->rdParm + 2, s1);
974 GlobalUnlock16(hndl);
975 MF_AddHandle(ht, nHandles,
976 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
977 GlobalFree16(hndl);
978 break;
980 default:
981 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
982 mr->rdParm[0]);
983 break;
985 break;
987 case META_CREATEPENINDIRECT:
988 MF_AddHandle(ht, nHandles,
989 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
990 break;
992 case META_CREATEFONTINDIRECT:
993 MF_AddHandle(ht, nHandles,
994 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
995 break;
997 case META_CREATEBRUSHINDIRECT:
998 MF_AddHandle(ht, nHandles,
999 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1000 break;
1002 case META_CREATEPALETTE:
1003 MF_AddHandle(ht, nHandles,
1004 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1005 break;
1007 case META_SETTEXTALIGN:
1008 SetTextAlign16(hdc, *(mr->rdParm));
1009 break;
1011 case META_SELECTPALETTE:
1012 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1013 *(mr->rdParm));
1014 break;
1016 case META_SETMAPPERFLAGS:
1017 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1018 break;
1020 case META_REALIZEPALETTE:
1021 GDIRealizePalette16(hdc);
1022 break;
1024 case META_ESCAPE:
1025 FIXME("META_ESCAPE unimplemented.\n");
1026 break;
1028 case META_EXTTEXTOUT:
1029 MF_Play_MetaExtTextOut( hdc, mr );
1030 break;
1032 case META_STRETCHDIB:
1034 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1035 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1036 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1037 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1038 mr->rdParm[4],mr->rdParm[3],bits,info,
1039 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1041 break;
1043 case META_DIBSTRETCHBLT:
1045 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1046 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1047 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1048 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1049 mr->rdParm[3],mr->rdParm[2],bits,info,
1050 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1052 break;
1054 case META_STRETCHBLT:
1056 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1057 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1058 mr->rdParm[11], /*Height*/
1059 mr->rdParm[13], /*Planes*/
1060 mr->rdParm[14], /*BitsPixel*/
1061 (LPSTR)&mr->rdParm[15]); /*bits*/
1062 SelectObject(hdcSrc,hbitmap);
1063 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1064 mr->rdParm[7],mr->rdParm[6],
1065 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1066 mr->rdParm[3],mr->rdParm[2],
1067 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1068 DeleteDC(hdcSrc);
1070 break;
1072 case META_BITBLT:
1074 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1075 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1076 mr->rdParm[8]/*Height*/,
1077 mr->rdParm[10]/*Planes*/,
1078 mr->rdParm[11]/*BitsPixel*/,
1079 (LPSTR)&mr->rdParm[12]/*bits*/);
1080 SelectObject(hdcSrc,hbitmap);
1081 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1082 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1083 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1084 MAKELONG(0,mr->rdParm[0]));
1085 DeleteDC(hdcSrc);
1087 break;
1089 case META_CREATEREGION:
1091 HRGN hrgn = CreateRectRgn(0,0,0,0);
1093 MF_Play_MetaCreateRegion(mr, hrgn);
1094 MF_AddHandle(ht, nHandles, hrgn);
1096 break;
1098 case META_FILLREGION:
1099 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1100 *(ht->objectHandle + *(mr->rdParm)));
1101 break;
1103 case META_FRAMEREGION:
1104 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1105 *(ht->objectHandle + *(mr->rdParm+2)),
1106 *(mr->rdParm+1), *(mr->rdParm));
1107 break;
1109 case META_INVERTREGION:
1110 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1111 break;
1113 case META_PAINTREGION:
1114 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1115 break;
1117 case META_SELECTCLIPREGION:
1118 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1119 break;
1121 case META_DIBCREATEPATTERNBRUSH:
1122 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1123 but there's no difference */
1125 TRACE("%d\n",*(mr->rdParm));
1126 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1127 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1128 ptr = GlobalLock16(hndl);
1129 memcpy(ptr, mr->rdParm + 2, s1);
1130 GlobalUnlock16(hndl);
1131 MF_AddHandle(ht, nHandles,
1132 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1133 GlobalFree16(hndl);
1134 break;
1136 case META_DIBBITBLT:
1137 /* In practice I've found that there are two layouts for
1138 META_DIBBITBLT, one (the first here) is the usual one when a src
1139 dc is actually passed to it, the second occurs when the src dc is
1140 passed in as NULL to the creating BitBlt. As the second case has
1141 no dib, a size check will suffice to distinguish.
1143 Caolan.McNamara@ul.ie */
1145 if (mr->rdSize > 12) {
1146 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1147 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1149 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1150 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1151 mr->rdParm[5], mr->rdParm[4], bits, info,
1152 DIB_RGB_COLORS,
1153 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1154 } else { /* equivalent to a PatBlt */
1155 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1156 mr->rdParm[6], mr->rdParm[5],
1157 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1159 break;
1161 case META_SETTEXTCHAREXTRA:
1162 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1163 break;
1165 case META_SETTEXTJUSTIFICATION:
1166 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1167 break;
1169 case META_EXTFLOODFILL:
1170 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1171 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1172 *(mr->rdParm));
1173 break;
1175 case META_SETDIBTODEV:
1177 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1178 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1179 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1180 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1181 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1182 mr->rdParm[2], mr->rdParm[1], bits, info,
1183 mr->rdParm[0]);
1184 break;
1187 #define META_UNIMP(x) case x: \
1188 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1189 break;
1190 META_UNIMP(META_DRAWTEXT)
1191 META_UNIMP(META_ANIMATEPALETTE)
1192 META_UNIMP(META_SETPALENTRIES)
1193 META_UNIMP(META_RESIZEPALETTE)
1194 META_UNIMP(META_RESETDC)
1195 META_UNIMP(META_STARTDOC)
1196 META_UNIMP(META_STARTPAGE)
1197 META_UNIMP(META_ENDPAGE)
1198 META_UNIMP(META_ABORTDOC)
1199 META_UNIMP(META_ENDDOC)
1200 META_UNIMP(META_CREATEBRUSH)
1201 META_UNIMP(META_CREATEBITMAPINDIRECT)
1202 META_UNIMP(META_CREATEBITMAP)
1203 #undef META_UNIMP
1205 default:
1206 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1207 mr->rdFunction);
1211 /******************************************************************
1212 * PlayMetaFileRecord (GDI32.266)
1214 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1215 METARECORD *metarecord, UINT handles )
1217 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1218 handles*sizeof(HANDLETABLE16));
1219 int i = 0;
1220 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1221 handles);
1222 for (i=0; i<handles; i++)
1223 ht->objectHandle[i] = handletable->objectHandle[i];
1224 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1225 for (i=0; i<handles; i++)
1226 handletable->objectHandle[i] = ht->objectHandle[i];
1227 GlobalFree((HGLOBAL)ht);
1228 return TRUE;
1231 /******************************************************************
1232 * GetMetaFileBits (GDI.159)
1234 * Trade in a metafile object handle for a handle to the metafile memory.
1238 HGLOBAL16 WINAPI GetMetaFileBits16(
1239 HMETAFILE16 hmf /* [in] metafile handle */
1242 TRACE("hMem out: %04x\n", hmf);
1243 return hmf;
1246 /******************************************************************
1247 * SetMetaFileBits (GDI.160)
1249 * Trade in a metafile memory handle for a handle to a metafile object.
1250 * The memory region should hold a proper metafile, otherwise
1251 * problems will occur when it is used. Validity of the memory is not
1252 * checked. The function is essentially just the identity function.
1254 HMETAFILE16 WINAPI SetMetaFileBits16(
1255 HGLOBAL16 hMem
1256 /* [in] handle to a memory region holding a metafile */
1259 TRACE("hmf out: %04x\n", hMem);
1261 return hMem;
1264 /******************************************************************
1265 * SetMetaFileBitsBetter (GDI.196)
1267 * Trade in a metafile memory handle for a handle to a metafile object,
1268 * making a cursory check (using IsValidMetaFile()) that the memory
1269 * handle points to a valid metafile.
1271 * RETURNS
1272 * Handle to a metafile on success, NULL on failure..
1274 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1276 if( IsValidMetaFile16( hMeta ) )
1277 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1278 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1279 return (HMETAFILE16)0;
1282 /******************************************************************
1283 * SetMetaFileBitsEx (GDI32.323)
1285 * Create a metafile from raw data. No checking of the data is performed.
1286 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1288 HMETAFILE WINAPI SetMetaFileBitsEx(
1289 UINT size, /* [in] size of metafile, in bytes */
1290 const BYTE *lpData /* [in] pointer to metafile data */
1293 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1294 if (!mh) return 0;
1295 memcpy(mh, lpData, size);
1296 return MF_Create_HMETAFILE(mh);
1299 /*****************************************************************
1300 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1302 * Copies the data from metafile _hmf_ into the buffer _buf_.
1303 * If _buf_ is zero, returns size of buffer required. Otherwise,
1304 * returns number of bytes copied.
1306 UINT WINAPI GetMetaFileBitsEx(
1307 HMETAFILE hmf, /* [in] metafile */
1308 UINT nSize, /* [in] size of buf */
1309 LPVOID buf /* [out] buffer to receive raw metafile data */
1311 METAHEADER *mh = MF_GetMetaHeader(hmf);
1312 UINT mfSize;
1314 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1315 if (!mh) return 0; /* FIXME: error code */
1316 if(mh->mtType == METAFILE_DISK)
1317 FIXME("Disk-based metafile?\n");
1318 mfSize = mh->mtSize * 2;
1319 if (!buf) {
1320 MF_ReleaseMetaHeader(hmf);
1321 TRACE("returning size %d\n", mfSize);
1322 return mfSize;
1324 if(mfSize > nSize) mfSize = nSize;
1325 memmove(buf, mh, mfSize);
1326 MF_ReleaseMetaHeader(hmf);
1327 return mfSize;
1330 /******************************************************************
1331 * GetWinMetaFileBits [GDI32.241]
1333 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1334 UINT cbBuffer, LPBYTE lpbBuffer,
1335 INT fnMapMode, HDC hdcRef)
1337 FIXME("(%d,%d,%p,%d,%d): stub\n",
1338 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1339 return 0;
1342 /******************************************************************
1343 * MF_Play_MetaCreateRegion
1345 * Handles META_CREATEREGION for PlayMetaFileRecord().
1349 * The layout of the record looks something like this:
1351 * rdParm meaning
1352 * 0 Always 0?
1353 * 1 Always 6?
1354 * 2 Looks like a handle? - not constant
1355 * 3 0 or 1 ??
1356 * 4 Total number of bytes
1357 * 5 No. of seperate bands = n [see below]
1358 * 6 Largest number of x co-ords in a band
1359 * 7-10 Bounding box x1 y1 x2 y2
1360 * 11-... n bands
1362 * Regions are divided into bands that are uniform in the
1363 * y-direction. Each band consists of pairs of on/off x-coords and is
1364 * written as
1365 * m y0 y1 x1 x2 x3 ... xm m
1366 * into successive rdParm[]s.
1368 * This is probably just a dump of the internal RGNOBJ?
1370 * HDMD - 18/12/97
1374 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1376 WORD band, pair;
1377 WORD *start, *end;
1378 INT16 y0, y1;
1379 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1381 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1382 band++, start = end + 1) {
1383 if(*start / 2 != (*start + 1) / 2) {
1384 WARN("Delimiter not even.\n");
1385 DeleteObject( hrgn2 );
1386 return FALSE;
1389 end = start + *start + 3;
1390 if(end > (WORD *)mr + mr->rdSize) {
1391 WARN("End points outside record.\n");
1392 DeleteObject( hrgn2 );
1393 return FALSE;
1396 if(*start != *end) {
1397 WARN("Mismatched delimiters.\n");
1398 DeleteObject( hrgn2 );
1399 return FALSE;
1402 y0 = *(INT16 *)(start + 1);
1403 y1 = *(INT16 *)(start + 2);
1404 for(pair = 0; pair < *start / 2; pair++) {
1405 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1406 *(INT16 *)(start + 4 + 2*pair), y1 );
1407 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1410 DeleteObject( hrgn2 );
1411 return TRUE;
1415 /******************************************************************
1416 * MF_Play_MetaExtTextOut
1418 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1421 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1423 LPINT16 dxx;
1424 LPSTR sot;
1425 DWORD len;
1426 WORD s1;
1428 s1 = mr->rdParm[2]; /* String length */
1429 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1430 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1431 /* rec len without dx array */
1433 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1434 if (mr->rdParm[3])
1435 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1437 if (mr->rdSize == len / 2)
1438 dxx = NULL; /* determine if array present */
1439 else
1440 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1441 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1442 else {
1443 TRACE("%s len: %ld\n", sot, mr->rdSize);
1444 WARN(
1445 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1446 len, s1, mr->rdSize, mr->rdParm[3]);
1447 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1449 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1450 mr->rdParm[0], /* Y position */
1451 mr->rdParm[3], /* options */
1452 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1453 /* rectangle */
1454 sot, /* string */
1455 s1, dxx); /* length, dx array */
1456 if (dxx)
1457 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1458 return TRUE;