4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * These functions are primarily involved with metafile playback or anything
24 * that touches a HMETAFILE.
25 * For recording of metafiles look in graphics/metafiledrv/
27 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
28 * global memory handles so these cannot be interchanged.
30 * Memory-based metafiles are just stored as a continuous block of memory with
31 * a METAHEADER at the head with METARECORDs appended to it. mtType is
32 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
33 * disk-based metafile - even mtType is METAFILE_MEMORY.
34 * 16bit HMETAFILE16s are global handles to this block
35 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
37 * Disk-based metafiles are rather different. HMETAFILE16s point to a
38 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
39 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
40 * more 0, then 2 which may be a time stamp of the file and then the path of
41 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
51 #include "wine/winbase16.h"
52 #include "wine/wingdi16.h"
55 #include "wine/debug.h"
57 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
74 #define MFHEADERSIZE (sizeof(METAHEADER))
75 #define MFVERSION 0x300
78 /******************************************************************
81 * Add a handle to an external handle table and return the index
83 static int MF_AddHandle(HANDLETABLE
*ht
, UINT htlen
, HGDIOBJ hobj
)
87 for (i
= 0; i
< htlen
; i
++)
89 if (*(ht
->objectHandle
+ i
) == 0)
91 *(ht
->objectHandle
+ i
) = hobj
;
99 /******************************************************************
100 * MF_Create_HMETATFILE
102 * Creates a (32 bit) HMETAFILE object from a METAHEADER
104 * HMETAFILEs are GDI objects.
106 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
109 METAFILEOBJ
*metaObj
= GDI_AllocObject( sizeof(METAFILEOBJ
), METAFILE_MAGIC
,
110 (HGDIOBJ
*)&hmf
, NULL
);
114 GDI_ReleaseObj( hmf
);
119 /******************************************************************
120 * MF_Create_HMETATFILE16
122 * Creates a HMETAFILE16 object from a METAHEADER
124 * HMETAFILE16s are Global memory handles.
126 HMETAFILE16
MF_Create_HMETAFILE16(METAHEADER
*mh
)
129 DWORD size
= mh
->mtSize
* sizeof(WORD
);
131 hmf
= GlobalAlloc16(GMEM_MOVEABLE
, size
);
134 METAHEADER
*mh_dest
= GlobalLock16(hmf
);
135 memcpy(mh_dest
, mh
, size
);
138 HeapFree(GetProcessHeap(), 0, mh
);
142 /******************************************************************
145 * Returns ptr to METAHEADER associated with HMETAFILE
147 static METAHEADER
*MF_GetMetaHeader( HMETAFILE hmf
)
149 METAHEADER
*ret
= NULL
;
150 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
154 GDI_ReleaseObj( hmf
);
159 /******************************************************************
162 * Returns ptr to METAHEADER associated with HMETAFILE16
163 * Should be followed by call to MF_ReleaseMetaHeader16
165 static METAHEADER
*MF_GetMetaHeader16( HMETAFILE16 hmf
)
167 return GlobalLock16(hmf
);
170 /******************************************************************
171 * MF_ReleaseMetaHeader16
173 * Releases METAHEADER associated with HMETAFILE16
175 static BOOL16
MF_ReleaseMetaHeader16( HMETAFILE16 hmf
)
177 return GlobalUnlock16( hmf
);
181 /******************************************************************
184 * Convert an array of POINT16 to an array of POINT.
185 * Result must be freed by caller.
187 static POINT
*convert_points( UINT count
, POINT16
*pt16
)
190 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
193 for (i
= 0; i
< count
; i
++)
195 ret
[i
].x
= pt16
[i
].x
;
196 ret
[i
].y
= pt16
[i
].y
;
203 /******************************************************************
204 * DeleteMetaFile (GDI.127)
206 BOOL16 WINAPI
DeleteMetaFile16( HMETAFILE16 hmf
)
208 return !GlobalFree16( hmf
);
211 /******************************************************************
212 * DeleteMetaFile (GDI32.@)
214 * Delete a memory-based metafile.
217 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
219 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
220 if (!metaObj
) return FALSE
;
221 HeapFree( GetProcessHeap(), 0, metaObj
->mh
);
222 GDI_FreeObject( hmf
, metaObj
);
226 /******************************************************************
229 * Returns a pointer to a memory based METAHEADER read in from file HFILE
232 static METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
235 DWORD BytesRead
, size
;
237 size
= sizeof(METAHEADER
);
238 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
240 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
242 HeapFree( GetProcessHeap(), 0, mh
);
245 size
= mh
->mtSize
* 2;
246 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
248 size
-= sizeof(METAHEADER
);
249 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
252 HeapFree( GetProcessHeap(), 0, mh
);
256 if (mh
->mtType
!= METAFILE_MEMORY
) {
257 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
258 mh
->mtType
= METAFILE_MEMORY
;
263 /******************************************************************
264 * GetMetaFile (GDI.124)
266 HMETAFILE16 WINAPI
GetMetaFile16( LPCSTR lpFilename
)
271 TRACE("%s\n", lpFilename
);
276 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
277 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
280 mh
= MF_ReadMetaFile(hFile
);
283 return MF_Create_HMETAFILE16( mh
);
286 /******************************************************************
287 * GetMetaFileA (GDI32.@)
289 * Read a metafile from a file. Returns handle to a memory-based metafile.
291 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
296 TRACE("%s\n", lpFilename
);
301 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
302 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
305 mh
= MF_ReadMetaFile(hFile
);
308 return MF_Create_HMETAFILE( mh
);
313 /******************************************************************
314 * GetMetaFileW (GDI32.@)
316 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
321 TRACE("%s\n", debugstr_w(lpFilename
));
326 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
327 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
330 mh
= MF_ReadMetaFile(hFile
);
333 return MF_Create_HMETAFILE( mh
);
337 /******************************************************************
338 * MF_LoadDiskBasedMetaFile
340 * Creates a new memory-based metafile from a disk-based one.
342 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
348 if(mh
->mtType
!= METAFILE_DISK
) {
349 ERR("Not a disk based metafile\n");
352 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
354 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
355 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
356 WARN("Can't open file of disk based metafile\n");
359 mh2
= MF_ReadMetaFile(hfile
);
364 /******************************************************************
365 * MF_CreateMetaHeaderDisk
367 * Take a memory based METAHEADER and change it to a disk based METAHEADER
368 * assosiated with filename. Note: Trashes contents of old one.
370 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCSTR filename
)
375 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
376 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
377 mh
->mtType
= METAFILE_DISK
;
378 size
= HeapSize( GetProcessHeap(), 0, mh
);
379 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
380 strcpy(mhd
->filename
, filename
);
384 /******************************************************************
385 * CopyMetaFile (GDI.151)
387 HMETAFILE16 WINAPI
CopyMetaFile16( HMETAFILE16 hSrcMetaFile
, LPCSTR lpFilename
)
389 METAHEADER
*mh
= MF_GetMetaHeader16( hSrcMetaFile
);
390 METAHEADER
*mh2
= NULL
;
393 TRACE("(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
397 if(mh
->mtType
== METAFILE_DISK
)
398 mh2
= MF_LoadDiskBasedMetaFile(mh
);
400 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
401 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
403 MF_ReleaseMetaHeader16( hSrcMetaFile
);
405 if(lpFilename
) { /* disk based metafile */
406 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
407 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
408 HeapFree( GetProcessHeap(), 0, mh2
);
411 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
413 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
);
416 return MF_Create_HMETAFILE16( mh2
);
420 /******************************************************************
421 * CopyMetaFileA (GDI32.@)
423 * Copies the metafile corresponding to hSrcMetaFile to either
424 * a disk file, if a filename is given, or to a new memory based
425 * metafile, if lpFileName is NULL.
429 * Handle to metafile copy on success, NULL on failure.
433 * Copying to disk returns NULL even if successful.
435 HMETAFILE WINAPI
CopyMetaFileA(
436 HMETAFILE hSrcMetaFile
, /* [in] handle of metafile to copy */
437 LPCSTR lpFilename
/* [in] filename if copying to a file */
439 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
440 METAHEADER
*mh2
= NULL
;
443 TRACE("(%p,%s)\n", hSrcMetaFile
, lpFilename
);
447 if(mh
->mtType
== METAFILE_DISK
)
448 mh2
= MF_LoadDiskBasedMetaFile(mh
);
450 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
451 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
454 if(lpFilename
) { /* disk based metafile */
455 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
456 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
457 HeapFree( GetProcessHeap(), 0, mh2
);
460 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
462 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
);
465 return MF_Create_HMETAFILE( mh2
);
469 /******************************************************************
470 * CopyMetaFileW (GDI32.@)
472 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
,
476 DWORD len
= WideCharToMultiByte( CP_ACP
, 0, lpFilename
, -1, NULL
, 0, NULL
, NULL
);
477 LPSTR p
= HeapAlloc( GetProcessHeap(), 0, len
);
481 WideCharToMultiByte( CP_ACP
, 0, lpFilename
, -1, p
, len
, NULL
, NULL
);
482 ret
= CopyMetaFileA( hSrcMetaFile
, p
);
483 HeapFree( GetProcessHeap(), 0, p
);
489 /******************************************************************
490 * IsValidMetaFile (GDI.410)
492 * Attempts to check if a given metafile is correctly formatted.
493 * Currently, the only things verified are several properties of the
497 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
500 * This is not exactly what windows does, see _Undocumented_Windows_
503 BOOL16 WINAPI
IsValidMetaFile16(HMETAFILE16 hmf
)
506 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
508 if (mh
->mtType
== METAFILE_MEMORY
|| mh
->mtType
== METAFILE_DISK
)
509 if (mh
->mtHeaderSize
== MFHEADERSIZE
/sizeof(INT16
))
510 if (mh
->mtVersion
== MFVERSION
)
512 MF_ReleaseMetaHeader16(hmf
);
514 TRACE("IsValidMetaFile %x => %d\n",hmf
,res
);
519 /*******************************************************************
522 * Helper for PlayMetaFile
524 static BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
529 unsigned int offset
= 0;
536 if (!mh
) return FALSE
;
537 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
538 mh
= MF_LoadDiskBasedMetaFile(mh
);
539 if(!mh
) return FALSE
;
543 /* save the current pen, brush and font */
544 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
545 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
546 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
548 /* create the handle table */
549 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
550 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
551 if(!ht
) return FALSE
;
553 /* loop through metafile playing records */
554 offset
= mh
->mtHeaderSize
* 2;
555 while (offset
< mh
->mtSize
* 2)
557 mr
= (METARECORD
*)((char *)mh
+ offset
);
558 TRACE("offset=%04x,size=%08lx\n",
562 "Entry got size 0 at offset %d, total mf length is %ld\n",
563 offset
,mh
->mtSize
*2);
564 break; /* would loop endlessly otherwise */
566 offset
+= mr
->rdSize
* 2;
567 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
570 SelectObject(hdc
, hBrush
);
571 SelectObject(hdc
, hPen
);
572 SelectObject(hdc
, hFont
);
574 /* free objects in handle table */
575 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
576 if(*(ht
->objectHandle
+ i
) != 0)
577 DeleteObject(*(ht
->objectHandle
+ i
));
579 /* free handle table */
580 HeapFree( GetProcessHeap(), 0, ht
);
582 HeapFree( GetProcessHeap(), 0, mh
);
586 /******************************************************************
587 * PlayMetaFile (GDI.123)
590 BOOL16 WINAPI
PlayMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
)
593 METAHEADER
*mh
= MF_GetMetaHeader16( hmf
);
594 ret
= MF_PlayMetaFile( HDC_32(hdc
), mh
);
595 MF_ReleaseMetaHeader16( hmf
);
599 /******************************************************************
600 * PlayMetaFile (GDI32.@)
602 * Renders the metafile specified by hmf in the DC specified by
603 * hdc. Returns FALSE on failure, TRUE on success.
605 BOOL WINAPI
PlayMetaFile(
606 HDC hdc
, /* [in] handle of DC to render in */
607 HMETAFILE hmf
/* [in] handle of metafile to render */
610 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
611 return MF_PlayMetaFile( hdc
, mh
);
615 /******************************************************************
616 * EnumMetaFile (GDI.175)
619 BOOL16 WINAPI
EnumMetaFile16( HDC16 hdc16
, HMETAFILE16 hmf
,
620 MFENUMPROC16 lpEnumFunc
, LPARAM lpData
)
622 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
625 HDC hdc
= HDC_32(hdc16
);
628 unsigned int offset
= 0;
634 BOOL16 result
= TRUE
, loaded
= FALSE
;
636 TRACE("(%p, %04x, %p, %08lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
638 if(!mh
) return FALSE
;
639 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
640 mh
= MF_LoadDiskBasedMetaFile(mh
);
641 if(!mh
) return FALSE
;
645 /* save the current pen, brush and font */
646 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
647 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
648 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
650 /* create the handle table */
652 hHT
= GlobalAlloc16(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
653 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
654 spht
= K32WOWGlobalLock16(hHT
);
657 offset
= mh
->mtHeaderSize
* 2;
659 /* loop through metafile records */
662 args
[6] = SELECTOROF(spht
);
663 args
[5] = OFFSETOF(spht
);
664 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
665 args
[3] = LOWORD(offset
);
666 args
[2] = mh
->mtNoObjects
;
667 args
[1] = HIWORD(lpData
);
668 args
[0] = LOWORD(lpData
);
670 while (offset
< (mh
->mtSize
* 2))
674 mr
= (METARECORD
*)((char *)mh
+ offset
);
676 WOWCallback16Ex( (DWORD
)lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
683 offset
+= (mr
->rdSize
* 2);
684 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
685 args
[3] = LOWORD(offset
);
688 SelectObject(hdc
, hBrush
);
689 SelectObject(hdc
, hPen
);
690 SelectObject(hdc
, hFont
);
692 ht
= (HANDLETABLE16
*)GlobalLock16(hHT
);
694 /* free objects in handle table */
695 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
696 if(*(ht
->objectHandle
+ i
) != 0)
697 DeleteObject( (HGDIOBJ
)(ULONG_PTR
)(*(ht
->objectHandle
+ i
) ));
699 /* free handle table */
702 HeapFree( GetProcessHeap(), 0, mh
);
703 MF_ReleaseMetaHeader16(hmf
);
707 /******************************************************************
708 * EnumMetaFile (GDI32.@)
710 * Loop through the metafile records in hmf, calling the user-specified
711 * function for each one, stopping when the user's function returns FALSE
712 * (which is considered to be failure)
713 * or when no records are left (which is considered to be success).
716 * TRUE on success, FALSE on failure.
719 * Niels de carpentier, april 1996
721 BOOL WINAPI
EnumMetaFile(
724 MFENUMPROC lpEnumFunc
,
727 METAHEADER
*mhTemp
= NULL
, *mh
= MF_GetMetaHeader(hmf
);
732 unsigned int offset
= 0;
737 TRACE("(%p,%p,%p,%p)\n", hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
739 if(mh
->mtType
== METAFILE_DISK
)
741 /* Create a memory-based copy */
742 if (!(mhTemp
= MF_LoadDiskBasedMetaFile(mh
))) return FALSE
;
746 /* save the current pen, brush and font */
747 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
748 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
749 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
751 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
752 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
754 /* loop through metafile records */
755 offset
= mh
->mtHeaderSize
* 2;
757 while (offset
< (mh
->mtSize
* 2))
759 mr
= (METARECORD
*)((char *)mh
+ offset
);
760 if(mr
->rdFunction
== META_EOF
) {
761 TRACE("Got META_EOF so stopping\n");
764 TRACE("Calling EnumFunc with record type %x\n",
766 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
772 offset
+= (mr
->rdSize
* 2);
775 /* restore pen, brush and font */
776 SelectObject(hdc
, hBrush
);
777 SelectObject(hdc
, hPen
);
778 SelectObject(hdc
, hFont
);
780 /* free objects in handle table */
781 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
782 if(*(ht
->objectHandle
+ i
) != 0)
783 DeleteObject(*(ht
->objectHandle
+ i
));
785 /* free handle table */
786 HeapFree( GetProcessHeap(), 0, ht
);
787 /* free a copy of metafile */
788 if (mhTemp
) HeapFree( GetProcessHeap(), 0, mhTemp
);
792 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
793 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
794 /******************************************************************
795 * PlayMetaFileRecord (GDI32.@)
797 * Render a single metafile record specified by *mr in the DC hdc, while
798 * using the handle table *ht, of length handles,
799 * to store metafile objects.
802 * The following metafile records are unimplemented:
804 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
805 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
806 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
808 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
812 BITMAPINFOHEADER
*infohdr
;
814 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
816 switch (mr
->rdFunction
)
821 case META_DELETEOBJECT
:
822 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
823 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
826 case META_SETBKCOLOR
:
827 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
831 SetBkMode(hdc
, mr
->rdParm
[0]);
834 case META_SETMAPMODE
:
835 SetMapMode(hdc
, mr
->rdParm
[0]);
839 SetROP2(hdc
, mr
->rdParm
[0]);
843 SetRelAbs(hdc
, mr
->rdParm
[0]);
846 case META_SETPOLYFILLMODE
:
847 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
850 case META_SETSTRETCHBLTMODE
:
851 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
854 case META_SETTEXTCOLOR
:
855 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
858 case META_SETWINDOWORG
:
859 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
862 case META_SETWINDOWEXT
:
863 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
866 case META_SETVIEWPORTORG
:
867 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
870 case META_SETVIEWPORTEXT
:
871 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
874 case META_OFFSETWINDOWORG
:
875 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
878 case META_SCALEWINDOWEXT
:
879 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
880 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
883 case META_OFFSETVIEWPORTORG
:
884 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
887 case META_SCALEVIEWPORTEXT
:
888 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
889 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
893 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
897 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
900 case META_EXCLUDECLIPRECT
:
901 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
902 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
905 case META_INTERSECTCLIPRECT
:
906 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
907 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
911 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
912 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
913 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
914 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
918 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
919 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
923 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
924 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
928 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
929 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
930 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
931 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
935 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
936 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
940 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
941 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
942 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
946 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
947 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
948 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
956 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
957 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
960 case META_OFFSETCLIPRGN
:
961 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
966 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
967 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
968 (char *)(mr
->rdParm
+ 1), s1
);
972 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
974 Polygon(hdc
, pt
, mr
->rdParm
[0]);
975 HeapFree( GetProcessHeap(), 0, pt
);
979 case META_POLYPOLYGON
:
982 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
984 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
985 pt
= convert_points( total
, (LPPOINT16
)(counts
+ mr
->rdParm
[0]) );
988 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
991 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
992 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
993 HeapFree( GetProcessHeap(), 0, cnt32
);
996 HeapFree( GetProcessHeap(), 0, pt
);
1001 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
1003 Polyline( hdc
, pt
, mr
->rdParm
[0] );
1004 HeapFree( GetProcessHeap(), 0, pt
);
1008 case META_RESTOREDC
:
1009 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
1012 case META_SELECTOBJECT
:
1013 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1017 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1018 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1019 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1020 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1023 case META_CREATEPATTERNBRUSH
:
1024 switch (mr
->rdParm
[0])
1027 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1028 MF_AddHandle(ht
, handles
,
1029 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
1032 infohdr
->biBitCount
,
1033 (LPSTR
)(mr
->rdParm
+
1034 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
1038 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1039 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
1043 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1049 case META_CREATEPENINDIRECT
:
1052 pen
.lopnStyle
= mr
->rdParm
[0];
1053 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
1054 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
1055 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
1056 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
1060 case META_CREATEFONTINDIRECT
:
1063 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
1064 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
1065 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
1066 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
1067 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
1068 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
1069 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
1070 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
1071 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
1072 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
1073 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
1074 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
1075 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
1076 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
1077 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
1081 case META_CREATEBRUSHINDIRECT
:
1084 brush
.lbStyle
= mr
->rdParm
[0];
1085 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
1086 brush
.lbHatch
= mr
->rdParm
[3];
1087 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
1091 case META_CREATEPALETTE
:
1092 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
1095 case META_SETTEXTALIGN
:
1096 SetTextAlign(hdc
, mr
->rdParm
[0]);
1099 case META_SELECTPALETTE
:
1100 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
1103 case META_SETMAPPERFLAGS
:
1104 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1107 case META_REALIZEPALETTE
:
1108 GDIRealizePalette(hdc
);
1112 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
1115 case META_EXTTEXTOUT
:
1116 MF_Play_MetaExtTextOut( hdc
, mr
);
1119 case META_STRETCHDIB
:
1121 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
1122 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1123 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1124 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1125 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
1126 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1130 case META_DIBSTRETCHBLT
:
1132 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
1133 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1134 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1135 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1136 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
1137 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1141 case META_STRETCHBLT
:
1143 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1144 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
1145 mr
->rdParm
[11], /*Height*/
1146 mr
->rdParm
[13], /*Planes*/
1147 mr
->rdParm
[14], /*BitsPixel*/
1148 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
1149 SelectObject(hdcSrc
,hbitmap
);
1150 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1151 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1152 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1153 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1154 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1161 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1162 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
1163 mr
->rdParm
[8]/*Height*/,
1164 mr
->rdParm
[10]/*Planes*/,
1165 mr
->rdParm
[11]/*BitsPixel*/,
1166 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
1167 SelectObject(hdcSrc
,hbitmap
);
1168 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
1169 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
1170 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
1171 MAKELONG(0,mr
->rdParm
[0]));
1176 case META_CREATEREGION
:
1178 HRGN hrgn
= CreateRectRgn(0,0,0,0);
1180 MF_Play_MetaCreateRegion(mr
, hrgn
);
1181 MF_AddHandle(ht
, handles
, hrgn
);
1185 case META_FILLREGION
:
1186 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
1187 *(ht
->objectHandle
+ mr
->rdParm
[0]));
1190 case META_FRAMEREGION
:
1191 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
1192 *(ht
->objectHandle
+ mr
->rdParm
[2]),
1193 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1196 case META_INVERTREGION
:
1197 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1200 case META_PAINTREGION
:
1201 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1204 case META_SELECTCLIPREGION
:
1205 SelectClipRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1208 case META_DIBCREATEPATTERNBRUSH
:
1209 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1210 but there's no difference */
1211 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
1214 case META_DIBBITBLT
:
1215 /* In practice I've found that there are two layouts for
1216 META_DIBBITBLT, one (the first here) is the usual one when a src
1217 dc is actually passed to it, the second occurs when the src dc is
1218 passed in as NULL to the creating BitBlt. As the second case has
1219 no dib, a size check will suffice to distinguish.
1221 Caolan.McNamara@ul.ie */
1223 if (mr
->rdSize
> 12) {
1224 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
1225 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize(info
, mr
->rdParm
[0]);
1227 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1228 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1229 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
1230 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1232 else /* equivalent to a PatBlt */
1233 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1234 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1235 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1238 case META_SETTEXTCHAREXTRA
:
1239 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
1242 case META_SETTEXTJUSTIFICATION
:
1243 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1246 case META_EXTFLOODFILL
:
1247 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1248 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
1252 case META_SETDIBTODEV
:
1254 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
1255 char *bits
= (char *)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[0] );
1256 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1257 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1258 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1259 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1264 #define META_UNIMP(x) case x: \
1265 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1267 META_UNIMP(META_DRAWTEXT
)
1268 META_UNIMP(META_ANIMATEPALETTE
)
1269 META_UNIMP(META_SETPALENTRIES
)
1270 META_UNIMP(META_RESIZEPALETTE
)
1271 META_UNIMP(META_RESETDC
)
1272 META_UNIMP(META_STARTDOC
)
1273 META_UNIMP(META_STARTPAGE
)
1274 META_UNIMP(META_ENDPAGE
)
1275 META_UNIMP(META_ABORTDOC
)
1276 META_UNIMP(META_ENDDOC
)
1277 META_UNIMP(META_CREATEBRUSH
)
1278 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1279 META_UNIMP(META_CREATEBITMAP
)
1283 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1289 /******************************************************************
1290 * GetMetaFileBits (GDI.159)
1292 * Trade in a metafile object handle for a handle to the metafile memory.
1296 HGLOBAL16 WINAPI
GetMetaFileBits16(
1297 HMETAFILE16 hmf
/* [in] metafile handle */
1300 TRACE("hMem out: %04x\n", hmf
);
1304 /******************************************************************
1305 * SetMetaFileBits (GDI.160)
1307 * Trade in a metafile memory handle for a handle to a metafile object.
1308 * The memory region should hold a proper metafile, otherwise
1309 * problems will occur when it is used. Validity of the memory is not
1310 * checked. The function is essentially just the identity function.
1312 HMETAFILE16 WINAPI
SetMetaFileBits16(
1314 /* [in] handle to a memory region holding a metafile */
1317 TRACE("hmf out: %04x\n", hMem
);
1322 /******************************************************************
1323 * SetMetaFileBitsBetter (GDI.196)
1325 * Trade in a metafile memory handle for a handle to a metafile object,
1326 * making a cursory check (using IsValidMetaFile()) that the memory
1327 * handle points to a valid metafile.
1330 * Handle to a metafile on success, NULL on failure..
1332 HMETAFILE16 WINAPI
SetMetaFileBitsBetter16( HMETAFILE16 hMeta
)
1334 if( IsValidMetaFile16( hMeta
) )
1335 return (HMETAFILE16
)GlobalReAlloc16( hMeta
, 0,
1336 GMEM_SHARE
| GMEM_NODISCARD
| GMEM_MODIFY
);
1337 return (HMETAFILE16
)0;
1340 /******************************************************************
1341 * SetMetaFileBitsEx (GDI32.@)
1343 * Create a metafile from raw data. No checking of the data is performed.
1344 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1346 HMETAFILE WINAPI
SetMetaFileBitsEx(
1347 UINT size
, /* [in] size of metafile, in bytes */
1348 const BYTE
*lpData
/* [in] pointer to metafile data */
1351 METAHEADER
*mh
= HeapAlloc( GetProcessHeap(), 0, size
);
1353 memcpy(mh
, lpData
, size
);
1354 return MF_Create_HMETAFILE(mh
);
1357 /*****************************************************************
1358 * GetMetaFileBitsEx (GDI32.@) Get raw metafile data
1360 * Copies the data from metafile _hmf_ into the buffer _buf_.
1361 * If _buf_ is zero, returns size of buffer required. Otherwise,
1362 * returns number of bytes copied.
1364 UINT WINAPI
GetMetaFileBitsEx(
1365 HMETAFILE hmf
, /* [in] metafile */
1366 UINT nSize
, /* [in] size of buf */
1367 LPVOID buf
/* [out] buffer to receive raw metafile data */
1369 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1372 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1373 if (!mh
) return 0; /* FIXME: error code */
1374 if(mh
->mtType
== METAFILE_DISK
)
1375 FIXME("Disk-based metafile?\n");
1376 mfSize
= mh
->mtSize
* 2;
1378 TRACE("returning size %d\n", mfSize
);
1381 if(mfSize
> nSize
) mfSize
= nSize
;
1382 memmove(buf
, mh
, mfSize
);
1386 /******************************************************************
1387 * GetWinMetaFileBits [GDI32.@]
1389 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1390 UINT cbBuffer
, LPBYTE lpbBuffer
,
1391 INT fnMapMode
, HDC hdcRef
)
1397 FIXME("(%p,%d,%p,%d,%p): stub\n", hemf
, cbBuffer
, lpbBuffer
, fnMapMode
, hdcRef
);
1398 hdcmf
= CreateMetaFileA(NULL
);
1399 /* PlayEnhMetaFile(hdcmf, hemf, lpRect); where does the bounding rect come from? */
1400 hmf
= CloseMetaFile(hdcmf
);
1401 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1402 DeleteMetaFile(hmf
);
1406 /******************************************************************
1407 * MF_Play_MetaCreateRegion
1409 * Handles META_CREATEREGION for PlayMetaFileRecord().
1413 * The layout of the record looks something like this:
1418 * 2 Looks like a handle? - not constant
1420 * 4 Total number of bytes
1421 * 5 No. of separate bands = n [see below]
1422 * 6 Largest number of x co-ords in a band
1423 * 7-10 Bounding box x1 y1 x2 y2
1426 * Regions are divided into bands that are uniform in the
1427 * y-direction. Each band consists of pairs of on/off x-coords and is
1429 * m y0 y1 x1 x2 x3 ... xm m
1430 * into successive rdParm[]s.
1432 * This is probably just a dump of the internal RGNOBJ?
1438 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1443 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1445 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1446 band
++, start
= end
+ 1) {
1447 if(*start
/ 2 != (*start
+ 1) / 2) {
1448 WARN("Delimiter not even.\n");
1449 DeleteObject( hrgn2
);
1453 end
= start
+ *start
+ 3;
1454 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1455 WARN("End points outside record.\n");
1456 DeleteObject( hrgn2
);
1460 if(*start
!= *end
) {
1461 WARN("Mismatched delimiters.\n");
1462 DeleteObject( hrgn2
);
1466 y0
= *(INT16
*)(start
+ 1);
1467 y1
= *(INT16
*)(start
+ 2);
1468 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1469 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1470 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1471 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1474 DeleteObject( hrgn2
);
1479 /******************************************************************
1480 * MF_Play_MetaExtTextOut
1482 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1485 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1494 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1496 s1
= mr
->rdParm
[2]; /* String length */
1497 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1498 + sizeof(UINT16
) + (isrect
? sizeof(RECT16
) : 0);
1499 /* rec len without dx array */
1501 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1504 rect
.left
= (SHORT
)mr
->rdParm
[4];
1505 rect
.top
= (SHORT
)mr
->rdParm
[5];
1506 rect
.right
= (SHORT
)mr
->rdParm
[6];
1507 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1508 sot
+= sizeof(RECT16
); /* there is a rectangle, so add offset */
1511 if (mr
->rdSize
== len
/ 2)
1512 dxx
= NULL
; /* determine if array present */
1514 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1516 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1517 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1518 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = (SHORT
)dxx
[i
];
1521 TRACE("%s len: %ld\n", sot
, mr
->rdSize
);
1523 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1524 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1525 dxx
= NULL
; /* should't happen -- but if, we continue with NULL */
1528 (SHORT
)mr
->rdParm
[1], /* X position */
1529 (SHORT
)mr
->rdParm
[0], /* Y position */
1530 mr
->rdParm
[3], /* options */
1531 &rect
, /* rectangle */
1533 s1
, dx
); /* length, dx array */
1536 TRACE("%s len: %ld dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1537 HeapFree( GetProcessHeap(), 0, dx
);