Terminate image data with a '>' [The PSLRM is rather vague about this].
[wine/multimedia.git] / objects / metafile.c
blob6c52e5736ac91f0bc9575cb794d8fde5d475251c
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( GetProcessHeap(), 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( GetProcessHeap(), 0, size );
186 if(!mh) return NULL;
187 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
188 BytesRead != size) {
189 HeapFree( GetProcessHeap(), 0, mh );
190 return NULL;
192 size = mh->mtSize * 2;
193 mh = HeapReAlloc( GetProcessHeap(), 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( GetProcessHeap(), 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( GetProcessHeap(), 0, mh,
323 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
324 mh->mtType = METAFILE_DISK;
325 size = HeapSize( GetProcessHeap(), 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( GetProcessHeap(), 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( GetProcessHeap(), 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( GetProcessHeap(), 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( GetProcessHeap(), 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 BOOL loaded = FALSE;
477 if (!mh) return FALSE;
478 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
479 mh = MF_LoadDiskBasedMetaFile(mh);
480 if(!mh) return FALSE;
481 loaded = TRUE;
484 /* save the current pen, brush and font */
485 hPen = GetCurrentObject(hdc, OBJ_PEN);
486 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
487 hFont = GetCurrentObject(hdc, OBJ_FONT);
489 /* create the handle table */
490 ht = HeapAlloc( GetProcessHeap(), 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("offset=%04x,size=%08lx\n",
500 offset, mr->rdSize);
501 if (!mr->rdSize) {
502 TRACE(
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( GetProcessHeap(), 0, ht );
522 if(loaded)
523 HeapFree( GetProcessHeap(), 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 BOOL16 result = TRUE, loaded = FALSE;
578 TRACE("(%04x, %04x, %08lx, %08lx)\n",
579 hdc, hmf, (DWORD)lpEnumFunc, lpData);
582 if(!mh) return FALSE;
583 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
584 mh = MF_LoadDiskBasedMetaFile(mh);
585 if(!mh) return FALSE;
586 loaded = TRUE;
589 /* save the current pen, brush and font */
590 hPen = GetCurrentObject(hdc, OBJ_PEN);
591 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
592 hFont = GetCurrentObject(hdc, OBJ_FONT);
594 /* create the handle table */
596 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
597 sizeof(HANDLETABLE16) * mh->mtNoObjects);
598 spht = WIN16_GlobalLock16(hHT);
600 seg = GlobalHandleToSel16(hmf);
601 offset = mh->mtHeaderSize * 2;
603 /* loop through metafile records */
605 while (offset < (mh->mtSize * 2))
607 mr = (METARECORD *)((char *)mh + offset);
608 if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
609 (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
610 mh->mtNoObjects, (LONG)lpData ))
612 result = FALSE;
613 break;
617 offset += (mr->rdSize * 2);
620 SelectObject(hdc, hBrush);
621 SelectObject(hdc, hPen);
622 SelectObject(hdc, hFont);
624 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
626 /* free objects in handle table */
627 for(i = 0; i < mh->mtNoObjects; i++)
628 if(*(ht->objectHandle + i) != 0)
629 DeleteObject(*(ht->objectHandle + i));
631 /* free handle table */
632 GlobalFree16(hHT);
633 if(loaded)
634 HeapFree( GetProcessHeap(), 0, mh );
635 MF_ReleaseMetaHeader16(hmf);
636 return result;
639 /******************************************************************
640 * EnumMetaFile (GDI32.88)
642 * Loop through the metafile records in hmf, calling the user-specified
643 * function for each one, stopping when the user's function returns FALSE
644 * (which is considered to be failure)
645 * or when no records are left (which is considered to be success).
647 * RETURNS
648 * TRUE on success, FALSE on failure.
650 * HISTORY
651 * Niels de carpentier, april 1996
653 BOOL WINAPI EnumMetaFile(
654 HDC hdc,
655 HMETAFILE hmf,
656 MFENUMPROC lpEnumFunc,
657 LPARAM lpData
659 METAHEADER *mh = MF_GetMetaHeader(hmf);
660 METARECORD *mr;
661 HANDLETABLE *ht;
662 BOOL result = TRUE, loaded = FALSE;
663 int i, offset = 0;
664 HPEN hPen;
665 HBRUSH hBrush;
666 HFONT hFont;
668 TRACE("(%08x,%08x,%p,%p)\n",
669 hdc, hmf, lpEnumFunc, (void*)lpData);
670 if (!mh) return 0;
671 if(mh->mtType == METAFILE_DISK) { /* Create a memoery-based copy */
672 mh = MF_LoadDiskBasedMetaFile(mh);
673 if(!mh) return 0;
674 loaded = TRUE;
677 /* save the current pen, brush and font */
678 hPen = GetCurrentObject(hdc, OBJ_PEN);
679 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
680 hFont = GetCurrentObject(hdc, OBJ_FONT);
682 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
683 sizeof(HANDLETABLE) * mh->mtNoObjects);
685 /* loop through metafile records */
686 offset = mh->mtHeaderSize * 2;
688 while (offset < (mh->mtSize * 2))
690 mr = (METARECORD *)((char *)mh + offset);
691 TRACE("Calling EnumFunc with record type %x\n",
692 mr->rdFunction);
693 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
695 result = FALSE;
696 break;
699 offset += (mr->rdSize * 2);
702 /* restore pen, brush and font */
703 SelectObject(hdc, hBrush);
704 SelectObject(hdc, hPen);
705 SelectObject(hdc, hFont);
707 /* free objects in handle table */
708 for(i = 0; i < mh->mtNoObjects; i++)
709 if(*(ht->objectHandle + i) != 0)
710 DeleteObject(*(ht->objectHandle + i));
712 /* free handle table */
713 HeapFree( GetProcessHeap(), 0, ht);
714 if(loaded)
715 HeapFree( GetProcessHeap(), 0, mh );
716 MF_ReleaseMetaHeader(hmf);
717 return result;
720 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
721 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
722 /******************************************************************
723 * PlayMetaFileRecord16 (GDI.176)
725 * Render a single metafile record specified by *mr in the DC hdc, while
726 * using the handle table *ht, of length nHandles,
727 * to store metafile objects.
729 * BUGS
730 * The following metafile records are unimplemented:
732 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
733 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
734 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
737 void WINAPI PlayMetaFileRecord16(
738 HDC16 hdc, /* DC to render metafile into */
739 HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
740 METARECORD *mr, /* pointer to metafile record to render */
741 UINT16 nHandles /* size of handle table */
743 short s1;
744 HANDLE16 hndl;
745 char *ptr;
746 BITMAPINFOHEADER *infohdr;
748 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
749 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
751 switch (mr->rdFunction)
753 case META_EOF:
754 break;
756 case META_DELETEOBJECT:
757 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
758 *(ht->objectHandle + *(mr->rdParm)) = 0;
759 break;
761 case META_SETBKCOLOR:
762 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
763 break;
765 case META_SETBKMODE:
766 SetBkMode16(hdc, *(mr->rdParm));
767 break;
769 case META_SETMAPMODE:
770 SetMapMode16(hdc, *(mr->rdParm));
771 break;
773 case META_SETROP2:
774 SetROP216(hdc, *(mr->rdParm));
775 break;
777 case META_SETRELABS:
778 SetRelAbs16(hdc, *(mr->rdParm));
779 break;
781 case META_SETPOLYFILLMODE:
782 SetPolyFillMode16(hdc, *(mr->rdParm));
783 break;
785 case META_SETSTRETCHBLTMODE:
786 SetStretchBltMode16(hdc, *(mr->rdParm));
787 break;
789 case META_SETTEXTCOLOR:
790 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
791 break;
793 case META_SETWINDOWORG:
794 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
795 break;
797 case META_SETWINDOWEXT:
798 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
799 break;
801 case META_SETVIEWPORTORG:
802 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
803 break;
805 case META_SETVIEWPORTEXT:
806 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
807 break;
809 case META_OFFSETWINDOWORG:
810 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
811 break;
813 case META_SCALEWINDOWEXT:
814 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
815 *(mr->rdParm + 1), *(mr->rdParm));
816 break;
818 case META_OFFSETVIEWPORTORG:
819 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
820 break;
822 case META_SCALEVIEWPORTEXT:
823 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
824 *(mr->rdParm + 1), *(mr->rdParm));
825 break;
827 case META_LINETO:
828 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
829 break;
831 case META_MOVETO:
832 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
833 break;
835 case META_EXCLUDECLIPRECT:
836 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
837 *(mr->rdParm + 1), *(mr->rdParm) );
838 break;
840 case META_INTERSECTCLIPRECT:
841 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
842 *(mr->rdParm + 1), *(mr->rdParm) );
843 break;
845 case META_ARC:
846 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
847 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
848 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
849 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
850 break;
852 case META_ELLIPSE:
853 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
854 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
855 break;
857 case META_FLOODFILL:
858 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
859 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
860 break;
862 case META_PIE:
863 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
864 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
865 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
866 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
867 break;
869 case META_RECTANGLE:
870 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
871 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
872 break;
874 case META_ROUNDRECT:
875 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
876 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
877 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
878 break;
880 case META_PATBLT:
881 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
882 *(mr->rdParm + 3), *(mr->rdParm + 2),
883 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
884 break;
886 case META_SAVEDC:
887 SaveDC(hdc);
888 break;
890 case META_SETPIXEL:
891 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
892 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
893 break;
895 case META_OFFSETCLIPRGN:
896 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
897 break;
899 case META_TEXTOUT:
900 s1 = *(mr->rdParm);
901 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
902 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
903 (char *)(mr->rdParm + 1), s1);
904 break;
906 case META_POLYGON:
907 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
908 break;
910 case META_POLYPOLYGON:
911 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
912 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
913 break;
915 case META_POLYLINE:
916 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
917 break;
919 case META_RESTOREDC:
920 RestoreDC(hdc, (INT16)*(mr->rdParm));
921 break;
923 case META_SELECTOBJECT:
924 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
925 break;
927 case META_CHORD:
928 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
929 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
930 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
931 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
932 break;
934 case META_CREATEPATTERNBRUSH:
935 switch (*(mr->rdParm))
937 case BS_PATTERN:
938 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
939 MF_AddHandle(ht, nHandles,
940 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
941 infohdr->biHeight,
942 infohdr->biPlanes,
943 infohdr->biBitCount,
944 (LPSTR)(mr->rdParm +
945 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
946 break;
948 case BS_DIBPATTERN:
949 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
950 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
951 ptr = GlobalLock16(hndl);
952 memcpy(ptr, mr->rdParm + 2, s1);
953 GlobalUnlock16(hndl);
954 MF_AddHandle(ht, nHandles,
955 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
956 GlobalFree16(hndl);
957 break;
959 default:
960 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
961 mr->rdParm[0]);
962 break;
964 break;
966 case META_CREATEPENINDIRECT:
967 MF_AddHandle(ht, nHandles,
968 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
969 break;
971 case META_CREATEFONTINDIRECT:
972 MF_AddHandle(ht, nHandles,
973 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
974 break;
976 case META_CREATEBRUSHINDIRECT:
977 MF_AddHandle(ht, nHandles,
978 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
979 break;
981 case META_CREATEPALETTE:
982 MF_AddHandle(ht, nHandles,
983 CreatePalette16((LPLOGPALETTE)mr->rdParm));
984 break;
986 case META_SETTEXTALIGN:
987 SetTextAlign16(hdc, *(mr->rdParm));
988 break;
990 case META_SELECTPALETTE:
991 SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
992 *(mr->rdParm));
993 break;
995 case META_SETMAPPERFLAGS:
996 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
997 break;
999 case META_REALIZEPALETTE:
1000 RealizePalette16(hdc);
1001 break;
1003 case META_ESCAPE:
1004 FIXME("META_ESCAPE unimplemented.\n");
1005 break;
1007 case META_EXTTEXTOUT:
1008 MF_Play_MetaExtTextOut( hdc, mr );
1009 break;
1011 case META_STRETCHDIB:
1013 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1014 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1015 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1016 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1017 mr->rdParm[4],mr->rdParm[3],bits,info,
1018 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1020 break;
1022 case META_DIBSTRETCHBLT:
1024 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1025 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1026 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1027 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1028 mr->rdParm[3],mr->rdParm[2],bits,info,
1029 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1031 break;
1033 case META_STRETCHBLT:
1035 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1036 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1037 mr->rdParm[11], /*Height*/
1038 mr->rdParm[13], /*Planes*/
1039 mr->rdParm[14], /*BitsPixel*/
1040 (LPSTR)&mr->rdParm[15]); /*bits*/
1041 SelectObject(hdcSrc,hbitmap);
1042 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1043 mr->rdParm[7],mr->rdParm[6],
1044 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1045 mr->rdParm[3],mr->rdParm[2],
1046 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1047 DeleteDC(hdcSrc);
1049 break;
1051 case META_BITBLT:
1053 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1054 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1055 mr->rdParm[8]/*Height*/,
1056 mr->rdParm[10]/*Planes*/,
1057 mr->rdParm[11]/*BitsPixel*/,
1058 (LPSTR)&mr->rdParm[12]/*bits*/);
1059 SelectObject(hdcSrc,hbitmap);
1060 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1061 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1062 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1063 MAKELONG(0,mr->rdParm[0]));
1064 DeleteDC(hdcSrc);
1066 break;
1068 case META_CREATEREGION:
1070 HRGN hrgn = CreateRectRgn(0,0,0,0);
1072 MF_Play_MetaCreateRegion(mr, hrgn);
1073 MF_AddHandle(ht, nHandles, hrgn);
1075 break;
1077 case META_FILLREGION:
1078 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1079 *(ht->objectHandle + *(mr->rdParm)));
1080 break;
1082 case META_FRAMEREGION:
1083 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1084 *(ht->objectHandle + *(mr->rdParm+2)),
1085 *(mr->rdParm+1), *(mr->rdParm));
1086 break;
1088 case META_INVERTREGION:
1089 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1090 break;
1092 case META_PAINTREGION:
1093 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1094 break;
1096 case META_SELECTCLIPREGION:
1097 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1098 break;
1100 case META_DIBCREATEPATTERNBRUSH:
1101 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1102 but there's no difference */
1104 TRACE("%d\n",*(mr->rdParm));
1105 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1106 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1107 ptr = GlobalLock16(hndl);
1108 memcpy(ptr, mr->rdParm + 2, s1);
1109 GlobalUnlock16(hndl);
1110 MF_AddHandle(ht, nHandles,
1111 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1112 GlobalFree16(hndl);
1113 break;
1115 case META_DIBBITBLT:
1116 /* In practice I've found that there are two layouts for
1117 META_DIBBITBLT, one (the first here) is the usual one when a src
1118 dc is actually passed to it, the second occurs when the src dc is
1119 passed in as NULL to the creating BitBlt. As the second case has
1120 no dib, a size check will suffice to distinguish.
1122 Caolan.McNamara@ul.ie */
1124 if (mr->rdSize > 12) {
1125 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1126 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1128 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1129 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1130 mr->rdParm[5], mr->rdParm[4], bits, info,
1131 DIB_RGB_COLORS,
1132 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1133 } else { /* equivalent to a PatBlt */
1134 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1135 mr->rdParm[6], mr->rdParm[5],
1136 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1138 break;
1140 case META_SETTEXTCHAREXTRA:
1141 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1142 break;
1144 case META_SETTEXTJUSTIFICATION:
1145 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1146 break;
1148 case META_EXTFLOODFILL:
1149 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1150 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1151 *(mr->rdParm));
1152 break;
1154 case META_SETDIBTODEV:
1156 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1157 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1158 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1159 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1160 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1161 mr->rdParm[2], mr->rdParm[1], bits, info,
1162 mr->rdParm[0]);
1163 break;
1166 #define META_UNIMP(x) case x: \
1167 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1168 break;
1169 META_UNIMP(META_DRAWTEXT)
1170 META_UNIMP(META_ANIMATEPALETTE)
1171 META_UNIMP(META_SETPALENTRIES)
1172 META_UNIMP(META_RESIZEPALETTE)
1173 META_UNIMP(META_RESETDC)
1174 META_UNIMP(META_STARTDOC)
1175 META_UNIMP(META_STARTPAGE)
1176 META_UNIMP(META_ENDPAGE)
1177 META_UNIMP(META_ABORTDOC)
1178 META_UNIMP(META_ENDDOC)
1179 META_UNIMP(META_CREATEBRUSH)
1180 META_UNIMP(META_CREATEBITMAPINDIRECT)
1181 META_UNIMP(META_CREATEBITMAP)
1182 #undef META_UNIMP
1184 default:
1185 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1186 mr->rdFunction);
1190 /******************************************************************
1191 * PlayMetaFileRecord (GDI32.266)
1193 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1194 METARECORD *metarecord, UINT handles )
1196 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1197 handles*sizeof(HANDLETABLE16));
1198 int i = 0;
1199 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1200 handles);
1201 for (i=0; i<handles; i++)
1202 ht->objectHandle[i] = handletable->objectHandle[i];
1203 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1204 for (i=0; i<handles; i++)
1205 handletable->objectHandle[i] = ht->objectHandle[i];
1206 GlobalFree((HGLOBAL)ht);
1207 return TRUE;
1210 /******************************************************************
1211 * GetMetaFileBits (GDI.159)
1213 * Trade in a metafile object handle for a handle to the metafile memory.
1217 HGLOBAL16 WINAPI GetMetaFileBits16(
1218 HMETAFILE16 hmf /* metafile handle */
1221 TRACE("hMem out: %04x\n", hmf);
1222 return hmf;
1225 /******************************************************************
1226 * SetMetaFileBits (GDI.160)
1228 * Trade in a metafile memory handle for a handle to a metafile object.
1229 * The memory region should hold a proper metafile, otherwise
1230 * problems will occur when it is used. Validity of the memory is not
1231 * checked. The function is essentially just the identity function.
1233 HMETAFILE16 WINAPI SetMetaFileBits16(
1234 HGLOBAL16 hMem
1235 /* handle to a memory region holding a metafile */
1238 TRACE("hmf out: %04x\n", hMem);
1240 return hMem;
1243 /******************************************************************
1244 * SetMetaFileBitsBetter (GDI.196)
1246 * Trade in a metafile memory handle for a handle to a metafile object,
1247 * making a cursory check (using IsValidMetaFile()) that the memory
1248 * handle points to a valid metafile.
1250 * RETURNS
1251 * Handle to a metafile on success, NULL on failure..
1253 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1255 if( IsValidMetaFile16( hMeta ) )
1256 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1257 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1258 return (HMETAFILE16)0;
1261 /******************************************************************
1262 * SetMetaFileBitsEx (GDI32.323)
1264 * Create a metafile from raw data. No checking of the data is performed.
1265 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1267 HMETAFILE WINAPI SetMetaFileBitsEx(
1268 UINT size, /* size of metafile, in bytes */
1269 const BYTE *lpData /* pointer to metafile data */
1272 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1273 if (!mh) return 0;
1274 memcpy(mh, lpData, size);
1275 return MF_Create_HMETAFILE(mh);
1278 /*****************************************************************
1279 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1281 * Copies the data from metafile _hmf_ into the buffer _buf_.
1282 * If _buf_ is zero, returns size of buffer required. Otherwise,
1283 * returns number of bytes copied.
1285 UINT WINAPI GetMetaFileBitsEx(
1286 HMETAFILE hmf, /* metafile */
1287 UINT nSize, /* size of buf */
1288 LPVOID buf /* buffer to receive raw metafile data */
1290 METAHEADER *mh = MF_GetMetaHeader(hmf);
1291 UINT mfSize;
1293 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1294 if (!mh) return 0; /* FIXME: error code */
1295 if(mh->mtType == METAFILE_DISK)
1296 FIXME("Disk-based metafile?\n");
1297 mfSize = mh->mtSize * 2;
1298 if (!buf) {
1299 MF_ReleaseMetaHeader(hmf);
1300 TRACE("returning size %d\n", mfSize);
1301 return mfSize;
1303 if(mfSize > nSize) mfSize = nSize;
1304 memmove(buf, mh, mfSize);
1305 MF_ReleaseMetaHeader(hmf);
1306 return mfSize;
1309 /******************************************************************
1310 * GetWinMetaFileBits [GDI32.241]
1312 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1313 UINT cbBuffer, LPBYTE lpbBuffer,
1314 INT fnMapMode, HDC hdcRef)
1316 FIXME("(%d,%d,%p,%d,%d): stub\n",
1317 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1318 return 0;
1321 /******************************************************************
1322 * MF_Play_MetaCreateRegion
1324 * Handles META_CREATEREGION for PlayMetaFileRecord().
1328 * The layout of the record looks something like this:
1330 * rdParm meaning
1331 * 0 Always 0?
1332 * 1 Always 6?
1333 * 2 Looks like a handle? - not constant
1334 * 3 0 or 1 ??
1335 * 4 Total number of bytes
1336 * 5 No. of seperate bands = n [see below]
1337 * 6 Largest number of x co-ords in a band
1338 * 7-10 Bounding box x1 y1 x2 y2
1339 * 11-... n bands
1341 * Regions are divided into bands that are uniform in the
1342 * y-direction. Each band consists of pairs of on/off x-coords and is
1343 * written as
1344 * m y0 y1 x1 x2 x3 ... xm m
1345 * into successive rdParm[]s.
1347 * This is probably just a dump of the internal RGNOBJ?
1349 * HDMD - 18/12/97
1353 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1355 WORD band, pair;
1356 WORD *start, *end;
1357 INT16 y0, y1;
1358 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1360 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1361 band++, start = end + 1) {
1362 if(*start / 2 != (*start + 1) / 2) {
1363 WARN("Delimiter not even.\n");
1364 DeleteObject( hrgn2 );
1365 return FALSE;
1368 end = start + *start + 3;
1369 if(end > (WORD *)mr + mr->rdSize) {
1370 WARN("End points outside record.\n");
1371 DeleteObject( hrgn2 );
1372 return FALSE;
1375 if(*start != *end) {
1376 WARN("Mismatched delimiters.\n");
1377 DeleteObject( hrgn2 );
1378 return FALSE;
1381 y0 = *(INT16 *)(start + 1);
1382 y1 = *(INT16 *)(start + 2);
1383 for(pair = 0; pair < *start / 2; pair++) {
1384 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1385 *(INT16 *)(start + 4 + 2*pair), y1 );
1386 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1389 DeleteObject( hrgn2 );
1390 return TRUE;
1394 /******************************************************************
1395 * MF_Play_MetaExtTextOut
1397 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1400 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1402 LPINT16 dxx;
1403 LPSTR sot;
1404 DWORD len;
1405 WORD s1;
1407 s1 = mr->rdParm[2]; /* String length */
1408 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1409 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1410 /* rec len without dx array */
1412 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1413 if (mr->rdParm[3])
1414 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1416 if (mr->rdSize == len / 2)
1417 dxx = NULL; /* determine if array present */
1418 else
1419 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1420 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1421 else {
1422 TRACE("%s len: %ld\n", sot, mr->rdSize);
1423 WARN(
1424 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1425 len, s1, mr->rdSize, mr->rdParm[3]);
1426 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1428 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1429 mr->rdParm[0], /* Y position */
1430 mr->rdParm[3], /* options */
1431 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1432 /* rectangle */
1433 sot, /* string */
1434 s1, dxx); /* length, dx array */
1435 if (dxx)
1436 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1437 return TRUE;