4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * These functions are primarily involved with metafile playback or anything
26 * that touches a HMETAFILE.
27 * For recording of metafiles look in graphics/metafiledrv/
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
32 * Memory-based metafiles are just stored as a continuous block of memory with
33 * a METAHEADER at the head with METARECORDs appended to it. mtType is
34 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
35 * disk-based metafile - even mtType is METAFILE_MEMORY.
36 * 16bit HMETAFILE16s are global handles to this block
37 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
39 * Disk-based metafiles are rather different. HMETAFILE16s point to a
40 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
41 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
42 * more 0, then 2 which may be a time stamp of the file and then the path of
43 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
53 #include "wine/winbase16.h"
54 #include "wine/wingdi16.h"
59 #include "gdi_private.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
79 #define MFHEADERSIZE (sizeof(METAHEADER))
80 #define MFVERSION 0x300
83 /******************************************************************
86 * Add a handle to an external handle table and return the index
88 static int MF_AddHandle(HANDLETABLE
*ht
, UINT htlen
, HGDIOBJ hobj
)
92 for (i
= 0; i
< htlen
; i
++)
94 if (*(ht
->objectHandle
+ i
) == 0)
96 *(ht
->objectHandle
+ i
) = hobj
;
104 /******************************************************************
105 * MF_Create_HMETATFILE
107 * Creates a (32 bit) HMETAFILE object from a METAHEADER
109 * HMETAFILEs are GDI objects.
111 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
114 METAFILEOBJ
*metaObj
= GDI_AllocObject( sizeof(METAFILEOBJ
), METAFILE_MAGIC
,
115 (HGDIOBJ
*)&hmf
, NULL
);
119 GDI_ReleaseObj( hmf
);
124 /******************************************************************
125 * MF_Create_HMETATFILE16
127 * Creates a HMETAFILE16 object from a METAHEADER
129 * HMETAFILE16s are Global memory handles.
131 HMETAFILE16
MF_Create_HMETAFILE16(METAHEADER
*mh
)
134 DWORD size
= mh
->mtSize
* sizeof(WORD
);
136 hmf
= GlobalAlloc16(GMEM_MOVEABLE
, size
);
139 METAHEADER
*mh_dest
= GlobalLock16(hmf
);
140 memcpy(mh_dest
, mh
, size
);
143 HeapFree(GetProcessHeap(), 0, mh
);
147 /******************************************************************
150 * Returns ptr to METAHEADER associated with HMETAFILE
152 static METAHEADER
*MF_GetMetaHeader( HMETAFILE hmf
)
154 METAHEADER
*ret
= NULL
;
155 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
159 GDI_ReleaseObj( hmf
);
164 /******************************************************************
167 * Returns ptr to METAHEADER associated with HMETAFILE16
168 * Should be followed by call to MF_ReleaseMetaHeader16
170 static METAHEADER
*MF_GetMetaHeader16( HMETAFILE16 hmf
)
172 return GlobalLock16(hmf
);
175 /******************************************************************
176 * MF_ReleaseMetaHeader16
178 * Releases METAHEADER associated with HMETAFILE16
180 static BOOL16
MF_ReleaseMetaHeader16( HMETAFILE16 hmf
)
182 return GlobalUnlock16( hmf
);
186 /******************************************************************
189 * Convert an array of POINT16 to an array of POINT.
190 * Result must be freed by caller.
192 static POINT
*convert_points( UINT count
, POINT16
*pt16
)
195 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
198 for (i
= 0; i
< count
; i
++)
200 ret
[i
].x
= pt16
[i
].x
;
201 ret
[i
].y
= pt16
[i
].y
;
208 /******************************************************************
209 * DeleteMetaFile (GDI.127)
211 BOOL16 WINAPI
DeleteMetaFile16( HMETAFILE16 hmf
)
213 return !GlobalFree16( hmf
);
216 /******************************************************************
217 * DeleteMetaFile (GDI32.@)
219 * Delete a memory-based metafile.
222 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
224 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
225 if (!metaObj
) return FALSE
;
226 HeapFree( GetProcessHeap(), 0, metaObj
->mh
);
227 GDI_FreeObject( hmf
, metaObj
);
231 /******************************************************************
234 * Returns a pointer to a memory based METAHEADER read in from file HFILE
237 static METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
240 DWORD BytesRead
, size
;
242 size
= sizeof(METAHEADER
);
243 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
245 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
247 HeapFree( GetProcessHeap(), 0, mh
);
250 if(mh
->mtVersion
!= MFVERSION
|| mh
->mtHeaderSize
!= size
/ 2) {
251 HeapFree( GetProcessHeap(), 0, mh
);
254 size
= mh
->mtSize
* 2;
255 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
257 size
-= sizeof(METAHEADER
);
258 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
261 HeapFree( GetProcessHeap(), 0, mh
);
265 if (mh
->mtType
!= METAFILE_MEMORY
) {
266 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
267 mh
->mtType
= METAFILE_MEMORY
;
272 /******************************************************************
273 * GetMetaFile (GDI.124)
275 HMETAFILE16 WINAPI
GetMetaFile16( LPCSTR lpFilename
)
280 TRACE("%s\n", lpFilename
);
285 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
286 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
289 mh
= MF_ReadMetaFile(hFile
);
292 return MF_Create_HMETAFILE16( mh
);
295 /******************************************************************
296 * GetMetaFileA (GDI32.@)
298 * Read a metafile from a file. Returns handle to a memory-based metafile.
300 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
305 TRACE("%s\n", lpFilename
);
310 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
311 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
314 mh
= MF_ReadMetaFile(hFile
);
317 return MF_Create_HMETAFILE( mh
);
322 /******************************************************************
323 * GetMetaFileW (GDI32.@)
325 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
330 TRACE("%s\n", debugstr_w(lpFilename
));
335 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
336 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
339 mh
= MF_ReadMetaFile(hFile
);
342 return MF_Create_HMETAFILE( mh
);
346 /******************************************************************
347 * MF_LoadDiskBasedMetaFile
349 * Creates a new memory-based metafile from a disk-based one.
351 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
357 if(mh
->mtType
!= METAFILE_DISK
) {
358 ERR("Not a disk based metafile\n");
361 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
363 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
364 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
365 WARN("Can't open file of disk based metafile\n");
368 mh2
= MF_ReadMetaFile(hfile
);
373 /******************************************************************
374 * MF_CreateMetaHeaderDisk
376 * Take a memory based METAHEADER and change it to a disk based METAHEADER
377 * assosiated with filename. Note: Trashes contents of old one.
379 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCVOID filename
, BOOL uni
)
384 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
385 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
386 mh
->mtType
= METAFILE_DISK
;
387 size
= HeapSize( GetProcessHeap(), 0, mh
);
388 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
391 WideCharToMultiByte(CP_ACP
, 0, filename
, -1,
392 mhd
->filename
, sizeof mhd
->filename
, NULL
, NULL
);
394 lstrcpynA( mhd
->filename
, filename
, sizeof mhd
->filename
);
398 /******************************************************************
399 * CopyMetaFile (GDI.151)
401 HMETAFILE16 WINAPI
CopyMetaFile16( HMETAFILE16 hSrcMetaFile
, LPCSTR lpFilename
)
403 METAHEADER
*mh
= MF_GetMetaHeader16( hSrcMetaFile
);
404 METAHEADER
*mh2
= NULL
;
407 TRACE("(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
411 if(mh
->mtType
== METAFILE_DISK
)
412 mh2
= MF_LoadDiskBasedMetaFile(mh
);
414 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
415 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
417 MF_ReleaseMetaHeader16( hSrcMetaFile
);
419 if(lpFilename
) { /* disk based metafile */
421 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
422 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
423 HeapFree( GetProcessHeap(), 0, mh2
);
426 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, &w
, NULL
);
428 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
, FALSE
);
431 return MF_Create_HMETAFILE16( mh2
);
435 /******************************************************************
436 * CopyMetaFileW (GDI32.@)
438 * Copies the metafile corresponding to hSrcMetaFile to either
439 * a disk file, if a filename is given, or to a new memory based
440 * metafile, if lpFileName is NULL.
443 * hSrcMetaFile [I] handle of metafile to copy
444 * lpFilename [I] filename if copying to a file
447 * Handle to metafile copy on success, NULL on failure.
450 * Copying to disk returns NULL even if successful.
452 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
, LPCWSTR lpFilename
)
454 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
455 METAHEADER
*mh2
= NULL
;
458 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
462 if(mh
->mtType
== METAFILE_DISK
)
463 mh2
= MF_LoadDiskBasedMetaFile(mh
);
465 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
466 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
469 if(lpFilename
) { /* disk based metafile */
471 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
472 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
473 HeapFree( GetProcessHeap(), 0, mh2
);
476 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, &w
, NULL
);
478 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
, TRUE
);
481 return MF_Create_HMETAFILE( mh2
);
485 /******************************************************************
486 * CopyMetaFileA (GDI32.@)
488 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
, LPCSTR lpFilename
)
490 UNICODE_STRING lpFilenameW
;
493 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
494 else lpFilenameW
.Buffer
= NULL
;
496 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
497 if (lpFilenameW
.Buffer
)
498 RtlFreeUnicodeString(&lpFilenameW
);
503 /******************************************************************
504 * IsValidMetaFile (GDI.410)
506 * Attempts to check if a given metafile is correctly formatted.
507 * Currently, the only things verified are several properties of the
511 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
514 * This is not exactly what windows does, see _Undocumented_Windows_
517 BOOL16 WINAPI
IsValidMetaFile16(HMETAFILE16 hmf
)
520 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
522 if (mh
->mtType
== METAFILE_MEMORY
|| mh
->mtType
== METAFILE_DISK
)
523 if (mh
->mtHeaderSize
== MFHEADERSIZE
/sizeof(INT16
))
524 if (mh
->mtVersion
== MFVERSION
)
526 MF_ReleaseMetaHeader16(hmf
);
528 TRACE("IsValidMetaFile %x => %d\n",hmf
,res
);
533 /*******************************************************************
536 * Helper for PlayMetaFile
538 static BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
543 unsigned int offset
= 0;
550 if (!mh
) return FALSE
;
551 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
552 mh
= MF_LoadDiskBasedMetaFile(mh
);
553 if(!mh
) return FALSE
;
557 /* save the current pen, brush and font */
558 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
559 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
560 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
562 /* create the handle table */
563 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
564 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
565 if(!ht
) return FALSE
;
567 /* loop through metafile playing records */
568 offset
= mh
->mtHeaderSize
* 2;
569 while (offset
< mh
->mtSize
* 2)
571 mr
= (METARECORD
*)((char *)mh
+ offset
);
572 TRACE("offset=%04x,size=%08lx\n",
576 "Entry got size 0 at offset %d, total mf length is %ld\n",
577 offset
,mh
->mtSize
*2);
578 break; /* would loop endlessly otherwise */
580 offset
+= mr
->rdSize
* 2;
581 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
584 SelectObject(hdc
, hBrush
);
585 SelectObject(hdc
, hPen
);
586 SelectObject(hdc
, hFont
);
588 /* free objects in handle table */
589 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
590 if(*(ht
->objectHandle
+ i
) != 0)
591 DeleteObject(*(ht
->objectHandle
+ i
));
593 /* free handle table */
594 HeapFree( GetProcessHeap(), 0, ht
);
596 HeapFree( GetProcessHeap(), 0, mh
);
600 /******************************************************************
601 * PlayMetaFile (GDI.123)
604 BOOL16 WINAPI
PlayMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
)
607 METAHEADER
*mh
= MF_GetMetaHeader16( hmf
);
608 ret
= MF_PlayMetaFile( HDC_32(hdc
), mh
);
609 MF_ReleaseMetaHeader16( hmf
);
613 /******************************************************************
614 * PlayMetaFile (GDI32.@)
616 * Renders the metafile specified by hmf in the DC specified by
617 * hdc. Returns FALSE on failure, TRUE on success.
620 * hdc [I] handle of DC to render in
621 * hmf [I] handle of metafile to render
623 BOOL WINAPI
PlayMetaFile( HDC hdc
, HMETAFILE hmf
)
625 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
626 return MF_PlayMetaFile( hdc
, mh
);
630 /******************************************************************
631 * EnumMetaFile (GDI.175)
634 BOOL16 WINAPI
EnumMetaFile16( HDC16 hdc16
, HMETAFILE16 hmf
,
635 MFENUMPROC16 lpEnumFunc
, LPARAM lpData
)
637 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
640 HDC hdc
= HDC_32(hdc16
);
643 unsigned int offset
= 0;
649 BOOL16 result
= TRUE
, loaded
= FALSE
;
651 TRACE("(%p, %04x, %p, %08lx)\n", hdc
, hmf
, lpEnumFunc
, lpData
);
653 if(!mh
) return FALSE
;
654 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
655 mh
= MF_LoadDiskBasedMetaFile(mh
);
656 if(!mh
) return FALSE
;
660 /* save the current pen, brush and font */
661 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
662 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
663 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
665 /* create the handle table */
667 hHT
= GlobalAlloc16(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
668 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
669 spht
= K32WOWGlobalLock16(hHT
);
672 offset
= mh
->mtHeaderSize
* 2;
674 /* loop through metafile records */
677 args
[6] = SELECTOROF(spht
);
678 args
[5] = OFFSETOF(spht
);
679 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
680 args
[3] = LOWORD(offset
);
681 args
[2] = mh
->mtNoObjects
;
682 args
[1] = HIWORD(lpData
);
683 args
[0] = LOWORD(lpData
);
685 while (offset
< (mh
->mtSize
* 2))
689 mr
= (METARECORD
*)((char *)mh
+ offset
);
691 WOWCallback16Ex( (DWORD
)lpEnumFunc
, WCB16_PASCAL
, sizeof(args
), args
, &ret
);
698 offset
+= (mr
->rdSize
* 2);
699 args
[4] = seg
+ (HIWORD(offset
) << __AHSHIFT
);
700 args
[3] = LOWORD(offset
);
703 SelectObject(hdc
, hBrush
);
704 SelectObject(hdc
, hPen
);
705 SelectObject(hdc
, hFont
);
707 ht
= (HANDLETABLE16
*)GlobalLock16(hHT
);
709 /* free objects in handle table */
710 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
711 if(*(ht
->objectHandle
+ i
) != 0)
712 DeleteObject( (HGDIOBJ
)(ULONG_PTR
)(*(ht
->objectHandle
+ i
) ));
714 /* free handle table */
717 HeapFree( GetProcessHeap(), 0, mh
);
718 MF_ReleaseMetaHeader16(hmf
);
722 /******************************************************************
723 * EnumMetaFile (GDI32.@)
725 * Loop through the metafile records in hmf, calling the user-specified
726 * function for each one, stopping when the user's function returns FALSE
727 * (which is considered to be failure)
728 * or when no records are left (which is considered to be success).
731 * TRUE on success, FALSE on failure.
733 BOOL WINAPI
EnumMetaFile(HDC hdc
, HMETAFILE hmf
, MFENUMPROC lpEnumFunc
, LPARAM lpData
)
735 METAHEADER
*mhTemp
= NULL
, *mh
= MF_GetMetaHeader(hmf
);
740 unsigned int offset
= 0;
745 TRACE("(%p,%p,%p,%p)\n", hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
747 if(mh
->mtType
== METAFILE_DISK
)
749 /* Create a memory-based copy */
750 if (!(mhTemp
= MF_LoadDiskBasedMetaFile(mh
))) return FALSE
;
754 /* save the current pen, brush and font */
755 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
756 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
757 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
759 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
760 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
762 /* loop through metafile records */
763 offset
= mh
->mtHeaderSize
* 2;
765 while (offset
< (mh
->mtSize
* 2))
767 mr
= (METARECORD
*)((char *)mh
+ offset
);
768 if(mr
->rdFunction
== META_EOF
) {
769 TRACE("Got META_EOF so stopping\n");
772 TRACE("Calling EnumFunc with record type %x\n",
774 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
780 offset
+= (mr
->rdSize
* 2);
783 /* restore pen, brush and font */
784 SelectObject(hdc
, hBrush
);
785 SelectObject(hdc
, hPen
);
786 SelectObject(hdc
, hFont
);
788 /* free objects in handle table */
789 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
790 if(*(ht
->objectHandle
+ i
) != 0)
791 DeleteObject(*(ht
->objectHandle
+ i
));
793 /* free handle table */
794 HeapFree( GetProcessHeap(), 0, ht
);
795 /* free a copy of metafile */
796 HeapFree( GetProcessHeap(), 0, mhTemp
);
800 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
801 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
802 /******************************************************************
803 * PlayMetaFileRecord (GDI32.@)
805 * Render a single metafile record specified by *mr in the DC hdc, while
806 * using the handle table *ht, of length handles,
807 * to store metafile objects.
810 * The following metafile records are unimplemented:
812 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
813 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
814 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
816 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
820 BITMAPINFOHEADER
*infohdr
;
822 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
824 switch (mr
->rdFunction
)
829 case META_DELETEOBJECT
:
830 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
831 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
834 case META_SETBKCOLOR
:
835 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
839 SetBkMode(hdc
, mr
->rdParm
[0]);
842 case META_SETMAPMODE
:
843 SetMapMode(hdc
, mr
->rdParm
[0]);
847 SetROP2(hdc
, mr
->rdParm
[0]);
851 SetRelAbs(hdc
, mr
->rdParm
[0]);
854 case META_SETPOLYFILLMODE
:
855 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
858 case META_SETSTRETCHBLTMODE
:
859 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
862 case META_SETTEXTCOLOR
:
863 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
866 case META_SETWINDOWORG
:
867 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
870 case META_SETWINDOWEXT
:
871 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
874 case META_SETVIEWPORTORG
:
875 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
878 case META_SETVIEWPORTEXT
:
879 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
882 case META_OFFSETWINDOWORG
:
883 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
886 case META_SCALEWINDOWEXT
:
887 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
888 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
891 case META_OFFSETVIEWPORTORG
:
892 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
895 case META_SCALEVIEWPORTEXT
:
896 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
897 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
901 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
905 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
908 case META_EXCLUDECLIPRECT
:
909 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
910 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
913 case META_INTERSECTCLIPRECT
:
914 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
915 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
919 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
920 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
921 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
922 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
926 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
927 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
931 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
932 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
936 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
937 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
938 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
939 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
943 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
944 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
948 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
949 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
950 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
954 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
955 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
956 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
964 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
965 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
968 case META_OFFSETCLIPRGN
:
969 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
974 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
975 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
976 (char *)(mr
->rdParm
+ 1), s1
);
980 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
982 Polygon(hdc
, pt
, mr
->rdParm
[0]);
983 HeapFree( GetProcessHeap(), 0, pt
);
987 case META_POLYPOLYGON
:
990 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
992 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
993 pt
= convert_points( total
, (LPPOINT16
)(counts
+ mr
->rdParm
[0]) );
996 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
999 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
1000 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
1001 HeapFree( GetProcessHeap(), 0, cnt32
);
1004 HeapFree( GetProcessHeap(), 0, pt
);
1009 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
1011 Polyline( hdc
, pt
, mr
->rdParm
[0] );
1012 HeapFree( GetProcessHeap(), 0, pt
);
1016 case META_RESTOREDC
:
1017 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
1020 case META_SELECTOBJECT
:
1021 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1025 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1026 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1027 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1028 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1031 case META_CREATEPATTERNBRUSH
:
1032 switch (mr
->rdParm
[0])
1035 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1036 MF_AddHandle(ht
, handles
,
1037 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
1040 infohdr
->biBitCount
,
1041 (LPSTR
)(mr
->rdParm
+
1042 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
1046 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
1047 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
1051 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1057 case META_CREATEPENINDIRECT
:
1060 pen
.lopnStyle
= mr
->rdParm
[0];
1061 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
1062 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
1063 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
1064 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
1068 case META_CREATEFONTINDIRECT
:
1071 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
1072 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
1073 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
1074 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
1075 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
1076 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
1077 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
1078 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
1079 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
1080 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
1081 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
1082 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
1083 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
1084 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
1085 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
1089 case META_CREATEBRUSHINDIRECT
:
1092 brush
.lbStyle
= mr
->rdParm
[0];
1093 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
1094 brush
.lbHatch
= mr
->rdParm
[3];
1095 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
1099 case META_CREATEPALETTE
:
1100 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
1103 case META_SETTEXTALIGN
:
1104 SetTextAlign(hdc
, mr
->rdParm
[0]);
1107 case META_SELECTPALETTE
:
1108 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
1111 case META_SETMAPPERFLAGS
:
1112 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1115 case META_REALIZEPALETTE
:
1116 GDIRealizePalette(hdc
);
1120 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
1123 case META_EXTTEXTOUT
:
1124 MF_Play_MetaExtTextOut( hdc
, mr
);
1127 case META_STRETCHDIB
:
1129 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
1130 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1131 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1132 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1133 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
1134 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1138 case META_DIBSTRETCHBLT
:
1140 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
1141 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1142 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1143 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1144 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
1145 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1149 case META_STRETCHBLT
:
1151 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1152 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
1153 mr
->rdParm
[11], /*Height*/
1154 mr
->rdParm
[13], /*Planes*/
1155 mr
->rdParm
[14], /*BitsPixel*/
1156 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
1157 SelectObject(hdcSrc
,hbitmap
);
1158 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
1159 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
1160 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
1161 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
1162 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1169 HDC hdcSrc
= CreateCompatibleDC(hdc
);
1170 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
1171 mr
->rdParm
[8]/*Height*/,
1172 mr
->rdParm
[10]/*Planes*/,
1173 mr
->rdParm
[11]/*BitsPixel*/,
1174 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
1175 SelectObject(hdcSrc
,hbitmap
);
1176 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
1177 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
1178 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
1179 MAKELONG(0,mr
->rdParm
[0]));
1184 case META_CREATEREGION
:
1186 HRGN hrgn
= CreateRectRgn(0,0,0,0);
1188 MF_Play_MetaCreateRegion(mr
, hrgn
);
1189 MF_AddHandle(ht
, handles
, hrgn
);
1193 case META_FILLREGION
:
1194 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
1195 *(ht
->objectHandle
+ mr
->rdParm
[0]));
1198 case META_FRAMEREGION
:
1199 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
1200 *(ht
->objectHandle
+ mr
->rdParm
[2]),
1201 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1204 case META_INVERTREGION
:
1205 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1208 case META_PAINTREGION
:
1209 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
1212 case META_SELECTCLIPREGION
:
1216 if (mr
->rdParm
[0]) hrgn
= *(ht
->objectHandle
+ mr
->rdParm
[0]);
1217 SelectClipRgn(hdc
, hrgn
);
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.
1308 * hmf [I] metafile handle
1311 HGLOBAL16 WINAPI
GetMetaFileBits16( HMETAFILE16 hmf
)
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.
1326 * hMem [I] handle to a memory region holding a metafile
1328 HMETAFILE16 WINAPI
SetMetaFileBits16( HGLOBAL16 hMem
)
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.
1360 * size [I] size of metafile, in bytes
1361 * lpData [I] pointer to metafile data
1363 HMETAFILE WINAPI
SetMetaFileBitsEx( UINT size
, const BYTE
*lpData
)
1365 METAHEADER
*mh
= HeapAlloc( GetProcessHeap(), 0, size
);
1367 memcpy(mh
, lpData
, size
);
1368 return MF_Create_HMETAFILE(mh
);
1371 /*****************************************************************
1372 * GetMetaFileBitsEx (GDI32.@)
1374 * Get raw metafile data.
1376 * Copies the data from metafile _hmf_ into the buffer _buf_.
1377 * If _buf_ is zero, returns size of buffer required. Otherwise,
1378 * returns number of bytes copied.
1382 * nSize [I] size of buf
1383 * buf [O] buffer to receive raw metafile data
1385 UINT WINAPI
GetMetaFileBitsEx( HMETAFILE hmf
, UINT nSize
, LPVOID buf
)
1387 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1390 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1391 if (!mh
) return 0; /* FIXME: error code */
1392 if(mh
->mtType
== METAFILE_DISK
)
1393 FIXME("Disk-based metafile?\n");
1394 mfSize
= mh
->mtSize
* 2;
1396 TRACE("returning size %d\n", mfSize
);
1399 if(mfSize
> nSize
) mfSize
= nSize
;
1400 memmove(buf
, mh
, mfSize
);
1404 /******************************************************************
1405 * GetWinMetaFileBits [GDI32.@]
1407 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1408 UINT cbBuffer
, LPBYTE lpbBuffer
,
1409 INT fnMapMode
, HDC hdcRef
)
1417 GetClipBox(hdcRef
, &rc
);
1418 oldMapMode
= SetMapMode(hdcRef
, fnMapMode
);
1420 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1421 fnMapMode
, hdcRef
, wine_dbgstr_rect(&rc
));
1423 hdcmf
= CreateMetaFileA(NULL
);
1424 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1425 hmf
= CloseMetaFile(hdcmf
);
1426 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1427 DeleteMetaFile(hmf
);
1429 SetMapMode(hdcRef
, oldMapMode
);
1434 /******************************************************************
1435 * MF_Play_MetaCreateRegion
1437 * Handles META_CREATEREGION for PlayMetaFileRecord().
1439 * The layout of the record looks something like this:
1444 * 2 Looks like a handle? - not constant
1446 * 4 Total number of bytes
1447 * 5 No. of separate bands = n [see below]
1448 * 6 Largest number of x co-ords in a band
1449 * 7-10 Bounding box x1 y1 x2 y2
1452 * Regions are divided into bands that are uniform in the
1453 * y-direction. Each band consists of pairs of on/off x-coords and is
1455 * m y0 y1 x1 x2 x3 ... xm m
1456 * into successive rdParm[]s.
1458 * This is probably just a dump of the internal RGNOBJ?
1464 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1469 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1471 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1472 band
++, start
= end
+ 1) {
1473 if(*start
/ 2 != (*start
+ 1) / 2) {
1474 WARN("Delimiter not even.\n");
1475 DeleteObject( hrgn2
);
1479 end
= start
+ *start
+ 3;
1480 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1481 WARN("End points outside record.\n");
1482 DeleteObject( hrgn2
);
1486 if(*start
!= *end
) {
1487 WARN("Mismatched delimiters.\n");
1488 DeleteObject( hrgn2
);
1492 y0
= *(INT16
*)(start
+ 1);
1493 y1
= *(INT16
*)(start
+ 2);
1494 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1495 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1496 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1497 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1500 DeleteObject( hrgn2
);
1505 /******************************************************************
1506 * MF_Play_MetaExtTextOut
1508 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1511 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1520 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1522 s1
= mr
->rdParm
[2]; /* String length */
1523 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1524 + sizeof(UINT16
) + (isrect
? sizeof(RECT16
) : 0);
1525 /* rec len without dx array */
1527 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1530 rect
.left
= (SHORT
)mr
->rdParm
[4];
1531 rect
.top
= (SHORT
)mr
->rdParm
[5];
1532 rect
.right
= (SHORT
)mr
->rdParm
[6];
1533 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1534 sot
+= sizeof(RECT16
); /* there is a rectangle, so add offset */
1537 if (mr
->rdSize
== len
/ 2)
1538 dxx
= NULL
; /* determine if array present */
1540 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1542 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1543 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1544 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = (SHORT
)dxx
[i
];
1547 TRACE("%s len: %ld\n", sot
, mr
->rdSize
);
1548 WARN("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
);