Fixed some bugs (mmioOpen with 16/32 bit strangeness, mmioAscend &
[wine.git] / objects / metafile.c
blob6a23ac4a493da219b717d9f963b23945ba634992
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 = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC );
77 METAFILEOBJ *metaObj = (METAFILEOBJ *)GDI_HEAP_LOCK( hmf );
78 metaObj->mh = mh;
79 GDI_HEAP_UNLOCK( hmf );
80 return hmf;
83 /******************************************************************
84 * MF_Create_HMETATFILE16
86 * Creates a HMETAFILE16 object from a METAHEADER
88 * HMETAFILE16s are Global memory handles.
90 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
92 HMETAFILE16 hmf;
93 DWORD size;
95 if(mh->mtType == METAFILE_MEMORY)
96 size = mh->mtSize * sizeof(WORD);
97 else
98 size = sizeof(METAHEADER) + sizeof(METAHEADERDISK);
100 hmf = GLOBAL_CreateBlock( GMEM_MOVEABLE, mh, mh->mtSize * sizeof(WORD),
101 GetCurrentPDB16(), FALSE, FALSE, FALSE, NULL );
102 return hmf;
105 /******************************************************************
106 * MF_GetMetaHeader
108 * Returns ptr to METAHEADER associated with HMETAFILE
109 * Should be followed by call to MF_ReleaseMetaHeader
111 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
113 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
114 return metaObj ? metaObj->mh : 0;
117 /******************************************************************
118 * MF_GetMetaHeader16
120 * Returns ptr to METAHEADER associated with HMETAFILE16
121 * Should be followed by call to MF_ReleaseMetaHeader16
123 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
125 return GlobalLock16(hmf);
128 /******************************************************************
129 * MF_ReleaseMetaHeader
131 * Releases METAHEADER associated with HMETAFILE
133 static BOOL MF_ReleaseMetaHeader( HMETAFILE hmf )
135 return GDI_HEAP_UNLOCK( hmf );
138 /******************************************************************
139 * MF_ReleaseMetaHeader16
141 * Releases METAHEADER associated with HMETAFILE16
143 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
145 return GlobalUnlock16( hmf );
149 /******************************************************************
150 * DeleteMetaFile16 (GDI.127)
152 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
154 return !GlobalFree16( hmf );
157 /******************************************************************
158 * DeleteMetaFile (GDI32.69)
160 * Delete a memory-based metafile.
163 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
165 METAHEADER *mh = MF_GetMetaHeader( hmf );
167 if(!mh) return FALSE;
168 HeapFree( SystemHeap, 0, mh );
169 GDI_FreeObject( hmf );
170 return TRUE;
173 /******************************************************************
174 * MF_ReadMetaFile
176 * Returns a pointer to a memory based METAHEADER read in from file HFILE
179 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
181 METAHEADER *mh;
182 DWORD BytesRead, size;
184 size = sizeof(METAHEADER);
185 mh = HeapAlloc( SystemHeap, 0, size );
186 if(!mh) return NULL;
187 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
188 BytesRead != size) {
189 HeapFree( SystemHeap, 0, mh );
190 return NULL;
192 size = mh->mtSize * 2;
193 mh = HeapReAlloc( SystemHeap, 0, mh, size );
194 if(!mh) return NULL;
195 size -= sizeof(METAHEADER);
196 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
197 NULL) == 0 ||
198 BytesRead != size) {
199 HeapFree( SystemHeap, 0, mh );
200 return NULL;
203 if (mh->mtType != METAFILE_MEMORY) {
204 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
205 mh->mtType = METAFILE_MEMORY;
207 return mh;
210 /******************************************************************
211 * GetMetaFile16 (GDI.124)
213 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
215 METAHEADER *mh;
216 HFILE hFile;
218 TRACE("%s\n", lpFilename);
220 if(!lpFilename)
221 return 0;
223 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
224 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
225 return 0;
227 mh = MF_ReadMetaFile(hFile);
228 CloseHandle(hFile);
229 if(!mh) return 0;
230 return MF_Create_HMETAFILE16( mh );
233 /******************************************************************
234 * GetMetaFileA (GDI32.197)
236 * Read a metafile from a file. Returns handle to a memory-based metafile.
238 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
240 METAHEADER *mh;
241 HFILE hFile;
243 TRACE("%s\n", lpFilename);
245 if(!lpFilename)
246 return 0;
248 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
249 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
250 return 0;
252 mh = MF_ReadMetaFile(hFile);
253 CloseHandle(hFile);
254 if(!mh) return 0;
255 return MF_Create_HMETAFILE( mh );
260 /******************************************************************
261 * GetMetaFileW (GDI32.199)
263 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
265 METAHEADER *mh;
266 HFILE hFile;
268 TRACE("%s\n", debugstr_w(lpFilename));
270 if(!lpFilename)
271 return 0;
273 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
274 OPEN_EXISTING, 0, -1)) == HFILE_ERROR)
275 return 0;
277 mh = MF_ReadMetaFile(hFile);
278 CloseHandle(hFile);
279 if(!mh) return 0;
280 return MF_Create_HMETAFILE( mh );
284 /******************************************************************
285 * MF_LoadDiskBasedMetaFile
287 * Creates a new memory-based metafile from a disk-based one.
289 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
291 METAHEADERDISK *mhd;
292 HFILE hfile;
293 METAHEADER *mh2;
295 if(mh->mtType != METAFILE_DISK) {
296 ERR("Not a disk based metafile\n");
297 return NULL;
299 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
301 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
302 OPEN_EXISTING, 0, -1)) == HFILE_ERROR) {
303 WARN("Can't open file of disk based metafile\n");
304 return NULL;
306 mh2 = MF_ReadMetaFile(hfile);
307 CloseHandle(hfile);
308 return mh2;
311 /******************************************************************
312 * MF_CreateMetaHeaderDisk
314 * Take a memory based METAHEADER and change it to a disk based METAHEADER
315 * assosiated with filename. Note: Trashes contents of old one.
317 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
319 METAHEADERDISK *mhd;
320 DWORD size;
322 mh = HeapReAlloc( SystemHeap, 0, mh,
323 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
324 mh->mtType = METAFILE_DISK;
325 size = HeapSize( SystemHeap, 0, mh );
326 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
327 strcpy(mhd->filename, filename);
328 return mh;
331 /******************************************************************
332 * CopyMetaFile16 (GDI.151)
334 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
336 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
337 METAHEADER *mh2 = NULL;
338 HFILE hFile;
340 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
342 if(!mh) return 0;
344 if(mh->mtType == METAFILE_DISK)
345 mh2 = MF_LoadDiskBasedMetaFile(mh);
346 else {
347 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
348 memcpy( mh2, mh, mh->mtSize * 2 );
350 MF_ReleaseMetaHeader16( hSrcMetaFile );
352 if(lpFilename) { /* disk based metafile */
353 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
354 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
355 HeapFree( SystemHeap, 0, mh2 );
356 return 0;
358 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
359 CloseHandle(hFile);
360 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
363 return MF_Create_HMETAFILE16( mh2 );
367 /******************************************************************
368 * CopyMetaFileA (GDI32.23)
370 * Copies the metafile corresponding to hSrcMetaFile to either
371 * a disk file, if a filename is given, or to a new memory based
372 * metafile, if lpFileName is NULL.
374 * RETURNS
376 * Handle to metafile copy on success, NULL on failure.
378 * BUGS
380 * Copying to disk returns NULL even if successful.
382 HMETAFILE WINAPI CopyMetaFileA(
383 HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
384 LPCSTR lpFilename /* filename if copying to a file */
386 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
387 METAHEADER *mh2 = NULL;
388 HFILE hFile;
390 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
392 if(!mh) return 0;
394 if(mh->mtType == METAFILE_DISK)
395 mh2 = MF_LoadDiskBasedMetaFile(mh);
396 else {
397 mh2 = HeapAlloc( SystemHeap, 0, mh->mtSize * 2 );
398 memcpy( mh2, mh, mh->mtSize * 2 );
400 MF_ReleaseMetaHeader( hSrcMetaFile );
402 if(lpFilename) { /* disk based metafile */
403 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
404 CREATE_ALWAYS, 0, -1)) == HFILE_ERROR) {
405 HeapFree( SystemHeap, 0, mh2 );
406 return 0;
408 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
409 CloseHandle(hFile);
410 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
413 return MF_Create_HMETAFILE( mh2 );
417 /******************************************************************
418 * CopyMetaFileW (GDI32.24)
420 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
421 LPCWSTR lpFilename )
423 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
424 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
425 HeapFree( GetProcessHeap(), 0, p );
426 return ret;
430 /******************************************************************
431 * IsValidMetaFile (GDI.410)
433 * Attempts to check if a given metafile is correctly formatted.
434 * Currently, the only things verified are several properties of the
435 * header.
437 * RETURNS
438 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
440 * BUGS
441 * This is not exactly what windows does, see _Undocumented_Windows_
442 * for details.
444 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
446 BOOL16 res=FALSE;
447 METAHEADER *mh = MF_GetMetaHeader16(hmf);
448 if (mh) {
449 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
450 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
451 if (mh->mtVersion == MFVERSION)
452 res=TRUE;
453 MF_ReleaseMetaHeader16(hmf);
455 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
456 return res;
460 /*******************************************************************
461 * MF_PlayMetaFile
463 * Helper for PlayMetaFile
465 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
468 METARECORD *mr;
469 HANDLETABLE16 *ht;
470 int offset = 0;
471 WORD i;
472 HPEN hPen;
473 HBRUSH hBrush;
474 HFONT hFont;
475 DC *dc;
476 BOOL loaded = FALSE;
478 if (!mh) return FALSE;
479 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
480 mh = MF_LoadDiskBasedMetaFile(mh);
481 if(!mh) return FALSE;
482 loaded = TRUE;
485 /* save the current pen, brush and font */
486 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
487 hPen = dc->w.hPen;
488 hBrush = dc->w.hBrush;
489 hFont = dc->w.hFont;
490 GDI_HEAP_UNLOCK(hdc);
491 /* create the handle table */
492 ht = HeapAlloc( SystemHeap, 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( SystemHeap, 0, ht );
524 if(loaded)
525 HeapFree( SystemHeap, 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, /* handle of DC to render in */
550 HMETAFILE hmf /* 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 DC *dc;
579 BOOL16 result = TRUE, loaded = FALSE;
581 TRACE("(%04x, %04x, %08lx, %08lx)\n",
582 hdc, hmf, (DWORD)lpEnumFunc, lpData);
585 if(!mh) return FALSE;
586 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
587 mh = MF_LoadDiskBasedMetaFile(mh);
588 if(!mh) return FALSE;
589 loaded = TRUE;
592 if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
593 hPen = dc->w.hPen;
594 hBrush = dc->w.hBrush;
595 hFont = dc->w.hFont;
596 GDI_HEAP_UNLOCK(hdc);
598 /* create the handle table */
600 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
601 sizeof(HANDLETABLE16) * mh->mtNoObjects);
602 spht = WIN16_GlobalLock16(hHT);
604 seg = GlobalHandleToSel16(hmf);
605 offset = mh->mtHeaderSize * 2;
607 /* loop through metafile records */
609 while (offset < (mh->mtSize * 2))
611 mr = (METARECORD *)((char *)mh + offset);
612 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
613 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
614 mh->mtNoObjects, (LONG)lpData ))
616 result = FALSE;
617 break;
621 offset += (mr->rdSize * 2);
624 SelectObject(hdc, hBrush);
625 SelectObject(hdc, hPen);
626 SelectObject(hdc, hFont);
628 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
630 /* free objects in handle table */
631 for(i = 0; i < mh->mtNoObjects; i++)
632 if(*(ht->objectHandle + i) != 0)
633 DeleteObject(*(ht->objectHandle + i));
635 /* free handle table */
636 GlobalFree16(hHT);
637 if(loaded)
638 HeapFree( SystemHeap, 0, mh );
639 MF_ReleaseMetaHeader16(hmf);
640 return result;
643 /******************************************************************
644 * EnumMetaFile (GDI32.88)
646 * Loop through the metafile records in hmf, calling the user-specified
647 * function for each one, stopping when the user's function returns FALSE
648 * (which is considered to be failure)
649 * or when no records are left (which is considered to be success).
651 * RETURNS
652 * TRUE on success, FALSE on failure.
654 * HISTORY
655 * Niels de carpentier, april 1996
657 BOOL WINAPI EnumMetaFile(
658 HDC hdc,
659 HMETAFILE hmf,
660 MFENUMPROC lpEnumFunc,
661 LPARAM lpData
663 METAHEADER *mh = MF_GetMetaHeader(hmf);
664 METARECORD *mr;
665 HANDLETABLE *ht;
666 BOOL result = TRUE, loaded = FALSE;
667 int i, offset = 0;
668 DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
669 HPEN hPen;
670 HBRUSH hBrush;
671 HFONT hFont;
673 TRACE("(%08x,%08x,%p,%p)\n",
674 hdc, hmf, lpEnumFunc, (void*)lpData);
675 if (!mh) return 0;
676 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
677 mh = MF_LoadDiskBasedMetaFile(mh);
678 if(!mh) return 0;
679 loaded = TRUE;
682 /* save the current pen, brush and font */
683 if (!dc) return 0;
684 hPen = dc->w.hPen;
685 hBrush = dc->w.hBrush;
686 hFont = dc->w.hFont;
687 GDI_HEAP_UNLOCK(hdc);
690 ht = HeapAlloc( SystemHeap, HEAP_ZERO_MEMORY,
691 sizeof(HANDLETABLE) * mh->mtNoObjects);
693 /* loop through metafile records */
694 offset = mh->mtHeaderSize * 2;
696 while (offset < (mh->mtSize * 2))
698 mr = (METARECORD *)((char *)mh + offset);
699 TRACE("Calling EnumFunc with record type %x\n",
700 mr->rdFunction);
701 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
703 result = FALSE;
704 break;
707 offset += (mr->rdSize * 2);
710 /* restore pen, brush and font */
711 SelectObject(hdc, hBrush);
712 SelectObject(hdc, hPen);
713 SelectObject(hdc, hFont);
715 /* free objects in handle table */
716 for(i = 0; i < mh->mtNoObjects; i++)
717 if(*(ht->objectHandle + i) != 0)
718 DeleteObject(*(ht->objectHandle + i));
720 /* free handle table */
721 HeapFree( SystemHeap, 0, ht);
722 if(loaded)
723 HeapFree( SystemHeap, 0, mh );
724 MF_ReleaseMetaHeader(hmf);
725 return result;
728 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
729 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
730 /******************************************************************
731 * PlayMetaFileRecord16 (GDI.176)
733 * Render a single metafile record specified by *mr in the DC hdc, while
734 * using the handle table *ht, of length nHandles,
735 * to store metafile objects.
737 * BUGS
738 * The following metafile records are unimplemented:
740 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
741 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
742 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
745 void WINAPI PlayMetaFileRecord16(
746 HDC16 hdc, /* DC to render metafile into */
747 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
748 METARECORD *mr, /* pointer to metafile record to render */
749 UINT16 nHandles /* size of handle table */
751 short s1;
752 HANDLE16 hndl;
753 char *ptr;
754 BITMAPINFOHEADER *infohdr;
756 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
757 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
759 switch (mr->rdFunction)
761 case META_EOF:
762 break;
764 case META_DELETEOBJECT:
765 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
766 *(ht->objectHandle + *(mr->rdParm)) = 0;
767 break;
769 case META_SETBKCOLOR:
770 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
771 break;
773 case META_SETBKMODE:
774 SetBkMode16(hdc, *(mr->rdParm));
775 break;
777 case META_SETMAPMODE:
778 SetMapMode16(hdc, *(mr->rdParm));
779 break;
781 case META_SETROP2:
782 SetROP216(hdc, *(mr->rdParm));
783 break;
785 case META_SETRELABS:
786 SetRelAbs16(hdc, *(mr->rdParm));
787 break;
789 case META_SETPOLYFILLMODE:
790 SetPolyFillMode16(hdc, *(mr->rdParm));
791 break;
793 case META_SETSTRETCHBLTMODE:
794 SetStretchBltMode16(hdc, *(mr->rdParm));
795 break;
797 case META_SETTEXTCOLOR:
798 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
799 break;
801 case META_SETWINDOWORG:
802 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
803 break;
805 case META_SETWINDOWEXT:
806 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
807 break;
809 case META_SETVIEWPORTORG:
810 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
811 break;
813 case META_SETVIEWPORTEXT:
814 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
815 break;
817 case META_OFFSETWINDOWORG:
818 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
819 break;
821 case META_SCALEWINDOWEXT:
822 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
823 *(mr->rdParm + 1), *(mr->rdParm));
824 break;
826 case META_OFFSETVIEWPORTORG:
827 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
828 break;
830 case META_SCALEVIEWPORTEXT:
831 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
832 *(mr->rdParm + 1), *(mr->rdParm));
833 break;
835 case META_LINETO:
836 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
837 break;
839 case META_MOVETO:
840 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
841 break;
843 case META_EXCLUDECLIPRECT:
844 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
845 *(mr->rdParm + 1), *(mr->rdParm) );
846 break;
848 case META_INTERSECTCLIPRECT:
849 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
850 *(mr->rdParm + 1), *(mr->rdParm) );
851 break;
853 case META_ARC:
854 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
855 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
856 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
857 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
858 break;
860 case META_ELLIPSE:
861 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
862 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
863 break;
865 case META_FLOODFILL:
866 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
867 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
868 break;
870 case META_PIE:
871 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
872 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
873 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
874 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
875 break;
877 case META_RECTANGLE:
878 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
879 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
880 break;
882 case META_ROUNDRECT:
883 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
884 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
885 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
886 break;
888 case META_PATBLT:
889 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
890 *(mr->rdParm + 3), *(mr->rdParm + 2),
891 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
892 break;
894 case META_SAVEDC:
895 SaveDC(hdc);
896 break;
898 case META_SETPIXEL:
899 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
900 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
901 break;
903 case META_OFFSETCLIPRGN:
904 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
905 break;
907 case META_TEXTOUT:
908 s1 = *(mr->rdParm);
909 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
910 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
911 (char *)(mr->rdParm + 1), s1);
912 break;
914 case META_POLYGON:
915 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
916 break;
918 case META_POLYPOLYGON:
919 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
920 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
921 break;
923 case META_POLYLINE:
924 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
925 break;
927 case META_RESTOREDC:
928 RestoreDC(hdc, (INT16)*(mr->rdParm));
929 break;
931 case META_SELECTOBJECT:
932 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
933 break;
935 case META_CHORD:
936 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
937 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
938 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
939 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
940 break;
942 case META_CREATEPATTERNBRUSH:
943 switch (*(mr->rdParm))
945 case BS_PATTERN:
946 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
947 MF_AddHandle(ht, nHandles,
948 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
949 infohdr->biHeight,
950 infohdr->biPlanes,
951 infohdr->biBitCount,
952 (LPSTR)(mr->rdParm +
953 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
954 break;
956 case BS_DIBPATTERN:
957 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
958 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
959 ptr = GlobalLock16(hndl);
960 memcpy(ptr, mr->rdParm + 2, s1);
961 GlobalUnlock16(hndl);
962 MF_AddHandle(ht, nHandles,
963 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
964 GlobalFree16(hndl);
965 break;
967 default:
968 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
969 mr->rdParm[0]);
970 break;
972 break;
974 case META_CREATEPENINDIRECT:
975 MF_AddHandle(ht, nHandles,
976 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
977 break;
979 case META_CREATEFONTINDIRECT:
980 MF_AddHandle(ht, nHandles,
981 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
982 break;
984 case META_CREATEBRUSHINDIRECT:
985 MF_AddHandle(ht, nHandles,
986 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
987 break;
989 case META_CREATEPALETTE:
990 MF_AddHandle(ht, nHandles,
991 CreatePalette16((LPLOGPALETTE)mr->rdParm));
992 break;
994 case META_SETTEXTALIGN:
995 SetTextAlign16(hdc, *(mr->rdParm));
996 break;
998 case META_SELECTPALETTE:
999 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1000 *(mr->rdParm));
1001 break;
1003 case META_SETMAPPERFLAGS:
1004 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1005 break;
1007 case META_REALIZEPALETTE:
1008 RealizePalette16(hdc);
1009 break;
1011 case META_ESCAPE:
1012 FIXME("META_ESCAPE unimplemented.\n");
1013 break;
1015 case META_EXTTEXTOUT:
1016 MF_Play_MetaExtTextOut( hdc, mr );
1017 break;
1019 case META_STRETCHDIB:
1021 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1022 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1023 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1024 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1025 mr->rdParm[4],mr->rdParm[3],bits,info,
1026 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1028 break;
1030 case META_DIBSTRETCHBLT:
1032 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1033 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1034 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1035 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1036 mr->rdParm[3],mr->rdParm[2],bits,info,
1037 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1039 break;
1041 case META_STRETCHBLT:
1043 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1044 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1045 mr->rdParm[11], /*Height*/
1046 mr->rdParm[13], /*Planes*/
1047 mr->rdParm[14], /*BitsPixel*/
1048 (LPSTR)&mr->rdParm[15]); /*bits*/
1049 SelectObject(hdcSrc,hbitmap);
1050 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1051 mr->rdParm[7],mr->rdParm[6],
1052 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1053 mr->rdParm[3],mr->rdParm[2],
1054 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1055 DeleteDC(hdcSrc);
1057 break;
1059 case META_BITBLT:
1061 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1062 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1063 mr->rdParm[8]/*Height*/,
1064 mr->rdParm[10]/*Planes*/,
1065 mr->rdParm[11]/*BitsPixel*/,
1066 (LPSTR)&mr->rdParm[12]/*bits*/);
1067 SelectObject(hdcSrc,hbitmap);
1068 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1069 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1070 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1071 MAKELONG(0,mr->rdParm[0]));
1072 DeleteDC(hdcSrc);
1074 break;
1076 case META_CREATEREGION:
1078 HRGN hrgn = CreateRectRgn(0,0,0,0);
1080 MF_Play_MetaCreateRegion(mr, hrgn);
1081 MF_AddHandle(ht, nHandles, hrgn);
1083 break;
1085 case META_FILLREGION:
1086 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1087 *(ht->objectHandle + *(mr->rdParm)));
1088 break;
1090 case META_FRAMEREGION:
1091 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1092 *(ht->objectHandle + *(mr->rdParm+2)),
1093 *(mr->rdParm+1), *(mr->rdParm));
1094 break;
1096 case META_INVERTREGION:
1097 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1098 break;
1100 case META_PAINTREGION:
1101 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1102 break;
1104 case META_SELECTCLIPREGION:
1105 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1106 break;
1108 case META_DIBCREATEPATTERNBRUSH:
1109 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1110 but there's no difference */
1112 TRACE("%d\n",*(mr->rdParm));
1113 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1114 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1115 ptr = GlobalLock16(hndl);
1116 memcpy(ptr, mr->rdParm + 2, s1);
1117 GlobalUnlock16(hndl);
1118 MF_AddHandle(ht, nHandles,
1119 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1120 GlobalFree16(hndl);
1121 break;
1123 case META_DIBBITBLT:
1124 /* In practice I've found that there are two layouts for
1125 META_DIBBITBLT, one (the first here) is the usual one when a src
1126 dc is actually passed to it, the second occurs when the src dc is
1127 passed in as NULL to the creating BitBlt. As the second case has
1128 no dib, a size check will suffice to distinguish.
1130 Caolan.McNamara@ul.ie */
1132 if (mr->rdSize > 12) {
1133 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1134 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1136 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1137 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1138 mr->rdParm[5], mr->rdParm[4], bits, info,
1139 DIB_RGB_COLORS,
1140 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1141 } else { /* equivalent to a PatBlt */
1142 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1143 mr->rdParm[6], mr->rdParm[5],
1144 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1146 break;
1148 case META_SETTEXTCHAREXTRA:
1149 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1150 break;
1152 case META_SETTEXTJUSTIFICATION:
1153 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1154 break;
1156 case META_EXTFLOODFILL:
1157 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1158 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1159 *(mr->rdParm));
1160 break;
1162 case META_SETDIBTODEV:
1164 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1165 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1166 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1167 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1168 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1169 mr->rdParm[2], mr->rdParm[1], bits, info,
1170 mr->rdParm[0]);
1171 break;
1174 #define META_UNIMP(x) case x: \
1175 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1176 break;
1177 META_UNIMP(META_DRAWTEXT)
1178 META_UNIMP(META_ANIMATEPALETTE)
1179 META_UNIMP(META_SETPALENTRIES)
1180 META_UNIMP(META_RESIZEPALETTE)
1181 META_UNIMP(META_RESETDC)
1182 META_UNIMP(META_STARTDOC)
1183 META_UNIMP(META_STARTPAGE)
1184 META_UNIMP(META_ENDPAGE)
1185 META_UNIMP(META_ABORTDOC)
1186 META_UNIMP(META_ENDDOC)
1187 META_UNIMP(META_CREATEBRUSH)
1188 META_UNIMP(META_CREATEBITMAPINDIRECT)
1189 META_UNIMP(META_CREATEBITMAP)
1190 #undef META_UNIMP
1192 default:
1193 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1194 mr->rdFunction);
1198 /******************************************************************
1199 * PlayMetaFileRecord (GDI32.266)
1201 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1202 METARECORD *metarecord, UINT handles )
1204 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1205 handles*sizeof(HANDLETABLE16));
1206 int i = 0;
1207 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1208 handles);
1209 for (i=0; i<handles; i++)
1210 ht->objectHandle[i] = handletable->objectHandle[i];
1211 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1212 for (i=0; i<handles; i++)
1213 handletable->objectHandle[i] = ht->objectHandle[i];
1214 GlobalFree((HGLOBAL)ht);
1215 return TRUE;
1218 /******************************************************************
1219 * GetMetaFileBits (GDI.159)
1221 * Trade in a metafile object handle for a handle to the metafile memory.
1225 HGLOBAL16 WINAPI GetMetaFileBits16(
1226 HMETAFILE16 hmf /* metafile handle */
1229 TRACE("hMem out: %04x\n", hmf);
1230 return hmf;
1233 /******************************************************************
1234 * SetMetaFileBits (GDI.160)
1236 * Trade in a metafile memory handle for a handle to a metafile object.
1237 * The memory region should hold a proper metafile, otherwise
1238 * problems will occur when it is used. Validity of the memory is not
1239 * checked. The function is essentially just the identity function.
1241 HMETAFILE16 WINAPI SetMetaFileBits16(
1242 HGLOBAL16 hMem
1243 /* handle to a memory region holding a metafile */
1246 TRACE("hmf out: %04x\n", hMem);
1248 return hMem;
1251 /******************************************************************
1252 * SetMetaFileBitsBetter (GDI.196)
1254 * Trade in a metafile memory handle for a handle to a metafile object,
1255 * making a cursory check (using IsValidMetaFile()) that the memory
1256 * handle points to a valid metafile.
1258 * RETURNS
1259 * Handle to a metafile on success, NULL on failure..
1261 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1263 if( IsValidMetaFile16( hMeta ) )
1264 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1265 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1266 return (HMETAFILE16)0;
1269 /******************************************************************
1270 * SetMetaFileBitsEx (GDI32.323)
1272 * Create a metafile from raw data. No checking of the data is performed.
1273 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1275 HMETAFILE WINAPI SetMetaFileBitsEx(
1276 UINT size, /* size of metafile, in bytes */
1277 const BYTE *lpData /* pointer to metafile data */
1280 METAHEADER *mh = HeapAlloc( SystemHeap, 0, size );
1281 if (!mh) return 0;
1282 memcpy(mh, lpData, size);
1283 return MF_Create_HMETAFILE(mh);
1286 /*****************************************************************
1287 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1289 * Copies the data from metafile _hmf_ into the buffer _buf_.
1290 * If _buf_ is zero, returns size of buffer required. Otherwise,
1291 * returns number of bytes copied.
1293 UINT WINAPI GetMetaFileBitsEx(
1294 HMETAFILE hmf, /* metafile */
1295 UINT nSize, /* size of buf */
1296 LPVOID buf /* buffer to receive raw metafile data */
1298 METAHEADER *mh = MF_GetMetaHeader(hmf);
1299 UINT mfSize;
1301 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1302 if (!mh) return 0; /* FIXME: error code */
1303 if(mh->mtType == METAFILE_DISK)
1304 FIXME("Disk-based metafile?\n");
1305 mfSize = mh->mtSize * 2;
1306 if (!buf) {
1307 MF_ReleaseMetaHeader(hmf);
1308 TRACE("returning size %d\n", mfSize);
1309 return mfSize;
1311 if(mfSize > nSize) mfSize = nSize;
1312 memmove(buf, mh, mfSize);
1313 MF_ReleaseMetaHeader(hmf);
1314 return mfSize;
1317 /******************************************************************
1318 * GetWinMetaFileBits [GDI32.241]
1320 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1321 UINT cbBuffer, LPBYTE lpbBuffer,
1322 INT fnMapMode, HDC hdcRef)
1324 FIXME("(%d,%d,%p,%d,%d): stub\n",
1325 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1326 return 0;
1329 /******************************************************************
1330 * MF_Play_MetaCreateRegion
1332 * Handles META_CREATEREGION for PlayMetaFileRecord().
1336 * The layout of the record looks something like this:
1338 * rdParm meaning
1339 * 0 Always 0?
1340 * 1 Always 6?
1341 * 2 Looks like a handle? - not constant
1342 * 3 0 or 1 ??
1343 * 4 Total number of bytes
1344 * 5 No. of seperate bands = n [see below]
1345 * 6 Largest number of x co-ords in a band
1346 * 7-10 Bounding box x1 y1 x2 y2
1347 * 11-... n bands
1349 * Regions are divided into bands that are uniform in the
1350 * y-direction. Each band consists of pairs of on/off x-coords and is
1351 * written as
1352 * m y0 y1 x1 x2 x3 ... xm m
1353 * into successive rdParm[]s.
1355 * This is probably just a dump of the internal RGNOBJ?
1357 * HDMD - 18/12/97
1361 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1363 WORD band, pair;
1364 WORD *start, *end;
1365 INT16 y0, y1;
1366 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1368 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1369 band++, start = end + 1) {
1370 if(*start / 2 != (*start + 1) / 2) {
1371 WARN("Delimiter not even.\n");
1372 DeleteObject( hrgn2 );
1373 return FALSE;
1376 end = start + *start + 3;
1377 if(end > (WORD *)mr + mr->rdSize) {
1378 WARN("End points outside record.\n");
1379 DeleteObject( hrgn2 );
1380 return FALSE;
1383 if(*start != *end) {
1384 WARN("Mismatched delimiters.\n");
1385 DeleteObject( hrgn2 );
1386 return FALSE;
1389 y0 = *(INT16 *)(start + 1);
1390 y1 = *(INT16 *)(start + 2);
1391 for(pair = 0; pair < *start / 2; pair++) {
1392 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1393 *(INT16 *)(start + 4 + 2*pair), y1 );
1394 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1397 DeleteObject( hrgn2 );
1398 return TRUE;
1402 /******************************************************************
1403 * MF_Play_MetaExtTextOut
1405 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1408 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1410 LPINT16 dxx;
1411 LPSTR sot;
1412 DWORD len;
1413 WORD s1;
1415 s1 = mr->rdParm[2]; /* String length */
1416 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1417 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1418 /* rec len without dx array */
1420 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1421 if (mr->rdParm[3])
1422 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1424 if (mr->rdSize == len / 2)
1425 dxx = NULL; /* determine if array present */
1426 else
1427 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1428 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1429 else {
1430 TRACE("%s len: %ld\n", sot, mr->rdSize);
1431 WARN(
1432 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1433 len, s1, mr->rdSize, mr->rdParm[3]);
1434 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1436 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1437 mr->rdParm[0], /* Y position */
1438 mr->rdParm[3], /* options */
1439 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1440 /* rectangle */
1441 sot, /* string */
1442 s1, dxx); /* length, dx array */
1443 if (dxx)
1444 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1445 return TRUE;