4 * Copyright David W. Metcalfe, 1994
5 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
10 * These functions are primarily involved with metafile playback or anything
11 * that touches a HMETAFILE.
12 * For recording of metafiles look in graphics/metafiledrv/
14 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
15 * global memory handles so these cannot be interchanged.
17 * Memory-based metafiles are just stored as a continuous block of memory with
18 * a METAHEADER at the head with METARECORDs appended to it. mtType is
19 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
20 * disk-based metafile - even mtType is METAFILE_MEMORY.
21 * 16bit HMETAFILE16s are global handles to this block
22 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
24 * Disk-based metafiles are rather different. HMETAFILE16s point to a
25 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
26 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
27 * more 0, then 2 which may be a time stamp of the file and then the path of
28 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
36 #include "wine/winbase16.h"
44 /******************************************************************
47 * Add a handle to an external handle table and return the index
49 static int MF_AddHandle(HANDLETABLE16
*ht
, WORD htlen
, HGDIOBJ16 hobj
)
53 for (i
= 0; i
< htlen
; i
++)
55 if (*(ht
->objectHandle
+ i
) == 0)
57 *(ht
->objectHandle
+ i
) = hobj
;
65 /******************************************************************
66 * MF_Create_HMETATFILE
68 * Creates a (32 bit) HMETAFILE object from a METAHEADER
70 * HMETAFILEs are GDI objects.
72 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
74 HMETAFILE hmf
= GDI_AllocObject( sizeof(METAFILEOBJ
), METAFILE_MAGIC
);
75 METAFILEOBJ
*metaObj
= (METAFILEOBJ
*)GDI_HEAP_LOCK( hmf
);
77 GDI_HEAP_UNLOCK( hmf
);
81 /******************************************************************
82 * MF_Create_HMETATFILE16
84 * Creates a HMETAFILE16 object from a METAHEADER
86 * HMETAFILE16s are Global memory handles.
88 HMETAFILE16
MF_Create_HMETAFILE16(METAHEADER
*mh
)
93 if(mh
->mtType
== METAFILE_MEMORY
)
94 size
= mh
->mtSize
* sizeof(WORD
);
96 size
= sizeof(METAHEADER
) + sizeof(METAHEADERDISK
);
98 hmf
= GLOBAL_CreateBlock( GMEM_MOVEABLE
, mh
, mh
->mtSize
* sizeof(WORD
),
99 GetCurrentPDB16(), FALSE
, FALSE
, FALSE
, NULL
);
103 /******************************************************************
106 * Returns ptr to METAHEADER associated with HMETAFILE
107 * Should be followed by call to MF_ReleaseMetaHeader
109 static METAHEADER
*MF_GetMetaHeader( HMETAFILE hmf
)
111 METAFILEOBJ
*metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
115 /******************************************************************
118 * Returns ptr to METAHEADER associated with HMETAFILE16
119 * Should be followed by call to MF_ReleaseMetaHeader16
121 static METAHEADER
*MF_GetMetaHeader16( HMETAFILE16 hmf
)
123 return GlobalLock16(hmf
);
126 /******************************************************************
127 * MF_ReleaseMetaHeader
129 * Releases METAHEADER associated with HMETAFILE
131 static BOOL
MF_ReleaseMetaHeader( HMETAFILE hmf
)
133 return GDI_HEAP_UNLOCK( hmf
);
136 /******************************************************************
137 * MF_ReleaseMetaHeader16
139 * Releases METAHEADER associated with HMETAFILE16
141 static BOOL16
MF_ReleaseMetaHeader16( HMETAFILE16 hmf
)
143 return GlobalUnlock16( hmf
);
147 /******************************************************************
148 * DeleteMetaFile16 (GDI.127)
150 BOOL16 WINAPI
DeleteMetaFile16( HMETAFILE16 hmf
)
152 return !GlobalFree16( hmf
);
155 /******************************************************************
156 * DeleteMetaFile (GDI32.69)
158 * Delete a memory-based metafile.
161 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
163 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
165 if(!mh
) return FALSE
;
166 HeapFree( SystemHeap
, 0, mh
);
167 GDI_FreeObject( hmf
);
171 /******************************************************************
174 * Returns a pointer to a memory based METAHEADER read in from file HFILE
177 static METAHEADER
*MF_ReadMetaFile(HFILE hfile
)
180 DWORD BytesRead
, size
;
182 size
= sizeof(METAHEADER
);
183 mh
= HeapAlloc( SystemHeap
, 0, size
);
185 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
187 HeapFree( SystemHeap
, 0, mh
);
190 size
= mh
->mtSize
* 2;
191 mh
= HeapReAlloc( SystemHeap
, 0, mh
, size
);
193 size
-= sizeof(METAHEADER
);
194 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
197 HeapFree( SystemHeap
, 0, mh
);
201 if (mh
->mtType
!= METAFILE_MEMORY
) {
202 WARN(metafile
, "Disk metafile had mtType = %04x\n", mh
->mtType
);
203 mh
->mtType
= METAFILE_MEMORY
;
208 /******************************************************************
209 * GetMetaFile16 (GDI.124)
211 HMETAFILE16 WINAPI
GetMetaFile16( LPCSTR lpFilename
)
216 TRACE(metafile
,"%s\n", lpFilename
);
221 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
222 0, -1)) == HFILE_ERROR
)
225 mh
= MF_ReadMetaFile(hFile
);
228 return MF_Create_HMETAFILE16( mh
);
231 /******************************************************************
232 * GetMetaFileA (GDI32.197)
234 * Read a metafile from a file. Returns handle to a memory-based metafile.
236 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
241 TRACE(metafile
,"%s\n", lpFilename
);
246 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
247 0, -1)) == HFILE_ERROR
)
250 mh
= MF_ReadMetaFile(hFile
);
253 return MF_Create_HMETAFILE( mh
);
258 /******************************************************************
259 * GetMetaFileW (GDI32.199)
261 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
266 TRACE(metafile
,"%s\n", debugstr_w(lpFilename
));
271 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
,
272 0, -1)) == HFILE_ERROR
)
275 mh
= MF_ReadMetaFile(hFile
);
278 return MF_Create_HMETAFILE( mh
);
282 /******************************************************************
283 * MF_LoadDiskBasedMetaFile
285 * Creates a new memory-based metafile from a disk-based one.
287 static METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
293 if(mh
->mtType
!= METAFILE_DISK
) {
294 ERR(metafile
, "Not a disk based metafile\n");
297 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
299 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, 0, NULL
,
300 OPEN_EXISTING
, 0, -1)) == HFILE_ERROR
) {
301 WARN(metafile
, "Can't open file of disk based metafile\n");
304 mh2
= MF_ReadMetaFile(hfile
);
309 /******************************************************************
310 * MF_CreateMetaHeaderDisk
312 * Take a memory based METAHEADER and change it to a disk based METAHEADER
313 * assosiated with filename. Note: Trashes contents of old one.
315 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCSTR filename
)
320 mh
= HeapReAlloc( SystemHeap
, 0, mh
,
321 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
322 mh
->mtType
= METAFILE_DISK
;
323 size
= HeapSize( SystemHeap
, 0, mh
);
324 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
325 strcpy(mhd
->filename
, filename
);
329 /******************************************************************
330 * CopyMetaFile16 (GDI.151)
332 HMETAFILE16 WINAPI
CopyMetaFile16( HMETAFILE16 hSrcMetaFile
, LPCSTR lpFilename
)
334 METAHEADER
*mh
= MF_GetMetaHeader16( hSrcMetaFile
);
335 METAHEADER
*mh2
= NULL
;
338 TRACE(metafile
,"(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
342 if(mh
->mtType
== METAFILE_DISK
)
343 mh2
= MF_LoadDiskBasedMetaFile(mh
);
345 mh2
= HeapAlloc( SystemHeap
, 0, mh
->mtSize
* 2 );
346 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
348 MF_ReleaseMetaHeader16( hSrcMetaFile
);
350 if(lpFilename
) { /* disk based metafile */
351 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
352 CREATE_ALWAYS
, 0, -1)) == HFILE_ERROR
) {
353 HeapFree( SystemHeap
, 0, mh2
);
356 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
358 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
);
361 return MF_Create_HMETAFILE16( mh2
);
365 /******************************************************************
366 * CopyMetaFileA (GDI32.23)
368 * Copies the metafile corresponding to hSrcMetaFile to either
369 * a disk file, if a filename is given, or to a new memory based
370 * metafile, if lpFileName is NULL.
374 * Handle to metafile copy on success, NULL on failure.
378 * Copying to disk returns NULL even if successful.
380 HMETAFILE WINAPI
CopyMetaFileA(
381 HMETAFILE hSrcMetaFile
, /* handle of metafile to copy */
382 LPCSTR lpFilename
/* filename if copying to a file */
384 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
385 METAHEADER
*mh2
= NULL
;
388 TRACE(metafile
,"(%08x,%s)\n", hSrcMetaFile
, lpFilename
);
392 if(mh
->mtType
== METAFILE_DISK
)
393 mh2
= MF_LoadDiskBasedMetaFile(mh
);
395 mh2
= HeapAlloc( SystemHeap
, 0, mh
->mtSize
* 2 );
396 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
398 MF_ReleaseMetaHeader( hSrcMetaFile
);
400 if(lpFilename
) { /* disk based metafile */
401 if((hFile
= CreateFileA(lpFilename
, GENERIC_WRITE
, 0, NULL
,
402 CREATE_ALWAYS
, 0, -1)) == HFILE_ERROR
) {
403 HeapFree( SystemHeap
, 0, mh2
);
406 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, NULL
, NULL
);
408 mh2
= MF_CreateMetaHeaderDisk(mh2
, lpFilename
);
411 return MF_Create_HMETAFILE( mh2
);
415 /******************************************************************
416 * CopyMetaFileW (GDI32.24)
418 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
,
421 LPSTR p
= HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename
);
422 HMETAFILE ret
= CopyMetaFileA( hSrcMetaFile
, p
);
423 HeapFree( GetProcessHeap(), 0, p
);
428 /******************************************************************
429 * IsValidMetaFile (GDI.410)
431 * Attempts to check if a given metafile is correctly formatted.
432 * Currently, the only things verified are several properties of the
436 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
439 * This is not exactly what windows does, see _Undocumented_Windows_
442 BOOL16 WINAPI
IsValidMetaFile16(HMETAFILE16 hmf
)
445 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
447 if (mh
->mtType
== METAFILE_MEMORY
|| mh
->mtType
== METAFILE_DISK
)
448 if (mh
->mtHeaderSize
== MFHEADERSIZE
/sizeof(INT16
))
449 if (mh
->mtVersion
== MFVERSION
)
451 MF_ReleaseMetaHeader16(hmf
);
453 TRACE(metafile
,"IsValidMetaFile %x => %d\n",hmf
,res
);
458 /*******************************************************************
461 * Helper for PlayMetaFile
463 static BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
476 if (!mh
) return FALSE
;
477 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memoery-based copy */
478 mh
= MF_LoadDiskBasedMetaFile(mh
);
479 if(!mh
) return FALSE
;
483 /* save the current pen, brush and font */
484 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
486 hBrush
= dc
->w
.hBrush
;
488 GDI_HEAP_UNLOCK(hdc
);
489 /* create the handle table */
490 ht
= HeapAlloc( SystemHeap
, HEAP_ZERO_MEMORY
,
491 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
492 if(!ht
) return FALSE
;
494 /* loop through metafile playing records */
495 offset
= mh
->mtHeaderSize
* 2;
496 while (offset
< mh
->mtSize
* 2)
498 mr
= (METARECORD
*)((char *)mh
+ offset
);
499 TRACE(metafile
,"offset=%04x,size=%08lx\n",
503 "Entry got size 0 at offset %d, total mf length is %ld\n",
504 offset
,mh
->mtSize
*2);
505 break; /* would loop endlessly otherwise */
507 offset
+= mr
->rdSize
* 2;
508 PlayMetaFileRecord16( hdc
, ht
, mr
, mh
->mtNoObjects
);
511 SelectObject(hdc
, hBrush
);
512 SelectObject(hdc
, hPen
);
513 SelectObject(hdc
, hFont
);
515 /* free objects in handle table */
516 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
517 if(*(ht
->objectHandle
+ i
) != 0)
518 DeleteObject(*(ht
->objectHandle
+ i
));
520 /* free handle table */
521 HeapFree( SystemHeap
, 0, ht
);
523 HeapFree( SystemHeap
, 0, mh
);
527 /******************************************************************
528 * PlayMetaFile16 (GDI.123)
531 BOOL16 WINAPI
PlayMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
)
534 METAHEADER
*mh
= MF_GetMetaHeader16( hmf
);
535 ret
= MF_PlayMetaFile( hdc
, mh
);
536 MF_ReleaseMetaHeader16( hmf
);
540 /******************************************************************
541 * PlayMetaFile (GDI32.265)
543 * Renders the metafile specified by hmf in the DC specified by
544 * hdc. Returns FALSE on failure, TRUE on success.
546 BOOL WINAPI
PlayMetaFile(
547 HDC hdc
, /* handle of DC to render in */
548 HMETAFILE hmf
/* handle of metafile to render */
552 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
553 ret
= MF_PlayMetaFile( hdc
, mh
);
554 MF_ReleaseMetaHeader( hmf
);
559 /******************************************************************
560 * EnumMetaFile16 (GDI.175)
563 BOOL16 WINAPI
EnumMetaFile16( HDC16 hdc
, HMETAFILE16 hmf
,
564 MFENUMPROC16 lpEnumFunc
, LPARAM lpData
)
566 METAHEADER
*mh
= MF_GetMetaHeader16(hmf
);
577 BOOL16 result
= TRUE
, loaded
= FALSE
;
579 TRACE(metafile
,"(%04x, %04x, %08lx, %08lx)\n",
580 hdc
, hmf
, (DWORD
)lpEnumFunc
, lpData
);
583 if(!mh
) return FALSE
;
584 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memoery-based copy */
585 mh
= MF_LoadDiskBasedMetaFile(mh
);
586 if(!mh
) return FALSE
;
590 if (!(dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
))) return 0;
592 hBrush
= dc
->w
.hBrush
;
594 GDI_HEAP_UNLOCK(hdc
);
596 /* create the handle table */
598 hHT
= GlobalAlloc16(GMEM_MOVEABLE
| GMEM_ZEROINIT
,
599 sizeof(HANDLETABLE16
) * mh
->mtNoObjects
);
600 spht
= WIN16_GlobalLock16(hHT
);
602 seg
= GlobalHandleToSel16(hmf
);
603 offset
= mh
->mtHeaderSize
* 2;
605 /* loop through metafile records */
607 while (offset
< (mh
->mtSize
* 2))
609 mr
= (METARECORD
*)((char *)mh
+ offset
);
610 if (!lpEnumFunc( hdc
, (HANDLETABLE16
*)spht
,
611 (METARECORD
*) PTR_SEG_OFF_TO_HUGEPTR(seg
, offset
),
612 mh
->mtNoObjects
, (LONG
)lpData
))
619 offset
+= (mr
->rdSize
* 2);
622 SelectObject(hdc
, hBrush
);
623 SelectObject(hdc
, hPen
);
624 SelectObject(hdc
, hFont
);
626 ht
= (HANDLETABLE16
*)GlobalLock16(hHT
);
628 /* free objects in handle table */
629 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
630 if(*(ht
->objectHandle
+ i
) != 0)
631 DeleteObject(*(ht
->objectHandle
+ i
));
633 /* free handle table */
636 HeapFree( SystemHeap
, 0, mh
);
637 MF_ReleaseMetaHeader16(hmf
);
641 /******************************************************************
642 * EnumMetaFile (GDI32.88)
644 * Loop through the metafile records in hmf, calling the user-specified
645 * function for each one, stopping when the user's function returns FALSE
646 * (which is considered to be failure)
647 * or when no records are left (which is considered to be success).
650 * TRUE on success, FALSE on failure.
653 * Niels de carpentier, april 1996
655 BOOL WINAPI
EnumMetaFile(
658 MFENUMPROC lpEnumFunc
,
661 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
664 BOOL result
= TRUE
, loaded
= FALSE
;
666 DC
*dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
671 TRACE(metafile
,"(%08x,%08x,%p,%p)\n",
672 hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
674 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memoery-based copy */
675 mh
= MF_LoadDiskBasedMetaFile(mh
);
680 /* save the current pen, brush and font */
683 hBrush
= dc
->w
.hBrush
;
685 GDI_HEAP_UNLOCK(hdc
);
688 ht
= HeapAlloc( SystemHeap
, HEAP_ZERO_MEMORY
,
689 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
691 /* loop through metafile records */
692 offset
= mh
->mtHeaderSize
* 2;
694 while (offset
< (mh
->mtSize
* 2))
696 mr
= (METARECORD
*)((char *)mh
+ offset
);
697 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
703 offset
+= (mr
->rdSize
* 2);
706 /* restore pen, brush and font */
707 SelectObject(hdc
, hBrush
);
708 SelectObject(hdc
, hPen
);
709 SelectObject(hdc
, hFont
);
711 /* free objects in handle table */
712 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
713 if(*(ht
->objectHandle
+ i
) != 0)
714 DeleteObject(*(ht
->objectHandle
+ i
));
716 /* free handle table */
717 HeapFree( SystemHeap
, 0, ht
);
719 HeapFree( SystemHeap
, 0, mh
);
720 MF_ReleaseMetaHeader(hmf
);
724 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
726 /******************************************************************
727 * PlayMetaFileRecord16 (GDI.176)
729 * Render a single metafile record specified by *mr in the DC hdc, while
730 * using the handle table *ht, of length nHandles,
731 * to store metafile objects.
734 * The following metafile records are unimplemented:
736 * FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
737 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
738 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
741 void WINAPI
PlayMetaFileRecord16(
742 HDC16 hdc
, /* DC to render metafile into */
743 HANDLETABLE16
*ht
, /* pointer to handle table for metafile objects */
744 METARECORD
*mr
, /* pointer to metafile record to render */
745 UINT16 nHandles
/* size of handle table */
750 BITMAPINFOHEADER
*infohdr
;
752 TRACE(metafile
,"(%04x %08lx %08lx %04x) function %04x\n",
753 hdc
,(LONG
)ht
, (LONG
)mr
, nHandles
, mr
->rdFunction
);
755 switch (mr
->rdFunction
)
760 case META_DELETEOBJECT
:
761 DeleteObject(*(ht
->objectHandle
+ *(mr
->rdParm
)));
762 *(ht
->objectHandle
+ *(mr
->rdParm
)) = 0;
765 case META_SETBKCOLOR
:
766 SetBkColor16(hdc
, MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
770 SetBkMode16(hdc
, *(mr
->rdParm
));
773 case META_SETMAPMODE
:
774 SetMapMode16(hdc
, *(mr
->rdParm
));
778 SetROP216(hdc
, *(mr
->rdParm
));
782 SetRelAbs16(hdc
, *(mr
->rdParm
));
785 case META_SETPOLYFILLMODE
:
786 SetPolyFillMode16(hdc
, *(mr
->rdParm
));
789 case META_SETSTRETCHBLTMODE
:
790 SetStretchBltMode16(hdc
, *(mr
->rdParm
));
793 case META_SETTEXTCOLOR
:
794 SetTextColor16(hdc
, MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
797 case META_SETWINDOWORG
:
798 SetWindowOrg16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
801 case META_SETWINDOWEXT
:
802 SetWindowExt16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
805 case META_SETVIEWPORTORG
:
806 SetViewportOrg16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
809 case META_SETVIEWPORTEXT
:
810 SetViewportExt16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
813 case META_OFFSETWINDOWORG
:
814 OffsetWindowOrg16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
817 case META_SCALEWINDOWEXT
:
818 ScaleWindowExt16(hdc
, *(mr
->rdParm
+ 3), *(mr
->rdParm
+ 2),
819 *(mr
->rdParm
+ 1), *(mr
->rdParm
));
822 case META_OFFSETVIEWPORTORG
:
823 OffsetViewportOrg16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
826 case META_SCALEVIEWPORTEXT
:
827 ScaleViewportExt16(hdc
, *(mr
->rdParm
+ 3), *(mr
->rdParm
+ 2),
828 *(mr
->rdParm
+ 1), *(mr
->rdParm
));
832 LineTo(hdc
, (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
836 MoveTo16(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
839 case META_EXCLUDECLIPRECT
:
840 ExcludeClipRect16( hdc
, *(mr
->rdParm
+ 3), *(mr
->rdParm
+ 2),
841 *(mr
->rdParm
+ 1), *(mr
->rdParm
) );
844 case META_INTERSECTCLIPRECT
:
845 IntersectClipRect16( hdc
, *(mr
->rdParm
+ 3), *(mr
->rdParm
+ 2),
846 *(mr
->rdParm
+ 1), *(mr
->rdParm
) );
850 Arc(hdc
, (INT16
)*(mr
->rdParm
+ 7), (INT16
)*(mr
->rdParm
+ 6),
851 (INT16
)*(mr
->rdParm
+ 5), (INT16
)*(mr
->rdParm
+ 4),
852 (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
853 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
857 Ellipse(hdc
, (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
858 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
862 FloodFill(hdc
, (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
863 MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
867 Pie(hdc
, (INT16
)*(mr
->rdParm
+ 7), (INT16
)*(mr
->rdParm
+ 6),
868 (INT16
)*(mr
->rdParm
+ 5), (INT16
)*(mr
->rdParm
+ 4),
869 (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
870 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
874 Rectangle(hdc
, (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
875 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
879 RoundRect(hdc
, (INT16
)*(mr
->rdParm
+ 5), (INT16
)*(mr
->rdParm
+ 4),
880 (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
881 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
885 PatBlt16(hdc
, *(mr
->rdParm
+ 5), *(mr
->rdParm
+ 4),
886 *(mr
->rdParm
+ 3), *(mr
->rdParm
+ 2),
887 MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
895 SetPixel(hdc
, (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
896 MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
899 case META_OFFSETCLIPRGN
:
900 OffsetClipRgn16( hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
) );
905 TextOut16(hdc
, *(mr
->rdParm
+ ((s1
+ 1) >> 1) + 2),
906 *(mr
->rdParm
+ ((s1
+ 1) >> 1) + 1),
907 (char *)(mr
->rdParm
+ 1), s1
);
911 Polygon16(hdc
, (LPPOINT16
)(mr
->rdParm
+ 1), *(mr
->rdParm
));
914 case META_POLYPOLYGON
:
915 PolyPolygon16(hdc
, (LPPOINT16
)(mr
->rdParm
+ *(mr
->rdParm
) + 1),
916 (LPINT16
)(mr
->rdParm
+ 1), *(mr
->rdParm
));
920 Polyline16(hdc
, (LPPOINT16
)(mr
->rdParm
+ 1), *(mr
->rdParm
));
924 RestoreDC(hdc
, (INT16
)*(mr
->rdParm
));
927 case META_SELECTOBJECT
:
928 SelectObject(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
)));
932 Chord(hdc
, (INT16
)*(mr
->rdParm
+ 7), (INT16
)*(mr
->rdParm
+ 6),
933 (INT16
)*(mr
->rdParm
+5), (INT16
)*(mr
->rdParm
+ 4),
934 (INT16
)*(mr
->rdParm
+ 3), (INT16
)*(mr
->rdParm
+ 2),
935 (INT16
)*(mr
->rdParm
+ 1), (INT16
)*(mr
->rdParm
));
938 case META_CREATEPATTERNBRUSH
:
939 switch (*(mr
->rdParm
))
942 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
943 MF_AddHandle(ht
, nHandles
,
944 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
949 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
953 s1
= mr
->rdSize
* 2 - sizeof(METARECORD
) - 2;
954 hndl
= GlobalAlloc16(GMEM_MOVEABLE
, s1
);
955 ptr
= GlobalLock16(hndl
);
956 memcpy(ptr
, mr
->rdParm
+ 2, s1
);
957 GlobalUnlock16(hndl
);
958 MF_AddHandle(ht
, nHandles
,
959 CreateDIBPatternBrush(hndl
, *(mr
->rdParm
+ 1)));
964 case META_CREATEPENINDIRECT
:
965 MF_AddHandle(ht
, nHandles
,
966 CreatePenIndirect16((LOGPEN16
*)(&(mr
->rdParm
))));
969 case META_CREATEFONTINDIRECT
:
970 MF_AddHandle(ht
, nHandles
,
971 CreateFontIndirect16((LOGFONT16
*)(&(mr
->rdParm
))));
974 case META_CREATEBRUSHINDIRECT
:
975 MF_AddHandle(ht
, nHandles
,
976 CreateBrushIndirect16((LOGBRUSH16
*)(&(mr
->rdParm
))));
979 case META_CREATEPALETTE
:
980 MF_AddHandle(ht
, nHandles
,
981 CreatePalette16((LPLOGPALETTE
)mr
->rdParm
));
984 case META_SETTEXTALIGN
:
985 SetTextAlign16(hdc
, *(mr
->rdParm
));
988 case META_SELECTPALETTE
:
989 SelectPalette16(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
+1)),
993 case META_SETMAPPERFLAGS
:
994 SetMapperFlags16(hdc
, *(mr
->rdParm
));
997 case META_REALIZEPALETTE
:
998 RealizePalette16(hdc
);
1002 FIXME(metafile
, "META_ESCAPE unimplemented.\n");
1005 case META_EXTTEXTOUT
:
1011 s1
= mr
->rdParm
[2]; /* String length */
1012 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1013 + sizeof(UINT16
) + (mr
->rdParm
[3] ? sizeof(RECT16
) : 0); /* rec len without dx array */
1015 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1017 sot
+=sizeof(RECT16
); /* there is a rectangle, so add offset */
1019 if (mr
->rdSize
== len
/ 2)
1020 dxx
= NULL
; /* determine if array present */
1022 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1023 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1026 TRACE(metafile
,"%s len: %ld\n",
1029 "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1030 len
,s1
,mr
->rdSize
,mr
->rdParm
[3]);
1031 dxx
= NULL
; /* should't happen -- but if, we continue with NULL [for workaround] */
1033 ExtTextOut16( hdc
, mr
->rdParm
[1], /* X position */
1034 mr
->rdParm
[0], /* Y position */
1035 mr
->rdParm
[3], /* options */
1036 mr
->rdParm
[3] ? (LPRECT16
) &mr
->rdParm
[4]:NULL
, /* rectangle */
1038 s1
, dxx
); /* length, dx array */
1040 TRACE(metafile
,"%s len: %ld dx0: %d\n",
1041 sot
,mr
->rdSize
,dxx
[0]);
1045 case META_STRETCHDIB
:
1047 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
1048 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1049 StretchDIBits16(hdc
,mr
->rdParm
[10],mr
->rdParm
[9],mr
->rdParm
[8],
1050 mr
->rdParm
[7],mr
->rdParm
[6],mr
->rdParm
[5],
1051 mr
->rdParm
[4],mr
->rdParm
[3],bits
,info
,
1052 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1056 case META_DIBSTRETCHBLT
:
1058 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
1059 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
1060 StretchDIBits16(hdc
,mr
->rdParm
[9],mr
->rdParm
[8],mr
->rdParm
[7],
1061 mr
->rdParm
[6],mr
->rdParm
[5],mr
->rdParm
[4],
1062 mr
->rdParm
[3],mr
->rdParm
[2],bits
,info
,
1063 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1067 case META_STRETCHBLT
:
1069 HDC16 hdcSrc
=CreateCompatibleDC16(hdc
);
1070 HBITMAP hbitmap
=CreateBitmap(mr
->rdParm
[10], /*Width */
1071 mr
->rdParm
[11], /*Height*/
1072 mr
->rdParm
[13], /*Planes*/
1073 mr
->rdParm
[14], /*BitsPixel*/
1074 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
1075 SelectObject(hdcSrc
,hbitmap
);
1076 StretchBlt16(hdc
,mr
->rdParm
[9],mr
->rdParm
[8],
1077 mr
->rdParm
[7],mr
->rdParm
[6],
1078 hdcSrc
,mr
->rdParm
[5],mr
->rdParm
[4],
1079 mr
->rdParm
[3],mr
->rdParm
[2],
1080 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1087 HDC16 hdcSrc
=CreateCompatibleDC16(hdc
);
1088 HBITMAP hbitmap
=CreateBitmap(mr
->rdParm
[7]/*Width */,
1089 mr
->rdParm
[8]/*Height*/,
1090 mr
->rdParm
[10]/*Planes*/,
1091 mr
->rdParm
[11]/*BitsPixel*/,
1092 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
1093 SelectObject(hdcSrc
,hbitmap
);
1094 BitBlt(hdc
,(INT16
)mr
->rdParm
[6],(INT16
)mr
->rdParm
[5],
1095 (INT16
)mr
->rdParm
[4],(INT16
)mr
->rdParm
[3],
1096 hdcSrc
, (INT16
)mr
->rdParm
[2],(INT16
)mr
->rdParm
[1],
1097 MAKELONG(0,mr
->rdParm
[0]));
1102 case META_CREATEREGION
:
1104 HRGN hrgn
= CreateRectRgn(0,0,0,0);
1106 MF_Play_MetaCreateRegion(mr
, hrgn
);
1107 MF_AddHandle(ht
, nHandles
, hrgn
);
1111 case META_FILLREGION
:
1112 FillRgn16(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
)),
1113 *(ht
->objectHandle
+ *(mr
->rdParm
+1)));
1116 case META_INVERTREGION
:
1117 InvertRgn16(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
)));
1120 case META_PAINTREGION
:
1121 PaintRgn16(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
)));
1124 case META_SELECTCLIPREGION
:
1125 SelectClipRgn(hdc
, *(ht
->objectHandle
+ *(mr
->rdParm
)));
1128 case META_DIBCREATEPATTERNBRUSH
:
1129 /* *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
1130 TRACE(metafile
,"%d\n",*(mr
->rdParm
));
1131 s1
= mr
->rdSize
* 2 - sizeof(METARECORD
) - 2;
1132 hndl
= GlobalAlloc16(GMEM_MOVEABLE
, s1
);
1133 ptr
= GlobalLock16(hndl
);
1134 memcpy(ptr
, mr
->rdParm
+ 2, s1
);
1135 GlobalUnlock16(hndl
);
1136 MF_AddHandle(ht
, nHandles
,CreateDIBPatternBrush16(hndl
, *(mr
->rdParm
+ 1)));
1140 case META_DIBBITBLT
:
1142 /*In practice ive found that theres two layout for META_DIBBITBLT,
1143 one (the first here) is the usual one when a src dc is actually passed
1144 int, the second occurs when the src dc is passed in as NULL to
1145 the creating BitBlt.
1146 as the second case has no dib, a size check will suffice to distinguish.
1149 Caolan.McNamara@ul.ie
1151 if (mr
->rdSize
> 12)
1153 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
1154 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[0] );
1155 StretchDIBits16(hdc
,mr
->rdParm
[7],mr
->rdParm
[6],mr
->rdParm
[5],
1156 mr
->rdParm
[4],mr
->rdParm
[3],mr
->rdParm
[2],
1157 mr
->rdParm
[5],mr
->rdParm
[4],bits
,info
,
1158 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
1160 else /*equivalent to a PatBlt*/
1162 PatBlt16(hdc
, mr
->rdParm
[8], mr
->rdParm
[7],
1163 mr
->rdParm
[6], mr
->rdParm
[5],
1164 MAKELONG(*(mr
->rdParm
), *(mr
->rdParm
+ 1)));
1169 case META_SETTEXTCHAREXTRA
:
1170 SetTextCharacterExtra16(hdc
, (INT16
)*(mr
->rdParm
));
1173 case META_SETTEXTJUSTIFICATION
:
1174 SetTextJustification(hdc
, *(mr
->rdParm
+ 1), *(mr
->rdParm
));
1177 case META_EXTFLOODFILL
:
1178 ExtFloodFill(hdc
, (INT16
)*(mr
->rdParm
+ 4), (INT16
)*(mr
->rdParm
+ 3),
1179 MAKELONG(*(mr
->rdParm
+1), *(mr
->rdParm
+ 2)),*(mr
->rdParm
));
1182 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
1183 META_UNIMP(META_FRAMEREGION
)
1184 META_UNIMP(META_DRAWTEXT
)
1185 META_UNIMP(META_SETDIBTODEV
)
1186 META_UNIMP(META_ANIMATEPALETTE
)
1187 META_UNIMP(META_SETPALENTRIES
)
1188 META_UNIMP(META_RESIZEPALETTE
)
1189 META_UNIMP(META_RESETDC
)
1190 META_UNIMP(META_STARTDOC
)
1191 META_UNIMP(META_STARTPAGE
)
1192 META_UNIMP(META_ENDPAGE
)
1193 META_UNIMP(META_ABORTDOC
)
1194 META_UNIMP(META_ENDDOC
)
1195 META_UNIMP(META_CREATEBRUSH
)
1196 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1197 META_UNIMP(META_CREATEBITMAP
)
1201 WARN(metafile
, "PlayMetaFileRecord: Unknown record type %x\n",
1206 /******************************************************************
1207 * PlayMetaFileRecord (GDI32.266)
1209 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*handletable
,
1210 METARECORD
*metarecord
, UINT handles
)
1212 HANDLETABLE16
* ht
= (void *)GlobalAlloc(GPTR
,
1213 handles
*sizeof(HANDLETABLE16
));
1215 TRACE(metafile
, "(%08x,%p,%p,%d)\n", hdc
, handletable
, metarecord
,
1217 for (i
=0; i
<handles
; i
++)
1218 ht
->objectHandle
[i
] = handletable
->objectHandle
[i
];
1219 PlayMetaFileRecord16(hdc
, ht
, metarecord
, handles
);
1220 for (i
=0; i
<handles
; i
++)
1221 handletable
->objectHandle
[i
] = ht
->objectHandle
[i
];
1222 GlobalFree((HGLOBAL
)ht
);
1226 /******************************************************************
1227 * GetMetaFileBits (GDI.159)
1229 * Trade in a metafile object handle for a handle to the metafile memory.
1233 HGLOBAL16 WINAPI
GetMetaFileBits16(
1234 HMETAFILE16 hmf
/* metafile handle */
1237 TRACE(metafile
,"hMem out: %04x\n", hmf
);
1241 /******************************************************************
1242 * SetMetaFileBits (GDI.160)
1244 * Trade in a metafile memory handle for a handle to a metafile object.
1245 * The memory region should hold a proper metafile, otherwise
1246 * problems will occur when it is used. Validity of the memory is not
1247 * checked. The function is essentially just the identity function.
1249 HMETAFILE16 WINAPI
SetMetaFileBits16(
1251 /* handle to a memory region holding a metafile */
1254 TRACE(metafile
,"hmf out: %04x\n", hMem
);
1259 /******************************************************************
1260 * SetMetaFileBitsBetter (GDI.196)
1262 * Trade in a metafile memory handle for a handle to a metafile object,
1263 * making a cursory check (using IsValidMetaFile()) that the memory
1264 * handle points to a valid metafile.
1267 * Handle to a metafile on success, NULL on failure..
1269 HMETAFILE16 WINAPI
SetMetaFileBitsBetter16( HMETAFILE16 hMeta
)
1271 if( IsValidMetaFile16( hMeta
) )
1272 return (HMETAFILE16
)GlobalReAlloc16( hMeta
, 0,
1273 GMEM_SHARE
| GMEM_NODISCARD
| GMEM_MODIFY
);
1274 return (HMETAFILE16
)0;
1277 /******************************************************************
1278 * SetMetaFileBitsEx (GDI32.323)
1280 * Create a metafile from raw data. No checking of the data is performed.
1281 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1283 HMETAFILE WINAPI
SetMetaFileBitsEx(
1284 UINT size
, /* size of metafile, in bytes */
1285 const BYTE
*lpData
/* pointer to metafile data */
1288 METAHEADER
*mh
= HeapAlloc( SystemHeap
, 0, size
);
1290 memcpy(mh
, lpData
, size
);
1291 return MF_Create_HMETAFILE(mh
);
1294 /*****************************************************************
1295 * GetMetaFileBitsEx (GDI32.198) Get raw metafile data
1297 * Copies the data from metafile _hmf_ into the buffer _buf_.
1298 * If _buf_ is zero, returns size of buffer required. Otherwise,
1299 * returns number of bytes copied.
1301 UINT WINAPI
GetMetaFileBitsEx(
1302 HMETAFILE hmf
, /* metafile */
1303 UINT nSize
, /* size of buf */
1304 LPVOID buf
/* buffer to receive raw metafile data */
1306 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1309 TRACE(metafile
, "(%08x,%d,%p)\n", hmf
, nSize
, buf
);
1310 if (!mh
) return 0; /* FIXME: error code */
1311 if(mh
->mtType
== METAFILE_DISK
)
1312 FIXME(metafile
, "Disk-based metafile?\n");
1313 mfSize
= mh
->mtSize
* 2;
1315 MF_ReleaseMetaHeader(hmf
);
1316 TRACE(metafile
,"returning size %d\n", mfSize
);
1319 if(mfSize
> nSize
) mfSize
= nSize
;
1320 memmove(buf
, mh
, mfSize
);
1321 MF_ReleaseMetaHeader(hmf
);
1325 /******************************************************************
1326 * GetWinMetaFileBits [GDI32.241]
1328 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1329 UINT cbBuffer
, LPBYTE lpbBuffer
,
1330 INT fnMapMode
, HDC hdcRef
)
1332 FIXME(metafile
, "(%d,%d,%p,%d,%d): stub\n",
1333 hemf
, cbBuffer
, lpbBuffer
, fnMapMode
, hdcRef
);
1337 /******************************************************************
1338 * MF_Play_MetaCreateRegion
1340 * Handles META_CREATEREGION for PlayMetaFileRecord().
1344 * The layout of the record looks something like this:
1349 * 2 Looks like a handle? - not constant
1351 * 4 Total number of bytes
1352 * 5 No. of seperate bands = n [see below]
1353 * 6 Largest number of x co-ords in a band
1354 * 7-10 Bounding box x1 y1 x2 y2
1357 * Regions are divided into bands that are uniform in the
1358 * y-direction. Each band consists of pairs of on/off x-coords and is
1360 * m y0 y1 x1 x2 x3 ... xm m
1361 * into successive rdParm[]s.
1363 * This is probably just a dump of the internal RGNOBJ?
1369 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1374 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1376 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1377 band
++, start
= end
+ 1) {
1378 if(*start
/ 2 != (*start
+ 1) / 2) {
1379 WARN(metafile
, "Delimiter not even.\n");
1380 DeleteObject( hrgn2
);
1384 end
= start
+ *start
+ 3;
1385 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1386 WARN(metafile
, "End points outside record.\n");
1387 DeleteObject( hrgn2
);
1391 if(*start
!= *end
) {
1392 WARN(metafile
, "Mismatched delimiters.\n");
1393 DeleteObject( hrgn2
);
1397 y0
= *(INT16
*)(start
+ 1);
1398 y1
= *(INT16
*)(start
+ 2);
1399 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1400 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1401 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1402 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1405 DeleteObject( hrgn2
);
1410 /* LocalWords: capatibility