Changed 16-bit GDI Enum* functions to not use thunks, now that 16-bit
[wine/gsoc_dplay.git] / objects / metafile.c
blobb6b917a703e376a23d95ee05e5eeb1f518b1dbd8
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 */
33 #include "config.h"
35 #include <string.h>
36 #include <fcntl.h>
38 #include "wine/winbase16.h"
39 #include "wine/wingdi16.h"
40 #include "bitmap.h"
41 #include "global.h"
42 #include "heap.h"
43 #include "metafile.h"
45 #include "debugtools.h"
47 DEFAULT_DEBUG_CHANNEL(metafile);
49 #include "pshpack1.h"
50 typedef struct
52 DWORD dw1, dw2, dw3;
53 WORD w4;
54 CHAR filename[0x100];
55 } METAHEADERDISK;
56 #include "poppack.h"
58 #define MFHEADERSIZE (sizeof(METAHEADER))
59 #define MFVERSION 0x300
61 /* ### start build ### */
62 extern WORD CALLBACK MF_CallTo16_word_wllwl(MFENUMPROC16,WORD,LONG,LONG,WORD,LONG);
63 /* ### stop build ### */
65 /******************************************************************
66 * MF_AddHandle
68 * Add a handle to an external handle table and return the index
70 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
72 int i;
74 for (i = 0; i < htlen; i++)
76 if (*(ht->objectHandle + i) == 0)
78 *(ht->objectHandle + i) = hobj;
79 return i;
82 return -1;
86 /******************************************************************
87 * MF_Create_HMETATFILE
89 * Creates a (32 bit) HMETAFILE object from a METAHEADER
91 * HMETAFILEs are GDI objects.
93 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
95 HMETAFILE hmf = 0;
96 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC, &hmf );
97 if (metaObj)
99 metaObj->mh = mh;
100 GDI_ReleaseObj( hmf );
102 return hmf;
105 /******************************************************************
106 * MF_Create_HMETATFILE16
108 * Creates a HMETAFILE16 object from a METAHEADER
110 * HMETAFILE16s are Global memory handles.
112 HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
114 HMETAFILE16 hmf;
115 DWORD size = mh->mtSize * sizeof(WORD);
117 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
118 if(hmf)
120 METAHEADER *mh_dest = GlobalLock16(hmf);
121 memcpy(mh_dest, mh, size);
122 GlobalUnlock16(hmf);
124 HeapFree(GetProcessHeap(), 0, mh);
125 return hmf;
128 /******************************************************************
129 * MF_GetMetaHeader
131 * Returns ptr to METAHEADER associated with HMETAFILE
133 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
135 METAHEADER *ret = NULL;
136 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
137 if (metaObj)
139 ret = metaObj->mh;
140 GDI_ReleaseObj( hmf );
142 return ret;
145 /******************************************************************
146 * MF_GetMetaHeader16
148 * Returns ptr to METAHEADER associated with HMETAFILE16
149 * Should be followed by call to MF_ReleaseMetaHeader16
151 static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
153 return GlobalLock16(hmf);
156 /******************************************************************
157 * MF_ReleaseMetaHeader16
159 * Releases METAHEADER associated with HMETAFILE16
161 static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
163 return GlobalUnlock16( hmf );
167 /******************************************************************
168 * DeleteMetaFile (GDI.127)
170 BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
172 return !GlobalFree16( hmf );
175 /******************************************************************
176 * DeleteMetaFile (GDI32.@)
178 * Delete a memory-based metafile.
181 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
183 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
184 if (!metaObj) return FALSE;
185 HeapFree( GetProcessHeap(), 0, metaObj->mh );
186 GDI_FreeObject( hmf, metaObj );
187 return TRUE;
190 /******************************************************************
191 * MF_ReadMetaFile
193 * Returns a pointer to a memory based METAHEADER read in from file HFILE
196 static METAHEADER *MF_ReadMetaFile(HFILE hfile)
198 METAHEADER *mh;
199 DWORD BytesRead, size;
201 size = sizeof(METAHEADER);
202 mh = HeapAlloc( GetProcessHeap(), 0, size );
203 if(!mh) return NULL;
204 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
205 BytesRead != size) {
206 HeapFree( GetProcessHeap(), 0, mh );
207 return NULL;
209 size = mh->mtSize * 2;
210 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
211 if(!mh) return NULL;
212 size -= sizeof(METAHEADER);
213 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
214 NULL) == 0 ||
215 BytesRead != size) {
216 HeapFree( GetProcessHeap(), 0, mh );
217 return NULL;
220 if (mh->mtType != METAFILE_MEMORY) {
221 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
222 mh->mtType = METAFILE_MEMORY;
224 return mh;
227 /******************************************************************
228 * GetMetaFile (GDI.124)
230 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
232 METAHEADER *mh;
233 HANDLE hFile;
235 TRACE("%s\n", lpFilename);
237 if(!lpFilename)
238 return 0;
240 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
241 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
242 return 0;
244 mh = MF_ReadMetaFile(hFile);
245 CloseHandle(hFile);
246 if(!mh) return 0;
247 return MF_Create_HMETAFILE16( mh );
250 /******************************************************************
251 * GetMetaFileA (GDI32.@)
253 * Read a metafile from a file. Returns handle to a memory-based metafile.
255 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
257 METAHEADER *mh;
258 HANDLE hFile;
260 TRACE("%s\n", lpFilename);
262 if(!lpFilename)
263 return 0;
265 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
266 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
267 return 0;
269 mh = MF_ReadMetaFile(hFile);
270 CloseHandle(hFile);
271 if(!mh) return 0;
272 return MF_Create_HMETAFILE( mh );
277 /******************************************************************
278 * GetMetaFileW (GDI32.@)
280 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
282 METAHEADER *mh;
283 HANDLE hFile;
285 TRACE("%s\n", debugstr_w(lpFilename));
287 if(!lpFilename)
288 return 0;
290 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
291 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
292 return 0;
294 mh = MF_ReadMetaFile(hFile);
295 CloseHandle(hFile);
296 if(!mh) return 0;
297 return MF_Create_HMETAFILE( mh );
301 /******************************************************************
302 * MF_LoadDiskBasedMetaFile
304 * Creates a new memory-based metafile from a disk-based one.
306 static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
308 METAHEADERDISK *mhd;
309 HANDLE hfile;
310 METAHEADER *mh2;
312 if(mh->mtType != METAFILE_DISK) {
313 ERR("Not a disk based metafile\n");
314 return NULL;
316 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
318 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
319 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
320 WARN("Can't open file of disk based metafile\n");
321 return NULL;
323 mh2 = MF_ReadMetaFile(hfile);
324 CloseHandle(hfile);
325 return mh2;
328 /******************************************************************
329 * MF_CreateMetaHeaderDisk
331 * Take a memory based METAHEADER and change it to a disk based METAHEADER
332 * assosiated with filename. Note: Trashes contents of old one.
334 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCSTR filename)
336 METAHEADERDISK *mhd;
337 DWORD size;
339 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
340 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
341 mh->mtType = METAFILE_DISK;
342 size = HeapSize( GetProcessHeap(), 0, mh );
343 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
344 strcpy(mhd->filename, filename);
345 return mh;
348 /******************************************************************
349 * CopyMetaFile (GDI.151)
351 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
353 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
354 METAHEADER *mh2 = NULL;
355 HANDLE hFile;
357 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
359 if(!mh) return 0;
361 if(mh->mtType == METAFILE_DISK)
362 mh2 = MF_LoadDiskBasedMetaFile(mh);
363 else {
364 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
365 memcpy( mh2, mh, mh->mtSize * 2 );
367 MF_ReleaseMetaHeader16( hSrcMetaFile );
369 if(lpFilename) { /* disk based metafile */
370 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
371 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
372 HeapFree( GetProcessHeap(), 0, mh2 );
373 return 0;
375 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
376 CloseHandle(hFile);
377 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
380 return MF_Create_HMETAFILE16( mh2 );
384 /******************************************************************
385 * CopyMetaFileA (GDI32.@)
387 * Copies the metafile corresponding to hSrcMetaFile to either
388 * a disk file, if a filename is given, or to a new memory based
389 * metafile, if lpFileName is NULL.
391 * RETURNS
393 * Handle to metafile copy on success, NULL on failure.
395 * BUGS
397 * Copying to disk returns NULL even if successful.
399 HMETAFILE WINAPI CopyMetaFileA(
400 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
401 LPCSTR lpFilename /* [in] filename if copying to a file */
403 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
404 METAHEADER *mh2 = NULL;
405 HANDLE hFile;
407 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
409 if(!mh) return 0;
411 if(mh->mtType == METAFILE_DISK)
412 mh2 = MF_LoadDiskBasedMetaFile(mh);
413 else {
414 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
415 memcpy( mh2, mh, mh->mtSize * 2 );
418 if(lpFilename) { /* disk based metafile */
419 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
420 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
421 HeapFree( GetProcessHeap(), 0, mh2 );
422 return 0;
424 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
425 CloseHandle(hFile);
426 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename);
429 return MF_Create_HMETAFILE( mh2 );
433 /******************************************************************
434 * CopyMetaFileW (GDI32.@)
436 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
437 LPCWSTR lpFilename )
439 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
440 HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
441 HeapFree( GetProcessHeap(), 0, p );
442 return ret;
446 /******************************************************************
447 * IsValidMetaFile (GDI.410)
449 * Attempts to check if a given metafile is correctly formatted.
450 * Currently, the only things verified are several properties of the
451 * header.
453 * RETURNS
454 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
456 * BUGS
457 * This is not exactly what windows does, see _Undocumented_Windows_
458 * for details.
460 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
462 BOOL16 res=FALSE;
463 METAHEADER *mh = MF_GetMetaHeader16(hmf);
464 if (mh) {
465 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
466 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
467 if (mh->mtVersion == MFVERSION)
468 res=TRUE;
469 MF_ReleaseMetaHeader16(hmf);
471 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
472 return res;
476 /*******************************************************************
477 * MF_PlayMetaFile
479 * Helper for PlayMetaFile
481 static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
484 METARECORD *mr;
485 HANDLETABLE16 *ht;
486 unsigned int offset = 0;
487 WORD i;
488 HPEN hPen;
489 HBRUSH hBrush;
490 HFONT hFont;
491 BOOL loaded = FALSE;
493 if (!mh) return FALSE;
494 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
495 mh = MF_LoadDiskBasedMetaFile(mh);
496 if(!mh) return FALSE;
497 loaded = TRUE;
500 /* save the current pen, brush and font */
501 hPen = GetCurrentObject(hdc, OBJ_PEN);
502 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
503 hFont = GetCurrentObject(hdc, OBJ_FONT);
505 /* create the handle table */
506 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
507 sizeof(HANDLETABLE16) * mh->mtNoObjects);
508 if(!ht) return FALSE;
510 /* loop through metafile playing records */
511 offset = mh->mtHeaderSize * 2;
512 while (offset < mh->mtSize * 2)
514 mr = (METARECORD *)((char *)mh + offset);
515 TRACE("offset=%04x,size=%08lx\n",
516 offset, mr->rdSize);
517 if (!mr->rdSize) {
518 TRACE(
519 "Entry got size 0 at offset %d, total mf length is %ld\n",
520 offset,mh->mtSize*2);
521 break; /* would loop endlessly otherwise */
523 offset += mr->rdSize * 2;
524 PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
527 SelectObject(hdc, hBrush);
528 SelectObject(hdc, hPen);
529 SelectObject(hdc, hFont);
531 /* free objects in handle table */
532 for(i = 0; i < mh->mtNoObjects; i++)
533 if(*(ht->objectHandle + i) != 0)
534 DeleteObject(*(ht->objectHandle + i));
536 /* free handle table */
537 HeapFree( GetProcessHeap(), 0, ht );
538 if(loaded)
539 HeapFree( GetProcessHeap(), 0, mh );
540 return TRUE;
543 /******************************************************************
544 * PlayMetaFile (GDI.123)
547 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
549 BOOL16 ret;
550 METAHEADER *mh = MF_GetMetaHeader16( hmf );
551 ret = MF_PlayMetaFile( hdc, mh );
552 MF_ReleaseMetaHeader16( hmf );
553 return ret;
556 /******************************************************************
557 * PlayMetaFile (GDI32.@)
559 * Renders the metafile specified by hmf in the DC specified by
560 * hdc. Returns FALSE on failure, TRUE on success.
562 BOOL WINAPI PlayMetaFile(
563 HDC hdc, /* [in] handle of DC to render in */
564 HMETAFILE hmf /* [in] handle of metafile to render */
567 METAHEADER *mh = MF_GetMetaHeader( hmf );
568 return MF_PlayMetaFile( hdc, mh );
572 /******************************************************************
573 * EnumMetaFile16 (GDI.175)
576 BOOL16 WINAPI EnumMetaFile16( HDC16 hdc, HMETAFILE16 hmf,
577 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
579 METAHEADER *mh = MF_GetMetaHeader16(hmf);
580 METARECORD *mr;
581 HANDLETABLE16 *ht;
582 HGLOBAL16 hHT;
583 SEGPTR spht;
584 unsigned int offset = 0;
585 WORD i, seg;
586 HPEN hPen;
587 HBRUSH hBrush;
588 HFONT hFont;
589 BOOL16 result = TRUE, loaded = FALSE;
591 TRACE("(%04x, %04x, %08lx, %08lx)\n",
592 hdc, hmf, (DWORD)lpEnumFunc, lpData);
595 if(!mh) return FALSE;
596 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
597 mh = MF_LoadDiskBasedMetaFile(mh);
598 if(!mh) return FALSE;
599 loaded = TRUE;
602 /* save the current pen, brush and font */
603 hPen = GetCurrentObject(hdc, OBJ_PEN);
604 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
605 hFont = GetCurrentObject(hdc, OBJ_FONT);
607 /* create the handle table */
609 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
610 sizeof(HANDLETABLE16) * mh->mtNoObjects);
611 spht = K32WOWGlobalLock16(hHT);
613 seg = hmf | 7;
614 offset = mh->mtHeaderSize * 2;
616 /* loop through metafile records */
618 while (offset < (mh->mtSize * 2))
620 mr = (METARECORD *)((char *)mh + offset);
622 if (!MF_CallTo16_word_wllwl( lpEnumFunc, hdc, spht,
623 MAKESEGPTR( seg + (HIWORD(offset) << __AHSHIFT), LOWORD(offset) ),
624 mh->mtNoObjects, (LONG)lpData ))
626 result = FALSE;
627 break;
631 offset += (mr->rdSize * 2);
634 SelectObject(hdc, hBrush);
635 SelectObject(hdc, hPen);
636 SelectObject(hdc, hFont);
638 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
640 /* free objects in handle table */
641 for(i = 0; i < mh->mtNoObjects; i++)
642 if(*(ht->objectHandle + i) != 0)
643 DeleteObject(*(ht->objectHandle + i));
645 /* free handle table */
646 GlobalFree16(hHT);
647 if(loaded)
648 HeapFree( GetProcessHeap(), 0, mh );
649 MF_ReleaseMetaHeader16(hmf);
650 return result;
653 /******************************************************************
654 * EnumMetaFile (GDI32.@)
656 * Loop through the metafile records in hmf, calling the user-specified
657 * function for each one, stopping when the user's function returns FALSE
658 * (which is considered to be failure)
659 * or when no records are left (which is considered to be success).
661 * RETURNS
662 * TRUE on success, FALSE on failure.
664 * HISTORY
665 * Niels de carpentier, april 1996
667 BOOL WINAPI EnumMetaFile(
668 HDC hdc,
669 HMETAFILE hmf,
670 MFENUMPROC lpEnumFunc,
671 LPARAM lpData
673 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
674 METARECORD *mr;
675 HANDLETABLE *ht;
676 BOOL result = TRUE;
677 int i;
678 unsigned int offset = 0;
679 HPEN hPen;
680 HBRUSH hBrush;
681 HFONT hFont;
683 TRACE("(%08x,%08x,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
684 if (!mh) return 0;
685 if(mh->mtType == METAFILE_DISK)
687 /* Create a memory-based copy */
688 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
689 mh = mhTemp;
692 /* save the current pen, brush and font */
693 hPen = GetCurrentObject(hdc, OBJ_PEN);
694 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
695 hFont = GetCurrentObject(hdc, OBJ_FONT);
697 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
698 sizeof(HANDLETABLE) * mh->mtNoObjects);
700 /* loop through metafile records */
701 offset = mh->mtHeaderSize * 2;
703 while (offset < (mh->mtSize * 2))
705 mr = (METARECORD *)((char *)mh + offset);
706 TRACE("Calling EnumFunc with record type %x\n",
707 mr->rdFunction);
708 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
710 result = FALSE;
711 break;
714 offset += (mr->rdSize * 2);
717 /* restore pen, brush and font */
718 SelectObject(hdc, hBrush);
719 SelectObject(hdc, hPen);
720 SelectObject(hdc, hFont);
722 /* free objects in handle table */
723 for(i = 0; i < mh->mtNoObjects; i++)
724 if(*(ht->objectHandle + i) != 0)
725 DeleteObject(*(ht->objectHandle + i));
727 /* free handle table */
728 HeapFree( GetProcessHeap(), 0, ht);
729 /* free a copy of metafile */
730 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
731 return result;
734 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
735 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr);
736 /******************************************************************
737 * PlayMetaFileRecord (GDI.176)
739 * Render a single metafile record specified by *mr in the DC hdc, while
740 * using the handle table *ht, of length nHandles,
741 * to store metafile objects.
743 * BUGS
744 * The following metafile records are unimplemented:
746 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
747 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
748 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
751 void WINAPI PlayMetaFileRecord16(
752 HDC16 hdc, /* [in] DC to render metafile into */
753 HANDLETABLE16 *ht, /* [in] pointer to handle table for metafile objects */
754 METARECORD *mr, /* [in] pointer to metafile record to render */
755 UINT16 nHandles /* [in] size of handle table */
757 short s1;
758 HANDLE16 hndl;
759 char *ptr;
760 BITMAPINFOHEADER *infohdr;
762 TRACE("(%04x %08lx %08lx %04x) function %04x\n",
763 hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
765 switch (mr->rdFunction)
767 case META_EOF:
768 break;
770 case META_DELETEOBJECT:
771 DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
772 *(ht->objectHandle + *(mr->rdParm)) = 0;
773 break;
775 case META_SETBKCOLOR:
776 SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
777 break;
779 case META_SETBKMODE:
780 SetBkMode16(hdc, *(mr->rdParm));
781 break;
783 case META_SETMAPMODE:
784 SetMapMode16(hdc, *(mr->rdParm));
785 break;
787 case META_SETROP2:
788 SetROP216(hdc, *(mr->rdParm));
789 break;
791 case META_SETRELABS:
792 SetRelAbs16(hdc, *(mr->rdParm));
793 break;
795 case META_SETPOLYFILLMODE:
796 SetPolyFillMode16(hdc, *(mr->rdParm));
797 break;
799 case META_SETSTRETCHBLTMODE:
800 SetStretchBltMode16(hdc, *(mr->rdParm));
801 break;
803 case META_SETTEXTCOLOR:
804 SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
805 break;
807 case META_SETWINDOWORG:
808 SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
809 break;
811 case META_SETWINDOWEXT:
812 SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
813 break;
815 case META_SETVIEWPORTORG:
816 SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
817 break;
819 case META_SETVIEWPORTEXT:
820 SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
821 break;
823 case META_OFFSETWINDOWORG:
824 OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
825 break;
827 case META_SCALEWINDOWEXT:
828 ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
829 *(mr->rdParm + 1), *(mr->rdParm));
830 break;
832 case META_OFFSETVIEWPORTORG:
833 OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
834 break;
836 case META_SCALEVIEWPORTEXT:
837 ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
838 *(mr->rdParm + 1), *(mr->rdParm));
839 break;
841 case META_LINETO:
842 LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
843 break;
845 case META_MOVETO:
846 MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
847 break;
849 case META_EXCLUDECLIPRECT:
850 ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
851 *(mr->rdParm + 1), *(mr->rdParm) );
852 break;
854 case META_INTERSECTCLIPRECT:
855 IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
856 *(mr->rdParm + 1), *(mr->rdParm) );
857 break;
859 case META_ARC:
860 Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
861 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
862 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
863 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
864 break;
866 case META_ELLIPSE:
867 Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
868 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
869 break;
871 case META_FLOODFILL:
872 FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
873 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
874 break;
876 case META_PIE:
877 Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
878 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
879 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
880 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
881 break;
883 case META_RECTANGLE:
884 Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
885 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
886 break;
888 case META_ROUNDRECT:
889 RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
890 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
891 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
892 break;
894 case META_PATBLT:
895 PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
896 *(mr->rdParm + 3), *(mr->rdParm + 2),
897 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
898 break;
900 case META_SAVEDC:
901 SaveDC(hdc);
902 break;
904 case META_SETPIXEL:
905 SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
906 MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
907 break;
909 case META_OFFSETCLIPRGN:
910 OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
911 break;
913 case META_TEXTOUT:
914 s1 = *(mr->rdParm);
915 TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
916 *(mr->rdParm + ((s1 + 1) >> 1) + 1),
917 (char *)(mr->rdParm + 1), s1);
918 break;
920 case META_POLYGON:
921 Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
922 break;
924 case META_POLYPOLYGON:
925 PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
926 (LPINT16)(mr->rdParm + 1), *(mr->rdParm));
927 break;
929 case META_POLYLINE:
930 Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
931 break;
933 case META_RESTOREDC:
934 RestoreDC(hdc, (INT16)*(mr->rdParm));
935 break;
937 case META_SELECTOBJECT:
938 SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
939 break;
941 case META_CHORD:
942 Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
943 (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
944 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
945 (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
946 break;
948 case META_CREATEPATTERNBRUSH:
949 switch (*(mr->rdParm))
951 case BS_PATTERN:
952 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
953 MF_AddHandle(ht, nHandles,
954 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
955 infohdr->biHeight,
956 infohdr->biPlanes,
957 infohdr->biBitCount,
958 (LPSTR)(mr->rdParm +
959 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
960 break;
962 case BS_DIBPATTERN:
963 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
964 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
965 ptr = GlobalLock16(hndl);
966 memcpy(ptr, mr->rdParm + 2, s1);
967 GlobalUnlock16(hndl);
968 MF_AddHandle(ht, nHandles,
969 CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
970 GlobalFree16(hndl);
971 break;
973 default:
974 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
975 mr->rdParm[0]);
976 break;
978 break;
980 case META_CREATEPENINDIRECT:
981 MF_AddHandle(ht, nHandles,
982 CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
983 break;
985 case META_CREATEFONTINDIRECT:
986 MF_AddHandle(ht, nHandles,
987 CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
988 break;
990 case META_CREATEBRUSHINDIRECT:
991 MF_AddHandle(ht, nHandles,
992 CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
993 break;
995 case META_CREATEPALETTE:
996 MF_AddHandle(ht, nHandles,
997 CreatePalette16((LPLOGPALETTE)mr->rdParm));
998 break;
1000 case META_SETTEXTALIGN:
1001 SetTextAlign16(hdc, *(mr->rdParm));
1002 break;
1004 case META_SELECTPALETTE:
1005 GDISelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1006 *(mr->rdParm));
1007 break;
1009 case META_SETMAPPERFLAGS:
1010 SetMapperFlags16(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1011 break;
1013 case META_REALIZEPALETTE:
1014 GDIRealizePalette16(hdc);
1015 break;
1017 case META_ESCAPE:
1018 FIXME("META_ESCAPE unimplemented.\n");
1019 break;
1021 case META_EXTTEXTOUT:
1022 MF_Play_MetaExtTextOut( hdc, mr );
1023 break;
1025 case META_STRETCHDIB:
1027 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1028 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1029 StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
1030 mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
1031 mr->rdParm[4],mr->rdParm[3],bits,info,
1032 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1034 break;
1036 case META_DIBSTRETCHBLT:
1038 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1039 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1040 StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
1041 mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
1042 mr->rdParm[3],mr->rdParm[2],bits,info,
1043 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1045 break;
1047 case META_STRETCHBLT:
1049 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1050 HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
1051 mr->rdParm[11], /*Height*/
1052 mr->rdParm[13], /*Planes*/
1053 mr->rdParm[14], /*BitsPixel*/
1054 (LPSTR)&mr->rdParm[15]); /*bits*/
1055 SelectObject(hdcSrc,hbitmap);
1056 StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
1057 mr->rdParm[7],mr->rdParm[6],
1058 hdcSrc,mr->rdParm[5],mr->rdParm[4],
1059 mr->rdParm[3],mr->rdParm[2],
1060 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1061 DeleteDC(hdcSrc);
1063 break;
1065 case META_BITBLT:
1067 HDC16 hdcSrc=CreateCompatibleDC16(hdc);
1068 HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
1069 mr->rdParm[8]/*Height*/,
1070 mr->rdParm[10]/*Planes*/,
1071 mr->rdParm[11]/*BitsPixel*/,
1072 (LPSTR)&mr->rdParm[12]/*bits*/);
1073 SelectObject(hdcSrc,hbitmap);
1074 BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
1075 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
1076 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
1077 MAKELONG(0,mr->rdParm[0]));
1078 DeleteDC(hdcSrc);
1080 break;
1082 case META_CREATEREGION:
1084 HRGN hrgn = CreateRectRgn(0,0,0,0);
1086 MF_Play_MetaCreateRegion(mr, hrgn);
1087 MF_AddHandle(ht, nHandles, hrgn);
1089 break;
1091 case META_FILLREGION:
1092 FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),
1093 *(ht->objectHandle + *(mr->rdParm)));
1094 break;
1096 case META_FRAMEREGION:
1097 FrameRgn16(hdc, *(ht->objectHandle + *(mr->rdParm+3)),
1098 *(ht->objectHandle + *(mr->rdParm+2)),
1099 *(mr->rdParm+1), *(mr->rdParm));
1100 break;
1102 case META_INVERTREGION:
1103 InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1104 break;
1106 case META_PAINTREGION:
1107 PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
1108 break;
1110 case META_SELECTCLIPREGION:
1111 SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
1112 break;
1114 case META_DIBCREATEPATTERNBRUSH:
1115 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN:
1116 but there's no difference */
1118 TRACE("%d\n",*(mr->rdParm));
1119 s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
1120 hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
1121 ptr = GlobalLock16(hndl);
1122 memcpy(ptr, mr->rdParm + 2, s1);
1123 GlobalUnlock16(hndl);
1124 MF_AddHandle(ht, nHandles,
1125 CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
1126 GlobalFree16(hndl);
1127 break;
1129 case META_DIBBITBLT:
1130 /* In practice I've found that there are two layouts for
1131 META_DIBBITBLT, one (the first here) is the usual one when a src
1132 dc is actually passed to it, the second occurs when the src dc is
1133 passed in as NULL to the creating BitBlt. As the second case has
1134 no dib, a size check will suffice to distinguish.
1136 Caolan.McNamara@ul.ie */
1138 if (mr->rdSize > 12) {
1139 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1140 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
1142 StretchDIBits16(hdc, mr->rdParm[7], mr->rdParm[6], mr->rdParm[5],
1143 mr->rdParm[4], mr->rdParm[3], mr->rdParm[2],
1144 mr->rdParm[5], mr->rdParm[4], bits, info,
1145 DIB_RGB_COLORS,
1146 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1147 } else { /* equivalent to a PatBlt */
1148 PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
1149 mr->rdParm[6], mr->rdParm[5],
1150 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1152 break;
1154 case META_SETTEXTCHAREXTRA:
1155 SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
1156 break;
1158 case META_SETTEXTJUSTIFICATION:
1159 SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
1160 break;
1162 case META_EXTFLOODFILL:
1163 ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
1164 MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),
1165 *(mr->rdParm));
1166 break;
1168 case META_SETDIBTODEV:
1170 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1171 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1172 SetDIBitsToDevice(hdc, (INT16)mr->rdParm[8], (INT16)mr->rdParm[7],
1173 (INT16)mr->rdParm[6], (INT16)mr->rdParm[5],
1174 (INT16)mr->rdParm[4], (INT16)mr->rdParm[3],
1175 mr->rdParm[2], mr->rdParm[1], bits, info,
1176 mr->rdParm[0]);
1177 break;
1180 #define META_UNIMP(x) case x: \
1181 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1182 break;
1183 META_UNIMP(META_DRAWTEXT)
1184 META_UNIMP(META_ANIMATEPALETTE)
1185 META_UNIMP(META_SETPALENTRIES)
1186 META_UNIMP(META_RESIZEPALETTE)
1187 META_UNIMP(META_RESETDC)
1188 META_UNIMP(META_STARTDOC)
1189 META_UNIMP(META_STARTPAGE)
1190 META_UNIMP(META_ENDPAGE)
1191 META_UNIMP(META_ABORTDOC)
1192 META_UNIMP(META_ENDDOC)
1193 META_UNIMP(META_CREATEBRUSH)
1194 META_UNIMP(META_CREATEBITMAPINDIRECT)
1195 META_UNIMP(META_CREATEBITMAP)
1196 #undef META_UNIMP
1198 default:
1199 WARN("PlayMetaFileRecord: Unknown record type %x\n",
1200 mr->rdFunction);
1204 /******************************************************************
1205 * PlayMetaFileRecord (GDI32.@)
1207 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *handletable,
1208 METARECORD *metarecord, UINT handles )
1210 HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR,
1211 handles*sizeof(HANDLETABLE16));
1212 unsigned int i = 0;
1213 TRACE("(%08x,%p,%p,%d)\n", hdc, handletable, metarecord,
1214 handles);
1215 for (i=0; i<handles; i++)
1216 ht->objectHandle[i] = handletable->objectHandle[i];
1217 PlayMetaFileRecord16(hdc, ht, metarecord, handles);
1218 for (i=0; i<handles; i++)
1219 handletable->objectHandle[i] = ht->objectHandle[i];
1220 GlobalFree((HGLOBAL)ht);
1221 return TRUE;
1224 /******************************************************************
1225 * GetMetaFileBits (GDI.159)
1227 * Trade in a metafile object handle for a handle to the metafile memory.
1231 HGLOBAL16 WINAPI GetMetaFileBits16(
1232 HMETAFILE16 hmf /* [in] metafile handle */
1235 TRACE("hMem out: %04x\n", hmf);
1236 return hmf;
1239 /******************************************************************
1240 * SetMetaFileBits (GDI.160)
1242 * Trade in a metafile memory handle for a handle to a metafile object.
1243 * The memory region should hold a proper metafile, otherwise
1244 * problems will occur when it is used. Validity of the memory is not
1245 * checked. The function is essentially just the identity function.
1247 HMETAFILE16 WINAPI SetMetaFileBits16(
1248 HGLOBAL16 hMem
1249 /* [in] handle to a memory region holding a metafile */
1252 TRACE("hmf out: %04x\n", hMem);
1254 return hMem;
1257 /******************************************************************
1258 * SetMetaFileBitsBetter (GDI.196)
1260 * Trade in a metafile memory handle for a handle to a metafile object,
1261 * making a cursory check (using IsValidMetaFile()) that the memory
1262 * handle points to a valid metafile.
1264 * RETURNS
1265 * Handle to a metafile on success, NULL on failure..
1267 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1269 if( IsValidMetaFile16( hMeta ) )
1270 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
1271 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1272 return (HMETAFILE16)0;
1275 /******************************************************************
1276 * SetMetaFileBitsEx (GDI32.@)
1278 * Create a metafile from raw data. No checking of the data is performed.
1279 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1281 HMETAFILE WINAPI SetMetaFileBitsEx(
1282 UINT size, /* [in] size of metafile, in bytes */
1283 const BYTE *lpData /* [in] pointer to metafile data */
1286 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
1287 if (!mh) return 0;
1288 memcpy(mh, lpData, size);
1289 return MF_Create_HMETAFILE(mh);
1292 /*****************************************************************
1293 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1295 * Copies the data from metafile _hmf_ into the buffer _buf_.
1296 * If _buf_ is zero, returns size of buffer required. Otherwise,
1297 * returns number of bytes copied.
1299 UINT WINAPI GetMetaFileBitsEx(
1300 HMETAFILE hmf, /* [in] metafile */
1301 UINT nSize, /* [in] size of buf */
1302 LPVOID buf /* [out] buffer to receive raw metafile data */
1304 METAHEADER *mh = MF_GetMetaHeader(hmf);
1305 UINT mfSize;
1307 TRACE("(%08x,%d,%p)\n", hmf, nSize, buf);
1308 if (!mh) return 0; /* FIXME: error code */
1309 if(mh->mtType == METAFILE_DISK)
1310 FIXME("Disk-based metafile?\n");
1311 mfSize = mh->mtSize * 2;
1312 if (!buf) {
1313 TRACE("returning size %d\n", mfSize);
1314 return mfSize;
1316 if(mfSize > nSize) mfSize = nSize;
1317 memmove(buf, mh, mfSize);
1318 return mfSize;
1321 /******************************************************************
1322 * GetWinMetaFileBits [GDI32.@]
1324 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1325 UINT cbBuffer, LPBYTE lpbBuffer,
1326 INT fnMapMode, HDC hdcRef)
1328 FIXME("(%d,%d,%p,%d,%d): stub\n",
1329 hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1330 return 0;
1333 /******************************************************************
1334 * MF_Play_MetaCreateRegion
1336 * Handles META_CREATEREGION for PlayMetaFileRecord().
1340 * The layout of the record looks something like this:
1342 * rdParm meaning
1343 * 0 Always 0?
1344 * 1 Always 6?
1345 * 2 Looks like a handle? - not constant
1346 * 3 0 or 1 ??
1347 * 4 Total number of bytes
1348 * 5 No. of separate bands = n [see below]
1349 * 6 Largest number of x co-ords in a band
1350 * 7-10 Bounding box x1 y1 x2 y2
1351 * 11-... n bands
1353 * Regions are divided into bands that are uniform in the
1354 * y-direction. Each band consists of pairs of on/off x-coords and is
1355 * written as
1356 * m y0 y1 x1 x2 x3 ... xm m
1357 * into successive rdParm[]s.
1359 * This is probably just a dump of the internal RGNOBJ?
1361 * HDMD - 18/12/97
1365 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1367 WORD band, pair;
1368 WORD *start, *end;
1369 INT16 y0, y1;
1370 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1372 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1373 band++, start = end + 1) {
1374 if(*start / 2 != (*start + 1) / 2) {
1375 WARN("Delimiter not even.\n");
1376 DeleteObject( hrgn2 );
1377 return FALSE;
1380 end = start + *start + 3;
1381 if(end > (WORD *)mr + mr->rdSize) {
1382 WARN("End points outside record.\n");
1383 DeleteObject( hrgn2 );
1384 return FALSE;
1387 if(*start != *end) {
1388 WARN("Mismatched delimiters.\n");
1389 DeleteObject( hrgn2 );
1390 return FALSE;
1393 y0 = *(INT16 *)(start + 1);
1394 y1 = *(INT16 *)(start + 2);
1395 for(pair = 0; pair < *start / 2; pair++) {
1396 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1397 *(INT16 *)(start + 4 + 2*pair), y1 );
1398 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1401 DeleteObject( hrgn2 );
1402 return TRUE;
1406 /******************************************************************
1407 * MF_Play_MetaExtTextOut
1409 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1412 static BOOL MF_Play_MetaExtTextOut(HDC16 hdc, METARECORD *mr)
1414 LPINT16 dxx;
1415 LPSTR sot;
1416 DWORD len;
1417 WORD s1;
1419 s1 = mr->rdParm[2]; /* String length */
1420 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1421 + sizeof(UINT16) + (mr->rdParm[3] ? sizeof(RECT16) : 0);
1422 /* rec len without dx array */
1424 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
1425 if (mr->rdParm[3])
1426 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
1428 if (mr->rdSize == len / 2)
1429 dxx = NULL; /* determine if array present */
1430 else
1431 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1432 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1433 else {
1434 TRACE("%s len: %ld\n", sot, mr->rdSize);
1435 WARN(
1436 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1437 len, s1, mr->rdSize, mr->rdParm[3]);
1438 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1440 ExtTextOut16( hdc, mr->rdParm[1], /* X position */
1441 mr->rdParm[0], /* Y position */
1442 mr->rdParm[3], /* options */
1443 mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,
1444 /* rectangle */
1445 sot, /* string */
1446 s1, dxx); /* length, dx array */
1447 if (dxx)
1448 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dxx[0]);
1449 return TRUE;