~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/gdi32/metafile.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  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 = 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 = 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, DIB_RGB_COLORS );
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]));
971         break;
972 
973     case META_FRAMEREGION:
974         FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]),
975                  *(ht->objectHandle + mr->rdParm[2]),
976                  (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
977         break;
978 
979     case META_INVERTREGION:
980         InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
981         break;
982 
983     case META_PAINTREGION:
984         PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0]));
985         break;
986 
987     case META_SELECTCLIPREGION:
988         {
989             HRGN hrgn = 0;
990 
991             if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]);
992             SelectClipRgn(hdc, hrgn);
993         }
994         break;
995 
996     case META_DIBCREATEPATTERNBRUSH:
997         /*  mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN:
998             but there's no difference */
999         MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] ));
1000         break;
1001 
1002     case META_DIBBITBLT:
1003       /* In practice I've found that there are two layouts for
1004          META_DIBBITBLT, one (the first here) is the usual one when a src
1005          dc is actually passed to it, the second occurs when the src dc is
1006          passed in as NULL to the creating BitBlt. As the second case has
1007          no dib, a size check will suffice to distinguish.
1008 
1009          Caolan.McNamara@ul.ie */
1010 
1011         if (mr->rdSize > 12) {
1012             LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
1013             LPSTR bits = (LPSTR)info + bitmap_info_size(info, mr->rdParm[0]);
1014 
1015             StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1016                           (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2],
1017                           (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info,
1018                           DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1019         }
1020         else /* equivalent to a PatBlt */
1021             PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1022                    (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1023                    MAKELONG(mr->rdParm[0], mr->rdParm[1]));
1024         break;
1025 
1026     case META_SETTEXTCHAREXTRA:
1027         SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]);
1028         break;
1029 
1030     case META_SETTEXTJUSTIFICATION:
1031         SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]);
1032         break;
1033 
1034     case META_EXTFLOODFILL:
1035         ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1036                      MAKELONG(mr->rdParm[1], mr->rdParm[2]),
1037                      mr->rdParm[0]);
1038         break;
1039 
1040     case META_SETDIBTODEV:
1041         {
1042             BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]);
1043             char *bits = (char *)info + bitmap_info_size( info, mr->rdParm[0] );
1044             SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7],
1045                               (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5],
1046                               (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3],
1047                               mr->rdParm[2], mr->rdParm[1], bits, info,
1048                               mr->rdParm[0]);
1049             break;
1050         }
1051 
1052 #define META_UNIMP(x) case x: \
1053 FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \
1054 break;
1055     META_UNIMP(META_DRAWTEXT)
1056     META_UNIMP(META_ANIMATEPALETTE)
1057     META_UNIMP(META_SETPALENTRIES)
1058     META_UNIMP(META_RESIZEPALETTE)
1059     META_UNIMP(META_RESETDC)
1060     META_UNIMP(META_STARTDOC)
1061     META_UNIMP(META_STARTPAGE)
1062     META_UNIMP(META_ENDPAGE)
1063     META_UNIMP(META_ABORTDOC)
1064     META_UNIMP(META_ENDDOC)
1065     META_UNIMP(META_CREATEBRUSH)
1066     META_UNIMP(META_CREATEBITMAPINDIRECT)
1067     META_UNIMP(META_CREATEBITMAP)
1068 #undef META_UNIMP
1069 
1070     default:
1071         WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction);
1072         return FALSE;
1073     }
1074     return TRUE;
1075 }
1076 
1077 /******************************************************************
1078  *         SetMetaFileBitsEx    (GDI32.@)
1079  *
1080  *  Create a metafile from raw data. No checking of the data is performed.
1081  *  Use GetMetaFileBitsEx() to get raw data from a metafile.
1082  *
1083  * PARAMS
1084  *  size   [I] size of metafile, in bytes
1085  *  lpData [I] pointer to metafile data
1086  *
1087  * RETURNS
1088  *  Success: Handle to metafile.
1089  *  Failure: NULL.
1090  */
1091 HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData )
1092 {
1093     const METAHEADER *mh_in = (const METAHEADER *)lpData;
1094     METAHEADER *mh_out;
1095 
1096     if (size & 1) return 0;
1097 
1098     if (!size || mh_in->mtType != METAFILE_MEMORY || mh_in->mtVersion != MFVERSION ||
1099         mh_in->mtHeaderSize != sizeof(METAHEADER) / 2)
1100     {
1101         SetLastError(ERROR_INVALID_DATA);
1102         return 0;
1103     }
1104 
1105     mh_out = HeapAlloc( GetProcessHeap(), 0, size );
1106     if (!mh_out)
1107     {
1108         SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1109         return 0;
1110     }
1111 
1112     memcpy(mh_out, mh_in, size);
1113     mh_out->mtSize = size / 2;
1114     return MF_Create_HMETAFILE(mh_out);
1115 }
1116 
1117 /*****************************************************************
1118  *  GetMetaFileBitsEx     (GDI32.@)
1119  *
1120  * Get raw metafile data.
1121  *
1122  *  Copies the data from metafile _hmf_ into the buffer _buf_.
1123  *
1124  * PARAMS
1125  *  hmf   [I] metafile
1126  *  nSize [I] size of buf
1127  *  buf   [O] buffer to receive raw metafile data
1128  *
1129  * RETURNS
1130  *  If _buf_ is zero, returns size of buffer required. Otherwise,
1131  *  returns number of bytes copied.
1132  */
1133 UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf )
1134 {
1135     METAHEADER *mh = MF_GetMetaHeader(hmf);
1136     UINT mfSize;
1137 
1138     TRACE("(%p,%d,%p)\n", hmf, nSize, buf);
1139     if (!mh) return 0;  /* FIXME: error code */
1140     if(mh->mtType == METAFILE_DISK)
1141         FIXME("Disk-based metafile?\n");
1142     mfSize = mh->mtSize * 2;
1143     if (!buf) {
1144         TRACE("returning size %d\n", mfSize);
1145         return mfSize;
1146     }
1147     if(mfSize > nSize) mfSize = nSize;
1148     memmove(buf, mh, mfSize);
1149     return mfSize;
1150 }
1151 
1152 /******************************************************************
1153  *         GetWinMetaFileBits [GDI32.@]
1154  */
1155 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1156                                 UINT cbBuffer, LPBYTE lpbBuffer,
1157                                 INT fnMapMode, HDC hdcRef)
1158 {
1159     HDC hdcmf;
1160     HMETAFILE hmf;
1161     UINT ret;
1162     RECT rc;
1163     INT oldMapMode;
1164 
1165     GetClipBox(hdcRef, &rc);
1166     oldMapMode = SetMapMode(hdcRef, fnMapMode);
1167 
1168     TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer,
1169         fnMapMode, hdcRef, wine_dbgstr_rect(&rc));
1170 
1171     hdcmf = CreateMetaFileA(NULL);
1172     PlayEnhMetaFile(hdcmf, hemf, &rc);
1173     hmf = CloseMetaFile(hdcmf);
1174     ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer);
1175     DeleteMetaFile(hmf);
1176 
1177     SetMapMode(hdcRef, oldMapMode);
1178 
1179     return ret;
1180 }
1181 
1182 /******************************************************************
1183  *         MF_Play_MetaCreateRegion
1184  *
1185  *  Handles META_CREATEREGION for PlayMetaFileRecord().
1186  *
1187  *      The layout of the record looks something like this:
1188  *
1189  *       rdParm meaning
1190  *       0              Always 0?
1191  *       1              Always 6?
1192  *       2              Looks like a handle? - not constant
1193  *       3              0 or 1 ??
1194  *       4              Total number of bytes
1195  *       5              No. of separate bands = n [see below]
1196  *       6              Largest number of x co-ords in a band
1197  *       7-10           Bounding box x1 y1 x2 y2
1198  *       11-...         n bands
1199  *
1200  *       Regions are divided into bands that are uniform in the
1201  *       y-direction. Each band consists of pairs of on/off x-coords and is
1202  *       written as
1203  *              m y0 y1 x1 x2 x3 ... xm m
1204  *       into successive rdParm[]s.
1205  *
1206  *       This is probably just a dump of the internal RGNOBJ?
1207  *
1208  *       HDMD - 18/12/97
1209  *
1210  */
1211 
1212 static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn )
1213 {
1214     WORD band, pair;
1215     WORD *start, *end;
1216     INT16 y0, y1;
1217     HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1218 
1219     for(band  = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1220                                                 band++, start = end + 1) {
1221         if(*start / 2 != (*start + 1) / 2) {
1222             WARN("Delimiter not even.\n");
1223             DeleteObject( hrgn2 );
1224             return FALSE;
1225         }
1226 
1227         end = start + *start + 3;
1228         if(end > (WORD *)mr + mr->rdSize) {
1229             WARN("End points outside record.\n");
1230             DeleteObject( hrgn2 );
1231             return FALSE;
1232         }
1233 
1234         if(*start != *end) {
1235             WARN("Mismatched delimiters.\n");
1236             DeleteObject( hrgn2 );
1237             return FALSE;
1238         }
1239 
1240         y0 = *(INT16 *)(start + 1);
1241         y1 = *(INT16 *)(start + 2);
1242         for(pair = 0; pair < *start / 2; pair++) {
1243             SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1244                                  *(INT16 *)(start + 4 + 2*pair), y1 );
1245             CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1246         }
1247     }
1248     DeleteObject( hrgn2 );
1249     return TRUE;
1250  }
1251 
1252 
1253 /******************************************************************
1254  *         MF_Play_MetaExtTextOut
1255  *
1256  *  Handles META_EXTTEXTOUT for PlayMetaFileRecord().
1257  */
1258 
1259 static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr)
1260 {
1261     INT *dx = NULL;
1262     int i;
1263     LPINT16 dxx;
1264     LPSTR sot;
1265     DWORD len;
1266     WORD s1;
1267     RECT rect;
1268     BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED);
1269 
1270     s1 = mr->rdParm[2];                              /* String length */
1271     len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
1272       + sizeof(UINT16) + (isrect ? sizeof(RECT16) : 0);
1273                                            /* rec len without dx array */
1274 
1275     sot = (LPSTR)&mr->rdParm[4];                      /* start_of_text */
1276     if (isrect)
1277     {
1278         rect.left   = (SHORT)mr->rdParm[4];
1279         rect.top    = (SHORT)mr->rdParm[5];
1280         rect.right  = (SHORT)mr->rdParm[6];
1281         rect.bottom = (SHORT)mr->rdParm[7];
1282         sot += sizeof(RECT16);  /* there is a rectangle, so add offset */
1283     }
1284 
1285     if (mr->rdSize == len / 2)
1286         dxx = NULL;                      /* determine if array is present */
1287     else
1288         if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
1289         {
1290             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));
1291             dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT));
1292             if (dx) for (i = 0; i < s1; i++) dx[i] = dxx[i];
1293         }
1294         else {
1295             TRACE("%s  len: %d\n",  sot, mr->rdSize);
1296             WARN("Please report: ExtTextOut len=%d slen=%d rdSize=%d opt=%04x\n",
1297                  len, s1, mr->rdSize, mr->rdParm[3]);
1298             dxx = NULL; /* shouldn't happen -- but if, we continue with NULL */
1299         }
1300     ExtTextOutA( hdc,
1301                  (SHORT)mr->rdParm[1],       /* X position */
1302                  (SHORT)mr->rdParm[0],       /* Y position */
1303                  mr->rdParm[3],              /* options */
1304                  &rect,                      /* rectangle */
1305                  sot,                        /* string */
1306                  s1, dx);                    /* length, dx array */
1307     if (dx)
1308     {
1309         TRACE("%s  len: %d  dx0: %d\n", sot, mr->rdSize, dx[0]);
1310         HeapFree( GetProcessHeap(), 0, dx );
1311     }
1312     return TRUE;
1313 }
1314 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.