blob: 9c917eee7ed113fa03c98ef2d157830e278087b3 [file] [log] [blame]
Alexandre Julliard58199531994-04-21 01:20:00 +00001/*
2 * Metafile functions
3 *
4 * Copyright David W. Metcalfe, 1994
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +00005 * Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
Alexandre Julliard234bc241994-12-10 13:02:28 +00006 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00007 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard59730ae1996-03-24 16:20:51 +000020 */
Alexandre Julliard58199531994-04-21 01:20:00 +000021
Huw D M Daviesb94e4331999-04-15 16:46:51 +000022/*
23 * These functions are primarily involved with metafile playback or anything
24 * that touches a HMETAFILE.
25 * For recording of metafiles look in graphics/metafiledrv/
26 *
Vincent Béron9a624912002-05-31 23:06:46 +000027 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
Huw D M Daviesb94e4331999-04-15 16:46:51 +000028 * global memory handles so these cannot be interchanged.
29 *
30 * Memory-based metafiles are just stored as a continuous block of memory with
31 * a METAHEADER at the head with METARECORDs appended to it. mtType is
32 * METAFILE_MEMORY (1). Note this is indentical to the disk image of a
33 * disk-based metafile - even mtType is METAFILE_MEMORY.
34 * 16bit HMETAFILE16s are global handles to this block
35 * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to
36 * the memory.
37 * Disk-based metafiles are rather different. HMETAFILE16s point to a
38 * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9
39 * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1
40 * more 0, then 2 which may be a time stamp of the file and then the path of
41 * the file (METAHEADERDISK). I've copied this for 16bit compatibility.
42 *
43 * HDMD - 14/4/1999
Vincent Béron9a624912002-05-31 23:06:46 +000044 */
Huw D M Daviesb94e4331999-04-15 16:46:51 +000045
Patrik Stridvall33929be2001-07-18 21:04:23 +000046#include "config.h"
Huw D M Daviesb94e4331999-04-15 16:46:51 +000047
Alexandre Julliardaca05781994-10-17 18:12:41 +000048#include <string.h>
Alexandre Julliardade697e1995-11-26 13:59:11 +000049#include <fcntl.h>
Patrik Stridvall33929be2001-07-18 21:04:23 +000050
Marcus Meissner317af321999-02-17 13:51:06 +000051#include "wine/winbase16.h"
Patrik Stridvall33929be2001-07-18 21:04:23 +000052#include "wine/wingdi16.h"
Alexandre Julliard05df86a2004-03-04 20:41:12 +000053#include "gdi.h"
Michael Stefaniuc28a632a2002-11-21 21:50:04 +000054#include "wownt32.h"
Vincent Béron506ab8b2004-01-13 04:54:45 +000055#include "winreg.h"
56#include "winternl.h"
Alexandre Julliard6ec42c02004-01-15 00:35:38 +000057#include "gdi_private.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000058#include "wine/debug.h"
Alexandre Julliard58199531994-04-21 01:20:00 +000059
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000060WINE_DEFAULT_DEBUG_CHANNEL(metafile);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000061
Alexandre Julliardf899ef02001-07-23 00:04:00 +000062#include "pshpack1.h"
63typedef struct
64{
65 DWORD dw1, dw2, dw3;
66 WORD w4;
67 CHAR filename[0x100];
68} METAHEADERDISK;
69#include "poppack.h"
70
Alexandre Julliard78b041c2002-06-04 01:02:51 +000071typedef struct
72{
73 GDIOBJHDR header;
74 METAHEADER *mh;
75} METAFILEOBJ;
76
Alexandre Julliardf899ef02001-07-23 00:04:00 +000077#define MFHEADERSIZE (sizeof(METAHEADER))
78#define MFVERSION 0x300
79
Alexandre Julliarded29c902001-12-17 21:01:58 +000080
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000081/******************************************************************
82 * MF_AddHandle
83 *
84 * Add a handle to an external handle table and return the index
85 */
Alexandre Julliard15b9ed92002-10-18 03:33:37 +000086static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
Alexandre Julliardbf9130a1996-10-13 17:45:47 +000087{
88 int i;
89
90 for (i = 0; i < htlen; i++)
91 {
92 if (*(ht->objectHandle + i) == 0)
93 {
94 *(ht->objectHandle + i) = hobj;
95 return i;
96 }
97 }
98 return -1;
99}
100
101
102/******************************************************************
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000103 * MF_Create_HMETATFILE
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000104 *
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000105 * Creates a (32 bit) HMETAFILE object from a METAHEADER
106 *
107 * HMETAFILEs are GDI objects.
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000108 */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000109HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000110{
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000111 HMETAFILE hmf = 0;
Michael Stefaniuc28a632a2002-11-21 21:50:04 +0000112 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
113 (HGDIOBJ *)&hmf, NULL );
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000114 if (metaObj)
115 {
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000116 metaObj->mh = mh;
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000117 GDI_ReleaseObj( hmf );
118 }
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000119 return hmf;
Alexandre Julliardbf9130a1996-10-13 17:45:47 +0000120}
121
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000122/******************************************************************
123 * MF_Create_HMETATFILE16
124 *
125 * Creates a HMETAFILE16 object from a METAHEADER
126 *
127 * HMETAFILE16s are Global memory handles.
128 */
129HMETAFILE16 MF_Create_HMETAFILE16(METAHEADER *mh)
130{
131 HMETAFILE16 hmf;
Dmitry Timoshkov4328e512001-05-22 19:18:06 +0000132 DWORD size = mh->mtSize * sizeof(WORD);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000133
Dmitry Timoshkov4328e512001-05-22 19:18:06 +0000134 hmf = GlobalAlloc16(GMEM_MOVEABLE, size);
135 if(hmf)
136 {
137 METAHEADER *mh_dest = GlobalLock16(hmf);
138 memcpy(mh_dest, mh, size);
139 GlobalUnlock16(hmf);
140 }
141 HeapFree(GetProcessHeap(), 0, mh);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000142 return hmf;
143}
144
145/******************************************************************
146 * MF_GetMetaHeader
147 *
148 * Returns ptr to METAHEADER associated with HMETAFILE
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000149 */
150static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
151{
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000152 METAHEADER *ret = NULL;
Juergen Schmieda904e161999-07-10 10:09:58 +0000153 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000154 if (metaObj)
155 {
156 ret = metaObj->mh;
157 GDI_ReleaseObj( hmf );
158 }
159 return ret;
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000160}
161
162/******************************************************************
163 * MF_GetMetaHeader16
164 *
165 * Returns ptr to METAHEADER associated with HMETAFILE16
166 * Should be followed by call to MF_ReleaseMetaHeader16
167 */
168static METAHEADER *MF_GetMetaHeader16( HMETAFILE16 hmf )
169{
170 return GlobalLock16(hmf);
171}
172
173/******************************************************************
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000174 * MF_ReleaseMetaHeader16
175 *
176 * Releases METAHEADER associated with HMETAFILE16
177 */
178static BOOL16 MF_ReleaseMetaHeader16( HMETAFILE16 hmf )
179{
180 return GlobalUnlock16( hmf );
181}
182
183
184/******************************************************************
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000185 * convert_points
186 *
187 * Convert an array of POINT16 to an array of POINT.
188 * Result must be freed by caller.
189 */
190static POINT *convert_points( UINT count, POINT16 *pt16 )
191{
192 UINT i;
193 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
194 if (ret)
195 {
196 for (i = 0; i < count; i++)
197 {
198 ret[i].x = pt16[i].x;
199 ret[i].y = pt16[i].y;
200 }
201 }
202 return ret;
203}
204
205
206/******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +0000207 * DeleteMetaFile (GDI.127)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000208 */
209BOOL16 WINAPI DeleteMetaFile16( HMETAFILE16 hmf )
210{
211 return !GlobalFree16( hmf );
212}
213
214/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000215 * DeleteMetaFile (GDI32.@)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000216 *
217 * Delete a memory-based metafile.
218 */
219
220BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
221{
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000222 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
223 if (!metaObj) return FALSE;
224 HeapFree( GetProcessHeap(), 0, metaObj->mh );
225 GDI_FreeObject( hmf, metaObj );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000226 return TRUE;
227}
228
229/******************************************************************
230 * MF_ReadMetaFile
231 *
232 * Returns a pointer to a memory based METAHEADER read in from file HFILE
233 *
234 */
Alexandre Julliard267ca682002-07-31 17:20:00 +0000235static METAHEADER *MF_ReadMetaFile(HANDLE hfile)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000236{
237 METAHEADER *mh;
238 DWORD BytesRead, size;
239
240 size = sizeof(METAHEADER);
Alexandre Julliard90476d62000-02-16 22:47:24 +0000241 mh = HeapAlloc( GetProcessHeap(), 0, size );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000242 if(!mh) return NULL;
243 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
244 BytesRead != size) {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000245 HeapFree( GetProcessHeap(), 0, mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000246 return NULL;
247 }
248 size = mh->mtSize * 2;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000249 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000250 if(!mh) return NULL;
251 size -= sizeof(METAHEADER);
252 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
253 NULL) == 0 ||
254 BytesRead != size) {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000255 HeapFree( GetProcessHeap(), 0, mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000256 return NULL;
257 }
258
259 if (mh->mtType != METAFILE_MEMORY) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000260 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000261 mh->mtType = METAFILE_MEMORY;
262 }
263 return mh;
264}
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000265
Alexandre Julliard58199531994-04-21 01:20:00 +0000266/******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +0000267 * GetMetaFile (GDI.124)
Alexandre Julliard234bc241994-12-10 13:02:28 +0000268 */
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000269HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000270{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000271 METAHEADER *mh;
François Gougetda2b6a92001-01-06 01:29:18 +0000272 HANDLE hFile;
Vincent Béron9a624912002-05-31 23:06:46 +0000273
Alexandre Julliard15657091999-05-23 10:25:25 +0000274 TRACE("%s\n", lpFilename);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000275
276 if(!lpFilename)
277 return 0;
278
Huw D M Daviese9876341999-06-12 06:50:57 +0000279 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000280 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000281 return 0;
282
283 mh = MF_ReadMetaFile(hFile);
284 CloseHandle(hFile);
285 if(!mh) return 0;
286 return MF_Create_HMETAFILE16( mh );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000287}
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000288
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000289/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000290 * GetMetaFileA (GDI32.@)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000291 *
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000292 * Read a metafile from a file. Returns handle to a memory-based metafile.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000293 */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000294HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
Alexandre Julliard234bc241994-12-10 13:02:28 +0000295{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000296 METAHEADER *mh;
François Gougetda2b6a92001-01-06 01:29:18 +0000297 HANDLE hFile;
Vincent Béron9a624912002-05-31 23:06:46 +0000298
Alexandre Julliard15657091999-05-23 10:25:25 +0000299 TRACE("%s\n", lpFilename);
Alexandre Julliard234bc241994-12-10 13:02:28 +0000300
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000301 if(!lpFilename)
302 return 0;
Alexandre Julliard234bc241994-12-10 13:02:28 +0000303
Huw D M Daviese9876341999-06-12 06:50:57 +0000304 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000305 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000306 return 0;
Alexandre Julliard234bc241994-12-10 13:02:28 +0000307
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000308 mh = MF_ReadMetaFile(hFile);
309 CloseHandle(hFile);
310 if(!mh) return 0;
311 return MF_Create_HMETAFILE( mh );
Alexandre Julliard234bc241994-12-10 13:02:28 +0000312}
313
Alexandre Julliard58199531994-04-21 01:20:00 +0000314
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000315
Alexandre Julliard58199531994-04-21 01:20:00 +0000316/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000317 * GetMetaFileW (GDI32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000318 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000319HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000320{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000321 METAHEADER *mh;
François Gougetda2b6a92001-01-06 01:29:18 +0000322 HANDLE hFile;
Vincent Béron9a624912002-05-31 23:06:46 +0000323
Alexandre Julliard15657091999-05-23 10:25:25 +0000324 TRACE("%s\n", debugstr_w(lpFilename));
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000325
326 if(!lpFilename)
327 return 0;
328
Huw D M Daviese9876341999-06-12 06:50:57 +0000329 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000330 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000331 return 0;
332
333 mh = MF_ReadMetaFile(hFile);
334 CloseHandle(hFile);
335 if(!mh) return 0;
336 return MF_Create_HMETAFILE( mh );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000337}
338
339
340/******************************************************************
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000341 * MF_LoadDiskBasedMetaFile
342 *
343 * Creates a new memory-based metafile from a disk-based one.
344 */
345static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
346{
347 METAHEADERDISK *mhd;
François Gougetda2b6a92001-01-06 01:29:18 +0000348 HANDLE hfile;
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000349 METAHEADER *mh2;
350
351 if(mh->mtType != METAFILE_DISK) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000352 ERR("Not a disk based metafile\n");
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000353 return NULL;
354 }
355 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
356
Huw D M Daviese9876341999-06-12 06:50:57 +0000357 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000358 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000359 WARN("Can't open file of disk based metafile\n");
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000360 return NULL;
361 }
362 mh2 = MF_ReadMetaFile(hfile);
363 CloseHandle(hfile);
364 return mh2;
365}
366
367/******************************************************************
368 * MF_CreateMetaHeaderDisk
369 *
370 * Take a memory based METAHEADER and change it to a disk based METAHEADER
Vincent Béron9a624912002-05-31 23:06:46 +0000371 * assosiated with filename. Note: Trashes contents of old one.
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000372 */
Mike McCormack4eaf41b2004-03-29 20:27:18 +0000373METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000374{
375 METAHEADERDISK *mhd;
376 DWORD size;
377
Alexandre Julliard90476d62000-02-16 22:47:24 +0000378 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000379 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
380 mh->mtType = METAFILE_DISK;
Alexandre Julliard90476d62000-02-16 22:47:24 +0000381 size = HeapSize( GetProcessHeap(), 0, mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000382 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
Mike McCormack4eaf41b2004-03-29 20:27:18 +0000383
384 if( uni )
385 WideCharToMultiByte(CP_ACP, 0, filename, -1,
386 mhd->filename, sizeof mhd->filename, NULL, NULL);
387 else
388 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000389 return mh;
390}
391
392/******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +0000393 * CopyMetaFile (GDI.151)
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000394 */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000395HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000396{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000397 METAHEADER *mh = MF_GetMetaHeader16( hSrcMetaFile );
398 METAHEADER *mh2 = NULL;
François Gougetda2b6a92001-01-06 01:29:18 +0000399 HANDLE hFile;
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000400
Alexandre Julliard15657091999-05-23 10:25:25 +0000401 TRACE("(%08x,%s)\n", hSrcMetaFile, lpFilename);
Vincent Béron9a624912002-05-31 23:06:46 +0000402
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000403 if(!mh) return 0;
Vincent Béron9a624912002-05-31 23:06:46 +0000404
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000405 if(mh->mtType == METAFILE_DISK)
406 mh2 = MF_LoadDiskBasedMetaFile(mh);
407 else {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000408 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000409 memcpy( mh2, mh, mh->mtSize * 2 );
410 }
411 MF_ReleaseMetaHeader16( hSrcMetaFile );
412
413 if(lpFilename) { /* disk based metafile */
414 if((hFile = CreateFileA(lpFilename, GENERIC_WRITE, 0, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000415 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000416 HeapFree( GetProcessHeap(), 0, mh2 );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000417 return 0;
418 }
419 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
420 CloseHandle(hFile);
Mike McCormack4eaf41b2004-03-29 20:27:18 +0000421 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, FALSE);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000422 }
423
424 return MF_Create_HMETAFILE16( mh2 );
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000425}
426
427
428/******************************************************************
Vincent Béron506ab8b2004-01-13 04:54:45 +0000429 * CopyMetaFileW (GDI32.@)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000430 *
431 * Copies the metafile corresponding to hSrcMetaFile to either
432 * a disk file, if a filename is given, or to a new memory based
433 * metafile, if lpFileName is NULL.
434 *
435 * RETURNS
436 *
437 * Handle to metafile copy on success, NULL on failure.
438 *
439 * BUGS
440 *
441 * Copying to disk returns NULL even if successful.
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000442 */
Vincent Béron506ab8b2004-01-13 04:54:45 +0000443HMETAFILE WINAPI CopyMetaFileW(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000444 HMETAFILE hSrcMetaFile, /* [in] handle of metafile to copy */
Jon Griffiths783a3952004-02-09 20:47:42 +0000445 LPCWSTR lpFilename /* [in] filename if copying to a file */)
446{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000447 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
448 METAHEADER *mh2 = NULL;
François Gougetda2b6a92001-01-06 01:29:18 +0000449 HANDLE hFile;
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000450
Vincent Béron506ab8b2004-01-13 04:54:45 +0000451 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
Vincent Béron9a624912002-05-31 23:06:46 +0000452
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000453 if(!mh) return 0;
Vincent Béron9a624912002-05-31 23:06:46 +0000454
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000455 if(mh->mtType == METAFILE_DISK)
456 mh2 = MF_LoadDiskBasedMetaFile(mh);
457 else {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000458 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000459 memcpy( mh2, mh, mh->mtSize * 2 );
460 }
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000461
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000462 if(lpFilename) { /* disk based metafile */
Vincent Béron506ab8b2004-01-13 04:54:45 +0000463 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +0000464 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
Alexandre Julliard90476d62000-02-16 22:47:24 +0000465 HeapFree( GetProcessHeap(), 0, mh2 );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000466 return 0;
467 }
468 WriteFile(hFile, mh2, mh2->mtSize * 2, NULL, NULL);
469 CloseHandle(hFile);
Mike McCormack4eaf41b2004-03-29 20:27:18 +0000470 mh2 = MF_CreateMetaHeaderDisk(mh2, lpFilename, TRUE);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000471 }
472
473 return MF_Create_HMETAFILE( mh2 );
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000474}
475
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000476
477/******************************************************************
Vincent Béron506ab8b2004-01-13 04:54:45 +0000478 * CopyMetaFileA (GDI32.@)
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000479 */
Vincent Béron506ab8b2004-01-13 04:54:45 +0000480HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile,
481 LPCSTR lpFilename )
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000482{
Vincent Béron506ab8b2004-01-13 04:54:45 +0000483 UNICODE_STRING lpFilenameW;
Alexandre Julliard193cf502002-01-01 00:24:30 +0000484 HMETAFILE ret = 0;
Alexandre Julliard193cf502002-01-01 00:24:30 +0000485
Vincent Béron506ab8b2004-01-13 04:54:45 +0000486 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
487 else lpFilenameW.Buffer = NULL;
488
Huw Davies766315e2004-04-19 20:13:31 +0000489 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
490 if (lpFilenameW.Buffer)
491 RtlFreeUnicodeString(&lpFilenameW);
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +0000492 return ret;
493}
494
495
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000496/******************************************************************
497 * IsValidMetaFile (GDI.410)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000498 *
499 * Attempts to check if a given metafile is correctly formatted.
500 * Currently, the only things verified are several properties of the
501 * header.
502 *
503 * RETURNS
504 * TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
505 *
506 * BUGS
507 * This is not exactly what windows does, see _Undocumented_Windows_
508 * for details.
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000509 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000510BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000511{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000512 BOOL16 res=FALSE;
513 METAHEADER *mh = MF_GetMetaHeader16(hmf);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000514 if (mh) {
Vincent Béron9a624912002-05-31 23:06:46 +0000515 if (mh->mtType == METAFILE_MEMORY || mh->mtType == METAFILE_DISK)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000516 if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
517 if (mh->mtVersion == MFVERSION)
518 res=TRUE;
519 MF_ReleaseMetaHeader16(hmf);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000520 }
Alexandre Julliard15657091999-05-23 10:25:25 +0000521 TRACE("IsValidMetaFile %x => %d\n",hmf,res);
Vincent Béron9a624912002-05-31 23:06:46 +0000522 return res;
Alexandre Julliard8cc3a5e1996-08-11 15:49:51 +0000523}
524
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000525
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000526/*******************************************************************
527 * MF_PlayMetaFile
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000528 *
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000529 * Helper for PlayMetaFile
Alexandre Julliard58199531994-04-21 01:20:00 +0000530 */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000531static BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
Alexandre Julliard58199531994-04-21 01:20:00 +0000532{
Alexandre Julliard58199531994-04-21 01:20:00 +0000533
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000534 METARECORD *mr;
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000535 HANDLETABLE *ht;
Joerg Mayer4d756402001-01-10 22:45:33 +0000536 unsigned int offset = 0;
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000537 WORD i;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000538 HPEN hPen;
539 HBRUSH hBrush;
540 HFONT hFont;
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000541 BOOL loaded = FALSE;
542
Alexandre Julliard491502b1997-11-01 19:08:16 +0000543 if (!mh) return FALSE;
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000544 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000545 mh = MF_LoadDiskBasedMetaFile(mh);
546 if(!mh) return FALSE;
547 loaded = TRUE;
548 }
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000549
550 /* save the current pen, brush and font */
Huw D M Davies7c57a721999-12-20 03:56:09 +0000551 hPen = GetCurrentObject(hdc, OBJ_PEN);
552 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
553 hFont = GetCurrentObject(hdc, OBJ_FONT);
554
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000555 /* create the handle table */
Alexandre Julliard90476d62000-02-16 22:47:24 +0000556 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000557 sizeof(HANDLETABLE) * mh->mtNoObjects);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000558 if(!ht) return FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +0000559
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000560 /* loop through metafile playing records */
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000561 offset = mh->mtHeaderSize * 2;
562 while (offset < mh->mtSize * 2)
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000563 {
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000564 mr = (METARECORD *)((char *)mh + offset);
Alexandre Julliard15657091999-05-23 10:25:25 +0000565 TRACE("offset=%04x,size=%08lx\n",
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000566 offset, mr->rdSize);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000567 if (!mr->rdSize) {
Alexandre Julliard15657091999-05-23 10:25:25 +0000568 TRACE(
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000569 "Entry got size 0 at offset %d, total mf length is %ld\n",
570 offset,mh->mtSize*2);
Alexandre Julliard44ed71f1997-12-21 19:17:50 +0000571 break; /* would loop endlessly otherwise */
572 }
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000573 offset += mr->rdSize * 2;
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000574 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000575 }
576
Alexandre Julliarda3960291999-02-26 11:11:13 +0000577 SelectObject(hdc, hBrush);
578 SelectObject(hdc, hPen);
579 SelectObject(hdc, hFont);
Alexandre Julliard349a9531997-02-02 19:01:52 +0000580
Alexandre Julliard2ace16a1996-04-28 15:09:19 +0000581 /* free objects in handle table */
582 for(i = 0; i < mh->mtNoObjects; i++)
583 if(*(ht->objectHandle + i) != 0)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000584 DeleteObject(*(ht->objectHandle + i));
Vincent Béron9a624912002-05-31 23:06:46 +0000585
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000586 /* free handle table */
Alexandre Julliard90476d62000-02-16 22:47:24 +0000587 HeapFree( GetProcessHeap(), 0, ht );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000588 if(loaded)
Alexandre Julliard90476d62000-02-16 22:47:24 +0000589 HeapFree( GetProcessHeap(), 0, mh );
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000590 return TRUE;
591}
592
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000593/******************************************************************
Patrik Stridvall17fd4e32001-06-28 18:04:41 +0000594 * PlayMetaFile (GDI.123)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000595 *
596 */
597BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
598{
599 BOOL16 ret;
600 METAHEADER *mh = MF_GetMetaHeader16( hmf );
Michael Stefaniuc28a632a2002-11-21 21:50:04 +0000601 ret = MF_PlayMetaFile( HDC_32(hdc), mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000602 MF_ReleaseMetaHeader16( hmf );
603 return ret;
604}
605
606/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000607 * PlayMetaFile (GDI32.@)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000608 *
609 * Renders the metafile specified by hmf in the DC specified by
610 * hdc. Returns FALSE on failure, TRUE on success.
611 */
Vincent Béron9a624912002-05-31 23:06:46 +0000612BOOL WINAPI PlayMetaFile(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +0000613 HDC hdc, /* [in] handle of DC to render in */
614 HMETAFILE hmf /* [in] handle of metafile to render */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000615)
616{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000617 METAHEADER *mh = MF_GetMetaHeader( hmf );
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000618 return MF_PlayMetaFile( hdc, mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000619}
620
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000621
622/******************************************************************
Patrik Stridvall19d66cc2002-01-07 21:16:46 +0000623 * EnumMetaFile (GDI.175)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000624 *
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000625 */
Michael Stefaniuc28a632a2002-11-21 21:50:04 +0000626BOOL16 WINAPI EnumMetaFile16( HDC16 hdc16, HMETAFILE16 hmf,
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000627 MFENUMPROC16 lpEnumFunc, LPARAM lpData )
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000628{
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000629 METAHEADER *mh = MF_GetMetaHeader16(hmf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000630 METARECORD *mr;
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000631 HANDLETABLE16 *ht;
Michael Stefaniuc28a632a2002-11-21 21:50:04 +0000632 HDC hdc = HDC_32(hdc16);
Alexandre Julliard2c69f6d1996-09-28 18:11:01 +0000633 HGLOBAL16 hHT;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000634 SEGPTR spht;
Joerg Mayer4d756402001-01-10 22:45:33 +0000635 unsigned int offset = 0;
Alexandre Julliard03468f71998-02-15 19:40:49 +0000636 WORD i, seg;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000637 HPEN hPen;
638 HBRUSH hBrush;
639 HFONT hFont;
Alexandre Julliard7e92c9a2003-02-27 21:09:45 +0000640 WORD args[8];
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000641 BOOL16 result = TRUE, loaded = FALSE;
642
Alexandre Julliard547cdc22002-11-22 22:16:53 +0000643 TRACE("(%p, %04x, %p, %08lx)\n", hdc, hmf, lpEnumFunc, lpData);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000644
645 if(!mh) return FALSE;
Alexandre Julliard2a2321b2000-08-19 21:38:55 +0000646 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000647 mh = MF_LoadDiskBasedMetaFile(mh);
648 if(!mh) return FALSE;
649 loaded = TRUE;
650 }
651
Huw D M Davies7c57a721999-12-20 03:56:09 +0000652 /* save the current pen, brush and font */
653 hPen = GetCurrentObject(hdc, OBJ_PEN);
654 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
655 hFont = GetCurrentObject(hdc, OBJ_FONT);
Alexandre Julliard670cdc41997-08-24 16:00:30 +0000656
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000657 /* create the handle table */
Vincent Béron9a624912002-05-31 23:06:46 +0000658
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000659 hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
Alexandre Julliardf1aa3031996-08-05 17:42:43 +0000660 sizeof(HANDLETABLE16) * mh->mtNoObjects);
Alexandre Julliard58017232000-12-22 01:09:26 +0000661 spht = K32WOWGlobalLock16(hHT);
Vincent Béron9a624912002-05-31 23:06:46 +0000662
Alexandre Julliard95153362001-03-23 19:13:23 +0000663 seg = hmf | 7;
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000664 offset = mh->mtHeaderSize * 2;
Vincent Béron9a624912002-05-31 23:06:46 +0000665
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000666 /* loop through metafile records */
Vincent Béron9a624912002-05-31 23:06:46 +0000667
Alexandre Julliard7e92c9a2003-02-27 21:09:45 +0000668 args[7] = hdc16;
669 args[6] = SELECTOROF(spht);
670 args[5] = OFFSETOF(spht);
671 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
672 args[3] = LOWORD(offset);
673 args[2] = mh->mtNoObjects;
674 args[1] = HIWORD(lpData);
675 args[0] = LOWORD(lpData);
676
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000677 while (offset < (mh->mtSize * 2))
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000678 {
Alexandre Julliard7e92c9a2003-02-27 21:09:45 +0000679 DWORD ret;
680
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000681 mr = (METARECORD *)((char *)mh + offset);
Alexandre Julliarded29c902001-12-17 21:01:58 +0000682
Alexandre Julliard7e92c9a2003-02-27 21:09:45 +0000683 WOWCallback16Ex( (DWORD)lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &ret );
684 if (!LOWORD(ret))
Alexandre Julliard03468f71998-02-15 19:40:49 +0000685 {
686 result = FALSE;
687 break;
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000688 }
Vincent Béron9a624912002-05-31 23:06:46 +0000689
Alexandre Julliardcdcdede1996-04-21 14:57:41 +0000690 offset += (mr->rdSize * 2);
Alexandre Julliard7e92c9a2003-02-27 21:09:45 +0000691 args[4] = seg + (HIWORD(offset) << __AHSHIFT);
692 args[3] = LOWORD(offset);
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000693 }
694
Alexandre Julliarda3960291999-02-26 11:11:13 +0000695 SelectObject(hdc, hBrush);
696 SelectObject(hdc, hPen);
697 SelectObject(hdc, hFont);
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000698
699 ht = (HANDLETABLE16 *)GlobalLock16(hHT);
700
701 /* free objects in handle table */
702 for(i = 0; i < mh->mtNoObjects; i++)
703 if(*(ht->objectHandle + i) != 0)
Alexandre Julliard6c428e52002-11-22 21:58:03 +0000704 DeleteObject( (HGDIOBJ)(ULONG_PTR)(*(ht->objectHandle + i) ));
Alexandre Julliard23946ad1997-06-16 17:43:53 +0000705
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000706 /* free handle table */
Alexandre Julliard1285c2f1996-05-06 16:06:24 +0000707 GlobalFree16(hHT);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000708 if(loaded)
Alexandre Julliard90476d62000-02-16 22:47:24 +0000709 HeapFree( GetProcessHeap(), 0, mh );
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000710 MF_ReleaseMetaHeader16(hmf);
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000711 return result;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000712}
713
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000714/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000715 * EnumMetaFile (GDI32.@)
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000716 *
717 * Loop through the metafile records in hmf, calling the user-specified
718 * function for each one, stopping when the user's function returns FALSE
719 * (which is considered to be failure)
Vincent Béron9a624912002-05-31 23:06:46 +0000720 * or when no records are left (which is considered to be success).
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000721 *
722 * RETURNS
723 * TRUE on success, FALSE on failure.
Vincent Béron9a624912002-05-31 23:06:46 +0000724 *
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000725 * HISTORY
726 * Niels de carpentier, april 1996
727 */
Vincent Béron9a624912002-05-31 23:06:46 +0000728BOOL WINAPI EnumMetaFile(
729 HDC hdc,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000730 HMETAFILE hmf,
Vincent Béron9a624912002-05-31 23:06:46 +0000731 MFENUMPROC lpEnumFunc,
Jon Griffiths783a3952004-02-09 20:47:42 +0000732 LPARAM lpData)
733{
Alexandre Julliardab86a9e2000-09-19 02:37:48 +0000734 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000735 METARECORD *mr;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000736 HANDLETABLE *ht;
Alexandre Julliardab86a9e2000-09-19 02:37:48 +0000737 BOOL result = TRUE;
Joerg Mayer4d756402001-01-10 22:45:33 +0000738 int i;
739 unsigned int offset = 0;
Alexandre Julliarda3960291999-02-26 11:11:13 +0000740 HPEN hPen;
741 HBRUSH hBrush;
742 HFONT hFont;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000743
Alexandre Julliard547cdc22002-11-22 22:16:53 +0000744 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000745 if (!mh) return 0;
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000746 if(mh->mtType == METAFILE_DISK)
Alexandre Julliardab86a9e2000-09-19 02:37:48 +0000747 {
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000748 /* Create a memory-based copy */
749 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
Alexandre Julliardab86a9e2000-09-19 02:37:48 +0000750 mh = mhTemp;
751 }
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000752
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000753 /* save the current pen, brush and font */
Huw D M Davies7c57a721999-12-20 03:56:09 +0000754 hPen = GetCurrentObject(hdc, OBJ_PEN);
755 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
756 hFont = GetCurrentObject(hdc, OBJ_FONT);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000757
Vincent Béron9a624912002-05-31 23:06:46 +0000758 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
Alexandre Julliarda3960291999-02-26 11:11:13 +0000759 sizeof(HANDLETABLE) * mh->mtNoObjects);
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000760
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000761 /* loop through metafile records */
762 offset = mh->mtHeaderSize * 2;
Vincent Béron9a624912002-05-31 23:06:46 +0000763
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000764 while (offset < (mh->mtSize * 2))
765 {
766 mr = (METARECORD *)((char *)mh + offset);
Huw D M Davies43ff7d22002-04-03 22:46:32 +0000767 if(mr->rdFunction == META_EOF) {
768 TRACE("Got META_EOF so stopping\n");
769 break;
770 }
Alexandre Julliard15657091999-05-23 10:25:25 +0000771 TRACE("Calling EnumFunc with record type %x\n",
Huw D M Davies56166a61999-04-19 16:45:24 +0000772 mr->rdFunction);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000773 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
774 {
775 result = FALSE;
776 break;
777 }
Vincent Béron9a624912002-05-31 23:06:46 +0000778
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000779 offset += (mr->rdSize * 2);
780 }
781
782 /* restore pen, brush and font */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000783 SelectObject(hdc, hBrush);
784 SelectObject(hdc, hPen);
785 SelectObject(hdc, hFont);
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000786
787 /* free objects in handle table */
788 for(i = 0; i < mh->mtNoObjects; i++)
789 if(*(ht->objectHandle + i) != 0)
Alexandre Julliarda3960291999-02-26 11:11:13 +0000790 DeleteObject(*(ht->objectHandle + i));
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000791
792 /* free handle table */
Alexandre Julliard90476d62000-02-16 22:47:24 +0000793 HeapFree( GetProcessHeap(), 0, ht);
Alexandre Julliardab86a9e2000-09-19 02:37:48 +0000794 /* free a copy of metafile */
Alexandre Julliard8af0eda2001-08-23 23:37:00 +0000795 if (mhTemp) HeapFree( GetProcessHeap(), 0, mhTemp );
Alexandre Julliard46ea8b31998-05-03 19:01:20 +0000796 return result;
797}
798
Huw D M Daviesb94e4331999-04-15 16:46:51 +0000799static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000800static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000801/******************************************************************
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000802 * PlayMetaFileRecord (GDI32.@)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000803 *
804 * Render a single metafile record specified by *mr in the DC hdc, while
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000805 * using the handle table *ht, of length handles,
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000806 * to store metafile objects.
807 *
808 * BUGS
809 * The following metafile records are unimplemented:
810 *
Huw D M Davies7603dea1999-04-25 09:24:23 +0000811 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
Alexandre Julliard60ce85c1998-02-01 18:33:27 +0000812 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
813 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000814 */
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000815BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
816{
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000817 short s1;
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000818 POINT *pt;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000819 BITMAPINFOHEADER *infohdr;
820
Alexandre Julliard547cdc22002-11-22 22:16:53 +0000821 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
Vincent Béron9a624912002-05-31 23:06:46 +0000822
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000823 switch (mr->rdFunction)
824 {
Alexandre Julliard234bc241994-12-10 13:02:28 +0000825 case META_EOF:
Huw D M Davies56166a61999-04-19 16:45:24 +0000826 break;
Alexandre Julliard234bc241994-12-10 13:02:28 +0000827
828 case META_DELETEOBJECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000829 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
830 *(ht->objectHandle + mr->rdParm[0]) = 0;
831 break;
Alexandre Julliard234bc241994-12-10 13:02:28 +0000832
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000833 case META_SETBKCOLOR:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000834 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
835 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000836
837 case META_SETBKMODE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000838 SetBkMode(hdc, mr->rdParm[0]);
839 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000840
841 case META_SETMAPMODE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000842 SetMapMode(hdc, mr->rdParm[0]);
843 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000844
845 case META_SETROP2:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000846 SetROP2(hdc, mr->rdParm[0]);
847 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000848
849 case META_SETRELABS:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000850 SetRelAbs(hdc, mr->rdParm[0]);
851 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000852
853 case META_SETPOLYFILLMODE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000854 SetPolyFillMode(hdc, mr->rdParm[0]);
855 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000856
857 case META_SETSTRETCHBLTMODE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000858 SetStretchBltMode(hdc, mr->rdParm[0]);
859 break;
Alexandre Julliard0623a6f1998-01-18 18:01:49 +0000860
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000861 case META_SETTEXTCOLOR:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000862 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
863 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000864
865 case META_SETWINDOWORG:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000866 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
867 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000868
869 case META_SETWINDOWEXT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000870 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
871 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000872
873 case META_SETVIEWPORTORG:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000874 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
875 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000876
877 case META_SETVIEWPORTEXT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000878 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
879 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000880
881 case META_OFFSETWINDOWORG:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000882 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
883 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000884
885 case META_SCALEWINDOWEXT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000886 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
887 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
888 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000889
890 case META_OFFSETVIEWPORTORG:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000891 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
892 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000893
894 case META_SCALEVIEWPORTEXT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000895 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
896 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
897 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000898
899 case META_LINETO:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000900 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
901 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000902
903 case META_MOVETO:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000904 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
905 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000906
907 case META_EXCLUDECLIPRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000908 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
909 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
910 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000911
912 case META_INTERSECTCLIPRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000913 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
914 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
915 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000916
917 case META_ARC:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000918 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
919 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
920 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
921 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
922 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000923
924 case META_ELLIPSE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000925 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
926 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
927 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000928
929 case META_FLOODFILL:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000930 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
931 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
932 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000933
934 case META_PIE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000935 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
936 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
937 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
938 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
939 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000940
941 case META_RECTANGLE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000942 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
943 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
944 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000945
946 case META_ROUNDRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000947 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
948 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
949 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
950 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000951
952 case META_PATBLT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000953 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
954 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
955 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
956 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000957
958 case META_SAVEDC:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000959 SaveDC(hdc);
960 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000961
962 case META_SETPIXEL:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000963 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
964 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
965 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000966
967 case META_OFFSETCLIPRGN:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000968 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
969 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000970
971 case META_TEXTOUT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000972 s1 = mr->rdParm[0];
973 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
974 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
975 (char *)(mr->rdParm + 1), s1);
976 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000977
978 case META_POLYGON:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000979 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
980 {
981 Polygon(hdc, pt, mr->rdParm[0]);
982 HeapFree( GetProcessHeap(), 0, pt );
983 }
984 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +0000985
Alexandre Julliard234bc241994-12-10 13:02:28 +0000986 case META_POLYPOLYGON:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +0000987 {
988 UINT i, total;
989 SHORT *counts = (SHORT *)(mr->rdParm + 1);
990
991 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
992 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
993 if (pt)
994 {
995 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
996 if (cnt32)
997 {
998 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
999 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
1000 HeapFree( GetProcessHeap(), 0, cnt32 );
1001 }
1002 }
1003 HeapFree( GetProcessHeap(), 0, pt );
1004 }
1005 break;
Alexandre Julliard234bc241994-12-10 13:02:28 +00001006
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001007 case META_POLYLINE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001008 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
1009 {
1010 Polyline( hdc, pt, mr->rdParm[0] );
1011 HeapFree( GetProcessHeap(), 0, pt );
1012 }
1013 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001014
1015 case META_RESTOREDC:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001016 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
1017 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001018
1019 case META_SELECTOBJECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001020 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
1021 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001022
1023 case META_CHORD:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001024 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1025 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1026 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1027 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1028 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001029
1030 case META_CREATEPATTERNBRUSH:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001031 switch (mr->rdParm[0])
1032 {
1033 case BS_PATTERN:
1034 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1035 MF_AddHandle(ht, handles,
1036 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
1037 infohdr->biHeight,
1038 infohdr->biPlanes,
1039 infohdr->biBitCount,
1040 (LPSTR)(mr->rdParm +
1041 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
1042 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001043
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001044 case BS_DIBPATTERN:
1045 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
1046 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
1047 break;
Huw D M Davies56166a61999-04-19 16:45:24 +00001048
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001049 default:
1050 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
1051 mr->rdParm[0]);
1052 break;
1053 }
1054 break;
Vincent Béron9a624912002-05-31 23:06:46 +00001055
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001056 case META_CREATEPENINDIRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001057 {
1058 LOGPEN pen;
1059 pen.lopnStyle = mr->rdParm[0];
1060 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
1061 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
1062 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
1063 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
1064 }
1065 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001066
Alexandre Julliard988ca971994-06-21 16:15:21 +00001067 case META_CREATEFONTINDIRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001068 {
1069 LOGFONTA font;
1070 font.lfHeight = (SHORT)mr->rdParm[0];
1071 font.lfWidth = (SHORT)mr->rdParm[1];
1072 font.lfEscapement = (SHORT)mr->rdParm[2];
1073 font.lfOrientation = (SHORT)mr->rdParm[3];
1074 font.lfWeight = (SHORT)mr->rdParm[4];
1075 font.lfItalic = LOBYTE(mr->rdParm[5]);
1076 font.lfUnderline = HIBYTE(mr->rdParm[5]);
1077 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
1078 font.lfCharSet = HIBYTE(mr->rdParm[6]);
1079 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
1080 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
1081 font.lfQuality = LOBYTE(mr->rdParm[8]);
1082 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
1083 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
1084 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
1085 }
1086 break;
Alexandre Julliard988ca971994-06-21 16:15:21 +00001087
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001088 case META_CREATEBRUSHINDIRECT:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001089 {
1090 LOGBRUSH brush;
1091 brush.lbStyle = mr->rdParm[0];
1092 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
1093 brush.lbHatch = mr->rdParm[3];
1094 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
1095 }
1096 break;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001097
Alexandre Julliard902da691995-11-05 14:39:02 +00001098 case META_CREATEPALETTE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001099 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
1100 break;
Alexandre Julliard902da691995-11-05 14:39:02 +00001101
1102 case META_SETTEXTALIGN:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001103 SetTextAlign(hdc, mr->rdParm[0]);
1104 break;
Alexandre Julliard902da691995-11-05 14:39:02 +00001105
1106 case META_SELECTPALETTE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001107 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
1108 break;
Alexandre Julliard902da691995-11-05 14:39:02 +00001109
1110 case META_SETMAPPERFLAGS:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001111 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1112 break;
Alexandre Julliard902da691995-11-05 14:39:02 +00001113
1114 case META_REALIZEPALETTE:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001115 GDIRealizePalette(hdc);
1116 break;
Alexandre Julliard902da691995-11-05 14:39:02 +00001117
1118 case META_ESCAPE:
Huw Davies187c2b42003-05-11 03:07:03 +00001119 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
Alexandre Julliard902da691995-11-05 14:39:02 +00001120 break;
1121
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001122 case META_EXTTEXTOUT:
Huw D M Davies56166a61999-04-19 16:45:24 +00001123 MF_Play_MetaExtTextOut( hdc, mr );
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001124 break;
Vincent Béron9a624912002-05-31 23:06:46 +00001125
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001126 case META_STRETCHDIB:
1127 {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001128 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
1129 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1130 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1131 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1132 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001133 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001134 }
1135 break;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001136
1137 case META_DIBSTRETCHBLT:
1138 {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001139 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
1140 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
1141 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1142 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1143 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001144 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001145 }
Vincent Béron9a624912002-05-31 23:06:46 +00001146 break;
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001147
1148 case META_STRETCHBLT:
1149 {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001150 HDC hdcSrc = CreateCompatibleDC(hdc);
1151 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
1152 mr->rdParm[11], /*Height*/
1153 mr->rdParm[13], /*Planes*/
1154 mr->rdParm[14], /*BitsPixel*/
1155 (LPSTR)&mr->rdParm[15]); /*bits*/
1156 SelectObject(hdcSrc,hbitmap);
1157 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
1158 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
1159 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
1160 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1161 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
1162 DeleteDC(hdcSrc);
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001163 }
1164 break;
1165
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001166 case META_BITBLT:
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001167 {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001168 HDC hdcSrc = CreateCompatibleDC(hdc);
1169 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001170 mr->rdParm[8]/*Height*/,
1171 mr->rdParm[10]/*Planes*/,
1172 mr->rdParm[11]/*BitsPixel*/,
1173 (LPSTR)&mr->rdParm[12]/*bits*/);
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001174 SelectObject(hdcSrc,hbitmap);
1175 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
1176 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
1177 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001178 MAKELONG(0,mr->rdParm[0]));
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001179 DeleteDC(hdcSrc);
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001180 }
1181 break;
Alexandre Julliard889f7421997-04-15 17:19:52 +00001182
Alexandre Julliard889f7421997-04-15 17:19:52 +00001183 case META_CREATEREGION:
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001184 {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001185 HRGN hrgn = CreateRectRgn(0,0,0,0);
Vincent Béron9a624912002-05-31 23:06:46 +00001186
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001187 MF_Play_MetaCreateRegion(mr, hrgn);
1188 MF_AddHandle(ht, handles, hrgn);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001189 }
1190 break;
Alexandre Julliard889f7421997-04-15 17:19:52 +00001191
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001192 case META_FILLREGION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001193 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
1194 *(ht->objectHandle + mr->rdParm[0]));
Huw D M Davies7603dea1999-04-25 09:24:23 +00001195 break;
1196
1197 case META_FRAMEREGION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001198 FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
1199 *(ht->objectHandle + mr->rdParm[2]),
1200 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
Alexandre Julliard889f7421997-04-15 17:19:52 +00001201 break;
1202
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001203 case META_INVERTREGION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001204 InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
Vincent Béron9a624912002-05-31 23:06:46 +00001205 break;
Alexandre Julliard889f7421997-04-15 17:19:52 +00001206
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001207 case META_PAINTREGION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001208 PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
Alexandre Julliard889f7421997-04-15 17:19:52 +00001209 break;
1210
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001211 case META_SELECTCLIPREGION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001212 SelectClipRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
1213 break;
Alexandre Julliard889f7421997-04-15 17:19:52 +00001214
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001215 case META_DIBCREATEPATTERNBRUSH:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001216 /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
1217 but there's no difference */
1218 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1219 break;
Alexandre Julliard84c70f51997-05-09 08:40:27 +00001220
Huw D M Davies56166a61999-04-19 16:45:24 +00001221 case META_DIBBITBLT:
1222 /* In practice I've found that there are two layouts for
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001223 META_DIBBITBLT, one (the first here) is the usual one when a src
1224 dc is actually passed to it, the second occurs when the src dc is
1225 passed in as NULL to the creating BitBlt. As the second case has
1226 no dib, a size check will suffice to distinguish.
Caolan McNamara8e5e5881999-03-13 12:47:36 +00001227
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001228 Caolan.McNamara@ul.ie */
Caolan McNamara8e5e5881999-03-13 12:47:36 +00001229
Huw D M Davies56166a61999-04-19 16:45:24 +00001230 if (mr->rdSize > 12) {
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001231 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1232 LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize(info, mr->rdParm[0]);
Huw D M Davies56166a61999-04-19 16:45:24 +00001233
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001234 StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1235 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1236 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1237 DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1238 }
1239 else /* equivalent to a PatBlt */
1240 PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1241 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1242 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1243 break;
Vincent Béron9a624912002-05-31 23:06:46 +00001244
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001245 case META_SETTEXTCHAREXTRA:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001246 SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1247 break;
Alexandre Julliard491502b1997-11-01 19:08:16 +00001248
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001249 case META_SETTEXTJUSTIFICATION:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001250 SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1251 break;
Alexandre Julliard7ff1c411997-05-25 13:58:18 +00001252
Caolan McNamaraae8a7481999-03-14 13:40:12 +00001253 case META_EXTFLOODFILL:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001254 ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1255 MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1256 mr->rdParm[0]);
Caolan McNamaraae8a7481999-03-14 13:40:12 +00001257 break;
1258
Huw D M Davies56166a61999-04-19 16:45:24 +00001259 case META_SETDIBTODEV:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001260 {
1261 BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1262 char *bits = (char *)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
1263 SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1264 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1265 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1266 mr->rdParm[2], mr->rdParm[1], bits, info,
1267 mr->rdParm[0]);
1268 break;
1269 }
Huw D M Davies56166a61999-04-19 16:45:24 +00001270
1271#define META_UNIMP(x) case x: \
Alexandre Julliard15657091999-05-23 10:25:25 +00001272FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
Huw D M Davies56166a61999-04-19 16:45:24 +00001273break;
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001274 META_UNIMP(META_DRAWTEXT)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001275 META_UNIMP(META_ANIMATEPALETTE)
1276 META_UNIMP(META_SETPALENTRIES)
1277 META_UNIMP(META_RESIZEPALETTE)
Alexandre Julliardc6c09441997-01-12 18:32:19 +00001278 META_UNIMP(META_RESETDC)
1279 META_UNIMP(META_STARTDOC)
1280 META_UNIMP(META_STARTPAGE)
1281 META_UNIMP(META_ENDPAGE)
1282 META_UNIMP(META_ABORTDOC)
1283 META_UNIMP(META_ENDDOC)
1284 META_UNIMP(META_CREATEBRUSH)
1285 META_UNIMP(META_CREATEBITMAPINDIRECT)
1286 META_UNIMP(META_CREATEBITMAP)
1287#undef META_UNIMP
Alexandre Julliardf1aa3031996-08-05 17:42:43 +00001288
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001289 default:
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001290 WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1291 return FALSE;
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001292 }
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001293 return TRUE;
Alexandre Julliard54c27111998-03-29 19:44:57 +00001294}
1295
Alexandre Julliard902da691995-11-05 14:39:02 +00001296/******************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001297 * GetMetaFileBits (GDI.159)
Alexandre Julliard902da691995-11-05 14:39:02 +00001298 *
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001299 * Trade in a metafile object handle for a handle to the metafile memory.
1300 *
Alexandre Julliard902da691995-11-05 14:39:02 +00001301 */
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001302
Alexandre Julliarda3960291999-02-26 11:11:13 +00001303HGLOBAL16 WINAPI GetMetaFileBits16(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00001304 HMETAFILE16 hmf /* [in] metafile handle */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001305 )
Alexandre Julliard902da691995-11-05 14:39:02 +00001306{
Alexandre Julliard15657091999-05-23 10:25:25 +00001307 TRACE("hMem out: %04x\n", hmf);
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001308 return hmf;
Alexandre Julliard902da691995-11-05 14:39:02 +00001309}
1310
1311/******************************************************************
Alexandre Julliardf0cbfa01997-02-15 14:29:56 +00001312 * SetMetaFileBits (GDI.160)
Alexandre Julliard902da691995-11-05 14:39:02 +00001313 *
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001314 * Trade in a metafile memory handle for a handle to a metafile object.
1315 * The memory region should hold a proper metafile, otherwise
1316 * problems will occur when it is used. Validity of the memory is not
1317 * checked. The function is essentially just the identity function.
Alexandre Julliard902da691995-11-05 14:39:02 +00001318 */
Vincent Béron9a624912002-05-31 23:06:46 +00001319HMETAFILE16 WINAPI SetMetaFileBits16(
1320 HGLOBAL16 hMem
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00001321 /* [in] handle to a memory region holding a metafile */
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001322)
Alexandre Julliard902da691995-11-05 14:39:02 +00001323{
Alexandre Julliard15657091999-05-23 10:25:25 +00001324 TRACE("hmf out: %04x\n", hMem);
Alexandre Julliard902da691995-11-05 14:39:02 +00001325
Alexandre Julliardcdcdede1996-04-21 14:57:41 +00001326 return hMem;
Alexandre Julliard902da691995-11-05 14:39:02 +00001327}
Alexandre Julliard36ca1361994-06-02 22:38:20 +00001328
1329/******************************************************************
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001330 * SetMetaFileBitsBetter (GDI.196)
Alexandre Julliard60ce85c1998-02-01 18:33:27 +00001331 *
1332 * Trade in a metafile memory handle for a handle to a metafile object,
1333 * making a cursory check (using IsValidMetaFile()) that the memory
1334 * handle points to a valid metafile.
1335 *
1336 * RETURNS
1337 * Handle to a metafile on success, NULL on failure..
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001338 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001339HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001340{
Huw D M Davies56166a61999-04-19 16:45:24 +00001341 if( IsValidMetaFile16( hMeta ) )
Vincent Béron9a624912002-05-31 23:06:46 +00001342 return (HMETAFILE16)GlobalReAlloc16( hMeta, 0,
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001343 GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
Huw D M Davies56166a61999-04-19 16:45:24 +00001344 return (HMETAFILE16)0;
Alexandre Julliarddf2673b1997-03-29 17:20:20 +00001345}
1346
1347/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00001348 * SetMetaFileBitsEx (GDI32.@)
Vincent Béron9a624912002-05-31 23:06:46 +00001349 *
Alexandre Julliardc7c217b1998-04-13 12:21:30 +00001350 * Create a metafile from raw data. No checking of the data is performed.
1351 * Use _GetMetaFileBitsEx_ to get raw data from a metafile.
Alexandre Julliard54c27111998-03-29 19:44:57 +00001352 */
Vincent Béron9a624912002-05-31 23:06:46 +00001353HMETAFILE WINAPI SetMetaFileBitsEx(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00001354 UINT size, /* [in] size of metafile, in bytes */
Vincent Béron9a624912002-05-31 23:06:46 +00001355 const BYTE *lpData /* [in] pointer to metafile data */
Alexandre Julliard54c27111998-03-29 19:44:57 +00001356 )
1357{
Alexandre Julliard90476d62000-02-16 22:47:24 +00001358 METAHEADER *mh = HeapAlloc( GetProcessHeap(), 0, size );
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001359 if (!mh) return 0;
1360 memcpy(mh, lpData, size);
1361 return MF_Create_HMETAFILE(mh);
Alexandre Julliard54c27111998-03-29 19:44:57 +00001362}
1363
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001364/*****************************************************************
Jon Griffiths783a3952004-02-09 20:47:42 +00001365 * GetMetaFileBitsEx (GDI32.@)
1366 *
1367 * Get raw metafile data.
Vincent Béron9a624912002-05-31 23:06:46 +00001368 *
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001369 * Copies the data from metafile _hmf_ into the buffer _buf_.
1370 * If _buf_ is zero, returns size of buffer required. Otherwise,
1371 * returns number of bytes copied.
1372 */
Vincent Béron9a624912002-05-31 23:06:46 +00001373UINT WINAPI GetMetaFileBitsEx(
Patrik Stridvall2b3aa612000-12-01 23:58:28 +00001374 HMETAFILE hmf, /* [in] metafile */
Vincent Béron9a624912002-05-31 23:06:46 +00001375 UINT nSize, /* [in] size of buf */
Jon Griffiths783a3952004-02-09 20:47:42 +00001376 LPVOID buf /* [out] buffer to receive raw metafile data */)
1377{
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001378 METAHEADER *mh = MF_GetMetaHeader(hmf);
1379 UINT mfSize;
Huw D M Davies7bb6fd11999-02-09 15:32:19 +00001380
Alexandre Julliard547cdc22002-11-22 22:16:53 +00001381 TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001382 if (!mh) return 0; /* FIXME: error code */
1383 if(mh->mtType == METAFILE_DISK)
Alexandre Julliard15657091999-05-23 10:25:25 +00001384 FIXME("Disk-based metafile?\n");
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001385 mfSize = mh->mtSize * 2;
1386 if (!buf) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001387 TRACE("returning size %d\n", mfSize);
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001388 return mfSize;
1389 }
1390 if(mfSize > nSize) mfSize = nSize;
1391 memmove(buf, mh, mfSize);
Huw D M Davies7bb6fd11999-02-09 15:32:19 +00001392 return mfSize;
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001393}
1394
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001395/******************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00001396 * GetWinMetaFileBits [GDI32.@]
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001397 */
Alexandre Julliarda3960291999-02-26 11:11:13 +00001398UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1399 UINT cbBuffer, LPBYTE lpbBuffer,
1400 INT fnMapMode, HDC hdcRef)
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001401{
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001402 HDC hdcmf;
1403 HMETAFILE hmf;
1404 UINT ret;
Ulrich Czekalla6cc56742004-02-20 01:08:57 +00001405 RECT rc;
1406 INT oldMapMode;
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001407
Ulrich Czekalla6cc56742004-02-20 01:08:57 +00001408 GetClipBox(hdcRef, &rc);
1409 oldMapMode = SetMapMode(hdcRef, fnMapMode);
1410
1411 TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1412 fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1413
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001414 hdcmf = CreateMetaFileA(NULL);
Ulrich Czekalla6cc56742004-02-20 01:08:57 +00001415 PlayEnhMetaFile(hdcmf, hemf, &rc);
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001416 hmf = CloseMetaFile(hdcmf);
1417 ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1418 DeleteMetaFile(hmf);
Ulrich Czekalla6cc56742004-02-20 01:08:57 +00001419
1420 SetMapMode(hdcRef, oldMapMode);
1421
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001422 return ret;
Alexandre Julliard0c0e3be1998-12-10 15:49:22 +00001423}
Alexandre Julliard46ea8b31998-05-03 19:01:20 +00001424
Alexandre Julliard54c27111998-03-29 19:44:57 +00001425/******************************************************************
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001426 * MF_Play_MetaCreateRegion
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001427 *
1428 * Handles META_CREATEREGION for PlayMetaFileRecord().
1429 */
1430
1431/*
1432 * The layout of the record looks something like this:
Vincent Béron9a624912002-05-31 23:06:46 +00001433 *
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001434 * rdParm meaning
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001435 * 0 Always 0?
1436 * 1 Always 6?
1437 * 2 Looks like a handle? - not constant
1438 * 3 0 or 1 ??
1439 * 4 Total number of bytes
Francois Gouget282f7272001-02-28 05:31:02 +00001440 * 5 No. of separate bands = n [see below]
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001441 * 6 Largest number of x co-ords in a band
1442 * 7-10 Bounding box x1 y1 x2 y2
1443 * 11-... n bands
1444 *
1445 * Regions are divided into bands that are uniform in the
1446 * y-direction. Each band consists of pairs of on/off x-coords and is
1447 * written as
1448 * m y0 y1 x1 x2 x3 ... xm m
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001449 * into successive rdParm[]s.
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001450 *
1451 * This is probably just a dump of the internal RGNOBJ?
1452 *
1453 * HDMD - 18/12/97
1454 *
1455 */
1456
Huw D M Daviesb94e4331999-04-15 16:46:51 +00001457static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001458{
1459 WORD band, pair;
1460 WORD *start, *end;
1461 INT16 y0, y1;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001462 HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001463
Alexandre Julliard8da12c41999-01-17 16:55:11 +00001464 for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001465 band++, start = end + 1) {
1466 if(*start / 2 != (*start + 1) / 2) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001467 WARN("Delimiter not even.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001468 DeleteObject( hrgn2 );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001469 return FALSE;
1470 }
1471
1472 end = start + *start + 3;
1473 if(end > (WORD *)mr + mr->rdSize) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001474 WARN("End points outside record.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001475 DeleteObject( hrgn2 );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001476 return FALSE;
1477 }
1478
1479 if(*start != *end) {
Alexandre Julliard15657091999-05-23 10:25:25 +00001480 WARN("Mismatched delimiters.\n");
Alexandre Julliarda3960291999-02-26 11:11:13 +00001481 DeleteObject( hrgn2 );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001482 return FALSE;
1483 }
1484
1485 y0 = *(INT16 *)(start + 1);
1486 y1 = *(INT16 *)(start + 2);
1487 for(pair = 0; pair < *start / 2; pair++) {
Alexandre Julliarda3960291999-02-26 11:11:13 +00001488 SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001489 *(INT16 *)(start + 4 + 2*pair), y1 );
Alexandre Julliarda3960291999-02-26 11:11:13 +00001490 CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001491 }
1492 }
Alexandre Julliarda3960291999-02-26 11:11:13 +00001493 DeleteObject( hrgn2 );
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001494 return TRUE;
1495 }
Vincent Béron9a624912002-05-31 23:06:46 +00001496
Alexandre Julliard0623a6f1998-01-18 18:01:49 +00001497
Huw D M Davies56166a61999-04-19 16:45:24 +00001498/******************************************************************
1499 * MF_Play_MetaExtTextOut
1500 *
1501 * Handles META_EXTTEXTOUT for PlayMetaFileRecord().
Alexandre Julliard58199531994-04-21 01:20:00 +00001502 */
Huw D M Davies56166a61999-04-19 16:45:24 +00001503
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001504static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
Huw D M Davies56166a61999-04-19 16:45:24 +00001505{
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001506 INT *dx = NULL;
1507 int i;
Huw D M Davies56166a61999-04-19 16:45:24 +00001508 LPINT16 dxx;
Vincent Béron9a624912002-05-31 23:06:46 +00001509 LPSTR sot;
Huw D M Davies56166a61999-04-19 16:45:24 +00001510 DWORD len;
1511 WORD s1;
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001512 RECT rect;
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001513 BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
Huw D M Davies56166a61999-04-19 16:45:24 +00001514
1515 s1 = mr->rdParm[2]; /* String length */
1516 len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001517 + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
Huw D M Davies56166a61999-04-19 16:45:24 +00001518 /* rec len without dx array */
1519
1520 sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */
Huw D M Daviesb482e9a2002-08-16 20:04:29 +00001521 if (isrect)
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001522 {
1523 rect.left = (SHORT)mr->rdParm[4];
1524 rect.top = (SHORT)mr->rdParm[5];
1525 rect.right = (SHORT)mr->rdParm[6];
1526 rect.bottom = (SHORT)mr->rdParm[7];
Huw D M Davies56166a61999-04-19 16:45:24 +00001527 sot += sizeof(RECT16); /* there is a rectangle, so add offset */
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001528 }
Vincent Béron9a624912002-05-31 23:06:46 +00001529
Huw D M Davies56166a61999-04-19 16:45:24 +00001530 if (mr->rdSize == len / 2)
1531 dxx = NULL; /* determine if array present */
Vincent Béron9a624912002-05-31 23:06:46 +00001532 else
Huw D M Davies56166a61999-04-19 16:45:24 +00001533 if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001534 {
1535 dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1536 dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1537 if (dx) for (i = 0; i < s1; i++) dx[i] = (SHORT)dxx[i];
1538 }
Huw D M Davies56166a61999-04-19 16:45:24 +00001539 else {
Alexandre Julliard15657091999-05-23 10:25:25 +00001540 TRACE("%s len: %ld\n", sot, mr->rdSize);
1541 WARN(
Huw D M Davies56166a61999-04-19 16:45:24 +00001542 "Please report: ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
1543 len, s1, mr->rdSize, mr->rdParm[3]);
1544 dxx = NULL; /* should't happen -- but if, we continue with NULL */
1545 }
Alexandre Julliard15b9ed92002-10-18 03:33:37 +00001546 ExtTextOutA( hdc,
1547 (SHORT)mr->rdParm[1], /* X position */
1548 (SHORT)mr->rdParm[0], /* Y position */
1549 mr->rdParm[3], /* options */
1550 &rect, /* rectangle */
1551 sot, /* string */
1552 s1, dx); /* length, dx array */
1553 if (dx)
1554 {
1555 TRACE("%s len: %ld dx0: %d\n", sot, mr->rdSize, dx[0]);
1556 HeapFree( GetProcessHeap(), 0, dx );
1557 }
Huw D M Davies56166a61999-04-19 16:45:24 +00001558 return TRUE;
1559}