1 /*
2 * Metafile functions
3 *
4 * Copyright David W. Metcalfe, 1994
5 * Copyright Niels de Carpentier, 1996
6 * Copyright Albrecht Kleine, 1996
7 * Copyright Huw Davies, 1996
8 *
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.
13 *
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.
18 *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 *
23 * NOTES
24 *
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/
28 *
29 * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are
30 * global memory handles so these cannot be interchanged.
31 *
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 identical 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
38 * the memory.
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.
44 *
45 * HDMD - 14/4/1999
46 */
47
48 #include "config.h"
49
50 #include <stdarg.h>
51 #include <string.h>
52 #include <fcntl.h>
53
54 #include "windef.h"
55 #include "winbase.h"
56 #include "wingdi.h"
57 #include "winreg.h"
58 #include "winternl.h"
59 #include "gdi_private.h"
60 #include "wine/debug.h"
61
62 WINE_DEFAULT_DEBUG_CHANNEL(metafile);
63
64 #include "pshpack1.h"
65 typedef struct
66 {
67 DWORD dw1, dw2, dw3;
68 WORD w4;
69 CHAR filename[0x100];
70 } METAHEADERDISK;
71 #include "poppack.h"
72
73 typedef struct
74 {
75 GDIOBJHDR header;
76 METAHEADER *mh;
77 } METAFILEOBJ;
78
79
80 /******************************************************************
81 * MF_AddHandle
82 *
83 * Add a handle to an external handle table and return the index
84 */
85 static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj)
86 {
87 int i;
88
89 for (i = 0; i < htlen; i++)
90 {
91 if (*(ht->objectHandle + i) == 0)
92 {
93 *(ht->objectHandle + i) = hobj;
94 return i;
95 }
96 }
97 return -1;
98 }
99
100
101 /******************************************************************
102 * MF_Create_HMETATFILE
103 *
104 * Creates a (32 bit) HMETAFILE object from a METAHEADER
105 *
106 * HMETAFILEs are GDI objects.
107 */
108 HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh)
109 {
110 HMETAFILE hmf = 0;
111 METAFILEOBJ *metaObj = GDI_AllocObject( sizeof(METAFILEOBJ), METAFILE_MAGIC,
112 (HGDIOBJ *)&hmf, NULL );
113 if (metaObj)
114 {
115 metaObj->mh = mh;
116 GDI_ReleaseObj( hmf );
117 }
118 return hmf;
119 }
120
121 /******************************************************************
122 * MF_GetMetaHeader
123 *
124 * Returns ptr to METAHEADER associated with HMETAFILE
125 */
126 static METAHEADER *MF_GetMetaHeader( HMETAFILE hmf )
127 {
128 METAHEADER *ret = NULL;
129 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
130 if (metaObj)
131 {
132 ret = metaObj->mh;
133 GDI_ReleaseObj( hmf );
134 }
135 return ret;
136 }
137
138 /******************************************************************
139 * convert_points
140 *
141 * Convert an array of POINT16 to an array of POINT.
142 * Result must be freed by caller.
143 */
144 static POINT *convert_points( UINT count, POINT16 *pt16 )
145 {
146 UINT i;
147 POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) );
148 if (ret)
149 {
150 for (i = 0; i < count; i++)
151 {
152 ret[i].x = pt16[i].x;
153 ret[i].y = pt16[i].y;
154 }
155 }
156 return ret;
157 }
158
159 /******************************************************************
160 * DeleteMetaFile (GDI32.@)
161 *
162 * Delete a memory-based metafile.
163 */
164
165 BOOL WINAPI DeleteMetaFile( HMETAFILE hmf )
166 {
167 METAFILEOBJ * metaObj = (METAFILEOBJ *)GDI_GetObjPtr( hmf, METAFILE_MAGIC );
168 if (!metaObj) return FALSE;
169 HeapFree( GetProcessHeap(), 0, metaObj->mh );
170 GDI_FreeObject( hmf, metaObj );
171 return TRUE;
172 }
173
174 /******************************************************************
175 * MF_ReadMetaFile
176 *
177 * Returns a pointer to a memory based METAHEADER read in from file HFILE
178 *
179 */
180 METAHEADER *MF_ReadMetaFile(HANDLE hfile)
181 {
182 METAHEADER *mh;
183 DWORD BytesRead, size;
184
185 size = sizeof(METAHEADER);
186 mh = HeapAlloc( GetProcessHeap(), 0, size );
187 if(!mh) return NULL;
188 if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 ||
189 BytesRead != size) {
190 HeapFree( GetProcessHeap(), 0, mh );
191 return NULL;
192 }
193 if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION ||
194 mh->mtHeaderSize != size / 2)
195 {
196 HeapFree( GetProcessHeap(), 0, mh );
197 return NULL;
198 }
199 size = mh->mtSize * 2;
200 mh = HeapReAlloc( GetProcessHeap(), 0, mh, size );
201 if(!mh) return NULL;
202 size -= sizeof(METAHEADER);
203 if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead,
204 NULL) == 0 ||
205 BytesRead != size) {
206 HeapFree( GetProcessHeap(), 0, mh );
207 return NULL;
208 }
209
210 if (mh->mtType != METAFILE_MEMORY) {
211 WARN("Disk metafile had mtType = %04x\n", mh->mtType);
212 mh->mtType = METAFILE_MEMORY;
213 }
214 return mh;
215 }
216
217 /******************************************************************
218 * GetMetaFileA (GDI32.@)
219 *
220 * Read a metafile from a file. Returns handle to a memory-based metafile.
221 */
222 HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename )
223 {
224 METAHEADER *mh;
225 HANDLE hFile;
226
227 TRACE("%s\n", lpFilename);
228
229 if(!lpFilename)
230 return 0;
231
232 if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
233 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
234 return 0;
235
236 mh = MF_ReadMetaFile(hFile);
237 CloseHandle(hFile);
238 if(!mh) return 0;
239 return MF_Create_HMETAFILE( mh );
240 }
241
242 /******************************************************************
243 * GetMetaFileW (GDI32.@)
244 */
245 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
246 {
247 METAHEADER *mh;
248 HANDLE hFile;
249
250 TRACE("%s\n", debugstr_w(lpFilename));
251
252 if(!lpFilename)
253 return 0;
254
255 if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
256 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE)
257 return 0;
258
259 mh = MF_ReadMetaFile(hFile);
260 CloseHandle(hFile);
261 if(!mh) return 0;
262 return MF_Create_HMETAFILE( mh );
263 }
264
265
266 /******************************************************************
267 * MF_LoadDiskBasedMetaFile
268 *
269 * Creates a new memory-based metafile from a disk-based one.
270 */
271 METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh)
272 {
273 METAHEADERDISK *mhd;
274 HANDLE hfile;
275 METAHEADER *mh2;
276
277 if(mh->mtType != METAFILE_DISK) {
278 ERR("Not a disk based metafile\n");
279 return NULL;
280 }
281 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
282
283 if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL,
284 OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
285 WARN("Can't open file of disk based metafile\n");
286 return NULL;
287 }
288 mh2 = MF_ReadMetaFile(hfile);
289 CloseHandle(hfile);
290 return mh2;
291 }
292
293 /******************************************************************
294 * MF_CreateMetaHeaderDisk
295 *
296 * Take a memory based METAHEADER and change it to a disk based METAHEADER
297 * associated with filename. Note: Trashes contents of old one.
298 */
299 METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni )
300 {
301 METAHEADERDISK *mhd;
302
303 mh = HeapReAlloc( GetProcessHeap(), 0, mh,
304 sizeof(METAHEADER) + sizeof(METAHEADERDISK));
305 mh->mtType = METAFILE_DISK;
306 mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER));
307
308 if( uni )
309 WideCharToMultiByte(CP_ACP, 0, filename, -1,
310 mhd->filename, sizeof mhd->filename, NULL, NULL);
311 else
312 lstrcpynA( mhd->filename, filename, sizeof mhd->filename );
313 return mh;
314 }
315
316 /******************************************************************
317 * CopyMetaFileW (GDI32.@)
318 *
319 * Copies the metafile corresponding to hSrcMetaFile to either
320 * a disk file, if a filename is given, or to a new memory based
321 * metafile, if lpFileName is NULL.
322 *
323 * PARAMS
324 * hSrcMetaFile [I] handle of metafile to copy
325 * lpFilename [I] filename if copying to a file
326 *
327 * RETURNS
328 * Handle to metafile copy on success, NULL on failure.
329 *
330 * BUGS
331 * Copying to disk returns NULL even if successful.
332 */
333 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename )
334 {
335 METAHEADER *mh = MF_GetMetaHeader( hSrcMetaFile );
336 METAHEADER *mh2 = NULL;
337 HANDLE hFile;
338
339 TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename));
340
341 if(!mh) return 0;
342
343 if(mh->mtType == METAFILE_DISK)
344 mh2 = MF_LoadDiskBasedMetaFile(mh);
345 else {
346 mh2 = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 );
347 memcpy( mh2, mh, mh->mtSize * 2 );
348 }
349
350 if(lpFilename) { /* disk based metafile */
351 DWORD w;
352 if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL,
353 CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
354 HeapFree( GetProcessHeap(), 0, mh2 );
355 return 0;
356 }
357 WriteFile(hFile, mh2, mh2->mtSize * 2, &w, NULL);
358 CloseHandle(hFile);
359 }
360
361 return MF_Create_HMETAFILE( mh2 );
362 }
363
364
365 /******************************************************************
366 * CopyMetaFileA (GDI32.@)
367 *
368 * See CopyMetaFileW.
369 */
370 HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename )
371 {
372 UNICODE_STRING lpFilenameW;
373 HMETAFILE ret = 0;
374
375 if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename);
376 else lpFilenameW.Buffer = NULL;
377
378 ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer );
379 if (lpFilenameW.Buffer)
380 RtlFreeUnicodeString(&lpFilenameW);
381 return ret;
382 }
383
384 /*******************************************************************
385 * MF_PlayMetaFile
386 *
387 * Helper for PlayMetaFile
388 */
389 BOOL MF_PlayMetaFile( HDC hdc, METAHEADER *mh)
390 {
391
392 METARECORD *mr;
393 HANDLETABLE *ht;
394 unsigned int offset = 0;
395 WORD i;
396 HPEN hPen;
397 HBRUSH hBrush;
398 HFONT hFont;
399 HPALETTE hPal;
400 HRGN hRgn;
401 BOOL loaded = FALSE;
402
403 if (!mh) return FALSE;
404 if(mh->mtType == METAFILE_DISK) { /* Create a memory-based copy */
405 mh = MF_LoadDiskBasedMetaFile(mh);
406 if(!mh) return FALSE;
407 loaded = TRUE;
408 }
409
410 /* save DC */
411 hPen = GetCurrentObject(hdc, OBJ_PEN);
412 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
413 hFont = GetCurrentObject(hdc, OBJ_FONT);
414 hPal = GetCurrentObject(hdc, OBJ_PAL);
415
416 hRgn = CreateRectRgn(0, 0, 0, 0);
417 if (!GetClipRgn(hdc, hRgn))
418 {
419 DeleteObject(hRgn);
420 hRgn = 0;
421 }
422
423 /* create the handle table */
424 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
425 sizeof(HANDLETABLE) * mh->mtNoObjects);
426 if(!ht) return FALSE;
427
428 /* loop through metafile playing records */
429 offset = mh->mtHeaderSize * 2;
430 while (offset < mh->mtSize * 2)
431 {
432 mr = (METARECORD *)((char *)mh + offset);
433 TRACE("offset=%04x,size=%08x\n",
434 offset, mr->rdSize);
435 if (mr->rdSize < 3) { /* catch illegal record sizes */
436 TRACE("Entry got size %d at offset %d, total mf length is %d\n",
437 mr->rdSize,offset,mh->mtSize*2);
438 break;
439 }
440
441 offset += mr->rdSize * 2;
442 if (mr->rdFunction == META_EOF) {
443 TRACE("Got META_EOF so stopping\n");
444 break;
445 }
446 PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects );
447 }
448
449 /* restore DC */
450 SelectObject(hdc, hPen);
451 SelectObject(hdc, hBrush);
452 SelectPalette(hdc, hPal, FALSE);
453 ExtSelectClipRgn(hdc, hRgn, RGN_COPY);
454 DeleteObject(hRgn);
455
456 /* free objects in handle table */
457 for(i = 0; i < mh->mtNoObjects; i++)
458 if(*(ht->objectHandle + i) != 0)
459 DeleteObject(*(ht->objectHandle + i));
460
461 /* free handle table */
462 HeapFree( GetProcessHeap(), 0, ht );
463 if(loaded)
464 HeapFree( GetProcessHeap(), 0, mh );
465 return TRUE;
466 }
467
468 /******************************************************************
469 * PlayMetaFile (GDI32.@)
470 *
471 * Renders the metafile specified by hmf in the DC specified by
472 * hdc. Returns FALSE on failure, TRUE on success.
473 *
474 * PARAMS
475 * hdc [I] handle of DC to render in
476 * hmf [I] handle of metafile to render
477 *
478 * RETURNS
479 * Success: TRUE
480 * Failure: FALSE
481 */
482 BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf )
483 {
484 METAHEADER *mh = MF_GetMetaHeader( hmf );
485 return MF_PlayMetaFile( hdc, mh );
486 }
487
488 /******************************************************************
489 * EnumMetaFile (GDI32.@)
490 *
491 * Loop through the metafile records in hmf, calling the user-specified
492 * function for each one, stopping when the user's function returns FALSE
493 * (which is considered to be failure)
494 * or when no records are left (which is considered to be success).
495 *
496 * RETURNS
497 * TRUE on success, FALSE on failure.
498 */
499 BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData)
500 {
501 METAHEADER *mhTemp = NULL, *mh = MF_GetMetaHeader(hmf);
502 METARECORD *mr;
503 HANDLETABLE *ht;
504 BOOL result = TRUE;
505 int i;
506 unsigned int offset = 0;
507 HPEN hPen;
508 HBRUSH hBrush;
509 HFONT hFont;
510
511 TRACE("(%p,%p,%p,%p)\n", hdc, hmf, lpEnumFunc, (void*)lpData);
512 if (!mh) return 0;
513 if(mh->mtType == METAFILE_DISK)
514 {
515 /* Create a memory-based copy */
516 if (!(mhTemp = MF_LoadDiskBasedMetaFile(mh))) return FALSE;
517 mh = mhTemp;
518 }
519
520 /* save the current pen, brush and font */
521 hPen = GetCurrentObject(hdc, OBJ_PEN);
522 hBrush = GetCurrentObject(hdc, OBJ_BRUSH);
523 hFont = GetCurrentObject(hdc, OBJ_FONT);
524
525 ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
526 sizeof(HANDLETABLE) * mh->mtNoObjects);
527
528 /* loop through metafile records */
529 offset = mh->mtHeaderSize * 2;
530
531 while (offset < (mh->mtSize * 2))
532 {
533 mr = (METARECORD *)((char *)mh + offset);
534 if(mr->rdFunction == META_EOF) {
535 TRACE("Got META_EOF so stopping\n");
536 break;
537 }
538 TRACE("Calling EnumFunc with record type %x\n",
539 mr->rdFunction);
540 if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
541 {
542 result = FALSE;
543 break;
544 }
545
546 offset += (mr->rdSize * 2);
547 }
548
549 /* restore pen, brush and font */
550 SelectObject(hdc, hBrush);
551 SelectObject(hdc, hPen);
552 SelectObject(hdc, hFont);
553
554 /* free objects in handle table */
555 for(i = 0; i < mh->mtNoObjects; i++)
556 if(*(ht->objectHandle + i) != 0)
557 DeleteObject(*(ht->objectHandle + i));
558
559 /* free handle table */
560 HeapFree( GetProcessHeap(), 0, ht);
561 /* free a copy of metafile */
562 HeapFree( GetProcessHeap(), 0, mhTemp );
563 return result;
564 }
565
566 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn );
567 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr);
568 /******************************************************************
569 * PlayMetaFileRecord (GDI32.@)
570 *
571 * Render a single metafile record specified by *mr in the DC hdc, while
572 * using the handle table *ht, of length handles,
573 * to store metafile objects.
574 *
575 * BUGS
576 * The following metafile records are unimplemented:
577 *
578 * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES,
579 * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
580 * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
581 */
582 BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles )
583 {
584 short s1;
585 POINT *pt;
586 BITMAPINFOHEADER *infohdr;
587
588 TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction);
589
590 switch (mr->rdFunction)
591 {
592 case META_EOF:
593 break;
594
595 case META_DELETEOBJECT:
596 DeleteObject(*(ht->objectHandle + mr->rdParm[0]));
597 *(ht->objectHandle + mr->rdParm[0]) = 0;
598 break;
599
600 case META_SETBKCOLOR:
601 SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
602 break;
603
604 case META_SETBKMODE:
605 SetBkMode(hdc, mr->rdParm[0]);
606 break;
607
608 case META_SETMAPMODE:
609 SetMapMode(hdc, mr->rdParm[0]);
610 break;
611
612 case META_SETROP2:
613 SetROP2(hdc, mr->rdParm[0]);
614 break;
615
616 case META_SETRELABS:
617 SetRelAbs(hdc, mr->rdParm[0]);
618 break;
619
620 case META_SETPOLYFILLMODE:
621 SetPolyFillMode(hdc, mr->rdParm[0]);
622 break;
623
624 case META_SETSTRETCHBLTMODE:
625 SetStretchBltMode(hdc, mr->rdParm[0]);
626 break;
627
628 case META_SETTEXTCOLOR:
629 SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
630 break;
631
632 case META_SETWINDOWORG:
633 SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
634 break;
635
636 case META_SETWINDOWEXT:
637 SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
638 break;
639
640 case META_SETVIEWPORTORG:
641 SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
642 break;
643
644 case META_SETVIEWPORTEXT:
645 SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
646 break;
647
648 case META_OFFSETWINDOWORG:
649 OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
650 break;
651
652 case META_SCALEWINDOWEXT:
653 ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
654 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
655 break;
656
657 case META_OFFSETVIEWPORTORG:
658 OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
659 break;
660
661 case META_SCALEVIEWPORTEXT:
662 ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
663 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
664 break;
665
666 case META_LINETO:
667 LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
668 break;
669
670 case META_MOVETO:
671 MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL);
672 break;
673
674 case META_EXCLUDECLIPRECT:
675 ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
676 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
677 break;
678
679 case META_INTERSECTCLIPRECT:
680 IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
681 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
682 break;
683
684 case META_ARC:
685 Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
686 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
687 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
688 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
689 break;
690
691 case META_ELLIPSE:
692 Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
693 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
694 break;
695
696 case META_FLOODFILL:
697 FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
698 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
699 break;
700
701 case META_PIE:
702 Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
703 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
704 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
705 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
706 break;
707
708 case META_RECTANGLE:
709 Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
710 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
711 break;
712
713 case META_ROUNDRECT:
714 RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
715 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
716 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
717 break;
718
719 case META_PATBLT:
720 PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
721 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
722 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
723 break;
724
725 case META_SAVEDC:
726 SaveDC(hdc);
727 break;
728
729 case META_SETPIXEL:
730 SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
731 MAKELONG(mr->rdParm[0], mr->rdParm[1]));
732 break;
733
734 case META_OFFSETCLIPRGN:
735 OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] );
736 break;
737
738 case META_TEXTOUT:
739 s1 = mr->rdParm[0];
740 TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2],
741 (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1],
742 (char *)(mr->rdParm + 1), s1);
743 break;
744
745 case META_POLYGON:
746 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
747 {
748 Polygon(hdc, pt, mr->rdParm[0]);
749 HeapFree( GetProcessHeap(), 0, pt );
750 }
751 break;
752
753 case META_POLYPOLYGON:
754 {
755 UINT i, total;
756 SHORT *counts = (SHORT *)(mr->rdParm + 1);
757
758 for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i];
759 pt = convert_points( total, (LPPOINT16)(counts + mr->rdParm[0]) );
760 if (pt)
761 {
762 INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) );
763 if (cnt32)
764 {
765 for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i];
766 PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]);
767 HeapFree( GetProcessHeap(), 0, cnt32 );
768 }
769 }
770 HeapFree( GetProcessHeap(), 0, pt );
771 }
772 break;
773
774 case META_POLYLINE:
775 if ((pt = convert_points( mr->rdParm[0], (LPPOINT16)(mr->rdParm + 1))))
776 {
777 Polyline( hdc, pt, mr->rdParm[0] );
778 HeapFree( GetProcessHeap(), 0, pt );
779 }
780 break;
781
782 case META_RESTOREDC:
783 RestoreDC(hdc, (SHORT)mr->rdParm[0]);
784 break;
785
786 case META_SELECTOBJECT:
787 SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0]));
788 break;
789
790 case META_CHORD:
791 Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
792 (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
793 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
794 (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
795 break;
796
797 case META_CREATEPATTERNBRUSH:
798 switch (mr->rdParm[0])
799 {
800 case BS_PATTERN:
801 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
802 MF_AddHandle(ht, handles,
803 CreatePatternBrush(CreateBitmap(infohdr->biWidth,
804 infohdr->biHeight,
805 infohdr->biPlanes,
806 infohdr->biBitCount,
807 (LPSTR)(mr->rdParm +
808 (sizeof(BITMAPINFOHEADER) / 2) + 4))));
809 break;
810
811 case BS_DIBPATTERN:
812 infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
813 MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] ));
814 break;
815
816 default:
817 ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n",
818 mr->rdParm[0]);
819 break;
820 }
821 break;
822
823 case META_CREATEPENINDIRECT:
824 {
825 LOGPEN pen;
826 pen.lopnStyle = mr->rdParm[0];
827 pen.lopnWidth.x = (SHORT)mr->rdParm[1];
828 pen.lopnWidth.y = (SHORT)mr->rdParm[2];
829 pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] );
830 MF_AddHandle(ht, handles, CreatePenIndirect( &pen ));
831 }
832 break;
833
834 case META_CREATEFONTINDIRECT:
835 {
836 LOGFONTA font;
837 font.lfHeight = (SHORT)mr->rdParm[0];
838 font.lfWidth = (SHORT)mr->rdParm[1];
839 font.lfEscapement = (SHORT)mr->rdParm[2];
840 font.lfOrientation = (SHORT)mr->rdParm[3];
841 font.lfWeight = (SHORT)mr->rdParm[4];
842 font.lfItalic = LOBYTE(mr->rdParm[5]);
843 font.lfUnderline = HIBYTE(mr->rdParm[5]);
844 font.lfStrikeOut = LOBYTE(mr->rdParm[6]);
845 font.lfCharSet = HIBYTE(mr->rdParm[6]);
846 font.lfOutPrecision = LOBYTE(mr->rdParm[7]);
847 font.lfClipPrecision = HIBYTE(mr->rdParm[7]);
848 font.lfQuality = LOBYTE(mr->rdParm[8]);
849 font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]);
850 memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE );
851 MF_AddHandle(ht, handles, CreateFontIndirectA( &font ));
852 }
853 break;
854
855 case META_CREATEBRUSHINDIRECT:
856 {
857 LOGBRUSH brush;
858 brush.lbStyle = mr->rdParm[0];
859 brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] );
860 brush.lbHatch = mr->rdParm[3];
861 MF_AddHandle(ht, handles, CreateBrushIndirect( &brush ));
862 }
863 break;
864
865 case META_CREATEPALETTE:
866 MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm));
867 break;
868
869 case META_SETTEXTALIGN:
870 SetTextAlign(hdc, mr->rdParm[0]);
871 break;
872
873 case META_SELECTPALETTE:
874 GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]);
875 break;
876
877 case META_SETMAPPERFLAGS:
878 SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1]));
879 break;
880
881 case META_REALIZEPALETTE:
882 GDIRealizePalette(hdc);
883 break;
884
885 case META_ESCAPE:
886 switch (mr->rdParm[0]) {
887 case GETSCALINGFACTOR: /* get function ... would just NULL dereference */
888 case GETPHYSPAGESIZE:
889 case GETPRINTINGOFFSET:
890 return FALSE;
891 case SETABORTPROC:
892 FIXME("Filtering Escape(SETABORTPROC), possible virus?\n");
893 return FALSE;
894 }
895 Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL);
896 break;
897
898 case META_EXTTEXTOUT:
899 MF_Play_MetaExtTextOut( hdc, mr );
900 break;
901
902 case META_STRETCHDIB:
903 {
904 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
905 LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] );
906 StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
907 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
908 (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info,
909 mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
910 }
911 break;
912
913 case META_DIBSTRETCHBLT:
914 {
915 LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]);
916 LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] );
917 StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
918 (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
919 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info,
920 DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
921 }
922 break;
923
924 case META_STRETCHBLT:
925 {
926 HDC hdcSrc = CreateCompatibleDC(hdc);
927 HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */
928 mr->rdParm[11], /*Height*/
929 mr->rdParm[13], /*Planes*/
930 mr->rdParm[14], /*BitsPixel*/
931 (LPSTR)&mr->rdParm[15]); /*bits*/
932 SelectObject(hdcSrc,hbitmap);
933 StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8],
934 (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6],
935 hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4],
936 (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
937 MAKELONG(mr->rdParm[0],mr->rdParm[1]));
938 DeleteDC(hdcSrc);
939 }
940 break;
941
942 case META_BITBLT:
943 {
944 HDC hdcSrc = CreateCompatibleDC(hdc);
945 HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */,
946 mr->rdParm[8]/*Height*/,
947 mr->rdParm[10]/*Planes*/,
948 mr->rdParm[11]/*BitsPixel*/,
949 (LPSTR)&mr->rdParm[12]/*bits*/);
950 SelectObject(hdcSrc,hbitmap);
951 BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5],
952 (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3],
953 hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1],
954 MAKELONG(0,mr->rdParm[0]));
955 DeleteDC(hdcSrc);
956 }
957 break;
958
959 case META_CREATEREGION:
960 {
961 HRGN hrgn = CreateRectRgn(0,0,0,0);
962
963 MF_Play_MetaCreateRegion(mr, hrgn);
964 MF_AddHandle(ht, handles, hrgn);
965 }
966 break;
967
968 case META_FILLREGION:
969 FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]),
970 *(ht->objectHandle + mr->rdParm[0]));