Added unicode MDI client window proc.
[wine.git] / objects / metafile.c
blobccda9ab1ec23b8e05471fd0d656835df98f5df69
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 unsigned 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 unsigned 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;
666 unsigned int offset = 0;
667 HPEN hPen;
668 HBRUSH hBrush;
669 HFONT hFont;
671 TRACE("(%08x,%08x,%p,%p)\n",
672 hdc, hmf, lpEnumFunc, (void*)lpData);
673 if (!mh) return 0;
674 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
675 mhTemp = MF_LoadDiskBasedMetaFile(mh);
676 if(!mhTemp)
678 MF_ReleaseMetaHeader(hmf);
679 return FALSE;
681 mh = mhTemp;
683 else
685 /* We need to copy this thing instead of use it directly because we
686 * have to close the hmf handle for the purpose of avoiding deadlock.
688 mhTemp = HeapAlloc( GetProcessHeap(), 0, mh->mtHeaderSize + mh->mtSize*2 );
689 if(!mhTemp)
691 MF_ReleaseMetaHeader(hmf);
692 return FALSE;
694 memcpy( mhTemp, mh, mh->mtHeaderSize + mh->mtSize*2 );
695 mh = mhTemp;
697 MF_ReleaseMetaHeader(hmf);
698 hmf = 0; /* just in case */
700 /* save the current pen, brush and font */
701 hPen = GetCurrentObject(hdc, OBJ_PEN);
702 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
703 hFont = GetCurrentObject(hdc, OBJ_FONT);
705 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
706 sizeof(HANDLETABLE) * mh->mtNoObjects);
708 /* loop through metafile records */
709 offset = mh->mtHeaderSize * 2;
711 while (offset < (mh->mtSize * 2))
713 mr = (METARECORD *)((char *)mh + offset);
714 TRACE("Calling EnumFunc with record type %x\n",
715 mr->rdFunction);
716 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
718 result = FALSE;
719 break;
722 offset += (mr->rdSize * 2);
725 /* restore pen, brush and font */
726 SelectObject(hdc, hBrush);
727 SelectObject(hdc, hPen);
728 SelectObject(hdc, hFont);
730 /* free objects in handle table */
731 for(i = 0; i < mh->mtNoObjects; i++)
732 if(*(ht->objectHandle + i) != 0)
733 DeleteObject(*(ht->objectHandle + i));
735 /* free handle table */
736 HeapFree( GetProcessHeap(), 0, ht);
737 /* free a copy of metafile */
738 HeapFree( GetProcessHeap(), 0, mh );
739 return result;
742 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
743 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
744 /******************************************************************
745 * PlayMetaFileRecord16 (GDI.176)
747 * Render a single metafile record specified by *mr in the DC hdc, while
748 * using the handle table *ht, of length nHandles,
749 * to store metafile objects.
751 * BUGS
752 * The following metafile records are unimplemented:
754 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
755 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
756 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
759 void WINAPI PlayMetaFileRecord16(
760 HDC16 hdc, /* [in] DC to render metafile into */
761 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
762 METARECORD *mr, /* [in] pointer to metafile record to render */
763 UINT16 nHandles /* [in] size of handle table */
765 short s1;
766 HANDLE16 hndl;
767 char *ptr;
768 BITMAPINFOHEADER *infohdr;
770 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
771 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
773 switch (mr->rdFunction)
775 case META_EOF:
776 break;
778 case META_DELETEOBJECT:
779 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
780 *(ht->objectHandle + *(mr->rdParm)) = 0;
781 break;
783 case META_SETBKCOLOR:
784 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
785 break;
787 case META_SETBKMODE:
788 SetBkMode16(hdc, *(mr->rdParm));
789 break;
791 case META_SETMAPMODE:
792 SetMapMode16(hdc, *(mr->rdParm));
793 break;
795 case META_SETROP2:
796 SetROP216(hdc, *(mr->rdParm));
797 break;
799 case META_SETRELABS:
800 SetRelAbs16(hdc, *(mr->rdParm));
801 break;
803 case META_SETPOLYFILLMODE:
804 SetPolyFillMode16(hdc, *(mr->rdParm));
805 break;
807 case META_SETSTRETCHBLTMODE:
808 SetStretchBltMode16(hdc, *(mr->rdParm));
809 break;
811 case META_SETTEXTCOLOR:
812 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
813 break;
815 case META_SETWINDOWORG:
816 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
817 break;
819 case META_SETWINDOWEXT:
820 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
821 break;
823 case META_SETVIEWPORTORG:
824 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
825 break;
827 case META_SETVIEWPORTEXT:
828 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
829 break;
831 case META_OFFSETWINDOWORG:
832 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
833 break;
835 case META_SCALEWINDOWEXT:
836 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
837 *(mr->rdParm + 1), *(mr->rdParm));
838 break;
840 case META_OFFSETVIEWPORTORG:
841 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
842 break;
844 case META_SCALEVIEWPORTEXT:
845 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
846 *(mr->rdParm + 1), *(mr->rdParm));
847 break;
849 case META_LINETO:
850 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
851 break;
853 case META_MOVETO:
854 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
855 break;
857 case META_EXCLUDECLIPRECT:
858 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
859 *(mr->rdParm + 1), *(mr->rdParm) );
860 break;
862 case META_INTERSECTCLIPRECT:
863 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
864 *(mr->rdParm + 1), *(mr->rdParm) );
865 break;
867 case META_ARC:
868 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
869 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
870 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
871 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
872 break;
874 case META_ELLIPSE:
875 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
876 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
877 break;
879 case META_FLOODFILL:
880 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
881 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
882 break;
884 case META_PIE:
885 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
886 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
887 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
888 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
889 break;
891 case META_RECTANGLE:
892 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
893 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
894 break;
896 case META_ROUNDRECT:
897 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
898 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
899 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
900 break;
902 case META_PATBLT:
903 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
904 *(mr->rdParm + 3), *(mr->rdParm + 2),
905 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
906 break;
908 case META_SAVEDC:
909 SaveDC(hdc);
910 break;
912 case META_SETPIXEL:
913 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
914 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
915 break;
917 case META_OFFSETCLIPRGN:
918 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
919 break;
921 case META_TEXTOUT:
922 s1 = *(mr->rdParm);
923 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
924 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
925 (char *)(mr->rdParm + 1), s1);
926 break;
928 case META_POLYGON:
929 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
930 break;
932 case META_POLYPOLYGON:
933 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
934 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
935 break;
937 case META_POLYLINE:
938 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
939 break;
941 case META_RESTOREDC:
942 RestoreDC(hdc, (INT16)*(mr->rdParm));
943 break;
945 case META_SELECTOBJECT:
946 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
947 break;
949 case META_CHORD:
950 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
951 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
952 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
953 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
954 break;
956 case META_CREATEPATTERNBRUSH:
957 switch (*(mr->rdParm))
959 case BS_PATTERN:
960 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
961 MF_AddHandle(ht, nHandles,
962 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
963 infohdr->biHeight,
964 infohdr->biPlanes,
965 infohdr->biBitCount,
966 (LPSTR)(mr->rdParm +
967 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
968 break;
970 case BS_DIBPATTERN:
971 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
972 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
973 ptr = GlobalLock16(hndl);
974 memcpy(ptr, mr->rdParm + 2, s1);
975 GlobalUnlock16(hndl);
976 MF_AddHandle(ht, nHandles,
977 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
978 GlobalFree16(hndl);
979 break;
981 default:
982 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
983 mr->rdParm[0]);
984 break;
986 break;
988 case META_CREATEPENINDIRECT:
989 MF_AddHandle(ht, nHandles,
990 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
991 break;
993 case META_CREATEFONTINDIRECT:
994 MF_AddHandle(ht, nHandles,
995 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
996 break;
998 case META_CREATEBRUSHINDIRECT:
999 MF_AddHandle(ht, nHandles,
1000 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
1001 break;
1003 case META_CREATEPALETTE:
1004 MF_AddHandle(ht, nHandles,
1005 CreatePalette16((LPLOGPALETTE)mr->rdParm));
1006 break;
1008 case META_SETTEXTALIGN:
1009 SetTextAlign16(hdc, *(mr->rdParm));
1010 break;
1012 case META_SELECTPALETTE:
1013 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1014 *(mr->rdParm));
1015 break;
1017 case META_SETMAPPERFLAGS:
1018 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1019 break;
1021 case META_REALIZEPALETTE:
1022 GDIRealizePalette16(hdc);
1023 break;
1025 case META_ESCAPE:
1026 FIXME("META_ESCAPE unimplemented.\n");
1027 break;
1029 case META_EXTTEXTOUT:
1030 MF_Play_MetaExtTextOut( hdc, mr );
1031 break;
1033 case META_STRETCHDIB:
1035 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1036 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1037 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1038 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1039 mr->rdParm[4],mr->rdParm[3],bits,info,
1040 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1042 break;
1044 case META_DIBSTRETCHBLT:
1046 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1047 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1048 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1049 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1050 mr->rdParm[3],mr->rdParm[2],bits,info,
1051 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1053 break;
1055 case META_STRETCHBLT:
1057 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1058 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1059 mr->rdParm[11], /*Height*/
1060 mr->rdParm[13], /*Planes*/
1061 mr->rdParm[14], /*BitsPixel*/
1062 (LPSTR)&mr->rdParm[15]); /*bits*/
1063 SelectObject(hdcSrc,hbitmap);
1064 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1065 mr->rdParm[7],mr->rdParm[6],
1066 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1067 mr->rdParm[3],mr->rdParm[2],
1068 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1069 DeleteDC(hdcSrc);
1071 break;
1073 case META_BITBLT:
1075 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1076 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1077 mr->rdParm[8]/*Height*/,
1078 mr->rdParm[10]/*Planes*/,
1079 mr->rdParm[11]/*BitsPixel*/,
1080 (LPSTR)&mr->rdParm[12]/*bits*/);
1081 SelectObject(hdcSrc,hbitmap);
1082 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1083 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1084 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1085 MAKELONG(0,mr->rdParm[0]));
1086 DeleteDC(hdcSrc);
1088 break;
1090 case META_CREATEREGION:
1092 HRGN hrgn = CreateRectRgn(0,0,0,0);
1094 MF_Play_MetaCreateRegion(mr, hrgn);
1095 MF_AddHandle(ht, nHandles, hrgn);
1097 break;
1099 case META_FILLREGION:
1100 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1101 *(ht->objectHandle + *(mr->rdParm)));
1102 break;
1104 case META_FRAMEREGION:
1105 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1106 *(ht->objectHandle + *(mr->rdParm+2)),
1107 *(mr->rdParm+1), *(mr->rdParm));
1108 break;
1110 case META_INVERTREGION:
1111 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1112 break;
1114 case META_PAINTREGION:
1115 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1116 break;
1118 case META_SELECTCLIPREGION:
1119 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1120 break;
1122 case META_DIBCREATEPATTERNBRUSH:
1123 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1124 but there's no difference */
1126 TRACE("%d\n",*(mr->rdParm));
1127 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1128 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1129 ptr = GlobalLock16(hndl);
1130 memcpy(ptr, mr->rdParm + 2, s1);
1131 GlobalUnlock16(hndl);
1132 MF_AddHandle(ht, nHandles,
1133 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1134 GlobalFree16(hndl);
1135 break;
1137 case META_DIBBITBLT:
1138 /* In practice I've found that there are two layouts for
1139 META_DIBBITBLT, one (the first here) is the usual one when a src
1140 dc is actually passed to it, the second occurs when the src dc is
1141 passed in as NULL to the creating BitBlt. As the second case has
1142 no dib, a size check will suffice to distinguish.
1144 Caolan.McNamara@ul.ie */
1146 if (mr->rdSize > 12) {
1147 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1148 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1150 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1151 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1152 mr->rdParm[5], mr->rdParm[4], bits, info,
1153 DIB_RGB_COLORS,
1154 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1155 } else { /* equivalent to a PatBlt */
1156 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1157 mr->rdParm[6], mr->rdParm[5],
1158 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1160 break;
1162 case META_SETTEXTCHAREXTRA:
1163 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1164 break;
1166 case META_SETTEXTJUSTIFICATION:
1167 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1168 break;
1170 case META_EXTFLOODFILL:
1171 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1172 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1173 *(mr->rdParm));
1174 break;
1176 case META_SETDIBTODEV:
1178 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1179 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1180 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1181 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1182 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1183 mr->rdParm[2], mr->rdParm[1], bits, info,
1184 mr->rdParm[0]);
1185 break;
1188 #define META_UNIMP(x) case x: \
1189 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1190 break;
1191 META_UNIMP(META_DRAWTEXT)
1192 META_UNIMP(META_ANIMATEPALETTE)
1193 META_UNIMP(META_SETPALENTRIES)
1194 META_UNIMP(META_RESIZEPALETTE)
1195 META_UNIMP(META_RESETDC)
1196 META_UNIMP(META_STARTDOC)
1197 META_UNIMP(META_STARTPAGE)
1198 META_UNIMP(META_ENDPAGE)
1199 META_UNIMP(META_ABORTDOC)
1200 META_UNIMP(META_ENDDOC)
1201 META_UNIMP(META_CREATEBRUSH)
1202 META_UNIMP(META_CREATEBITMAPINDIRECT)
1203 META_UNIMP(META_CREATEBITMAP)
1204 #undef META_UNIMP
1206 default:
1207 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1208 mr->rdFunction);
1212 /******************************************************************
1213 * PlayMetaFileRecord (GDI32.266)
1215 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1216 METARECORD *metarecord, UINT handles )
1218 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1219 handles*sizeof(HANDLETABLE16));
1220 unsigned int i = 0;
1221 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1222 handles);
1223 for (i=0; i<handles; i++)
1224 ht->objectHandle[i] = handletable->objectHandle[i];
1225 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1226 for (i=0; i<handles; i++)
1227 handletable->objectHandle[i] = ht->objectHandle[i];
1228 GlobalFree((HGLOBAL)ht);
1229 return TRUE;
1232 /******************************************************************
1233 * GetMetaFileBits (GDI.159)
1235 * Trade in a metafile object handle for a handle to the metafile memory.
1239 HGLOBAL16 WINAPI GetMetaFileBits16(
1240 HMETAFILE16 hmf /* [in] metafile handle */
1243 TRACE("hMem out: %04x\n", hmf);
1244 return hmf;
1247 /******************************************************************
1248 * SetMetaFileBits (GDI.160)
1250 * Trade in a metafile memory handle for a handle to a metafile object.
1251 * The memory region should hold a proper metafile, otherwise
1252 * problems will occur when it is used. Validity of the memory is not
1253 * checked. The function is essentially just the identity function.
1255 HMETAFILE16 WINAPI SetMetaFileBits16(
1256 HGLOBAL16 hMem
1257 /* [in] handle to a memory region holding a metafile */
1260 TRACE("hmf out: %04x\n", hMem);
1262 return hMem;
1265 /******************************************************************
1266 * SetMetaFileBitsBetter (GDI.196)
1268 * Trade in a metafile memory handle for a handle to a metafile object,
1269 * making a cursory check (using IsValidMetaFile()) that the memory
1270 * handle points to a valid metafile.
1272 * RETURNS
1273 * Handle to a metafile on success, NULL on failure..
1275 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1277 if( IsValidMetaFile16( hMeta ) )
1278 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1279 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1280 return (HMETAFILE16)0;
1283 /******************************************************************
1284 * SetMetaFileBitsEx (GDI32.323)
1286 * Create a metafile from raw data. No checking of the data is performed.
1287 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1289 HMETAFILE WINAPI SetMetaFileBitsEx(
1290 UINT size, /* [in] size of metafile, in bytes */
1291 const BYTE *lpData /* [in] pointer to metafile data */
1294 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1295 if (!mh) return 0;
1296 memcpy(mh, lpData, size);
1297 return MF_Create_HMETAFILE(mh);
1300 /*****************************************************************
1301 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1303 * Copies the data from metafile _hmf_ into the buffer _buf_.
1304 * If _buf_ is zero, returns size of buffer required. Otherwise,
1305 * returns number of bytes copied.
1307 UINT WINAPI GetMetaFileBitsEx(
1308 HMETAFILE hmf, /* [in] metafile */
1309 UINT nSize, /* [in] size of buf */
1310 LPVOID buf /* [out] buffer to receive raw metafile data */
1312 METAHEADER *mh = MF_GetMetaHeader(hmf);
1313 UINT mfSize;
1315 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1316 if (!mh) return 0; /* FIXME: error code */
1317 if(mh->mtType == METAFILE_DISK)
1318 FIXME("Disk-based metafile?\n");
1319 mfSize = mh->mtSize * 2;
1320 if (!buf) {
1321 MF_ReleaseMetaHeader(hmf);
1322 TRACE("returning size %d\n", mfSize);
1323 return mfSize;
1325 if(mfSize > nSize) mfSize = nSize;
1326 memmove(buf, mh, mfSize);
1327 MF_ReleaseMetaHeader(hmf);
1328 return mfSize;
1331 /******************************************************************
1332 * GetWinMetaFileBits [GDI32.241]
1334 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1335 UINT cbBuffer, LPBYTE lpbBuffer,
1336 INT fnMapMode, HDC hdcRef)
1338 FIXME("(%d,%d,%p,%d,%d): stub\n",
1339 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1340 return 0;
1343 /******************************************************************
1344 * MF_Play_MetaCreateRegion
1346 * Handles META_CREATEREGION for PlayMetaFileRecord().
1350 * The layout of the record looks something like this:
1352 * rdParm meaning
1353 * 0 Always 0?
1354 * 1 Always 6?
1355 * 2 Looks like a handle? - not constant
1356 * 3 0 or 1 ??
1357 * 4 Total number of bytes
1358 * 5 No. of seperate bands = n [see below]
1359 * 6 Largest number of x co-ords in a band
1360 * 7-10 Bounding box x1 y1 x2 y2
1361 * 11-... n bands
1363 * Regions are divided into bands that are uniform in the
1364 * y-direction. Each band consists of pairs of on/off x-coords and is
1365 * written as
1366 * m y0 y1 x1 x2 x3 ... xm m
1367 * into successive rdParm[]s.
1369 * This is probably just a dump of the internal RGNOBJ?
1371 * HDMD - 18/12/97
1375 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1377 WORD band, pair;
1378 WORD *start, *end;
1379 INT16 y0, y1;
1380 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1382 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1383 band++, start = end + 1) {
1384 if(*start / 2 != (*start + 1) / 2) {
1385 WARN("Delimiter not even.\n");
1386 DeleteObject( hrgn2 );
1387 return FALSE;
1390 end = start + *start + 3;
1391 if(end > (WORD *)mr + mr->rdSize) {
1392 WARN("End points outside record.\n");
1393 DeleteObject( hrgn2 );
1394 return FALSE;
1397 if(*start != *end) {
1398 WARN("Mismatched delimiters.\n");
1399 DeleteObject( hrgn2 );
1400 return FALSE;
1403 y0 = *(INT16 *)(start + 1);
1404 y1 = *(INT16 *)(start + 2);
1405 for(pair = 0; pair < *start / 2; pair++) {
1406 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1407 *(INT16 *)(start + 4 + 2*pair), y1 );
1408 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1411 DeleteObject( hrgn2 );
1412 return TRUE;
1416 /******************************************************************
1417 * MF_Play_MetaExtTextOut
1419 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1422 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1424 LPINT16 dxx;
1425 LPSTR sot;
1426 DWORD len;
1427 WORD s1;
1429 s1 = mr->rdParm[2]; /* String length */
1430 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1431 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1432 /* rec len without dx array */
1434 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1435 if (mr->rdParm[3])
1436 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1438 if (mr->rdSize == len / 2)
1439 dxx = NULL; /* determine if array present */
1440 else
1441 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1442 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1443 else {
1444 TRACE("%s len: %ld\n", sot, mr->rdSize);
1445 WARN(
1446 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1447 len, s1, mr->rdSize, mr->rdParm[3]);
1448 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1450 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1451 mr->rdParm[0], /* Y position */
1452 mr->rdParm[3], /* options */
1453 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1454 /* rectangle */
1455 sot, /* string */
1456 s1, dxx); /* length, dx array */
1457 if (dxx)
1458 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1459 return TRUE;