Change (32 bit) HMETAFILEs to GDI objects (HMETAFILE16s remain as
[wine.git] / objects / metafile.c
blob8f35e12bc5e5e5469e52774f361b9d108732054e
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 "debug.h"
42 #include "global.h"
44 /******************************************************************
45 * MF_AddHandle
47 * Add a handle to an external handle table and return the index
49 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
51 int i;
53 for (i = 0; i < htlen; i++)
55 if (*(ht->objectHandle + i) == 0)
57 *(ht->objectHandle + i) = hobj;
58 return i;
61 return -1;
65 /******************************************************************
66 * MF_Create_HMETATFILE
68 * Creates a (32 bit) HMETAFILE object from a METAHEADER
70 * HMETAFILEs are GDI objects.
72 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
74 HMETAFILE hmf = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC );
75 METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_HEAP_LOCK( hmf );
76 metaObj->mh = mh;
77 GDI_HEAP_UNLOCK( hmf );
78 return hmf;
81 /******************************************************************
82 * MF_Create_HMETATFILE16
84 * Creates a HMETAFILE16 object from a METAHEADER
86 * HMETAFILE16s are Global memory handles.
88 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
90 HMETAFILE16 hmf;
91 DWORD size;
93 if(mh->mtType == METAFILE_MEMORY)
94 size = mh->mtSize * sizeof(WORD);
95 else
96 size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
98 hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
99 GetCurrentPDB16(), FALSE, FALSE, FALSE, NULL );
100 return hmf;
103 /******************************************************************
104 * MF_GetMetaHeader
106 * Returns ptr to METAHEADER associated with HMETAFILE
107 * Should be followed by call to MF_ReleaseMetaHeader
109 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
111 METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
112 return metaObj->mh;
115 /******************************************************************
116 * MF_GetMetaHeader16
118 * Returns ptr to METAHEADER associated with HMETAFILE16
119 * Should be followed by call to MF_ReleaseMetaHeader16
121 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
123 return GlobalLock16(hmf);
126 /******************************************************************
127 * MF_ReleaseMetaHeader
129 * Releases METAHEADER associated with HMETAFILE
131 static BOOL MF_ReleaseMetaHeader( HMETAFILE hmf )
133 return GDI_HEAP_UNLOCK( hmf );
136 /******************************************************************
137 * MF_ReleaseMetaHeader16
139 * Releases METAHEADER associated with HMETAFILE16
141 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
143 return GlobalUnlock16( hmf );
147 /******************************************************************
148 * DeleteMetaFile16 (GDI.127)
150 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
152 return !GlobalFree16( hmf );
155 /******************************************************************
156 * DeleteMetaFile (GDI32.69)
158 * Delete a memory-based metafile.
161 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
163 METAHEADER *mh = MF_GetMetaHeader( hmf );
165 if(!mh) return FALSE;
166 HeapFree( SystemHeap, 0, mh );
167 GDI_FreeObject( hmf );
168 return TRUE;
171 /******************************************************************
172 * MF_ReadMetaFile
174 * Returns a pointer to a memory based METAHEADER read in from file HFILE
177 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
179 METAHEADER *mh;
180 DWORD BytesRead, size;
182 size = sizeof(METAHEADER);
183 mh = HeapAlloc( SystemHeap, 0, size );
184 if(!mh) return NULL;
185 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
186 BytesRead != size) {
187 HeapFree( SystemHeap, 0, mh );
188 return NULL;
190 size = mh->mtSize * 2;
191 mh = HeapReAlloc( SystemHeap, 0, mh, size );
192 if(!mh) return NULL;
193 size -= sizeof(METAHEADER);
194 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
195 NULL) == 0 ||
196 BytesRead != size) {
197 HeapFree( SystemHeap, 0, mh );
198 return NULL;
201 if (mh->mtType != METAFILE_MEMORY) {
202 WARN(metafile, "Disk metafile had mtType = %04x\n", mh->mtType);
203 mh->mtType = METAFILE_MEMORY;
205 return mh;
208 /******************************************************************
209 * GetMetaFile16 (GDI.124)
211 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
213 METAHEADER *mh;
214 HFILE hFile;
216 TRACE(metafile,"%s\n", lpFilename);
218 if(!lpFilename)
219 return 0;
221 if((hFile = CreateFileA(lpFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
222 0, -1)) == HFILE_ERROR)
223 return 0;
225 mh = MF_ReadMetaFile(hFile);
226 CloseHandle(hFile);
227 if(!mh) return 0;
228 return MF_Create_HMETAFILE16( mh );
231 /******************************************************************
232 * GetMetaFileA (GDI32.197)
234 * Read a metafile from a file. Returns handle to a memory-based metafile.
236 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
238 METAHEADER *mh;
239 HFILE hFile;
241 TRACE(metafile,"%s\n", lpFilename);
243 if(!lpFilename)
244 return 0;
246 if((hFile = CreateFileA(lpFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
247 0, -1)) == HFILE_ERROR)
248 return 0;
250 mh = MF_ReadMetaFile(hFile);
251 CloseHandle(hFile);
252 if(!mh) return 0;
253 return MF_Create_HMETAFILE( mh );
258 /******************************************************************
259 * GetMetaFileW (GDI32.199)
261 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
263 METAHEADER *mh;
264 HFILE hFile;
266 TRACE(metafile,"%s\n", debugstr_w(lpFilename));
268 if(!lpFilename)
269 return 0;
271 if((hFile = CreateFileW(lpFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
272 0, -1)) == HFILE_ERROR)
273 return 0;
275 mh = MF_ReadMetaFile(hFile);
276 CloseHandle(hFile);
277 if(!mh) return 0;
278 return MF_Create_HMETAFILE( mh );
282 /******************************************************************
283 * MF_LoadDiskBasedMetaFile
285 * Creates a new memory-based metafile from a disk-based one.
287 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
289 METAHEADERDISK *mhd;
290 HFILE hfile;
291 METAHEADER *mh2;
293 if(mh->mtType != METAFILE_DISK) {
294 ERR(metafile, "Not a disk based metafile\n");
295 return NULL;
297 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
299 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, 0, NULL,
300 OPEN_EXISTING, 0, -1)) == HFILE_ERROR) {
301 WARN(metafile, "Can't open file of disk based metafile\n");
302 return NULL;
304 mh2 = MF_ReadMetaFile(hfile);
305 CloseHandle(hfile);
306 return mh2;
309 /******************************************************************
310 * MF_CreateMetaHeaderDisk
312 * Take a memory based METAHEADER and change it to a disk based METAHEADER
313 * assosiated with filename. Note: Trashes contents of old one.
315 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
317 METAHEADERDISK *mhd;
318 DWORD size;
320 mh = HeapReAlloc( SystemHeap, 0, mh,
321 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
322 mh->mtType = METAFILE_DISK;
323 size = HeapSize( SystemHeap, 0, mh );
324 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
325 strcpy(mhd->filename, filename);
326 return mh;
329 /******************************************************************
330 * CopyMetaFile16 (GDI.151)
332 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
334 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
335 METAHEADER *mh2 = NULL;
336 HFILE hFile;
338 TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
340 if(!mh) return 0;
342 if(mh->mtType == METAFILE_DISK)
343 mh2 = MF_LoadDiskBasedMetaFile(mh);
344 else {
345 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
346 memcpy( mh2, mh, mh->mtSize * 2 );
348 MF_ReleaseMetaHeader16( hSrcMetaFile );
350 if(lpFilename) { /* disk based metafile */
351 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
352 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
353 HeapFree( SystemHeap, 0, mh2 );
354 return 0;
356 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
357 CloseHandle(hFile);
358 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
361 return MF_Create_HMETAFILE16( mh2 );
365 /******************************************************************
366 * CopyMetaFileA (GDI32.23)
368 * Copies the metafile corresponding to hSrcMetaFile to either
369 * a disk file, if a filename is given, or to a new memory based
370 * metafile, if lpFileName is NULL.
372 * RETURNS
374 * Handle to metafile copy on success, NULL on failure.
376 * BUGS
378 * Copying to disk returns NULL even if successful.
380 HMETAFILE WINAPI CopyMetaFileA(
381 HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
382 LPCSTR lpFilename /* filename if copying to a file */
384 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
385 METAHEADER *mh2 = NULL;
386 HFILE hFile;
388 TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
390 if(!mh) return 0;
392 if(mh->mtType == METAFILE_DISK)
393 mh2 = MF_LoadDiskBasedMetaFile(mh);
394 else {
395 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
396 memcpy( mh2, mh, mh->mtSize * 2 );
398 MF_ReleaseMetaHeader( hSrcMetaFile );
400 if(lpFilename) { /* disk based metafile */
401 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
402 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
403 HeapFree( SystemHeap, 0, mh2 );
404 return 0;
406 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
407 CloseHandle(hFile);
408 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
411 return MF_Create_HMETAFILE( mh2 );
415 /******************************************************************
416 * CopyMetaFileW (GDI32.24)
418 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
419 LPCWSTR lpFilename )
421 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
422 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
423 HeapFree( GetProcessHeap(), 0, p );
424 return ret;
428 /******************************************************************
429 * IsValidMetaFile (GDI.410)
431 * Attempts to check if a given metafile is correctly formatted.
432 * Currently, the only things verified are several properties of the
433 * header.
435 * RETURNS
436 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
438 * BUGS
439 * This is not exactly what windows does, see _Undocumented_Windows_
440 * for details.
442 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
444 BOOL16 res=FALSE;
445 METAHEADER *mh = MF_GetMetaHeader16(hmf);
446 if (mh) {
447 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
448 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
449 if (mh->mtVersion == MFVERSION)
450 res=TRUE;
451 MF_ReleaseMetaHeader16(hmf);
453 TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,res);
454 return res;
458 /*******************************************************************
459 * MF_PlayMetaFile
461 * Helper for PlayMetaFile
463 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
466 METARECORD *mr;
467 HANDLETABLE16 *ht;
468 int offset = 0;
469 WORD i;
470 HPEN hPen;
471 HBRUSH hBrush;
472 HFONT hFont;
473 DC *dc;
474 BOOL loaded = FALSE;
476 if (!mh) return FALSE;
477 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
478 mh = MF_LoadDiskBasedMetaFile(mh);
479 if(!mh) return FALSE;
480 loaded = TRUE;
483 /* save the current pen, brush and font */
484 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
485 hPen = dc->w.hPen;
486 hBrush = dc->w.hBrush;
487 hFont = dc->w.hFont;
488 GDI_HEAP_UNLOCK(hdc);
489 /* create the handle table */
490 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
491 sizeof(HANDLETABLE16) * mh->mtNoObjects);
492 if(!ht) return FALSE;
494 /* loop through metafile playing records */
495 offset = mh->mtHeaderSize * 2;
496 while (offset < mh->mtSize * 2)
498 mr = (METARECORD *)((char *)mh + offset);
499 TRACE(metafile,"offset=%04x,size=%08lx\n",
500 offset, mr->rdSize);
501 if (!mr->rdSize) {
502 TRACE(metafile,
503 "Entry got size 0 at offset %d, total mf length is %ld\n",
504 offset,mh->mtSize*2);
505 break; /* would loop endlessly otherwise */
507 offset += mr->rdSize * 2;
508 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
511 SelectObject(hdc, hBrush);
512 SelectObject(hdc, hPen);
513 SelectObject(hdc, hFont);
515 /* free objects in handle table */
516 for(i = 0; i < mh->mtNoObjects; i++)
517 if(*(ht->objectHandle + i) != 0)
518 DeleteObject(*(ht->objectHandle + i));
520 /* free handle table */
521 HeapFree( SystemHeap, 0, ht );
522 if(loaded)
523 HeapFree( SystemHeap, 0, mh );
524 return TRUE;
527 /******************************************************************
528 * PlayMetaFile16 (GDI.123)
531 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
533 BOOL16 ret;
534 METAHEADER *mh = MF_GetMetaHeader16( hmf );
535 ret = MF_PlayMetaFile( hdc, mh );
536 MF_ReleaseMetaHeader16( hmf );
537 return ret;
540 /******************************************************************
541 * PlayMetaFile (GDI32.265)
543 * Renders the metafile specified by hmf in the DC specified by
544 * hdc. Returns FALSE on failure, TRUE on success.
546 BOOL WINAPI PlayMetaFile(
547 HDC hdc, /* handle of DC to render in */
548 HMETAFILE hmf /* handle of metafile to render */
551 BOOL ret;
552 METAHEADER *mh = MF_GetMetaHeader( hmf );
553 ret = MF_PlayMetaFile( hdc, mh );
554 MF_ReleaseMetaHeader( hmf );
555 return ret;
559 /******************************************************************
560 * EnumMetaFile16 (GDI.175)
563 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
564 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
566 METAHEADER *mh = MF_GetMetaHeader16(hmf);
567 METARECORD *mr;
568 HANDLETABLE16 *ht;
569 HGLOBAL16 hHT;
570 SEGPTR spht;
571 int offset = 0;
572 WORD i, seg;
573 HPEN hPen;
574 HBRUSH hBrush;
575 HFONT hFont;
576 DC *dc;
577 BOOL16 result = TRUE, loaded = FALSE;
579 TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
580 hdc, hmf, (DWORD)lpEnumFunc, lpData);
583 if(!mh) return FALSE;
584 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
585 mh = MF_LoadDiskBasedMetaFile(mh);
586 if(!mh) return FALSE;
587 loaded = TRUE;
590 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
591 hPen = dc->w.hPen;
592 hBrush = dc->w.hBrush;
593 hFont = dc->w.hFont;
594 GDI_HEAP_UNLOCK(hdc);
596 /* create the handle table */
598 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
599 sizeof(HANDLETABLE16) * mh->mtNoObjects);
600 spht = WIN16_GlobalLock16(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 *) PTR_SEG_OFF_TO_HUGEPTR(seg, 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( SystemHeap, 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 *mh = MF_GetMetaHeader(hmf);
662 METARECORD *mr;
663 HANDLETABLE *ht;
664 BOOL result = TRUE, loaded = FALSE;
665 int i, offset = 0;
666 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
667 HPEN hPen;
668 HBRUSH hBrush;
669 HFONT hFont;
671 TRACE(metafile,"(%08x,%08x,%p,%p)\n",
672 hdc, hmf, lpEnumFunc, (void*)lpData);
673 if (!mh) return 0;
674 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
675 mh = MF_LoadDiskBasedMetaFile(mh);
676 if(!mh) return 0;
677 loaded = TRUE;
680 /* save the current pen, brush and font */
681 if (!dc) return 0;
682 hPen = dc->w.hPen;
683 hBrush = dc->w.hBrush;
684 hFont = dc->w.hFont;
685 GDI_HEAP_UNLOCK(hdc);
688 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
689 sizeof(HANDLETABLE) * mh->mtNoObjects);
691 /* loop through metafile records */
692 offset = mh->mtHeaderSize * 2;
694 while (offset < (mh->mtSize * 2))
696 mr = (METARECORD *)((char *)mh + offset);
697 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
699 result = FALSE;
700 break;
703 offset += (mr->rdSize * 2);
706 /* restore pen, brush and font */
707 SelectObject(hdc, hBrush);
708 SelectObject(hdc, hPen);
709 SelectObject(hdc, hFont);
711 /* free objects in handle table */
712 for(i = 0; i < mh->mtNoObjects; i++)
713 if(*(ht->objectHandle + i) != 0)
714 DeleteObject(*(ht->objectHandle + i));
716 /* free handle table */
717 HeapFree( SystemHeap, 0, ht);
718 if(loaded)
719 HeapFree( SystemHeap, 0, mh );
720 MF_ReleaseMetaHeader(hmf);
721 return result;
724 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
726 /******************************************************************
727 * PlayMetaFileRecord16 (GDI.176)
729 * Render a single metafile record specified by *mr in the DC hdc, while
730 * using the handle table *ht, of length nHandles,
731 * to store metafile objects.
733 * BUGS
734 * The following metafile records are unimplemented:
736 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
737 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
738 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
741 void WINAPI PlayMetaFileRecord16(
742 HDC16 hdc, /* DC to render metafile into */
743 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
744 METARECORD *mr, /* pointer to metafile record to render */
745 UINT16 nHandles /* size of handle table */
747 short s1;
748 HANDLE16 hndl;
749 char *ptr;
750 BITMAPINFOHEADER *infohdr;
752 TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
753 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
755 switch (mr->rdFunction)
757 case META_EOF:
758 break;
760 case META_DELETEOBJECT:
761 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
762 *(ht->objectHandle + *(mr->rdParm)) = 0;
763 break;
765 case META_SETBKCOLOR:
766 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
767 break;
769 case META_SETBKMODE:
770 SetBkMode16(hdc, *(mr->rdParm));
771 break;
773 case META_SETMAPMODE:
774 SetMapMode16(hdc, *(mr->rdParm));
775 break;
777 case META_SETROP2:
778 SetROP216(hdc, *(mr->rdParm));
779 break;
781 case META_SETRELABS:
782 SetRelAbs16(hdc, *(mr->rdParm));
783 break;
785 case META_SETPOLYFILLMODE:
786 SetPolyFillMode16(hdc, *(mr->rdParm));
787 break;
789 case META_SETSTRETCHBLTMODE:
790 SetStretchBltMode16(hdc, *(mr->rdParm));
791 break;
793 case META_SETTEXTCOLOR:
794 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
795 break;
797 case META_SETWINDOWORG:
798 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
799 break;
801 case META_SETWINDOWEXT:
802 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
803 break;
805 case META_SETVIEWPORTORG:
806 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
807 break;
809 case META_SETVIEWPORTEXT:
810 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
811 break;
813 case META_OFFSETWINDOWORG:
814 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
815 break;
817 case META_SCALEWINDOWEXT:
818 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
819 *(mr->rdParm + 1), *(mr->rdParm));
820 break;
822 case META_OFFSETVIEWPORTORG:
823 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
824 break;
826 case META_SCALEVIEWPORTEXT:
827 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
828 *(mr->rdParm + 1), *(mr->rdParm));
829 break;
831 case META_LINETO:
832 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
833 break;
835 case META_MOVETO:
836 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
837 break;
839 case META_EXCLUDECLIPRECT:
840 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
841 *(mr->rdParm + 1), *(mr->rdParm) );
842 break;
844 case META_INTERSECTCLIPRECT:
845 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
846 *(mr->rdParm + 1), *(mr->rdParm) );
847 break;
849 case META_ARC:
850 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
851 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
852 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
853 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
854 break;
856 case META_ELLIPSE:
857 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
858 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
859 break;
861 case META_FLOODFILL:
862 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
863 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
864 break;
866 case META_PIE:
867 Pie(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_RECTANGLE:
874 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
875 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
876 break;
878 case META_ROUNDRECT:
879 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
880 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
881 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
882 break;
884 case META_PATBLT:
885 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
886 *(mr->rdParm + 3), *(mr->rdParm + 2),
887 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
888 break;
890 case META_SAVEDC:
891 SaveDC(hdc);
892 break;
894 case META_SETPIXEL:
895 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
896 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
897 break;
899 case META_OFFSETCLIPRGN:
900 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
901 break;
903 case META_TEXTOUT:
904 s1 = *(mr->rdParm);
905 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
906 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
907 (char *)(mr->rdParm + 1), s1);
908 break;
910 case META_POLYGON:
911 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
912 break;
914 case META_POLYPOLYGON:
915 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
916 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
917 break;
919 case META_POLYLINE:
920 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
921 break;
923 case META_RESTOREDC:
924 RestoreDC(hdc, (INT16)*(mr->rdParm));
925 break;
927 case META_SELECTOBJECT:
928 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
929 break;
931 case META_CHORD:
932 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
933 (INT16)*(mr->rdParm+5), (INT16)*(mr->rdParm + 4),
934 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
935 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
936 break;
938 case META_CREATEPATTERNBRUSH:
939 switch (*(mr->rdParm))
941 case BS_PATTERN:
942 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
943 MF_AddHandle(ht, nHandles,
944 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
945 infohdr->biHeight,
946 infohdr->biPlanes,
947 infohdr->biBitCount,
948 (LPSTR)(mr->rdParm +
949 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
950 break;
952 case BS_DIBPATTERN:
953 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
954 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
955 ptr = GlobalLock16(hndl);
956 memcpy(ptr, mr->rdParm + 2, s1);
957 GlobalUnlock16(hndl);
958 MF_AddHandle(ht, nHandles,
959 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
960 GlobalFree16(hndl);
962 break;
964 case META_CREATEPENINDIRECT:
965 MF_AddHandle(ht, nHandles,
966 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
967 break;
969 case META_CREATEFONTINDIRECT:
970 MF_AddHandle(ht, nHandles,
971 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
972 break;
974 case META_CREATEBRUSHINDIRECT:
975 MF_AddHandle(ht, nHandles,
976 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
977 break;
979 case META_CREATEPALETTE:
980 MF_AddHandle(ht, nHandles,
981 CreatePalette16((LPLOGPALETTE)mr->rdParm));
982 break;
984 case META_SETTEXTALIGN:
985 SetTextAlign16(hdc, *(mr->rdParm));
986 break;
988 case META_SELECTPALETTE:
989 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
990 *(mr->rdParm));
991 break;
993 case META_SETMAPPERFLAGS:
994 SetMapperFlags16(hdc, *(mr->rdParm));
995 break;
997 case META_REALIZEPALETTE:
998 RealizePalette16(hdc);
999 break;
1001 case META_ESCAPE:
1002 FIXME(metafile, "META_ESCAPE unimplemented.\n");
1003 break;
1005 case META_EXTTEXTOUT:
1007 LPINT16 dxx;
1008 LPSTR sot;
1009 DWORD len;
1011 s1 = mr->rdParm[2]; /* String length */
1012 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1013 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0); /* rec len without dx array */
1015 sot= (LPSTR)&mr->rdParm[4]; /* start_of_text */
1016 if (mr->rdParm[3])
1017 sot+=sizeof(RECT16); /* there is a rectangle, so add offset */
1019 if (mr->rdSize == len / 2)
1020 dxx = NULL; /* determine if array present */
1021 else
1022 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1023 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1024 else
1026 TRACE(metafile,"%s len: %ld\n",
1027 sot,mr->rdSize);
1028 WARN(metafile,
1029 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1030 len,s1,mr->rdSize,mr->rdParm[3]);
1031 dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
1033 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1034 mr->rdParm[0], /* Y position */
1035 mr->rdParm[3], /* options */
1036 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL, /* rectangle */
1037 sot, /* string */
1038 s1, dxx); /* length, dx array */
1039 if (dxx)
1040 TRACE(metafile,"%s len: %ld dx0: %d\n",
1041 sot,mr->rdSize,dxx[0]);
1043 break;
1045 case META_STRETCHDIB:
1047 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1048 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1049 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1050 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1051 mr->rdParm[4],mr->rdParm[3],bits,info,
1052 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1054 break;
1056 case META_DIBSTRETCHBLT:
1058 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1059 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1060 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1061 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1062 mr->rdParm[3],mr->rdParm[2],bits,info,
1063 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1065 break;
1067 case META_STRETCHBLT:
1069 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1070 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1071 mr->rdParm[11], /*Height*/
1072 mr->rdParm[13], /*Planes*/
1073 mr->rdParm[14], /*BitsPixel*/
1074 (LPSTR)&mr->rdParm[15]); /*bits*/
1075 SelectObject(hdcSrc,hbitmap);
1076 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1077 mr->rdParm[7],mr->rdParm[6],
1078 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1079 mr->rdParm[3],mr->rdParm[2],
1080 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1081 DeleteDC(hdcSrc);
1083 break;
1085 case META_BITBLT:
1087 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1088 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1089 mr->rdParm[8]/*Height*/,
1090 mr->rdParm[10]/*Planes*/,
1091 mr->rdParm[11]/*BitsPixel*/,
1092 (LPSTR)&mr->rdParm[12]/*bits*/);
1093 SelectObject(hdcSrc,hbitmap);
1094 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1095 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1096 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1097 MAKELONG(0,mr->rdParm[0]));
1098 DeleteDC(hdcSrc);
1100 break;
1102 case META_CREATEREGION:
1104 HRGN hrgn = CreateRectRgn(0,0,0,0);
1106 MF_Play_MetaCreateRegion(mr, hrgn);
1107 MF_AddHandle(ht, nHandles, hrgn);
1109 break;
1111 case META_FILLREGION:
1112 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)),
1113 *(ht->objectHandle + *(mr->rdParm+1)));
1114 break;
1116 case META_INVERTREGION:
1117 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1118 break;
1120 case META_PAINTREGION:
1121 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1122 break;
1124 case META_SELECTCLIPREGION:
1125 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1126 break;
1128 case META_DIBCREATEPATTERNBRUSH:
1129 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
1130 TRACE(metafile,"%d\n",*(mr->rdParm));
1131 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1132 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1133 ptr = GlobalLock16(hndl);
1134 memcpy(ptr, mr->rdParm + 2, s1);
1135 GlobalUnlock16(hndl);
1136 MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1137 GlobalFree16(hndl);
1138 break;
1140 case META_DIBBITBLT:
1142 /*In practice ive found that theres two layout for META_DIBBITBLT,
1143 one (the first here) is the usual one when a src dc is actually passed
1144 int, the second occurs when the src dc is passed in as NULL to
1145 the creating BitBlt.
1146 as the second case has no dib, a size check will suffice to distinguish.
1149 Caolan.McNamara@ul.ie
1151 if (mr->rdSize > 12)
1153 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1154 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1155 StretchDIBits16(hdc,mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1156 mr->rdParm[4],mr->rdParm[3],mr->rdParm[2],
1157 mr->rdParm[5],mr->rdParm[4],bits,info,
1158 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1160 else /*equivalent to a PatBlt*/
1162 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1163 mr->rdParm[6], mr->rdParm[5],
1164 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
1167 break;
1169 case META_SETTEXTCHAREXTRA:
1170 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1171 break;
1173 case META_SETTEXTJUSTIFICATION:
1174 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1175 break;
1177 case META_EXTFLOODFILL:
1178 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1179 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),*(mr->rdParm));
1180 break;
1182 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
1183 META_UNIMP(META_FRAMEREGION)
1184 META_UNIMP(META_DRAWTEXT)
1185 META_UNIMP(META_SETDIBTODEV)
1186 META_UNIMP(META_ANIMATEPALETTE)
1187 META_UNIMP(META_SETPALENTRIES)
1188 META_UNIMP(META_RESIZEPALETTE)
1189 META_UNIMP(META_RESETDC)
1190 META_UNIMP(META_STARTDOC)
1191 META_UNIMP(META_STARTPAGE)
1192 META_UNIMP(META_ENDPAGE)
1193 META_UNIMP(META_ABORTDOC)
1194 META_UNIMP(META_ENDDOC)
1195 META_UNIMP(META_CREATEBRUSH)
1196 META_UNIMP(META_CREATEBITMAPINDIRECT)
1197 META_UNIMP(META_CREATEBITMAP)
1198 #undef META_UNIMP
1200 default:
1201 WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
1202 mr->rdFunction);
1206 /******************************************************************
1207 * PlayMetaFileRecord (GDI32.266)
1209 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1210 METARECORD *metarecord, UINT handles )
1212 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1213 handles*sizeof(HANDLETABLE16));
1214 int i = 0;
1215 TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1216 handles);
1217 for (i=0; i<handles; i++)
1218 ht->objectHandle[i] = handletable->objectHandle[i];
1219 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1220 for (i=0; i<handles; i++)
1221 handletable->objectHandle[i] = ht->objectHandle[i];
1222 GlobalFree((HGLOBAL)ht);
1223 return TRUE;
1226 /******************************************************************
1227 * GetMetaFileBits (GDI.159)
1229 * Trade in a metafile object handle for a handle to the metafile memory.
1233 HGLOBAL16 WINAPI GetMetaFileBits16(
1234 HMETAFILE16 hmf /* metafile handle */
1237 TRACE(metafile,"hMem out: %04x\n", hmf);
1238 return hmf;
1241 /******************************************************************
1242 * SetMetaFileBits (GDI.160)
1244 * Trade in a metafile memory handle for a handle to a metafile object.
1245 * The memory region should hold a proper metafile, otherwise
1246 * problems will occur when it is used. Validity of the memory is not
1247 * checked. The function is essentially just the identity function.
1249 HMETAFILE16 WINAPI SetMetaFileBits16(
1250 HGLOBAL16 hMem
1251 /* handle to a memory region holding a metafile */
1254 TRACE(metafile,"hmf out: %04x\n", hMem);
1256 return hMem;
1259 /******************************************************************
1260 * SetMetaFileBitsBetter (GDI.196)
1262 * Trade in a metafile memory handle for a handle to a metafile object,
1263 * making a cursory check (using IsValidMetaFile()) that the memory
1264 * handle points to a valid metafile.
1266 * RETURNS
1267 * Handle to a metafile on success, NULL on failure..
1269 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1271 if( IsValidMetaFile16( hMeta ) )
1272 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1273 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1274 return (HMETAFILE16)0;
1277 /******************************************************************
1278 * SetMetaFileBitsEx (GDI32.323)
1280 * Create a metafile from raw data. No checking of the data is performed.
1281 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1283 HMETAFILE WINAPI SetMetaFileBitsEx(
1284 UINT size, /* size of metafile, in bytes */
1285 const BYTE *lpData /* pointer to metafile data */
1288 METAHEADER *mh = HeapAlloc( SystemHeap, 0, size );
1289 if (!mh) return 0;
1290 memcpy(mh, lpData, size);
1291 return MF_Create_HMETAFILE(mh);
1294 /*****************************************************************
1295 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1297 * Copies the data from metafile _hmf_ into the buffer _buf_.
1298 * If _buf_ is zero, returns size of buffer required. Otherwise,
1299 * returns number of bytes copied.
1301 UINT WINAPI GetMetaFileBitsEx(
1302 HMETAFILE hmf, /* metafile */
1303 UINT nSize, /* size of buf */
1304 LPVOID buf /* buffer to receive raw metafile data */
1306 METAHEADER *mh = MF_GetMetaHeader(hmf);
1307 UINT mfSize;
1309 TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1310 if (!mh) return 0; /* FIXME: error code */
1311 if(mh->mtType == METAFILE_DISK)
1312 FIXME(metafile, "Disk-based metafile?\n");
1313 mfSize = mh->mtSize * 2;
1314 if (!buf) {
1315 MF_ReleaseMetaHeader(hmf);
1316 TRACE(metafile,"returning size %d\n", mfSize);
1317 return mfSize;
1319 if(mfSize > nSize) mfSize = nSize;
1320 memmove(buf, mh, mfSize);
1321 MF_ReleaseMetaHeader(hmf);
1322 return mfSize;
1325 /******************************************************************
1326 * GetWinMetaFileBits [GDI32.241]
1328 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1329 UINT cbBuffer, LPBYTE lpbBuffer,
1330 INT fnMapMode, HDC hdcRef)
1332 FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1333 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1334 return 0;
1337 /******************************************************************
1338 * MF_Play_MetaCreateRegion
1340 * Handles META_CREATEREGION for PlayMetaFileRecord().
1344 * The layout of the record looks something like this:
1346 * rdParm meaning
1347 * 0 Always 0?
1348 * 1 Always 6?
1349 * 2 Looks like a handle? - not constant
1350 * 3 0 or 1 ??
1351 * 4 Total number of bytes
1352 * 5 No. of seperate bands = n [see below]
1353 * 6 Largest number of x co-ords in a band
1354 * 7-10 Bounding box x1 y1 x2 y2
1355 * 11-... n bands
1357 * Regions are divided into bands that are uniform in the
1358 * y-direction. Each band consists of pairs of on/off x-coords and is
1359 * written as
1360 * m y0 y1 x1 x2 x3 ... xm m
1361 * into successive rdParm[]s.
1363 * This is probably just a dump of the internal RGNOBJ?
1365 * HDMD - 18/12/97
1369 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1371 WORD band, pair;
1372 WORD *start, *end;
1373 INT16 y0, y1;
1374 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1376 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1377 band++, start = end + 1) {
1378 if(*start / 2 != (*start + 1) / 2) {
1379 WARN(metafile, "Delimiter not even.\n");
1380 DeleteObject( hrgn2 );
1381 return FALSE;
1384 end = start + *start + 3;
1385 if(end > (WORD *)mr + mr->rdSize) {
1386 WARN(metafile, "End points outside record.\n");
1387 DeleteObject( hrgn2 );
1388 return FALSE;
1391 if(*start != *end) {
1392 WARN(metafile, "Mismatched delimiters.\n");
1393 DeleteObject( hrgn2 );
1394 return FALSE;
1397 y0 = *(INT16 *)(start + 1);
1398 y1 = *(INT16 *)(start + 2);
1399 for(pair = 0; pair < *start / 2; pair++) {
1400 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1401 *(INT16 *)(start + 4 + 2*pair), y1 );
1402 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1405 DeleteObject( hrgn2 );
1406 return TRUE;
1410 /* LocalWords: capatibility