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.
56 #include "gdi_private.h"
57 #include "wine/debug.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(metafile
);
77 /******************************************************************
80 * Add a handle to an external handle table and return the index
82 static int MF_AddHandle(HANDLETABLE
*ht
, UINT htlen
, HGDIOBJ hobj
)
86 for (i
= 0; i
< htlen
; i
++)
88 if (*(ht
->objectHandle
+ i
) == 0)
90 *(ht
->objectHandle
+ i
) = hobj
;
98 /******************************************************************
99 * MF_Create_HMETATFILE
101 * Creates a (32 bit) HMETAFILE object from a METAHEADER
103 * HMETAFILEs are GDI objects.
105 HMETAFILE
MF_Create_HMETAFILE(METAHEADER
*mh
)
108 METAFILEOBJ
*metaObj
= GDI_AllocObject( sizeof(METAFILEOBJ
), METAFILE_MAGIC
,
109 (HGDIOBJ
*)&hmf
, NULL
);
113 GDI_ReleaseObj( hmf
);
118 /******************************************************************
121 * Returns ptr to METAHEADER associated with HMETAFILE
123 static METAHEADER
*MF_GetMetaHeader( HMETAFILE hmf
)
125 METAHEADER
*ret
= NULL
;
126 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
130 GDI_ReleaseObj( hmf
);
135 /******************************************************************
138 * Convert an array of POINT16 to an array of POINT.
139 * Result must be freed by caller.
141 static POINT
*convert_points( UINT count
, POINT16
*pt16
)
144 POINT
*ret
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*ret
) );
147 for (i
= 0; i
< count
; i
++)
149 ret
[i
].x
= pt16
[i
].x
;
150 ret
[i
].y
= pt16
[i
].y
;
156 /******************************************************************
157 * DeleteMetaFile (GDI32.@)
159 * Delete a memory-based metafile.
162 BOOL WINAPI
DeleteMetaFile( HMETAFILE hmf
)
164 METAFILEOBJ
* metaObj
= (METAFILEOBJ
*)GDI_GetObjPtr( hmf
, METAFILE_MAGIC
);
165 if (!metaObj
) return FALSE
;
166 HeapFree( GetProcessHeap(), 0, metaObj
->mh
);
167 GDI_FreeObject( hmf
, metaObj
);
171 /******************************************************************
174 * Returns a pointer to a memory based METAHEADER read in from file HFILE
177 METAHEADER
*MF_ReadMetaFile(HANDLE hfile
)
180 DWORD BytesRead
, size
;
182 size
= sizeof(METAHEADER
);
183 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
185 if(ReadFile( hfile
, mh
, size
, &BytesRead
, NULL
) == 0 ||
187 HeapFree( GetProcessHeap(), 0, mh
);
190 if (mh
->mtType
!= METAFILE_MEMORY
|| mh
->mtVersion
!= MFVERSION
||
191 mh
->mtHeaderSize
!= size
/ 2)
193 HeapFree( GetProcessHeap(), 0, mh
);
196 size
= mh
->mtSize
* 2;
197 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
, size
);
199 size
-= sizeof(METAHEADER
);
200 if(ReadFile( hfile
, (char *)mh
+ sizeof(METAHEADER
), size
, &BytesRead
,
203 HeapFree( GetProcessHeap(), 0, mh
);
207 if (mh
->mtType
!= METAFILE_MEMORY
) {
208 WARN("Disk metafile had mtType = %04x\n", mh
->mtType
);
209 mh
->mtType
= METAFILE_MEMORY
;
214 /******************************************************************
215 * GetMetaFileA (GDI32.@)
217 * Read a metafile from a file. Returns handle to a memory-based metafile.
219 HMETAFILE WINAPI
GetMetaFileA( LPCSTR lpFilename
)
224 TRACE("%s\n", lpFilename
);
229 if((hFile
= CreateFileA(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
230 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
233 mh
= MF_ReadMetaFile(hFile
);
236 return MF_Create_HMETAFILE( mh
);
239 /******************************************************************
240 * GetMetaFileW (GDI32.@)
242 HMETAFILE WINAPI
GetMetaFileW( LPCWSTR lpFilename
)
247 TRACE("%s\n", debugstr_w(lpFilename
));
252 if((hFile
= CreateFileW(lpFilename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
253 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
)
256 mh
= MF_ReadMetaFile(hFile
);
259 return MF_Create_HMETAFILE( mh
);
263 /******************************************************************
264 * MF_LoadDiskBasedMetaFile
266 * Creates a new memory-based metafile from a disk-based one.
268 METAHEADER
*MF_LoadDiskBasedMetaFile(METAHEADER
*mh
)
274 if(mh
->mtType
!= METAFILE_DISK
) {
275 ERR("Not a disk based metafile\n");
278 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
280 if((hfile
= CreateFileA(mhd
->filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
281 OPEN_EXISTING
, 0, 0)) == INVALID_HANDLE_VALUE
) {
282 WARN("Can't open file of disk based metafile\n");
285 mh2
= MF_ReadMetaFile(hfile
);
290 /******************************************************************
291 * MF_CreateMetaHeaderDisk
293 * Take a memory based METAHEADER and change it to a disk based METAHEADER
294 * assosiated with filename. Note: Trashes contents of old one.
296 METAHEADER
*MF_CreateMetaHeaderDisk(METAHEADER
*mh
, LPCVOID filename
, BOOL uni
)
300 mh
= HeapReAlloc( GetProcessHeap(), 0, mh
,
301 sizeof(METAHEADER
) + sizeof(METAHEADERDISK
));
302 mh
->mtType
= METAFILE_DISK
;
303 mhd
= (METAHEADERDISK
*)((char *)mh
+ sizeof(METAHEADER
));
306 WideCharToMultiByte(CP_ACP
, 0, filename
, -1,
307 mhd
->filename
, sizeof mhd
->filename
, NULL
, NULL
);
309 lstrcpynA( mhd
->filename
, filename
, sizeof mhd
->filename
);
313 /******************************************************************
314 * CopyMetaFileW (GDI32.@)
316 * Copies the metafile corresponding to hSrcMetaFile to either
317 * a disk file, if a filename is given, or to a new memory based
318 * metafile, if lpFileName is NULL.
321 * hSrcMetaFile [I] handle of metafile to copy
322 * lpFilename [I] filename if copying to a file
325 * Handle to metafile copy on success, NULL on failure.
328 * Copying to disk returns NULL even if successful.
330 HMETAFILE WINAPI
CopyMetaFileW( HMETAFILE hSrcMetaFile
, LPCWSTR lpFilename
)
332 METAHEADER
*mh
= MF_GetMetaHeader( hSrcMetaFile
);
333 METAHEADER
*mh2
= NULL
;
336 TRACE("(%p,%s)\n", hSrcMetaFile
, debugstr_w(lpFilename
));
340 if(mh
->mtType
== METAFILE_DISK
)
341 mh2
= MF_LoadDiskBasedMetaFile(mh
);
343 mh2
= HeapAlloc( GetProcessHeap(), 0, mh
->mtSize
* 2 );
344 memcpy( mh2
, mh
, mh
->mtSize
* 2 );
347 if(lpFilename
) { /* disk based metafile */
349 if((hFile
= CreateFileW(lpFilename
, GENERIC_WRITE
, 0, NULL
,
350 CREATE_ALWAYS
, 0, 0)) == INVALID_HANDLE_VALUE
) {
351 HeapFree( GetProcessHeap(), 0, mh2
);
354 WriteFile(hFile
, mh2
, mh2
->mtSize
* 2, &w
, NULL
);
358 return MF_Create_HMETAFILE( mh2
);
362 /******************************************************************
363 * CopyMetaFileA (GDI32.@)
367 HMETAFILE WINAPI
CopyMetaFileA( HMETAFILE hSrcMetaFile
, LPCSTR lpFilename
)
369 UNICODE_STRING lpFilenameW
;
372 if (lpFilename
) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW
, lpFilename
);
373 else lpFilenameW
.Buffer
= NULL
;
375 ret
= CopyMetaFileW( hSrcMetaFile
, lpFilenameW
.Buffer
);
376 if (lpFilenameW
.Buffer
)
377 RtlFreeUnicodeString(&lpFilenameW
);
381 /*******************************************************************
384 * Helper for PlayMetaFile
386 BOOL
MF_PlayMetaFile( HDC hdc
, METAHEADER
*mh
)
391 unsigned int offset
= 0;
398 if (!mh
) return FALSE
;
399 if(mh
->mtType
== METAFILE_DISK
) { /* Create a memory-based copy */
400 mh
= MF_LoadDiskBasedMetaFile(mh
);
401 if(!mh
) return FALSE
;
405 /* save the current pen, brush and font */
406 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
407 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
408 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
410 /* create the handle table */
411 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
412 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
413 if(!ht
) return FALSE
;
415 /* loop through metafile playing records */
416 offset
= mh
->mtHeaderSize
* 2;
417 while (offset
< mh
->mtSize
* 2)
419 mr
= (METARECORD
*)((char *)mh
+ offset
);
420 TRACE("offset=%04x,size=%08lx\n",
424 "Entry got size 0 at offset %d, total mf length is %ld\n",
425 offset
,mh
->mtSize
*2);
426 break; /* would loop endlessly otherwise */
428 offset
+= mr
->rdSize
* 2;
429 PlayMetaFileRecord( hdc
, ht
, mr
, mh
->mtNoObjects
);
432 SelectObject(hdc
, hBrush
);
433 SelectObject(hdc
, hPen
);
434 SelectObject(hdc
, hFont
);
436 /* free objects in handle table */
437 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
438 if(*(ht
->objectHandle
+ i
) != 0)
439 DeleteObject(*(ht
->objectHandle
+ i
));
441 /* free handle table */
442 HeapFree( GetProcessHeap(), 0, ht
);
444 HeapFree( GetProcessHeap(), 0, mh
);
448 /******************************************************************
449 * PlayMetaFile (GDI32.@)
451 * Renders the metafile specified by hmf in the DC specified by
452 * hdc. Returns FALSE on failure, TRUE on success.
455 * hdc [I] handle of DC to render in
456 * hmf [I] handle of metafile to render
462 BOOL WINAPI
PlayMetaFile( HDC hdc
, HMETAFILE hmf
)
464 METAHEADER
*mh
= MF_GetMetaHeader( hmf
);
465 return MF_PlayMetaFile( hdc
, mh
);
468 /******************************************************************
469 * EnumMetaFile (GDI32.@)
471 * Loop through the metafile records in hmf, calling the user-specified
472 * function for each one, stopping when the user's function returns FALSE
473 * (which is considered to be failure)
474 * or when no records are left (which is considered to be success).
477 * TRUE on success, FALSE on failure.
479 BOOL WINAPI
EnumMetaFile(HDC hdc
, HMETAFILE hmf
, MFENUMPROC lpEnumFunc
, LPARAM lpData
)
481 METAHEADER
*mhTemp
= NULL
, *mh
= MF_GetMetaHeader(hmf
);
486 unsigned int offset
= 0;
491 TRACE("(%p,%p,%p,%p)\n", hdc
, hmf
, lpEnumFunc
, (void*)lpData
);
493 if(mh
->mtType
== METAFILE_DISK
)
495 /* Create a memory-based copy */
496 if (!(mhTemp
= MF_LoadDiskBasedMetaFile(mh
))) return FALSE
;
500 /* save the current pen, brush and font */
501 hPen
= GetCurrentObject(hdc
, OBJ_PEN
);
502 hBrush
= GetCurrentObject(hdc
, OBJ_BRUSH
);
503 hFont
= GetCurrentObject(hdc
, OBJ_FONT
);
505 ht
= HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY
,
506 sizeof(HANDLETABLE
) * mh
->mtNoObjects
);
508 /* loop through metafile records */
509 offset
= mh
->mtHeaderSize
* 2;
511 while (offset
< (mh
->mtSize
* 2))
513 mr
= (METARECORD
*)((char *)mh
+ offset
);
514 if(mr
->rdFunction
== META_EOF
) {
515 TRACE("Got META_EOF so stopping\n");
518 TRACE("Calling EnumFunc with record type %x\n",
520 if (!lpEnumFunc( hdc
, ht
, mr
, mh
->mtNoObjects
, (LONG
)lpData
))
526 offset
+= (mr
->rdSize
* 2);
529 /* restore pen, brush and font */
530 SelectObject(hdc
, hBrush
);
531 SelectObject(hdc
, hPen
);
532 SelectObject(hdc
, hFont
);
534 /* free objects in handle table */
535 for(i
= 0; i
< mh
->mtNoObjects
; i
++)
536 if(*(ht
->objectHandle
+ i
) != 0)
537 DeleteObject(*(ht
->objectHandle
+ i
));
539 /* free handle table */
540 HeapFree( GetProcessHeap(), 0, ht
);
541 /* free a copy of metafile */
542 HeapFree( GetProcessHeap(), 0, mhTemp
);
546 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
);
547 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
);
548 /******************************************************************
549 * PlayMetaFileRecord (GDI32.@)
551 * Render a single metafile record specified by *mr in the DC hdc, while
552 * using the handle table *ht, of length handles,
553 * to store metafile objects.
556 * The following metafile records are unimplemented:
558 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
559 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
560 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
562 BOOL WINAPI
PlayMetaFileRecord( HDC hdc
, HANDLETABLE
*ht
, METARECORD
*mr
, UINT handles
)
566 BITMAPINFOHEADER
*infohdr
;
568 TRACE("(%p %p %p %u) function %04x\n", hdc
, ht
, mr
, handles
, mr
->rdFunction
);
570 switch (mr
->rdFunction
)
575 case META_DELETEOBJECT
:
576 DeleteObject(*(ht
->objectHandle
+ mr
->rdParm
[0]));
577 *(ht
->objectHandle
+ mr
->rdParm
[0]) = 0;
580 case META_SETBKCOLOR
:
581 SetBkColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
585 SetBkMode(hdc
, mr
->rdParm
[0]);
588 case META_SETMAPMODE
:
589 SetMapMode(hdc
, mr
->rdParm
[0]);
593 SetROP2(hdc
, mr
->rdParm
[0]);
597 SetRelAbs(hdc
, mr
->rdParm
[0]);
600 case META_SETPOLYFILLMODE
:
601 SetPolyFillMode(hdc
, mr
->rdParm
[0]);
604 case META_SETSTRETCHBLTMODE
:
605 SetStretchBltMode(hdc
, mr
->rdParm
[0]);
608 case META_SETTEXTCOLOR
:
609 SetTextColor(hdc
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
612 case META_SETWINDOWORG
:
613 SetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
616 case META_SETWINDOWEXT
:
617 SetWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
620 case META_SETVIEWPORTORG
:
621 SetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
624 case META_SETVIEWPORTEXT
:
625 SetViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
628 case META_OFFSETWINDOWORG
:
629 OffsetWindowOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
632 case META_SCALEWINDOWEXT
:
633 ScaleWindowExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
634 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
637 case META_OFFSETVIEWPORTORG
:
638 OffsetViewportOrgEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
641 case META_SCALEVIEWPORTEXT
:
642 ScaleViewportExtEx(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
643 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
647 LineTo(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
651 MoveToEx(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0], NULL
);
654 case META_EXCLUDECLIPRECT
:
655 ExcludeClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
656 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
659 case META_INTERSECTCLIPRECT
:
660 IntersectClipRect( hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
661 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
665 Arc(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
666 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
667 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
668 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
672 Ellipse(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
673 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
677 FloodFill(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
678 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
682 Pie(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
683 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
684 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
685 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
689 Rectangle(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
690 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
694 RoundRect(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
695 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
696 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
700 PatBlt(hdc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
701 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
702 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
710 SetPixel(hdc
, (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
711 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
714 case META_OFFSETCLIPRGN
:
715 OffsetClipRgn( hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0] );
720 TextOutA(hdc
, (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 2],
721 (SHORT
)mr
->rdParm
[((s1
+ 1) >> 1) + 1],
722 (char *)(mr
->rdParm
+ 1), s1
);
726 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
728 Polygon(hdc
, pt
, mr
->rdParm
[0]);
729 HeapFree( GetProcessHeap(), 0, pt
);
733 case META_POLYPOLYGON
:
736 SHORT
*counts
= (SHORT
*)(mr
->rdParm
+ 1);
738 for (i
= total
= 0; i
< mr
->rdParm
[0]; i
++) total
+= counts
[i
];
739 pt
= convert_points( total
, (LPPOINT16
)(counts
+ mr
->rdParm
[0]) );
742 INT
*cnt32
= HeapAlloc( GetProcessHeap(), 0, mr
->rdParm
[0] * sizeof(*cnt32
) );
745 for (i
= 0; i
< mr
->rdParm
[0]; i
++) cnt32
[i
] = counts
[i
];
746 PolyPolygon( hdc
, pt
, cnt32
, mr
->rdParm
[0]);
747 HeapFree( GetProcessHeap(), 0, cnt32
);
750 HeapFree( GetProcessHeap(), 0, pt
);
755 if ((pt
= convert_points( mr
->rdParm
[0], (LPPOINT16
)(mr
->rdParm
+ 1))))
757 Polyline( hdc
, pt
, mr
->rdParm
[0] );
758 HeapFree( GetProcessHeap(), 0, pt
);
763 RestoreDC(hdc
, (SHORT
)mr
->rdParm
[0]);
766 case META_SELECTOBJECT
:
767 SelectObject(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
771 Chord(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
772 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
773 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
774 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
777 case META_CREATEPATTERNBRUSH
:
778 switch (mr
->rdParm
[0])
781 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
782 MF_AddHandle(ht
, handles
,
783 CreatePatternBrush(CreateBitmap(infohdr
->biWidth
,
788 (sizeof(BITMAPINFOHEADER
) / 2) + 4))));
792 infohdr
= (BITMAPINFOHEADER
*)(mr
->rdParm
+ 2);
793 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( infohdr
, mr
->rdParm
[1] ));
797 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
803 case META_CREATEPENINDIRECT
:
806 pen
.lopnStyle
= mr
->rdParm
[0];
807 pen
.lopnWidth
.x
= (SHORT
)mr
->rdParm
[1];
808 pen
.lopnWidth
.y
= (SHORT
)mr
->rdParm
[2];
809 pen
.lopnColor
= MAKELONG( mr
->rdParm
[3], mr
->rdParm
[4] );
810 MF_AddHandle(ht
, handles
, CreatePenIndirect( &pen
));
814 case META_CREATEFONTINDIRECT
:
817 font
.lfHeight
= (SHORT
)mr
->rdParm
[0];
818 font
.lfWidth
= (SHORT
)mr
->rdParm
[1];
819 font
.lfEscapement
= (SHORT
)mr
->rdParm
[2];
820 font
.lfOrientation
= (SHORT
)mr
->rdParm
[3];
821 font
.lfWeight
= (SHORT
)mr
->rdParm
[4];
822 font
.lfItalic
= LOBYTE(mr
->rdParm
[5]);
823 font
.lfUnderline
= HIBYTE(mr
->rdParm
[5]);
824 font
.lfStrikeOut
= LOBYTE(mr
->rdParm
[6]);
825 font
.lfCharSet
= HIBYTE(mr
->rdParm
[6]);
826 font
.lfOutPrecision
= LOBYTE(mr
->rdParm
[7]);
827 font
.lfClipPrecision
= HIBYTE(mr
->rdParm
[7]);
828 font
.lfQuality
= LOBYTE(mr
->rdParm
[8]);
829 font
.lfPitchAndFamily
= HIBYTE(mr
->rdParm
[8]);
830 memcpy( font
.lfFaceName
, mr
->rdParm
+ 9, LF_FACESIZE
);
831 MF_AddHandle(ht
, handles
, CreateFontIndirectA( &font
));
835 case META_CREATEBRUSHINDIRECT
:
838 brush
.lbStyle
= mr
->rdParm
[0];
839 brush
.lbColor
= MAKELONG( mr
->rdParm
[1], mr
->rdParm
[2] );
840 brush
.lbHatch
= mr
->rdParm
[3];
841 MF_AddHandle(ht
, handles
, CreateBrushIndirect( &brush
));
845 case META_CREATEPALETTE
:
846 MF_AddHandle(ht
, handles
, CreatePalette((LPLOGPALETTE
)mr
->rdParm
));
849 case META_SETTEXTALIGN
:
850 SetTextAlign(hdc
, mr
->rdParm
[0]);
853 case META_SELECTPALETTE
:
854 GDISelectPalette(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]), mr
->rdParm
[0]);
857 case META_SETMAPPERFLAGS
:
858 SetMapperFlags(hdc
, MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
861 case META_REALIZEPALETTE
:
862 GDIRealizePalette(hdc
);
866 switch (mr
->rdParm
[0]) {
867 case GETSCALINGFACTOR
: /* get function ... would just NULL dereference */
870 FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
873 Escape(hdc
, mr
->rdParm
[0], mr
->rdParm
[1], (LPCSTR
)&mr
->rdParm
[2], NULL
);
876 case META_EXTTEXTOUT
:
877 MF_Play_MetaExtTextOut( hdc
, mr
);
880 case META_STRETCHDIB
:
882 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[11]);
883 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
884 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[10], (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
885 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
886 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], bits
, info
,
887 mr
->rdParm
[2],MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
891 case META_DIBSTRETCHBLT
:
893 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[10]);
894 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[2] );
895 StretchDIBits( hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
896 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
897 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2], bits
, info
,
898 DIB_RGB_COLORS
,MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
902 case META_STRETCHBLT
:
904 HDC hdcSrc
= CreateCompatibleDC(hdc
);
905 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[10], /*Width */
906 mr
->rdParm
[11], /*Height*/
907 mr
->rdParm
[13], /*Planes*/
908 mr
->rdParm
[14], /*BitsPixel*/
909 (LPSTR
)&mr
->rdParm
[15]); /*bits*/
910 SelectObject(hdcSrc
,hbitmap
);
911 StretchBlt(hdc
, (SHORT
)mr
->rdParm
[9], (SHORT
)mr
->rdParm
[8],
912 (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6],
913 hdcSrc
, (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4],
914 (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
915 MAKELONG(mr
->rdParm
[0],mr
->rdParm
[1]));
922 HDC hdcSrc
= CreateCompatibleDC(hdc
);
923 HBITMAP hbitmap
= CreateBitmap(mr
->rdParm
[7]/*Width */,
924 mr
->rdParm
[8]/*Height*/,
925 mr
->rdParm
[10]/*Planes*/,
926 mr
->rdParm
[11]/*BitsPixel*/,
927 (LPSTR
)&mr
->rdParm
[12]/*bits*/);
928 SelectObject(hdcSrc
,hbitmap
);
929 BitBlt(hdc
,(SHORT
)mr
->rdParm
[6],(SHORT
)mr
->rdParm
[5],
930 (SHORT
)mr
->rdParm
[4],(SHORT
)mr
->rdParm
[3],
931 hdcSrc
, (SHORT
)mr
->rdParm
[2],(SHORT
)mr
->rdParm
[1],
932 MAKELONG(0,mr
->rdParm
[0]));
937 case META_CREATEREGION
:
939 HRGN hrgn
= CreateRectRgn(0,0,0,0);
941 MF_Play_MetaCreateRegion(mr
, hrgn
);
942 MF_AddHandle(ht
, handles
, hrgn
);
946 case META_FILLREGION
:
947 FillRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[1]),
948 *(ht
->objectHandle
+ mr
->rdParm
[0]));
951 case META_FRAMEREGION
:
952 FrameRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[3]),
953 *(ht
->objectHandle
+ mr
->rdParm
[2]),
954 (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
957 case META_INVERTREGION
:
958 InvertRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
961 case META_PAINTREGION
:
962 PaintRgn(hdc
, *(ht
->objectHandle
+ mr
->rdParm
[0]));
965 case META_SELECTCLIPREGION
:
969 if (mr
->rdParm
[0]) hrgn
= *(ht
->objectHandle
+ mr
->rdParm
[0]);
970 SelectClipRgn(hdc
, hrgn
);
974 case META_DIBCREATEPATTERNBRUSH
:
975 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
976 but there's no difference */
977 MF_AddHandle(ht
, handles
, CreateDIBPatternBrushPt( mr
->rdParm
+ 2, mr
->rdParm
[1] ));
981 /* In practice I've found that there are two layouts for
982 META_DIBBITBLT, one (the first here) is the usual one when a src
983 dc is actually passed to it, the second occurs when the src dc is
984 passed in as NULL to the creating BitBlt. As the second case has
985 no dib, a size check will suffice to distinguish.
987 Caolan.McNamara@ul.ie */
989 if (mr
->rdSize
> 12) {
990 LPBITMAPINFO info
= (LPBITMAPINFO
) &(mr
->rdParm
[8]);
991 LPSTR bits
= (LPSTR
)info
+ DIB_BitmapInfoSize(info
, mr
->rdParm
[0]);
993 StretchDIBits(hdc
, (SHORT
)mr
->rdParm
[7], (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
994 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3], (SHORT
)mr
->rdParm
[2],
995 (SHORT
)mr
->rdParm
[5], (SHORT
)mr
->rdParm
[4], bits
, info
,
996 DIB_RGB_COLORS
, MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
998 else /* equivalent to a PatBlt */
999 PatBlt(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1000 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1001 MAKELONG(mr
->rdParm
[0], mr
->rdParm
[1]));
1004 case META_SETTEXTCHAREXTRA
:
1005 SetTextCharacterExtra(hdc
, (SHORT
)mr
->rdParm
[0]);
1008 case META_SETTEXTJUSTIFICATION
:
1009 SetTextJustification(hdc
, (SHORT
)mr
->rdParm
[1], (SHORT
)mr
->rdParm
[0]);
1012 case META_EXTFLOODFILL
:
1013 ExtFloodFill(hdc
, (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1014 MAKELONG(mr
->rdParm
[1], mr
->rdParm
[2]),
1018 case META_SETDIBTODEV
:
1020 BITMAPINFO
*info
= (BITMAPINFO
*) &(mr
->rdParm
[9]);
1021 char *bits
= (char *)info
+ DIB_BitmapInfoSize( info
, mr
->rdParm
[0] );
1022 SetDIBitsToDevice(hdc
, (SHORT
)mr
->rdParm
[8], (SHORT
)mr
->rdParm
[7],
1023 (SHORT
)mr
->rdParm
[6], (SHORT
)mr
->rdParm
[5],
1024 (SHORT
)mr
->rdParm
[4], (SHORT
)mr
->rdParm
[3],
1025 mr
->rdParm
[2], mr
->rdParm
[1], bits
, info
,
1030 #define META_UNIMP(x) case x: \
1031 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1033 META_UNIMP(META_DRAWTEXT
)
1034 META_UNIMP(META_ANIMATEPALETTE
)
1035 META_UNIMP(META_SETPALENTRIES
)
1036 META_UNIMP(META_RESIZEPALETTE
)
1037 META_UNIMP(META_RESETDC
)
1038 META_UNIMP(META_STARTDOC
)
1039 META_UNIMP(META_STARTPAGE
)
1040 META_UNIMP(META_ENDPAGE
)
1041 META_UNIMP(META_ABORTDOC
)
1042 META_UNIMP(META_ENDDOC
)
1043 META_UNIMP(META_CREATEBRUSH
)
1044 META_UNIMP(META_CREATEBITMAPINDIRECT
)
1045 META_UNIMP(META_CREATEBITMAP
)
1049 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr
->rdFunction
);
1055 /******************************************************************
1056 * SetMetaFileBitsEx (GDI32.@)
1058 * Create a metafile from raw data. No checking of the data is performed.
1059 * Use GetMetaFileBitsEx() to get raw data from a metafile.
1062 * size [I] size of metafile, in bytes
1063 * lpData [I] pointer to metafile data
1066 * Success: Handle to metafile.
1069 HMETAFILE WINAPI
SetMetaFileBitsEx( UINT size
, const BYTE
*lpData
)
1071 METAHEADER
*mh
= (METAHEADER
*)lpData
;
1073 if (size
& 1) return 0;
1075 if (!size
|| mh
->mtType
!= METAFILE_MEMORY
|| mh
->mtVersion
!= MFVERSION
||
1076 mh
->mtHeaderSize
!= sizeof(METAHEADER
) / 2)
1078 SetLastError(ERROR_INVALID_DATA
);
1082 mh
= HeapAlloc( GetProcessHeap(), 0, size
);
1085 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1089 memcpy(mh
, lpData
, size
);
1090 mh
->mtSize
= size
/ 2;
1091 return MF_Create_HMETAFILE(mh
);
1094 /*****************************************************************
1095 * GetMetaFileBitsEx (GDI32.@)
1097 * Get raw metafile data.
1099 * Copies the data from metafile _hmf_ into the buffer _buf_.
1103 * nSize [I] size of buf
1104 * buf [O] buffer to receive raw metafile data
1107 * If _buf_ is zero, returns size of buffer required. Otherwise,
1108 * returns number of bytes copied.
1110 UINT WINAPI
GetMetaFileBitsEx( HMETAFILE hmf
, UINT nSize
, LPVOID buf
)
1112 METAHEADER
*mh
= MF_GetMetaHeader(hmf
);
1115 TRACE("(%p,%d,%p)\n", hmf
, nSize
, buf
);
1116 if (!mh
) return 0; /* FIXME: error code */
1117 if(mh
->mtType
== METAFILE_DISK
)
1118 FIXME("Disk-based metafile?\n");
1119 mfSize
= mh
->mtSize
* 2;
1121 TRACE("returning size %d\n", mfSize
);
1124 if(mfSize
> nSize
) mfSize
= nSize
;
1125 memmove(buf
, mh
, mfSize
);
1129 /******************************************************************
1130 * GetWinMetaFileBits [GDI32.@]
1132 UINT WINAPI
GetWinMetaFileBits(HENHMETAFILE hemf
,
1133 UINT cbBuffer
, LPBYTE lpbBuffer
,
1134 INT fnMapMode
, HDC hdcRef
)
1142 GetClipBox(hdcRef
, &rc
);
1143 oldMapMode
= SetMapMode(hdcRef
, fnMapMode
);
1145 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf
, cbBuffer
, lpbBuffer
,
1146 fnMapMode
, hdcRef
, wine_dbgstr_rect(&rc
));
1148 hdcmf
= CreateMetaFileA(NULL
);
1149 PlayEnhMetaFile(hdcmf
, hemf
, &rc
);
1150 hmf
= CloseMetaFile(hdcmf
);
1151 ret
= GetMetaFileBitsEx(hmf
, cbBuffer
, lpbBuffer
);
1152 DeleteMetaFile(hmf
);
1154 SetMapMode(hdcRef
, oldMapMode
);
1159 /******************************************************************
1160 * MF_Play_MetaCreateRegion
1162 * Handles META_CREATEREGION for PlayMetaFileRecord().
1164 * The layout of the record looks something like this:
1169 * 2 Looks like a handle? - not constant
1171 * 4 Total number of bytes
1172 * 5 No. of separate bands = n [see below]
1173 * 6 Largest number of x co-ords in a band
1174 * 7-10 Bounding box x1 y1 x2 y2
1177 * Regions are divided into bands that are uniform in the
1178 * y-direction. Each band consists of pairs of on/off x-coords and is
1180 * m y0 y1 x1 x2 x3 ... xm m
1181 * into successive rdParm[]s.
1183 * This is probably just a dump of the internal RGNOBJ?
1189 static BOOL
MF_Play_MetaCreateRegion( METARECORD
*mr
, HRGN hrgn
)
1194 HRGN hrgn2
= CreateRectRgn( 0, 0, 0, 0 );
1196 for(band
= 0, start
= &(mr
->rdParm
[11]); band
< mr
->rdParm
[5];
1197 band
++, start
= end
+ 1) {
1198 if(*start
/ 2 != (*start
+ 1) / 2) {
1199 WARN("Delimiter not even.\n");
1200 DeleteObject( hrgn2
);
1204 end
= start
+ *start
+ 3;
1205 if(end
> (WORD
*)mr
+ mr
->rdSize
) {
1206 WARN("End points outside record.\n");
1207 DeleteObject( hrgn2
);
1211 if(*start
!= *end
) {
1212 WARN("Mismatched delimiters.\n");
1213 DeleteObject( hrgn2
);
1217 y0
= *(INT16
*)(start
+ 1);
1218 y1
= *(INT16
*)(start
+ 2);
1219 for(pair
= 0; pair
< *start
/ 2; pair
++) {
1220 SetRectRgn( hrgn2
, *(INT16
*)(start
+ 3 + 2*pair
), y0
,
1221 *(INT16
*)(start
+ 4 + 2*pair
), y1
);
1222 CombineRgn(hrgn
, hrgn
, hrgn2
, RGN_OR
);
1225 DeleteObject( hrgn2
);
1230 /******************************************************************
1231 * MF_Play_MetaExtTextOut
1233 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1236 static BOOL
MF_Play_MetaExtTextOut(HDC hdc
, METARECORD
*mr
)
1245 BOOL isrect
= mr
->rdParm
[3] & (ETO_OPAQUE
| ETO_CLIPPED
);
1247 s1
= mr
->rdParm
[2]; /* String length */
1248 len
= sizeof(METARECORD
) + (((s1
+ 1) >> 1) * 2) + 2 * sizeof(short)
1249 + sizeof(UINT16
) + (isrect
? sizeof(RECT16
) : 0);
1250 /* rec len without dx array */
1252 sot
= (LPSTR
)&mr
->rdParm
[4]; /* start_of_text */
1255 rect
.left
= (SHORT
)mr
->rdParm
[4];
1256 rect
.top
= (SHORT
)mr
->rdParm
[5];
1257 rect
.right
= (SHORT
)mr
->rdParm
[6];
1258 rect
.bottom
= (SHORT
)mr
->rdParm
[7];
1259 sot
+= sizeof(RECT16
); /* there is a rectangle, so add offset */
1262 if (mr
->rdSize
== len
/ 2)
1263 dxx
= NULL
; /* determine if array present */
1265 if (mr
->rdSize
== (len
+ s1
* sizeof(INT16
)) / 2)
1267 dxx
= (LPINT16
)(sot
+(((s1
+1)>>1)*2));
1268 dx
= HeapAlloc( GetProcessHeap(), 0, s1
*sizeof(INT
));
1269 if (dx
) for (i
= 0; i
< s1
; i
++) dx
[i
] = (SHORT
)dxx
[i
];
1272 TRACE("%s len: %ld\n", sot
, mr
->rdSize
);
1273 WARN("Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1274 len
, s1
, mr
->rdSize
, mr
->rdParm
[3]);
1275 dxx
= NULL
; /* should't happen -- but if, we continue with NULL */
1278 (SHORT
)mr
->rdParm
[1], /* X position */
1279 (SHORT
)mr
->rdParm
[0], /* Y position */
1280 mr
->rdParm
[3], /* options */
1281 &rect
, /* rectangle */
1283 s1
, dx
); /* length, dx array */
1286 TRACE("%s len: %ld dx0: %d\n", sot
, mr
->rdSize
, dx
[0]);
1287 HeapFree( GetProcessHeap(), 0, dx
);