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"
57 #include "gdi_private.h"
58 #include "wine/debug.h"
60 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
77 #define MFHEADERSIZE (sizeof(METAHEADER))
78 #define MFVERSION 0x300
81 /******************************************************************
84 * Add a handle to an external handle table and return the index
86 static int MF_AddHandle(HANDLETABLE
*ht
, UINT htlen
, HGDIOBJ hobj
)
90 for (i
= 0; i
< htlen
; i
++)
92 if (*(ht
->objectHandle
+ i
) == 0)
94 *(ht
->objectHandle
+ i
) = hobj
;
102 /******************************************************************
103 * MF_Create_HMETATFILE
105 * Creates a (32 bit) HMETAFILE object from a METAHEADER
107 * HMETAFILEs are GDI objects.
109 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
112 METAFILEOBJ
*metaObj
= GDI_AllocObject( sizeof(METAFILEOBJ
), METAFILE_MAGIC
,
113 (HGDIOBJ
*)&hmf
, NULL
);
117 GDI_ReleaseObj( hmf
);
122 /******************************************************************
123 * MF_Create_HMETATFILE16
125 * Creates a HMETAFILE16 object from a METAHEADER
127 * HMETAFILE16s are Global memory handles.
129 HMETAFILE16
MF_Create_HMETAFILE16(METAHEADER
*mh
)
132 DWORD size
= mh
->mtSize
* sizeof(WORD
);
134 hmf
= GlobalAlloc16(GMEM_MOVEABLE
, size
);
137 METAHEADER
*mh_dest
= GlobalLock16(hmf
);
138 memcpy(mh_dest
, mh
, size
);
141 HeapFree(GetProcessHeap(), 0, mh
);
145 /******************************************************************
148 * Returns ptr to METAHEADER associated with HMETAFILE
150 static METAHEADER
*MF_GetMetaHeader( HMETAFILE hmf
)
152 METAHEADER
*ret
= NULL
;
153 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
157 GDI_ReleaseObj( hmf
);
162 /******************************************************************
165 * Returns ptr to METAHEADER associated with HMETAFILE16
166 * Should be followed by call to MF_ReleaseMetaHeader16
168 static METAHEADER
*MF_GetMetaHeader16( HMETAFILE16 hmf
)
170 return GlobalLock16(hmf
);
173 /******************************************************************
174 * MF_ReleaseMetaHeader16
176 * Releases METAHEADER associated with HMETAFILE16
178 static BOOL16
MF_ReleaseMetaHeader16( HMETAFILE16 hmf
)
180 return GlobalUnlock16( hmf
);
184 /******************************************************************
187 * Convert an array of POINT16 to an array of POINT.
188 * Result must be freed by caller.
190 static POINT
*convert_points( UINT count
, POINT16
*pt16
)
193 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
196 for (i
= 0; i
< count
; i
++)
198 ret
[i
].x
= pt16
[i
].x
;
199 ret
[i
].y
= pt16
[i
].y
;
206 /******************************************************************
207 * DeleteMetaFile (GDI.127)
209 BOOL16 WINAPI
DeleteMetaFile16( HMETAFILE16 hmf
)
211 return !GlobalFree16( hmf
);
214 /******************************************************************
215 * DeleteMetaFile (GDI32.@)
217 * Delete a memory-based metafile.
220 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
222 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
223 if (!metaObj
) return FALSE
;
224 HeapFree( GetProcessHeap(), 0, metaObj
->mh
);
225 GDI_FreeObject( hmf
, metaObj
);
229 /******************************************************************
232 * Returns a pointer to a memory based METAHEADER read in from file HFILE
235 static METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
238 DWORD BytesRead
, size
;
240 size
= sizeof(METAHEADER
);
241 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
243 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
245 HeapFree( GetProcessHeap(), 0, mh
);
248 size
= mh
->mtSize
* 2;
249 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
251 size
-= sizeof(METAHEADER
);
252 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
255 HeapFree( GetProcessHeap(), 0, mh
);
259 if (mh
->mtType
!= METAFILE_MEMORY
) {
260 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
261 mh
->mtType
= METAFILE_MEMORY
;
266 /******************************************************************
267 * GetMetaFile (GDI.124)
269 HMETAFILE16 WINAPI
GetMetaFile16( LPCSTR lpFilename
)
274 TRACE("%s\n", lpFilename
);
279 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
280 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
283 mh
= MF_ReadMetaFile(hFile
);
286 return MF_Create_HMETAFILE16( mh
);
289 /******************************************************************
290 * GetMetaFileA (GDI32.@)
292 * Read a metafile from a file. Returns handle to a memory-based metafile.
294 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
299 TRACE("%s\n", lpFilename
);
304 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
305 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
308 mh
= MF_ReadMetaFile(hFile
);
311 return MF_Create_HMETAFILE( mh
);
316 /******************************************************************
317 * GetMetaFileW (GDI32.@)
319 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
324 TRACE("%s\n", debugstr_w(lpFilename
));
329 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
330 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
333 mh
= MF_ReadMetaFile(hFile
);
336 return MF_Create_HMETAFILE( mh
);
340 /******************************************************************
341 * MF_LoadDiskBasedMetaFile
343 * Creates a new memory-based metafile from a disk-based one.
345 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
351 if(mh
->mtType
!= METAFILE_DISK
) {
352 ERR("Not a disk based metafile\n");
355 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
357 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
358 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
359 WARN("Can't open file of disk based metafile\n");
362 mh2
= MF_ReadMetaFile(hfile
);
367 /******************************************************************
368 * MF_CreateMetaHeaderDisk
370 * Take a memory based METAHEADER and change it to a disk based METAHEADER
371 * assosiated with filename. Note: Trashes contents of old one.
373 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCSTR filename
)
378 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
379 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
380 mh
->mtType
= METAFILE_DISK
;
381 size
= HeapSize( GetProcessHeap(), 0, mh
);
382 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
383 strcpy(mhd
->filename
, filename
);
387 /******************************************************************
388 * CopyMetaFile (GDI.151)
390 HMETAFILE16 WINAPI
CopyMetaFile16( HMETAFILE16 hSrcMetaFile
, LPCSTR lpFilename
)
392 METAHEADER
*mh
= MF_GetMetaHeader16( hSrcMetaFile
);
393 METAHEADER
*mh2
= NULL
;
396 TRACE("(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
400 if(mh
->mtType
== METAFILE_DISK
)
401 mh2
= MF_LoadDiskBasedMetaFile(mh
);
403 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
404 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
406 MF_ReleaseMetaHeader16( hSrcMetaFile
);
408 if(lpFilename
) { /* disk based metafile */
409 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
410 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
411 HeapFree( GetProcessHeap(), 0, mh2
);
414 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
416 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
);
419 return MF_Create_HMETAFILE16( mh2
);
423 /******************************************************************
424 * CopyMetaFileW (GDI32.@)
426 * Copies the metafile corresponding to hSrcMetaFile to either
427 * a disk file, if a filename is given, or to a new memory based
428 * metafile, if lpFileName is NULL.
432 * Handle to metafile copy on success, NULL on failure.
436 * Copying to disk returns NULL even if successful.
438 HMETAFILE WINAPI
CopyMetaFileW(
439 HMETAFILE hSrcMetaFile
, /* [in] handle of metafile to copy */
440 LPCWSTR lpFilename
/* [in] filename if copying to a file */)
442 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
443 METAHEADER
*mh2
= NULL
;
446 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
450 if(mh
->mtType
== METAFILE_DISK
)
451 mh2
= MF_LoadDiskBasedMetaFile(mh
);
453 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
454 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
457 if(lpFilename
) { /* disk based metafile */
460 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
461 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
462 HeapFree( GetProcessHeap(), 0, mh2
);
465 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
467 len
= WideCharToMultiByte(CP_ACP
, 0, lpFilename
, -1, NULL
, 0, NULL
, NULL
);
468 lpFilenameA
= HeapAlloc(GetProcessHeap(), 0, len
);
469 WideCharToMultiByte(CP_ACP
, 0, lpFilename
, -1, lpFilenameA
, len
, NULL
, NULL
);
470 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilenameA
);
471 HeapFree(GetProcessHeap(), 0, lpFilenameA
);
474 return MF_Create_HMETAFILE( mh2
);
478 /******************************************************************
479 * CopyMetaFileA (GDI32.@)
481 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
,
484 UNICODE_STRING lpFilenameW
;
487 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
488 else lpFilenameW
.Buffer
= NULL
;
490 if (lpFilenameW
.Buffer
) {
491 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
493 RtlFreeUnicodeString(&lpFilenameW
);
498 /******************************************************************
499 * IsValidMetaFile (GDI.410)
501 * Attempts to check if a given metafile is correctly formatted.
502 * Currently, the only things verified are several properties of the
506 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
509 * This is not exactly what windows does, see _Undocumented_Windows_
512 BOOL16 WINAPI
IsValidMetaFile16(HMETAFILE16 hmf
)
515 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
517 if (mh
->mtType
== METAFILE_MEMORY
|| mh
->mtType
== METAFILE_DISK
)
518 if (mh
->mtHeaderSize
== MFHEADERSIZE
/sizeof(INT16
))
519 if (mh
->mtVersion
== MFVERSION
)
521 MF_ReleaseMetaHeader16(hmf
);
523 TRACE("IsValidMetaFile %x => %d\n",hmf
,res
);
528 /*******************************************************************
531 * Helper for PlayMetaFile
533 static BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
538 unsigned int offset
= 0;
545 if (!mh
) return FALSE
;
546 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
547 mh
= MF_LoadDiskBasedMetaFile(mh
);
548 if(!mh
) return FALSE
;
552 /* save the current pen, brush and font */
553 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
554 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
555 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
557 /* create the handle table */
558 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
559 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
560 if(!ht
) return FALSE
;
562 /* loop through metafile playing records */
563 offset
= mh
->mtHeaderSize
* 2;
564 while (offset
< mh
->mtSize
* 2)
566 mr
= (METARECORD
*)((char *)mh
+ offset
);
567 TRACE("offset=%04x,size=%08lx\n",
571 "Entry got size 0 at offset %d, total mf length is %ld\n",
572 offset
,mh
->mtSize
*2);
573 break; /* would loop endlessly otherwise */
575 offset
+= mr
->rdSize
* 2;
576 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
579 SelectObject(hdc
, hBrush
);
580 SelectObject(hdc
, hPen
);
581 SelectObject(hdc
, hFont
);
583 /* free objects in handle table */
584 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
585 if(*(ht
->objectHandle
+ i
) != 0)
586 DeleteObject(*(ht
->objectHandle
+ i
));
588 /* free handle table */
589 HeapFree( GetProcessHeap(), 0, ht
);
591 HeapFree( GetProcessHeap(), 0, mh
);
595 /******************************************************************
596 * PlayMetaFile (GDI.123)
599 BOOL16 WINAPI
PlayMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
)
602 METAHEADER
*mh
= MF_GetMetaHeader16( hmf
);
603 ret
= MF_PlayMetaFile( HDC_32(hdc
), mh
);
604 MF_ReleaseMetaHeader16( hmf
);
608 /******************************************************************
609 * PlayMetaFile (GDI32.@)
611 * Renders the metafile specified by hmf in the DC specified by
612 * hdc. Returns FALSE on failure, TRUE on success.
614 BOOL WINAPI
PlayMetaFile(
615 HDC hdc
, /* [in] handle of DC to render in */
616 HMETAFILE hmf
/* [in] handle of metafile to render */
619 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
620 return MF_PlayMetaFile( hdc
, mh
);
624 /******************************************************************
625 * EnumMetaFile (GDI.175)
628 BOOL16 WINAPI
EnumMetaFile16( HDC16 hdc16
, HMETAFILE16 hmf
,
629 MFENUMPROC16 lpEnumFunc
, LPARAM lpData
)
631 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
634 HDC hdc
= HDC_32(hdc16
);
637 unsigned int offset
= 0;
643 BOOL16 result
= TRUE
, loaded
= FALSE
;
645 TRACE("(%p, %04x, %p, %08lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
647 if(!mh
) return FALSE
;
648 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
649 mh
= MF_LoadDiskBasedMetaFile(mh
);
650 if(!mh
) return FALSE
;
654 /* save the current pen, brush and font */
655 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
656 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
657 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
659 /* create the handle table */
661 hHT
= GlobalAlloc16(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
662 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
663 spht
= K32WOWGlobalLock16(hHT
);
666 offset
= mh
->mtHeaderSize
* 2;
668 /* loop through metafile records */
671 args
[6] = SELECTOROF(spht
);
672 args
[5] = OFFSETOF(spht
);
673 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
674 args
[3] = LOWORD(offset
);
675 args
[2] = mh
->mtNoObjects
;
676 args
[1] = HIWORD(lpData
);
677 args
[0] = LOWORD(lpData
);
679 while (offset
< (mh
->mtSize
* 2))
683 mr
= (METARECORD
*)((char *)mh
+ offset
);
685 WOWCallback16Ex( (DWORD
)lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
692 offset
+= (mr
->rdSize
* 2);
693 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
694 args
[3] = LOWORD(offset
);
697 SelectObject(hdc
, hBrush
);
698 SelectObject(hdc
, hPen
);
699 SelectObject(hdc
, hFont
);
701 ht
= (HANDLETABLE16
*)GlobalLock16(hHT
);
703 /* free objects in handle table */
704 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
705 if(*(ht
->objectHandle
+ i
) != 0)
706 DeleteObject( (HGDIOBJ
)(ULONG_PTR
)(*(ht
->objectHandle
+ i
) ));
708 /* free handle table */
711 HeapFree( GetProcessHeap(), 0, mh
);
712 MF_ReleaseMetaHeader16(hmf
);
716 /******************************************************************
717 * EnumMetaFile (GDI32.@)
719 * Loop through the metafile records in hmf, calling the user-specified
720 * function for each one, stopping when the user's function returns FALSE
721 * (which is considered to be failure)
722 * or when no records are left (which is considered to be success).
725 * TRUE on success, FALSE on failure.
728 * Niels de carpentier, april 1996
730 BOOL WINAPI
EnumMetaFile(
733 MFENUMPROC lpEnumFunc
,
736 METAHEADER
*mhTemp
= NULL
, *mh
= MF_GetMetaHeader(hmf
);
741 unsigned int offset
= 0;
746 TRACE("(%p,%p,%p,%p)\n", hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
748 if(mh
->mtType
== METAFILE_DISK
)
750 /* Create a memory-based copy */
751 if (!(mhTemp
= MF_LoadDiskBasedMetaFile(mh
))) return FALSE
;
755 /* save the current pen, brush and font */
756 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
757 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
758 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
760 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
761 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
763 /* loop through metafile records */
764 offset
= mh
->mtHeaderSize
* 2;
766 while (offset
< (mh
->mtSize
* 2))
768 mr
= (METARECORD
*)((char *)mh
+ offset
);
769 if(mr
->rdFunction
== META_EOF
) {
770 TRACE("Got META_EOF so stopping\n");
773 TRACE("Calling EnumFunc with record type %x\n",
775 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
781 offset
+= (mr
->rdSize
* 2);
784 /* restore pen, brush and font */
785 SelectObject(hdc
, hBrush
);
786 SelectObject(hdc
, hPen
);
787 SelectObject(hdc
, hFont
);
789 /* free objects in handle table */
790 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
791 if(*(ht
->objectHandle
+ i
) != 0)
792 DeleteObject(*(ht
->objectHandle
+ i
));
794 /* free handle table */
795 HeapFree( GetProcessHeap(), 0, ht
);
796 /* free a copy of metafile */
797 if (mhTemp
) HeapFree( GetProcessHeap(), 0, mhTemp
);
801 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
802 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
803 /******************************************************************
804 * PlayMetaFileRecord (GDI32.@)
806 * Render a single metafile record specified by *mr in the DC hdc, while
807 * using the handle table *ht, of length handles,
808 * to store metafile objects.
811 * The following metafile records are unimplemented:
813 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
814 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
815 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
817 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
821 BITMAPINFOHEADER
*infohdr
;
823 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
825 switch (mr
->rdFunction
)
830 case META_DELETEOBJECT
:
831 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
832 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
835 case META_SETBKCOLOR
:
836 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
840 SetBkMode(hdc
, mr
->rdParm
[0]);
843 case META_SETMAPMODE
:
844 SetMapMode(hdc
, mr
->rdParm
[0]);
848 SetROP2(hdc
, mr
->rdParm
[0]);
852 SetRelAbs(hdc
, mr
->rdParm
[0]);
855 case META_SETPOLYFILLMODE
:
856 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
859 case META_SETSTRETCHBLTMODE
:
860 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
863 case META_SETTEXTCOLOR
:
864 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
867 case META_SETWINDOWORG
:
868 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
871 case META_SETWINDOWEXT
:
872 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
875 case META_SETVIEWPORTORG
:
876 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
879 case META_SETVIEWPORTEXT
:
880 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
883 case META_OFFSETWINDOWORG
:
884 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
887 case META_SCALEWINDOWEXT
:
888 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
889 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
892 case META_OFFSETVIEWPORTORG
:
893 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
896 case META_SCALEVIEWPORTEXT
:
897 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
898 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
902 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
906 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
909 case META_EXCLUDECLIPRECT
:
910 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
911 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
914 case META_INTERSECTCLIPRECT
:
915 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
916 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
920 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
921 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
922 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
923 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
927 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
928 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
932 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
933 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
937 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
938 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
939 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
940 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
944 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
945 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
949 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
950 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
951 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
955 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
956 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
957 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
965 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
966 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
969 case META_OFFSETCLIPRGN
:
970 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
975 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
976 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
977 (char *)(mr
->rdParm
+ 1), s1
);
981 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
983 Polygon(hdc
, pt
, mr
->rdParm
[0]);
984 HeapFree( GetProcessHeap(), 0, pt
);
988 case META_POLYPOLYGON
:
991 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
993 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
994 pt
= convert_points( total
, (LPPOINT16
)(counts
+ mr
->rdParm
[0]) );
997 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
1000 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
1001 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
1002 HeapFree( GetProcessHeap(), 0, cnt32
);
1005 HeapFree( GetProcessHeap(), 0, pt
);
1010 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
1012 Polyline( hdc
, pt
, mr
->rdParm
[0] );
1013 HeapFree( GetProcessHeap(), 0, pt
);
1017 case META_RESTOREDC
:
1018 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
1021 case META_SELECTOBJECT
:
1022 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1026 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1027 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1028 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1029 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1032 case META_CREATEPATTERNBRUSH
:
1033 switch (mr
->rdParm
[0])
1036 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1037 MF_AddHandle(ht
, handles
,
1038 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
1041 infohdr
->biBitCount
,
1042 (LPSTR
)(mr
->rdParm
+
1043 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
1047 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1048 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
1052 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1058 case META_CREATEPENINDIRECT
:
1061 pen
.lopnStyle
= mr
->rdParm
[0];
1062 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
1063 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
1064 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
1065 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
1069 case META_CREATEFONTINDIRECT
:
1072 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
1073 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
1074 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
1075 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
1076 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
1077 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
1078 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
1079 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
1080 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
1081 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
1082 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
1083 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
1084 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
1085 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
1086 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
1090 case META_CREATEBRUSHINDIRECT
:
1093 brush
.lbStyle
= mr
->rdParm
[0];
1094 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
1095 brush
.lbHatch
= mr
->rdParm
[3];
1096 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
1100 case META_CREATEPALETTE
:
1101 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
1104 case META_SETTEXTALIGN
:
1105 SetTextAlign(hdc
, mr
->rdParm
[0]);
1108 case META_SELECTPALETTE
:
1109 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
1112 case META_SETMAPPERFLAGS
:
1113 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1116 case META_REALIZEPALETTE
:
1117 GDIRealizePalette(hdc
);
1121 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
1124 case META_EXTTEXTOUT
:
1125 MF_Play_MetaExtTextOut( hdc
, mr
);
1128 case META_STRETCHDIB
:
1130 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
1131 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1132 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1133 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1134 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
1135 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1139 case META_DIBSTRETCHBLT
:
1141 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
1142 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1143 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1144 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1145 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
1146 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1150 case META_STRETCHBLT
:
1152 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1153 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
1154 mr
->rdParm
[11], /*Height*/
1155 mr
->rdParm
[13], /*Planes*/
1156 mr
->rdParm
[14], /*BitsPixel*/
1157 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
1158 SelectObject(hdcSrc
,hbitmap
);
1159 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1160 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1161 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1162 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1163 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1170 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1171 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
1172 mr
->rdParm
[8]/*Height*/,
1173 mr
->rdParm
[10]/*Planes*/,
1174 mr
->rdParm
[11]/*BitsPixel*/,
1175 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
1176 SelectObject(hdcSrc
,hbitmap
);
1177 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
1178 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
1179 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
1180 MAKELONG(0,mr
->rdParm
[0]));
1185 case META_CREATEREGION
:
1187 HRGN hrgn
= CreateRectRgn(0,0,0,0);
1189 MF_Play_MetaCreateRegion(mr
, hrgn
);
1190 MF_AddHandle(ht
, handles
, hrgn
);
1194 case META_FILLREGION
:
1195 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
1196 *(ht
->objectHandle
+ mr
->rdParm
[0]));
1199 case META_FRAMEREGION
:
1200 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
1201 *(ht
->objectHandle
+ mr
->rdParm
[2]),
1202 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1205 case META_INVERTREGION
:
1206 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1209 case META_PAINTREGION
:
1210 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1213 case META_SELECTCLIPREGION
:
1214 SelectClipRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1217 case META_DIBCREATEPATTERNBRUSH
:
1218 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1219 but there's no difference */
1220 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
1223 case META_DIBBITBLT
:
1224 /* In practice I've found that there are two layouts for
1225 META_DIBBITBLT, one (the first here) is the usual one when a src
1226 dc is actually passed to it, the second occurs when the src dc is
1227 passed in as NULL to the creating BitBlt. As the second case has
1228 no dib, a size check will suffice to distinguish.
1230 Caolan.McNamara@ul.ie */
1232 if (mr
->rdSize
> 12) {
1233 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
1234 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize(info
, mr
->rdParm
[0]);
1236 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1237 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1238 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
1239 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1241 else /* equivalent to a PatBlt */
1242 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1243 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1244 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1247 case META_SETTEXTCHAREXTRA
:
1248 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
1251 case META_SETTEXTJUSTIFICATION
:
1252 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1255 case META_EXTFLOODFILL
:
1256 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1257 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
1261 case META_SETDIBTODEV
:
1263 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
1264 char *bits
= (char *)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[0] );
1265 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1266 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1267 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1268 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1273 #define META_UNIMP(x) case x: \
1274 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1276 META_UNIMP(META_DRAWTEXT
)
1277 META_UNIMP(META_ANIMATEPALETTE
)
1278 META_UNIMP(META_SETPALENTRIES
)
1279 META_UNIMP(META_RESIZEPALETTE
)
1280 META_UNIMP(META_RESETDC
)
1281 META_UNIMP(META_STARTDOC
)
1282 META_UNIMP(META_STARTPAGE
)
1283 META_UNIMP(META_ENDPAGE
)
1284 META_UNIMP(META_ABORTDOC
)
1285 META_UNIMP(META_ENDDOC
)
1286 META_UNIMP(META_CREATEBRUSH
)
1287 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1288 META_UNIMP(META_CREATEBITMAP
)
1292 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1298 /******************************************************************
1299 * GetMetaFileBits (GDI.159)
1301 * Trade in a metafile object handle for a handle to the metafile memory.
1305 HGLOBAL16 WINAPI
GetMetaFileBits16(
1306 HMETAFILE16 hmf
/* [in] metafile handle */
1309 TRACE("hMem out: %04x\n", hmf
);
1313 /******************************************************************
1314 * SetMetaFileBits (GDI.160)
1316 * Trade in a metafile memory handle for a handle to a metafile object.
1317 * The memory region should hold a proper metafile, otherwise
1318 * problems will occur when it is used. Validity of the memory is not
1319 * checked. The function is essentially just the identity function.
1321 HMETAFILE16 WINAPI
SetMetaFileBits16(
1323 /* [in] handle to a memory region holding a metafile */
1326 TRACE("hmf out: %04x\n", hMem
);
1331 /******************************************************************
1332 * SetMetaFileBitsBetter (GDI.196)
1334 * Trade in a metafile memory handle for a handle to a metafile object,
1335 * making a cursory check (using IsValidMetaFile()) that the memory
1336 * handle points to a valid metafile.
1339 * Handle to a metafile on success, NULL on failure..
1341 HMETAFILE16 WINAPI
SetMetaFileBitsBetter16( HMETAFILE16 hMeta
)
1343 if( IsValidMetaFile16( hMeta
) )
1344 return (HMETAFILE16
)GlobalReAlloc16( hMeta
, 0,
1345 GMEM_SHARE
| GMEM_NODISCARD
| GMEM_MODIFY
);
1346 return (HMETAFILE16
)0;
1349 /******************************************************************
1350 * SetMetaFileBitsEx (GDI32.@)
1352 * Create a metafile from raw data. No checking of the data is performed.
1353 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1355 HMETAFILE WINAPI
SetMetaFileBitsEx(
1356 UINT size
, /* [in] size of metafile, in bytes */
1357 const BYTE
*lpData
/* [in] pointer to metafile data */
1360 METAHEADER
*mh
= HeapAlloc( GetProcessHeap(), 0, size
);
1362 memcpy(mh
, lpData
, size
);
1363 return MF_Create_HMETAFILE(mh
);
1366 /*****************************************************************
1367 * GetMetaFileBitsEx (GDI32.@)
1369 * Get raw metafile data.
1371 * Copies the data from metafile _hmf_ into the buffer _buf_.
1372 * If _buf_ is zero, returns size of buffer required. Otherwise,
1373 * returns number of bytes copied.
1375 UINT WINAPI
GetMetaFileBitsEx(
1376 HMETAFILE hmf
, /* [in] metafile */
1377 UINT nSize
, /* [in] size of buf */
1378 LPVOID buf
/* [out] buffer to receive raw metafile data */)
1380 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1383 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1384 if (!mh
) return 0; /* FIXME: error code */
1385 if(mh
->mtType
== METAFILE_DISK
)
1386 FIXME("Disk-based metafile?\n");
1387 mfSize
= mh
->mtSize
* 2;
1389 TRACE("returning size %d\n", mfSize
);
1392 if(mfSize
> nSize
) mfSize
= nSize
;
1393 memmove(buf
, mh
, mfSize
);
1397 /******************************************************************
1398 * GetWinMetaFileBits [GDI32.@]
1400 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1401 UINT cbBuffer
, LPBYTE lpbBuffer
,
1402 INT fnMapMode
, HDC hdcRef
)
1410 GetClipBox(hdcRef
, &rc
);
1411 oldMapMode
= SetMapMode(hdcRef
, fnMapMode
);
1413 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1414 fnMapMode
, hdcRef
, wine_dbgstr_rect(&rc
));
1416 hdcmf
= CreateMetaFileA(NULL
);
1417 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1418 hmf
= CloseMetaFile(hdcmf
);
1419 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1420 DeleteMetaFile(hmf
);
1422 SetMapMode(hdcRef
, oldMapMode
);
1427 /******************************************************************
1428 * MF_Play_MetaCreateRegion
1430 * Handles META_CREATEREGION for PlayMetaFileRecord().
1434 * The layout of the record looks something like this:
1439 * 2 Looks like a handle? - not constant
1441 * 4 Total number of bytes
1442 * 5 No. of separate bands = n [see below]
1443 * 6 Largest number of x co-ords in a band
1444 * 7-10 Bounding box x1 y1 x2 y2
1447 * Regions are divided into bands that are uniform in the
1448 * y-direction. Each band consists of pairs of on/off x-coords and is
1450 * m y0 y1 x1 x2 x3 ... xm m
1451 * into successive rdParm[]s.
1453 * This is probably just a dump of the internal RGNOBJ?
1459 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1464 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1466 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1467 band
++, start
= end
+ 1) {
1468 if(*start
/ 2 != (*start
+ 1) / 2) {
1469 WARN("Delimiter not even.\n");
1470 DeleteObject( hrgn2
);
1474 end
= start
+ *start
+ 3;
1475 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1476 WARN("End points outside record.\n");
1477 DeleteObject( hrgn2
);
1481 if(*start
!= *end
) {
1482 WARN("Mismatched delimiters.\n");
1483 DeleteObject( hrgn2
);
1487 y0
= *(INT16
*)(start
+ 1);
1488 y1
= *(INT16
*)(start
+ 2);
1489 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1490 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1491 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1492 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1495 DeleteObject( hrgn2
);
1500 /******************************************************************
1501 * MF_Play_MetaExtTextOut
1503 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1506 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1515 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1517 s1
= mr
->rdParm
[2]; /* String length */
1518 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1519 + sizeof(UINT16
) + (isrect
? sizeof(RECT16
) : 0);
1520 /* rec len without dx array */
1522 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1525 rect
.left
= (SHORT
)mr
->rdParm
[4];
1526 rect
.top
= (SHORT
)mr
->rdParm
[5];
1527 rect
.right
= (SHORT
)mr
->rdParm
[6];
1528 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1529 sot
+= sizeof(RECT16
); /* there is a rectangle, so add offset */
1532 if (mr
->rdSize
== len
/ 2)
1533 dxx
= NULL
; /* determine if array present */
1535 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1537 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1538 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1539 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = (SHORT
)dxx
[i
];
1542 TRACE("%s len: %ld\n", sot
, mr
->rdSize
);
1544 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1545 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1546 dxx
= NULL
; /* should't happen -- but if, we continue with NULL */
1549 (SHORT
)mr
->rdParm
[1], /* X position */
1550 (SHORT
)mr
->rdParm
[0], /* Y position */
1551 mr
->rdParm
[3], /* options */
1552 &rect
, /* rectangle */
1554 s1
, dx
); /* length, dx array */
1557 TRACE("%s len: %ld dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1558 HeapFree( GetProcessHeap(), 0, dx
);