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 if(mh
->mtVersion
!= MFVERSION
|| mh
->mtHeaderSize
!= size
/ 2) {
249 HeapFree( GetProcessHeap(), 0, mh
);
252 size
= mh
->mtSize
* 2;
253 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
255 size
-= sizeof(METAHEADER
);
256 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
259 HeapFree( GetProcessHeap(), 0, mh
);
263 if (mh
->mtType
!= METAFILE_MEMORY
) {
264 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
265 mh
->mtType
= METAFILE_MEMORY
;
270 /******************************************************************
271 * GetMetaFile (GDI.124)
273 HMETAFILE16 WINAPI
GetMetaFile16( LPCSTR lpFilename
)
278 TRACE("%s\n", lpFilename
);
283 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
284 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
287 mh
= MF_ReadMetaFile(hFile
);
290 return MF_Create_HMETAFILE16( mh
);
293 /******************************************************************
294 * GetMetaFileA (GDI32.@)
296 * Read a metafile from a file. Returns handle to a memory-based metafile.
298 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
303 TRACE("%s\n", lpFilename
);
308 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
309 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
312 mh
= MF_ReadMetaFile(hFile
);
315 return MF_Create_HMETAFILE( mh
);
320 /******************************************************************
321 * GetMetaFileW (GDI32.@)
323 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
328 TRACE("%s\n", debugstr_w(lpFilename
));
333 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
334 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
337 mh
= MF_ReadMetaFile(hFile
);
340 return MF_Create_HMETAFILE( mh
);
344 /******************************************************************
345 * MF_LoadDiskBasedMetaFile
347 * Creates a new memory-based metafile from a disk-based one.
349 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
355 if(mh
->mtType
!= METAFILE_DISK
) {
356 ERR("Not a disk based metafile\n");
359 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
361 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
362 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
363 WARN("Can't open file of disk based metafile\n");
366 mh2
= MF_ReadMetaFile(hfile
);
371 /******************************************************************
372 * MF_CreateMetaHeaderDisk
374 * Take a memory based METAHEADER and change it to a disk based METAHEADER
375 * assosiated with filename. Note: Trashes contents of old one.
377 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCVOID filename
, BOOL uni
)
382 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
383 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
384 mh
->mtType
= METAFILE_DISK
;
385 size
= HeapSize( GetProcessHeap(), 0, mh
);
386 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
389 WideCharToMultiByte(CP_ACP
, 0, filename
, -1,
390 mhd
->filename
, sizeof mhd
->filename
, NULL
, NULL
);
392 lstrcpynA( mhd
->filename
, filename
, sizeof mhd
->filename
);
396 /******************************************************************
397 * CopyMetaFile (GDI.151)
399 HMETAFILE16 WINAPI
CopyMetaFile16( HMETAFILE16 hSrcMetaFile
, LPCSTR lpFilename
)
401 METAHEADER
*mh
= MF_GetMetaHeader16( hSrcMetaFile
);
402 METAHEADER
*mh2
= NULL
;
405 TRACE("(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
409 if(mh
->mtType
== METAFILE_DISK
)
410 mh2
= MF_LoadDiskBasedMetaFile(mh
);
412 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
413 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
415 MF_ReleaseMetaHeader16( hSrcMetaFile
);
417 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
);
424 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, &w
, NULL
);
426 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
, FALSE
);
429 return MF_Create_HMETAFILE16( mh2
);
433 /******************************************************************
434 * CopyMetaFileW (GDI32.@)
436 * Copies the metafile corresponding to hSrcMetaFile to either
437 * a disk file, if a filename is given, or to a new memory based
438 * metafile, if lpFileName is NULL.
442 * Handle to metafile copy on success, NULL on failure.
446 * Copying to disk returns NULL even if successful.
448 HMETAFILE WINAPI
CopyMetaFileW(
449 HMETAFILE hSrcMetaFile
, /* [in] handle of metafile to copy */
450 LPCWSTR lpFilename
/* [in] filename if copying to a file */)
452 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
453 METAHEADER
*mh2
= NULL
;
456 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
460 if(mh
->mtType
== METAFILE_DISK
)
461 mh2
= MF_LoadDiskBasedMetaFile(mh
);
463 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
464 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
467 if(lpFilename
) { /* disk based metafile */
469 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
470 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
471 HeapFree( GetProcessHeap(), 0, mh2
);
474 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, &w
, NULL
);
476 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
, TRUE
);
479 return MF_Create_HMETAFILE( mh2
);
483 /******************************************************************
484 * CopyMetaFileA (GDI32.@)
486 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
,
489 UNICODE_STRING lpFilenameW
;
492 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
493 else lpFilenameW
.Buffer
= NULL
;
495 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
496 if (lpFilenameW
.Buffer
)
497 RtlFreeUnicodeString(&lpFilenameW
);
502 /******************************************************************
503 * IsValidMetaFile (GDI.410)
505 * Attempts to check if a given metafile is correctly formatted.
506 * Currently, the only things verified are several properties of the
510 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
513 * This is not exactly what windows does, see _Undocumented_Windows_
516 BOOL16 WINAPI
IsValidMetaFile16(HMETAFILE16 hmf
)
519 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
521 if (mh
->mtType
== METAFILE_MEMORY
|| mh
->mtType
== METAFILE_DISK
)
522 if (mh
->mtHeaderSize
== MFHEADERSIZE
/sizeof(INT16
))
523 if (mh
->mtVersion
== MFVERSION
)
525 MF_ReleaseMetaHeader16(hmf
);
527 TRACE("IsValidMetaFile %x => %d\n",hmf
,res
);
532 /*******************************************************************
535 * Helper for PlayMetaFile
537 static BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
542 unsigned int offset
= 0;
549 if (!mh
) return FALSE
;
550 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
551 mh
= MF_LoadDiskBasedMetaFile(mh
);
552 if(!mh
) return FALSE
;
556 /* save the current pen, brush and font */
557 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
558 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
559 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
561 /* create the handle table */
562 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
563 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
564 if(!ht
) return FALSE
;
566 /* loop through metafile playing records */
567 offset
= mh
->mtHeaderSize
* 2;
568 while (offset
< mh
->mtSize
* 2)
570 mr
= (METARECORD
*)((char *)mh
+ offset
);
571 TRACE("offset=%04x,size=%08lx\n",
575 "Entry got size 0 at offset %d, total mf length is %ld\n",
576 offset
,mh
->mtSize
*2);
577 break; /* would loop endlessly otherwise */
579 offset
+= mr
->rdSize
* 2;
580 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
583 SelectObject(hdc
, hBrush
);
584 SelectObject(hdc
, hPen
);
585 SelectObject(hdc
, hFont
);
587 /* free objects in handle table */
588 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
589 if(*(ht
->objectHandle
+ i
) != 0)
590 DeleteObject(*(ht
->objectHandle
+ i
));
592 /* free handle table */
593 HeapFree( GetProcessHeap(), 0, ht
);
595 HeapFree( GetProcessHeap(), 0, mh
);
599 /******************************************************************
600 * PlayMetaFile (GDI.123)
603 BOOL16 WINAPI
PlayMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
)
606 METAHEADER
*mh
= MF_GetMetaHeader16( hmf
);
607 ret
= MF_PlayMetaFile( HDC_32(hdc
), mh
);
608 MF_ReleaseMetaHeader16( hmf
);
612 /******************************************************************
613 * PlayMetaFile (GDI32.@)
615 * Renders the metafile specified by hmf in the DC specified by
616 * hdc. Returns FALSE on failure, TRUE on success.
618 BOOL WINAPI
PlayMetaFile(
619 HDC hdc
, /* [in] handle of DC to render in */
620 HMETAFILE hmf
/* [in] handle of metafile to render */
623 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
624 return MF_PlayMetaFile( hdc
, mh
);
628 /******************************************************************
629 * EnumMetaFile (GDI.175)
632 BOOL16 WINAPI
EnumMetaFile16( HDC16 hdc16
, HMETAFILE16 hmf
,
633 MFENUMPROC16 lpEnumFunc
, LPARAM lpData
)
635 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
638 HDC hdc
= HDC_32(hdc16
);
641 unsigned int offset
= 0;
647 BOOL16 result
= TRUE
, loaded
= FALSE
;
649 TRACE("(%p, %04x, %p, %08lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
651 if(!mh
) return FALSE
;
652 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
653 mh
= MF_LoadDiskBasedMetaFile(mh
);
654 if(!mh
) return FALSE
;
658 /* save the current pen, brush and font */
659 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
660 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
661 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
663 /* create the handle table */
665 hHT
= GlobalAlloc16(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
666 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
667 spht
= K32WOWGlobalLock16(hHT
);
670 offset
= mh
->mtHeaderSize
* 2;
672 /* loop through metafile records */
675 args
[6] = SELECTOROF(spht
);
676 args
[5] = OFFSETOF(spht
);
677 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
678 args
[3] = LOWORD(offset
);
679 args
[2] = mh
->mtNoObjects
;
680 args
[1] = HIWORD(lpData
);
681 args
[0] = LOWORD(lpData
);
683 while (offset
< (mh
->mtSize
* 2))
687 mr
= (METARECORD
*)((char *)mh
+ offset
);
689 WOWCallback16Ex( (DWORD
)lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
696 offset
+= (mr
->rdSize
* 2);
697 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
698 args
[3] = LOWORD(offset
);
701 SelectObject(hdc
, hBrush
);
702 SelectObject(hdc
, hPen
);
703 SelectObject(hdc
, hFont
);
705 ht
= (HANDLETABLE16
*)GlobalLock16(hHT
);
707 /* free objects in handle table */
708 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
709 if(*(ht
->objectHandle
+ i
) != 0)
710 DeleteObject( (HGDIOBJ
)(ULONG_PTR
)(*(ht
->objectHandle
+ i
) ));
712 /* free handle table */
715 HeapFree( GetProcessHeap(), 0, mh
);
716 MF_ReleaseMetaHeader16(hmf
);
720 /******************************************************************
721 * EnumMetaFile (GDI32.@)
723 * Loop through the metafile records in hmf, calling the user-specified
724 * function for each one, stopping when the user's function returns FALSE
725 * (which is considered to be failure)
726 * or when no records are left (which is considered to be success).
729 * TRUE on success, FALSE on failure.
732 * Niels de carpentier, april 1996
734 BOOL WINAPI
EnumMetaFile(
737 MFENUMPROC lpEnumFunc
,
740 METAHEADER
*mhTemp
= NULL
, *mh
= MF_GetMetaHeader(hmf
);
745 unsigned int offset
= 0;
750 TRACE("(%p,%p,%p,%p)\n", hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
752 if(mh
->mtType
== METAFILE_DISK
)
754 /* Create a memory-based copy */
755 if (!(mhTemp
= MF_LoadDiskBasedMetaFile(mh
))) return FALSE
;
759 /* save the current pen, brush and font */
760 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
761 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
762 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
764 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
765 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
767 /* loop through metafile records */
768 offset
= mh
->mtHeaderSize
* 2;
770 while (offset
< (mh
->mtSize
* 2))
772 mr
= (METARECORD
*)((char *)mh
+ offset
);
773 if(mr
->rdFunction
== META_EOF
) {
774 TRACE("Got META_EOF so stopping\n");
777 TRACE("Calling EnumFunc with record type %x\n",
779 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
785 offset
+= (mr
->rdSize
* 2);
788 /* restore pen, brush and font */
789 SelectObject(hdc
, hBrush
);
790 SelectObject(hdc
, hPen
);
791 SelectObject(hdc
, hFont
);
793 /* free objects in handle table */
794 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
795 if(*(ht
->objectHandle
+ i
) != 0)
796 DeleteObject(*(ht
->objectHandle
+ i
));
798 /* free handle table */
799 HeapFree( GetProcessHeap(), 0, ht
);
800 /* free a copy of metafile */
801 HeapFree( GetProcessHeap(), 0, mhTemp
);
805 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
806 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
807 /******************************************************************
808 * PlayMetaFileRecord (GDI32.@)
810 * Render a single metafile record specified by *mr in the DC hdc, while
811 * using the handle table *ht, of length handles,
812 * to store metafile objects.
815 * The following metafile records are unimplemented:
817 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
818 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
819 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
821 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
825 BITMAPINFOHEADER
*infohdr
;
827 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
829 switch (mr
->rdFunction
)
834 case META_DELETEOBJECT
:
835 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
836 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
839 case META_SETBKCOLOR
:
840 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
844 SetBkMode(hdc
, mr
->rdParm
[0]);
847 case META_SETMAPMODE
:
848 SetMapMode(hdc
, mr
->rdParm
[0]);
852 SetROP2(hdc
, mr
->rdParm
[0]);
856 SetRelAbs(hdc
, mr
->rdParm
[0]);
859 case META_SETPOLYFILLMODE
:
860 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
863 case META_SETSTRETCHBLTMODE
:
864 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
867 case META_SETTEXTCOLOR
:
868 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
871 case META_SETWINDOWORG
:
872 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
875 case META_SETWINDOWEXT
:
876 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
879 case META_SETVIEWPORTORG
:
880 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
883 case META_SETVIEWPORTEXT
:
884 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
887 case META_OFFSETWINDOWORG
:
888 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
891 case META_SCALEWINDOWEXT
:
892 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
893 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
896 case META_OFFSETVIEWPORTORG
:
897 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
900 case META_SCALEVIEWPORTEXT
:
901 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
902 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
906 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
910 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
913 case META_EXCLUDECLIPRECT
:
914 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
915 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
918 case META_INTERSECTCLIPRECT
:
919 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
920 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
924 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
925 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
926 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
927 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
931 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
932 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
936 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
937 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
941 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
942 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
943 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
944 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
948 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
949 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
953 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
954 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
955 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
959 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
960 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
961 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
969 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
970 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
973 case META_OFFSETCLIPRGN
:
974 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
979 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
980 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
981 (char *)(mr
->rdParm
+ 1), s1
);
985 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
987 Polygon(hdc
, pt
, mr
->rdParm
[0]);
988 HeapFree( GetProcessHeap(), 0, pt
);
992 case META_POLYPOLYGON
:
995 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
997 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
998 pt
= convert_points( total
, (LPPOINT16
)(counts
+ mr
->rdParm
[0]) );
1001 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
1004 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
1005 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
1006 HeapFree( GetProcessHeap(), 0, cnt32
);
1009 HeapFree( GetProcessHeap(), 0, pt
);
1014 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
1016 Polyline( hdc
, pt
, mr
->rdParm
[0] );
1017 HeapFree( GetProcessHeap(), 0, pt
);
1021 case META_RESTOREDC
:
1022 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
1025 case META_SELECTOBJECT
:
1026 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1030 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1031 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1032 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1033 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1036 case META_CREATEPATTERNBRUSH
:
1037 switch (mr
->rdParm
[0])
1040 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1041 MF_AddHandle(ht
, handles
,
1042 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
1045 infohdr
->biBitCount
,
1046 (LPSTR
)(mr
->rdParm
+
1047 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
1051 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1052 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
1056 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1062 case META_CREATEPENINDIRECT
:
1065 pen
.lopnStyle
= mr
->rdParm
[0];
1066 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
1067 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
1068 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
1069 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
1073 case META_CREATEFONTINDIRECT
:
1076 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
1077 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
1078 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
1079 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
1080 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
1081 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
1082 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
1083 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
1084 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
1085 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
1086 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
1087 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
1088 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
1089 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
1090 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
1094 case META_CREATEBRUSHINDIRECT
:
1097 brush
.lbStyle
= mr
->rdParm
[0];
1098 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
1099 brush
.lbHatch
= mr
->rdParm
[3];
1100 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
1104 case META_CREATEPALETTE
:
1105 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
1108 case META_SETTEXTALIGN
:
1109 SetTextAlign(hdc
, mr
->rdParm
[0]);
1112 case META_SELECTPALETTE
:
1113 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
1116 case META_SETMAPPERFLAGS
:
1117 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1120 case META_REALIZEPALETTE
:
1121 GDIRealizePalette(hdc
);
1125 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
1128 case META_EXTTEXTOUT
:
1129 MF_Play_MetaExtTextOut( hdc
, mr
);
1132 case META_STRETCHDIB
:
1134 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
1135 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1136 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1137 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1138 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
1139 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1143 case META_DIBSTRETCHBLT
:
1145 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
1146 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1147 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1148 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1149 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
1150 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1154 case META_STRETCHBLT
:
1156 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1157 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
1158 mr
->rdParm
[11], /*Height*/
1159 mr
->rdParm
[13], /*Planes*/
1160 mr
->rdParm
[14], /*BitsPixel*/
1161 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
1162 SelectObject(hdcSrc
,hbitmap
);
1163 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1164 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1165 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1166 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1167 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1174 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1175 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
1176 mr
->rdParm
[8]/*Height*/,
1177 mr
->rdParm
[10]/*Planes*/,
1178 mr
->rdParm
[11]/*BitsPixel*/,
1179 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
1180 SelectObject(hdcSrc
,hbitmap
);
1181 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
1182 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
1183 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
1184 MAKELONG(0,mr
->rdParm
[0]));
1189 case META_CREATEREGION
:
1191 HRGN hrgn
= CreateRectRgn(0,0,0,0);
1193 MF_Play_MetaCreateRegion(mr
, hrgn
);
1194 MF_AddHandle(ht
, handles
, hrgn
);
1198 case META_FILLREGION
:
1199 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
1200 *(ht
->objectHandle
+ mr
->rdParm
[0]));
1203 case META_FRAMEREGION
:
1204 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
1205 *(ht
->objectHandle
+ mr
->rdParm
[2]),
1206 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1209 case META_INVERTREGION
:
1210 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1213 case META_PAINTREGION
:
1214 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1217 case META_SELECTCLIPREGION
:
1218 SelectClipRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1221 case META_DIBCREATEPATTERNBRUSH
:
1222 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1223 but there's no difference */
1224 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
1227 case META_DIBBITBLT
:
1228 /* In practice I've found that there are two layouts for
1229 META_DIBBITBLT, one (the first here) is the usual one when a src
1230 dc is actually passed to it, the second occurs when the src dc is
1231 passed in as NULL to the creating BitBlt. As the second case has
1232 no dib, a size check will suffice to distinguish.
1234 Caolan.McNamara@ul.ie */
1236 if (mr
->rdSize
> 12) {
1237 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
1238 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize(info
, mr
->rdParm
[0]);
1240 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1241 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1242 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
1243 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1245 else /* equivalent to a PatBlt */
1246 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1247 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1248 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1251 case META_SETTEXTCHAREXTRA
:
1252 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
1255 case META_SETTEXTJUSTIFICATION
:
1256 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1259 case META_EXTFLOODFILL
:
1260 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1261 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
1265 case META_SETDIBTODEV
:
1267 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
1268 char *bits
= (char *)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[0] );
1269 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1270 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1271 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1272 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1277 #define META_UNIMP(x) case x: \
1278 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1280 META_UNIMP(META_DRAWTEXT
)
1281 META_UNIMP(META_ANIMATEPALETTE
)
1282 META_UNIMP(META_SETPALENTRIES
)
1283 META_UNIMP(META_RESIZEPALETTE
)
1284 META_UNIMP(META_RESETDC
)
1285 META_UNIMP(META_STARTDOC
)
1286 META_UNIMP(META_STARTPAGE
)
1287 META_UNIMP(META_ENDPAGE
)
1288 META_UNIMP(META_ABORTDOC
)
1289 META_UNIMP(META_ENDDOC
)
1290 META_UNIMP(META_CREATEBRUSH
)
1291 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1292 META_UNIMP(META_CREATEBITMAP
)
1296 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1302 /******************************************************************
1303 * GetMetaFileBits (GDI.159)
1305 * Trade in a metafile object handle for a handle to the metafile memory.
1309 HGLOBAL16 WINAPI
GetMetaFileBits16(
1310 HMETAFILE16 hmf
/* [in] metafile handle */
1313 TRACE("hMem out: %04x\n", hmf
);
1317 /******************************************************************
1318 * SetMetaFileBits (GDI.160)
1320 * Trade in a metafile memory handle for a handle to a metafile object.
1321 * The memory region should hold a proper metafile, otherwise
1322 * problems will occur when it is used. Validity of the memory is not
1323 * checked. The function is essentially just the identity function.
1325 HMETAFILE16 WINAPI
SetMetaFileBits16(
1327 /* [in] handle to a memory region holding a metafile */
1330 TRACE("hmf out: %04x\n", hMem
);
1335 /******************************************************************
1336 * SetMetaFileBitsBetter (GDI.196)
1338 * Trade in a metafile memory handle for a handle to a metafile object,
1339 * making a cursory check (using IsValidMetaFile()) that the memory
1340 * handle points to a valid metafile.
1343 * Handle to a metafile on success, NULL on failure..
1345 HMETAFILE16 WINAPI
SetMetaFileBitsBetter16( HMETAFILE16 hMeta
)
1347 if( IsValidMetaFile16( hMeta
) )
1348 return (HMETAFILE16
)GlobalReAlloc16( hMeta
, 0,
1349 GMEM_SHARE
| GMEM_NODISCARD
| GMEM_MODIFY
);
1350 return (HMETAFILE16
)0;
1353 /******************************************************************
1354 * SetMetaFileBitsEx (GDI32.@)
1356 * Create a metafile from raw data. No checking of the data is performed.
1357 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1359 HMETAFILE WINAPI
SetMetaFileBitsEx(
1360 UINT size
, /* [in] size of metafile, in bytes */
1361 const BYTE
*lpData
/* [in] pointer to metafile data */
1364 METAHEADER
*mh
= HeapAlloc( GetProcessHeap(), 0, size
);
1366 memcpy(mh
, lpData
, size
);
1367 return MF_Create_HMETAFILE(mh
);
1370 /*****************************************************************
1371 * GetMetaFileBitsEx (GDI32.@)
1373 * Get raw metafile data.
1375 * Copies the data from metafile _hmf_ into the buffer _buf_.
1376 * If _buf_ is zero, returns size of buffer required. Otherwise,
1377 * returns number of bytes copied.
1379 UINT WINAPI
GetMetaFileBitsEx(
1380 HMETAFILE hmf
, /* [in] metafile */
1381 UINT nSize
, /* [in] size of buf */
1382 LPVOID buf
/* [out] buffer to receive raw metafile data */)
1384 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1387 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1388 if (!mh
) return 0; /* FIXME: error code */
1389 if(mh
->mtType
== METAFILE_DISK
)
1390 FIXME("Disk-based metafile?\n");
1391 mfSize
= mh
->mtSize
* 2;
1393 TRACE("returning size %d\n", mfSize
);
1396 if(mfSize
> nSize
) mfSize
= nSize
;
1397 memmove(buf
, mh
, mfSize
);
1401 /******************************************************************
1402 * GetWinMetaFileBits [GDI32.@]
1404 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1405 UINT cbBuffer
, LPBYTE lpbBuffer
,
1406 INT fnMapMode
, HDC hdcRef
)
1414 GetClipBox(hdcRef
, &rc
);
1415 oldMapMode
= SetMapMode(hdcRef
, fnMapMode
);
1417 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1418 fnMapMode
, hdcRef
, wine_dbgstr_rect(&rc
));
1420 hdcmf
= CreateMetaFileA(NULL
);
1421 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1422 hmf
= CloseMetaFile(hdcmf
);
1423 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1424 DeleteMetaFile(hmf
);
1426 SetMapMode(hdcRef
, oldMapMode
);
1431 /******************************************************************
1432 * MF_Play_MetaCreateRegion
1434 * Handles META_CREATEREGION for PlayMetaFileRecord().
1438 * The layout of the record looks something like this:
1443 * 2 Looks like a handle? - not constant
1445 * 4 Total number of bytes
1446 * 5 No. of separate bands = n [see below]
1447 * 6 Largest number of x co-ords in a band
1448 * 7-10 Bounding box x1 y1 x2 y2
1451 * Regions are divided into bands that are uniform in the
1452 * y-direction. Each band consists of pairs of on/off x-coords and is
1454 * m y0 y1 x1 x2 x3 ... xm m
1455 * into successive rdParm[]s.
1457 * This is probably just a dump of the internal RGNOBJ?
1463 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1468 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1470 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1471 band
++, start
= end
+ 1) {
1472 if(*start
/ 2 != (*start
+ 1) / 2) {
1473 WARN("Delimiter not even.\n");
1474 DeleteObject( hrgn2
);
1478 end
= start
+ *start
+ 3;
1479 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1480 WARN("End points outside record.\n");
1481 DeleteObject( hrgn2
);
1485 if(*start
!= *end
) {
1486 WARN("Mismatched delimiters.\n");
1487 DeleteObject( hrgn2
);
1491 y0
= *(INT16
*)(start
+ 1);
1492 y1
= *(INT16
*)(start
+ 2);
1493 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1494 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1495 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1496 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1499 DeleteObject( hrgn2
);
1504 /******************************************************************
1505 * MF_Play_MetaExtTextOut
1507 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1510 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1519 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1521 s1
= mr
->rdParm
[2]; /* String length */
1522 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1523 + sizeof(UINT16
) + (isrect
? sizeof(RECT16
) : 0);
1524 /* rec len without dx array */
1526 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1529 rect
.left
= (SHORT
)mr
->rdParm
[4];
1530 rect
.top
= (SHORT
)mr
->rdParm
[5];
1531 rect
.right
= (SHORT
)mr
->rdParm
[6];
1532 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1533 sot
+= sizeof(RECT16
); /* there is a rectangle, so add offset */
1536 if (mr
->rdSize
== len
/ 2)
1537 dxx
= NULL
; /* determine if array present */
1539 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1541 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1542 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1543 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = (SHORT
)dxx
[i
];
1546 TRACE("%s len: %ld\n", sot
, mr
->rdSize
);
1548 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1549 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1550 dxx
= NULL
; /* should't happen -- but if, we continue with NULL */
1553 (SHORT
)mr
->rdParm
[1], /* X position */
1554 (SHORT
)mr
->rdParm
[0], /* Y position */
1555 mr
->rdParm
[3], /* options */
1556 &rect
, /* rectangle */
1558 s1
, dx
); /* length, dx array */
1561 TRACE("%s len: %ld dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1562 HeapFree( GetProcessHeap(), 0, dx
);