- clean-up of texture 'loading'
[wine] / objects / metafile.c
1 /*
2  * Metafile functions
3  *
4  * Copyright  David W. Metcalfe, 1994
5  *            Niels de Carpentier, Albrecht Kleine, Huw Davies 1996
6  *
7  */
8
9 #include <string.h>
10 #include <fcntl.h>
11 #include "wine/winbase16.h"
12 #include "metafiledrv.h"
13 #include "metafile.h"
14 #include "bitmap.h"
15 #include "heap.h"
16 #include "toolhelp.h"
17 #include "debug.h"
18
19 /******************************************************************
20  *         MF_AddHandle
21  *
22  *    Add a handle to an external handle table and return the index
23  */
24
25 static int MF_AddHandle(HANDLETABLE16 *ht, WORD htlen, HGDIOBJ16 hobj)
26 {
27     int i;
28
29     for (i = 0; i < htlen; i++)
30     {
31         if (*(ht->objectHandle + i) == 0)
32         {
33             *(ht->objectHandle + i) = hobj;
34             return i;
35         }
36     }
37     return -1;
38 }
39
40
41 /******************************************************************
42  *         MF_AddHandleDC
43  *
44  * Note: this function assumes that we never delete objects.
45  * If we do someday, we'll need to maintain a table to re-use deleted
46  * handles.
47  */
48 static int MF_AddHandleDC( DC *dc )
49 {
50     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
51     physDev->mh->mtNoObjects++;
52     return physDev->nextHandle++;
53 }
54
55
56 /******************************************************************
57  *         GetMetaFile16   (GDI.124)
58  */
59 HMETAFILE16 WINAPI GetMetaFile16( LPCSTR lpFilename )
60 {
61     return GetMetaFileA( lpFilename );
62 }
63
64
65 /******************************************************************
66  *         GetMetaFile32A   (GDI32.197)
67  *
68  *  Read a metafile from a file. Returns handle to a disk-based metafile.
69  */
70 HMETAFILE WINAPI GetMetaFileA( 
71                                   LPCSTR lpFilename 
72                       /* pointer to string containing filename to read */
73 )
74 {
75   HMETAFILE16 hmf;
76   METAHEADER *mh;
77   HFILE hFile;
78   DWORD size;
79   
80   TRACE(metafile,"%s\n", lpFilename);
81
82   if (!lpFilename)
83     return 0;
84
85   hmf = GlobalAlloc16(GMEM_MOVEABLE, MFHEADERSIZE);
86   mh = (METAHEADER *)GlobalLock16(hmf);
87   
88   if (!mh)
89   {
90     GlobalFree16(hmf);
91     return 0;
92   }
93   
94   if ((hFile = _lopen(lpFilename, OF_READ)) == HFILE_ERROR)
95   {
96     GlobalFree16(hmf);
97     return 0;
98   }
99   
100   if (_lread(hFile, (char *)mh, MFHEADERSIZE) == HFILE_ERROR)
101   {
102     _lclose( hFile );
103     GlobalFree16(hmf);
104     return 0;
105   }
106   
107   size = mh->mtSize * 2;         /* alloc memory for whole metafile */
108   GlobalUnlock16(hmf);
109   hmf = GlobalReAlloc16(hmf,size,GMEM_MOVEABLE);
110   mh = (METAHEADER *)GlobalLock16(hmf);
111   
112   if (!mh)
113   {
114     _lclose( hFile );
115     GlobalFree16(hmf);
116     return 0;
117   }
118   
119   if (_lread(hFile, (char*)mh + mh->mtHeaderSize * 2, 
120                 size - mh->mtHeaderSize * 2) == HFILE_ERROR)
121   {
122     _lclose( hFile );
123     GlobalFree16(hmf);
124     return 0;
125   }
126   
127   _lclose(hFile);
128
129   if (mh->mtType != 1)
130   {
131     GlobalFree16(hmf);
132     return 0;
133   }
134   
135   GlobalUnlock16(hmf);
136   return hmf;
137
138 }
139
140
141 /******************************************************************
142  *         GetMetaFile32W   (GDI32.199)
143  */
144 HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename )
145 {
146     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
147     HMETAFILE ret = GetMetaFileA( p );
148     HeapFree( GetProcessHeap(), 0, p );
149     return ret;
150 }
151
152
153 /******************************************************************
154  *         CopyMetaFile16   (GDI.151)
155  */
156
157 HMETAFILE16 WINAPI CopyMetaFile16( HMETAFILE16 hSrcMetaFile, LPCSTR lpFilename )
158 {
159     return CopyMetaFileA( hSrcMetaFile, lpFilename );
160 }
161
162
163 /******************************************************************
164  *         CopyMetaFile32A   (GDI32.23)
165  *
166  *  Copies the metafile corresponding to hSrcMetaFile to either
167  *  a disk file, if a filename is given, or to a new memory based
168  *  metafile, if lpFileName is NULL.
169  *
170  * RETURNS
171  *
172  *  Handle to metafile copy on success, NULL on failure.
173  *
174  * BUGS
175  *
176  *  Copying to disk returns NULL even if successful.
177  */
178 HMETAFILE WINAPI CopyMetaFileA(
179                    HMETAFILE hSrcMetaFile, /* handle of metafile to copy */
180                    LPCSTR lpFilename /* filename if copying to a file */
181 ) {
182     HMETAFILE16 handle = 0;
183     METAHEADER *mh;
184     METAHEADER *mh2;
185     HFILE hFile;
186     
187     TRACE(metafile,"(%08x,%s)\n", hSrcMetaFile, lpFilename);
188     
189     mh = (METAHEADER *)GlobalLock16(hSrcMetaFile);
190     
191     if (!mh)
192       return 0;
193     
194     if (lpFilename)          /* disk based metafile */
195         {
196         int i,j;
197         hFile = _lcreat(lpFilename, 0);
198         j=mh->mtType;
199         mh->mtType=1;        /* disk file version stores 1 here */
200         i=_lwrite(hFile, (char *)mh, mh->mtSize * 2) ;
201         mh->mtType=j;        /* restore old value  [0 or 1] */  
202         _lclose(hFile);
203         if (i == -1)
204             return 0;
205         /* FIXME: return value */
206         }
207     else                     /* memory based metafile */
208         {
209         handle = GlobalAlloc16(GMEM_MOVEABLE,mh->mtSize * 2);
210         mh2 = (METAHEADER *)GlobalLock16(handle);
211         memcpy(mh2,mh, mh->mtSize * 2);
212         GlobalUnlock16(handle);
213         }
214
215     GlobalUnlock16(hSrcMetaFile);
216     return handle;
217 }
218
219
220 /******************************************************************
221  *         CopyMetaFile32W   (GDI32.24)
222  */
223 HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile,
224                                     LPCWSTR lpFilename )
225 {
226     LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, lpFilename );
227     HMETAFILE ret = CopyMetaFileA( hSrcMetaFile, p );
228     HeapFree( GetProcessHeap(), 0, p );
229     return ret;
230 }
231
232
233 /******************************************************************
234  *         IsValidMetaFile   (GDI.410)
235  *
236  *  Attempts to check if a given metafile is correctly formatted.
237  *  Currently, the only things verified are several properties of the
238  *  header.
239  *
240  * RETURNS
241  *  TRUE if hmf passes some tests for being a valid metafile, FALSE otherwise.
242  *
243  * BUGS
244  *  This is not exactly what windows does, see _Undocumented_Windows_
245  *  for details.
246  */
247
248 BOOL16 WINAPI IsValidMetaFile16(HMETAFILE16 hmf)
249 {
250     BOOL16 resu=FALSE;
251     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
252     if (mh) {
253       if (mh->mtType == 1 || mh->mtType == 0) 
254         if (mh->mtHeaderSize == MFHEADERSIZE/sizeof(INT16))
255           if (mh->mtVersion == MFVERSION)
256             resu=TRUE;
257       GlobalUnlock16(hmf);
258     }
259     TRACE(metafile,"IsValidMetaFile %x => %d\n",hmf,resu);
260     return resu;         
261 }
262
263
264 /******************************************************************
265  *         PlayMetaFile16   (GDI.123)
266  *
267  */
268 BOOL16 WINAPI PlayMetaFile16( HDC16 hdc, HMETAFILE16 hmf )
269 {
270     return PlayMetaFile( hdc, hmf );
271 }
272
273 /******************************************************************
274  *         PlayMetaFile32   (GDI32.265)
275  *
276  *  Renders the metafile specified by hmf in the DC specified by
277  *  hdc. Returns FALSE on failure, TRUE on success.
278  */
279 BOOL WINAPI PlayMetaFile( 
280                              HDC hdc, /* handle of DC to render in */
281                              HMETAFILE hmf /* handle of metafile to render */
282 )
283 {
284     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
285     METARECORD *mr;
286     HANDLETABLE16 *ht;
287     HGLOBAL16 hHT;
288     int offset = 0;
289     WORD i;
290     HPEN hPen;
291     HBRUSH hBrush;
292     HFONT hFont;
293     DC *dc;
294     
295     TRACE(metafile,"(%04x %04x)\n",hdc,hmf);
296     if (!mh) return FALSE;
297
298     /* save the current pen, brush and font */
299     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
300     hPen = dc->w.hPen;
301     hBrush = dc->w.hBrush;
302     hFont = dc->w.hFont;
303     GDI_HEAP_UNLOCK(hdc);
304     /* create the handle table */
305     hHT = GlobalAlloc16(GMEM_MOVEABLE|GMEM_ZEROINIT,
306                       sizeof(HANDLETABLE16) * mh->mtNoObjects);
307     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
308
309     
310     /* loop through metafile playing records */
311     offset = mh->mtHeaderSize * 2;
312     while (offset < mh->mtSize * 2)
313     {
314         mr = (METARECORD *)((char *)mh + offset);
315         TRACE(metafile,"offset=%04x,size=%08lx\n",
316             offset, mr->rdSize);
317         if (!mr->rdSize) {
318             TRACE(metafile,"Entry got size 0 at offset %d, total mf length is %ld\n",
319                 offset,mh->mtSize*2);
320                 break; /* would loop endlessly otherwise */
321         }
322         offset += mr->rdSize * 2;
323         PlayMetaFileRecord16( hdc, ht, mr, mh->mtNoObjects );
324     }
325
326     SelectObject(hdc, hBrush);
327     SelectObject(hdc, hPen);
328     SelectObject(hdc, hFont);
329
330     /* free objects in handle table */
331     for(i = 0; i < mh->mtNoObjects; i++)
332       if(*(ht->objectHandle + i) != 0)
333         DeleteObject(*(ht->objectHandle + i));
334     
335     /* free handle table */
336     GlobalFree16(hHT);
337
338     return TRUE;
339 }
340
341
342 /******************************************************************
343  *            EnumMetaFile16   (GDI.175)
344  *
345  *  Loop through the metafile records in hmf, calling the user-specified
346  *  function for each one, stopping when the user's function returns FALSE
347  *  (which is considered to be failure)
348  *  or when no records are left (which is considered to be success). 
349  *
350  * RETURNS
351  *  TRUE on success, FALSE on failure.
352  * 
353  * HISTORY
354  *   Niels de carpentier, april 1996
355  */
356 BOOL16 WINAPI EnumMetaFile16( 
357                              HDC16 hdc, 
358                              HMETAFILE16 hmf,
359                              MFENUMPROC16 lpEnumFunc, 
360                              LPARAM lpData 
361 )
362 {
363     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
364     METARECORD *mr;
365     HANDLETABLE16 *ht;
366     HGLOBAL16 hHT;
367     SEGPTR spht;
368     int offset = 0;
369     WORD i, seg;
370     HPEN hPen;
371     HBRUSH hBrush;
372     HFONT hFont;
373     DC *dc;
374     BOOL16 result = TRUE;
375     
376     TRACE(metafile,"(%04x, %04x, %08lx, %08lx)\n",
377                      hdc, hmf, (DWORD)lpEnumFunc, lpData);
378
379     if (!(dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC ))) return 0;
380     hPen = dc->w.hPen;
381     hBrush = dc->w.hBrush;
382     hFont = dc->w.hFont;
383     GDI_HEAP_UNLOCK(hdc);
384
385     /* create the handle table */
386     
387     hHT = GlobalAlloc16(GMEM_MOVEABLE | GMEM_ZEROINIT,
388                      sizeof(HANDLETABLE16) * mh->mtNoObjects);
389     spht = WIN16_GlobalLock16(hHT);
390    
391     seg = GlobalHandleToSel16(hmf);
392     offset = mh->mtHeaderSize * 2;
393     
394     /* loop through metafile records */
395     
396     while (offset < (mh->mtSize * 2))
397     {
398         mr = (METARECORD *)((char *)mh + offset);
399         if (!lpEnumFunc( hdc, (HANDLETABLE16 *)spht,
400                          (METARECORD *) PTR_SEG_OFF_TO_HUGEPTR(seg, offset),
401                          mh->mtNoObjects, (LONG)lpData ))
402         {
403             result = FALSE;
404             break;
405         }
406         
407
408         offset += (mr->rdSize * 2);
409     }
410
411     SelectObject(hdc, hBrush);
412     SelectObject(hdc, hPen);
413     SelectObject(hdc, hFont);
414
415     ht = (HANDLETABLE16 *)GlobalLock16(hHT);
416
417     /* free objects in handle table */
418     for(i = 0; i < mh->mtNoObjects; i++)
419       if(*(ht->objectHandle + i) != 0)
420         DeleteObject(*(ht->objectHandle + i));
421
422     /* free handle table */
423     GlobalFree16(hHT);
424     GlobalUnlock16(hmf);
425     return result;
426 }
427
428 BOOL WINAPI EnumMetaFile( 
429                              HDC hdc, 
430                              HMETAFILE hmf,
431                              MFENUMPROC lpEnumFunc, 
432                              LPARAM lpData 
433 ) {
434     METAHEADER *mh = (METAHEADER *)GlobalLock16(hmf);
435     METARECORD *mr;
436     HANDLETABLE *ht;
437     BOOL result = TRUE;
438     int i, offset = 0;
439     DC *dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
440     HPEN hPen;
441     HBRUSH hBrush;
442     HFONT hFont;
443
444     TRACE(metafile,"(%08x,%08x,%p,%p)\n",
445                      hdc, hmf, lpEnumFunc, (void*)lpData);
446     if (!mh) return 0;
447
448     /* save the current pen, brush and font */
449     if (!dc) return 0;
450     hPen = dc->w.hPen;
451     hBrush = dc->w.hBrush;
452     hFont = dc->w.hFont;
453     GDI_HEAP_UNLOCK(hdc);
454
455
456     ht = (HANDLETABLE *) GlobalAlloc(GPTR, 
457                             sizeof(HANDLETABLE) * mh->mtNoObjects);
458     
459     /* loop through metafile records */
460     offset = mh->mtHeaderSize * 2;
461     
462     while (offset < (mh->mtSize * 2))
463     {
464         mr = (METARECORD *)((char *)mh + offset);
465         if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, (LONG)lpData ))
466         {
467             result = FALSE;
468             break;
469         }
470         
471         offset += (mr->rdSize * 2);
472     }
473
474     /* restore pen, brush and font */
475     SelectObject(hdc, hBrush);
476     SelectObject(hdc, hPen);
477     SelectObject(hdc, hFont);
478
479     /* free objects in handle table */
480     for(i = 0; i < mh->mtNoObjects; i++)
481       if(*(ht->objectHandle + i) != 0)
482         DeleteObject(*(ht->objectHandle + i));
483
484     /* free handle table */
485     GlobalFree((HGLOBAL)ht);
486     GlobalUnlock16(hmf);
487     return result;
488 }
489
490 static BOOL MF_Meta_CreateRegion( METARECORD *mr, HRGN hrgn );
491
492 /******************************************************************
493  *             PlayMetaFileRecord16   (GDI.176)
494  *
495  *   Render a single metafile record specified by *mr in the DC hdc, while
496  *   using the handle table *ht, of length nHandles, 
497  *   to store metafile objects.
498  *
499  * BUGS
500  *  The following metafile records are unimplemented:
501  *
502  *  FRAMEREGION, DRAWTEXT, SETDIBTODEV, ANIMATEPALETTE, SETPALENTRIES,
503  *  RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE,
504  *  ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP.
505  *
506  */
507 void WINAPI PlayMetaFileRecord16( 
508             HDC16 hdc, /* DC to render metafile into */
509             HANDLETABLE16 *ht, /* pointer to handle table for metafile objects */
510             METARECORD *mr, /* pointer to metafile record to render */
511             UINT16 nHandles /* size of handle table */
512 ) {
513     short s1;
514     HANDLE16 hndl;
515     char *ptr;
516     BITMAPINFOHEADER *infohdr;
517
518     TRACE(metafile,"(%04x %08lx %08lx %04x) function %04x\n",
519                  hdc,(LONG)ht, (LONG)mr, nHandles, mr->rdFunction);
520     
521     switch (mr->rdFunction)
522     {
523     case META_EOF:
524       break;
525
526     case META_DELETEOBJECT:
527       DeleteObject(*(ht->objectHandle + *(mr->rdParm)));
528       *(ht->objectHandle + *(mr->rdParm)) = 0;
529       break;
530
531     case META_SETBKCOLOR:
532         SetBkColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
533         break;
534
535     case META_SETBKMODE:
536         SetBkMode16(hdc, *(mr->rdParm));
537         break;
538
539     case META_SETMAPMODE:
540         SetMapMode16(hdc, *(mr->rdParm));
541         break;
542
543     case META_SETROP2:
544         SetROP216(hdc, *(mr->rdParm));
545         break;
546
547     case META_SETRELABS:
548         SetRelAbs16(hdc, *(mr->rdParm));
549         break;
550
551     case META_SETPOLYFILLMODE:
552         SetPolyFillMode16(hdc, *(mr->rdParm));
553         break;
554
555     case META_SETSTRETCHBLTMODE:
556         SetStretchBltMode16(hdc, *(mr->rdParm));
557         break;
558
559     case META_SETTEXTCOLOR:
560         SetTextColor16(hdc, MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
561         break;
562
563     case META_SETWINDOWORG:
564         SetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
565         break;
566
567     case META_SETWINDOWEXT:
568         SetWindowExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
569         break;
570
571     case META_SETVIEWPORTORG:
572         SetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
573         break;
574
575     case META_SETVIEWPORTEXT:
576         SetViewportExt16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
577         break;
578
579     case META_OFFSETWINDOWORG:
580         OffsetWindowOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
581         break;
582
583     case META_SCALEWINDOWEXT:
584         ScaleWindowExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
585                        *(mr->rdParm + 1), *(mr->rdParm));
586         break;
587
588     case META_OFFSETVIEWPORTORG:
589         OffsetViewportOrg16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
590         break;
591
592     case META_SCALEVIEWPORTEXT:
593         ScaleViewportExt16(hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
594                          *(mr->rdParm + 1), *(mr->rdParm));
595         break;
596
597     case META_LINETO:
598         LineTo(hdc, (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
599         break;
600
601     case META_MOVETO:
602         MoveTo16(hdc, *(mr->rdParm + 1), *(mr->rdParm));
603         break;
604
605     case META_EXCLUDECLIPRECT:
606         ExcludeClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
607                            *(mr->rdParm + 1), *(mr->rdParm) );
608         break;
609
610     case META_INTERSECTCLIPRECT:
611         IntersectClipRect16( hdc, *(mr->rdParm + 3), *(mr->rdParm + 2),
612                              *(mr->rdParm + 1), *(mr->rdParm) );
613         break;
614
615     case META_ARC:
616         Arc(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
617               (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
618               (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
619              (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
620         break;
621
622     case META_ELLIPSE:
623         Ellipse(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
624                   (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
625         break;
626
627     case META_FLOODFILL:
628         FloodFill(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
629                     MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
630         break;
631
632     case META_PIE:
633         Pie(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
634               (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
635               (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
636              (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
637         break;
638
639     case META_RECTANGLE:
640         Rectangle(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
641                     (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
642         break;
643
644     case META_ROUNDRECT:
645         RoundRect(hdc, (INT16)*(mr->rdParm + 5), (INT16)*(mr->rdParm + 4),
646                     (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
647                     (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
648         break;
649
650     case META_PATBLT:
651         PatBlt16(hdc, *(mr->rdParm + 5), *(mr->rdParm + 4),
652                  *(mr->rdParm + 3), *(mr->rdParm + 2),
653                  MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
654         break;
655
656     case META_SAVEDC:
657         SaveDC(hdc);
658         break;
659
660     case META_SETPIXEL:
661         SetPixel(hdc, (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
662                    MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
663         break;
664
665     case META_OFFSETCLIPRGN:
666         OffsetClipRgn16( hdc, *(mr->rdParm + 1), *(mr->rdParm) );
667         break;
668
669     case META_TEXTOUT:
670         s1 = *(mr->rdParm);
671         TextOut16(hdc, *(mr->rdParm + ((s1 + 1) >> 1) + 2),
672                   *(mr->rdParm + ((s1 + 1) >> 1) + 1), 
673                   (char *)(mr->rdParm + 1), s1);
674         break;
675
676     case META_POLYGON:
677         Polygon16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
678         break;
679
680     case META_POLYPOLYGON:
681       PolyPolygon16(hdc, (LPPOINT16)(mr->rdParm + *(mr->rdParm) + 1),
682                     (LPINT16)(mr->rdParm + 1), *(mr->rdParm)); 
683       break;
684
685     case META_POLYLINE:
686         Polyline16(hdc, (LPPOINT16)(mr->rdParm + 1), *(mr->rdParm));
687         break;
688
689     case META_RESTOREDC:
690         RestoreDC(hdc, (INT16)*(mr->rdParm));
691         break;
692
693     case META_SELECTOBJECT:
694         SelectObject(hdc, *(ht->objectHandle + *(mr->rdParm)));
695         break;
696
697     case META_CHORD:
698         Chord(hdc, (INT16)*(mr->rdParm + 7), (INT16)*(mr->rdParm + 6),
699                 (INT16)*(mr->rdParm+5), (INT16)*(mr->rdParm + 4),
700                 (INT16)*(mr->rdParm + 3), (INT16)*(mr->rdParm + 2),
701                (INT16)*(mr->rdParm + 1), (INT16)*(mr->rdParm));
702         break;
703
704     case META_CREATEPATTERNBRUSH:
705         switch (*(mr->rdParm))
706         {
707         case BS_PATTERN:
708             infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2);
709             MF_AddHandle(ht, nHandles,
710                          CreatePatternBrush(CreateBitmap(infohdr->biWidth, 
711                                       infohdr->biHeight, 
712                                       infohdr->biPlanes, 
713                                       infohdr->biBitCount,
714                                       (LPSTR)(mr->rdParm + 
715                                       (sizeof(BITMAPINFOHEADER) / 2) + 4))));
716             break;
717
718         case BS_DIBPATTERN:
719             s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
720             hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
721             ptr = GlobalLock16(hndl);
722             memcpy(ptr, mr->rdParm + 2, s1);
723             GlobalUnlock16(hndl);
724             MF_AddHandle(ht, nHandles,
725                          CreateDIBPatternBrush(hndl, *(mr->rdParm + 1)));
726             GlobalFree16(hndl);
727         }
728         break;
729         
730     case META_CREATEPENINDIRECT:
731         MF_AddHandle(ht, nHandles, 
732                      CreatePenIndirect16((LOGPEN16 *)(&(mr->rdParm))));
733         break;
734
735     case META_CREATEFONTINDIRECT:
736         MF_AddHandle(ht, nHandles, 
737                      CreateFontIndirect16((LOGFONT16 *)(&(mr->rdParm))));
738         break;
739
740     case META_CREATEBRUSHINDIRECT:
741         MF_AddHandle(ht, nHandles, 
742                      CreateBrushIndirect16((LOGBRUSH16 *)(&(mr->rdParm))));
743         break;
744
745     /* W. Magro: Some new metafile operations.  Not all debugged. */
746     case META_CREATEPALETTE:
747         MF_AddHandle(ht, nHandles, 
748                      CreatePalette16((LPLOGPALETTE)mr->rdParm));
749         break;
750
751     case META_SETTEXTALIGN:
752         SetTextAlign16(hdc, *(mr->rdParm));
753         break;
754
755     case META_SELECTPALETTE:
756         SelectPalette16(hdc, *(ht->objectHandle + *(mr->rdParm+1)),*(mr->rdParm));
757         break;
758
759     case META_SETMAPPERFLAGS:
760         SetMapperFlags16(hdc, *(mr->rdParm));
761         break;
762
763     case META_REALIZEPALETTE:
764         RealizePalette16(hdc);
765         break;
766
767     case META_ESCAPE:
768         FIXME(metafile, "META_ESCAPE unimplemented.\n");
769         break;
770
771         /* --- Begin of fixed or new metafile operations. July 1996 ----*/
772     case META_EXTTEXTOUT:
773       {
774         LPINT16 dxx;
775         LPSTR sot; 
776         DWORD len;
777
778         s1 = mr->rdParm[2];                              /* String length */
779         len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short)
780          + sizeof(UINT16) +  (mr->rdParm[3] ? sizeof(RECT16) : 0);  /* rec len without dx array */
781
782         sot= (LPSTR)&mr->rdParm[4];                     /* start_of_text */
783         if (mr->rdParm[3])
784            sot+=sizeof(RECT16);                         /* there is a rectangle, so add offset */
785          
786         if (mr->rdSize == len / 2)
787           dxx = NULL;                                   /* determine if array present */
788         else 
789           if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2)
790             dxx = (LPINT16)(sot+(((s1+1)>>1)*2));          
791           else 
792           {
793            TRACE(metafile,"%s  len: %ld\n",
794              sot,mr->rdSize);
795            WARN(metafile,
796              "Please report: PlayMetaFile/ExtTextOut len=%ld slen=%d rdSize=%ld opt=%04x\n",
797                    len,s1,mr->rdSize,mr->rdParm[3]);
798            dxx = NULL; /* should't happen -- but if, we continue with NULL [for workaround] */
799           }
800         ExtTextOut16( hdc, mr->rdParm[1],              /* X position */
801                            mr->rdParm[0],              /* Y position */
802                            mr->rdParm[3],              /* options */
803                            mr->rdParm[3] ? (LPRECT16) &mr->rdParm[4]:NULL,  /* rectangle */
804                            sot,                         /* string */
805                            s1, dxx);                    /* length, dx array */
806         if (dxx)                      
807           TRACE(metafile,"%s  len: %ld  dx0: %d\n",
808             sot,mr->rdSize,dxx[0]);
809        }
810        break;
811     
812     case META_STRETCHDIB:
813       {
814        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]);
815        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
816        StretchDIBits16(hdc,mr->rdParm[10],mr->rdParm[9],mr->rdParm[8],
817                        mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
818                        mr->rdParm[4],mr->rdParm[3],bits,info,
819                        mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1]));
820       }
821       break;
822
823     case META_DIBSTRETCHBLT:
824       {
825        LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]); 
826        LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[2] );
827        StretchDIBits16(hdc,mr->rdParm[9],mr->rdParm[8],mr->rdParm[7],
828                        mr->rdParm[6],mr->rdParm[5],mr->rdParm[4],
829                        mr->rdParm[3],mr->rdParm[2],bits,info,
830                        DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
831       }
832       break;              
833
834     case META_STRETCHBLT:
835       {
836        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
837        HBITMAP hbitmap=CreateBitmap(mr->rdParm[10], /*Width */
838                                         mr->rdParm[11], /*Height*/
839                                         mr->rdParm[13], /*Planes*/
840                                         mr->rdParm[14], /*BitsPixel*/
841                                         (LPSTR)&mr->rdParm[15]);  /*bits*/
842        SelectObject(hdcSrc,hbitmap);
843        StretchBlt16(hdc,mr->rdParm[9],mr->rdParm[8],
844                     mr->rdParm[7],mr->rdParm[6],
845                     hdcSrc,mr->rdParm[5],mr->rdParm[4],
846                     mr->rdParm[3],mr->rdParm[2],
847                     MAKELONG(mr->rdParm[0],mr->rdParm[1]));
848        DeleteDC(hdcSrc);                    
849       }
850       break;
851
852     case META_BITBLT:            /* <-- not yet debugged */
853       {
854        HDC16 hdcSrc=CreateCompatibleDC16(hdc);
855        HBITMAP hbitmap=CreateBitmap(mr->rdParm[7]/*Width */,
856                                         mr->rdParm[8]/*Height*/,
857                                         mr->rdParm[10]/*Planes*/,
858                                         mr->rdParm[11]/*BitsPixel*/,
859                                         (LPSTR)&mr->rdParm[12]/*bits*/);
860        SelectObject(hdcSrc,hbitmap);
861        BitBlt(hdc,(INT16)mr->rdParm[6],(INT16)mr->rdParm[5],
862                 (INT16)mr->rdParm[4],(INT16)mr->rdParm[3],
863                 hdcSrc, (INT16)mr->rdParm[2],(INT16)mr->rdParm[1],
864                 MAKELONG(0,mr->rdParm[0]));
865        DeleteDC(hdcSrc);                    
866       }
867       break;
868
869        /* --- Begin of new metafile operations. April, 1997 (ak) ----*/
870     case META_CREATEREGION:
871       {
872         HRGN hrgn = CreateRectRgn(0,0,0,0);
873  
874         MF_Meta_CreateRegion(mr, hrgn);
875         MF_AddHandle(ht, nHandles, hrgn);
876       }
877       break;
878
879      case META_FILLREGION:
880         FillRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)),
881                        *(ht->objectHandle + *(mr->rdParm+1)));
882         break;
883
884      case META_INVERTREGION:
885         InvertRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
886         break; 
887
888      case META_PAINTREGION:
889         PaintRgn16(hdc, *(ht->objectHandle + *(mr->rdParm)));
890         break;
891
892      case META_SELECTCLIPREGION:
893         SelectClipRgn(hdc, *(ht->objectHandle + *(mr->rdParm)));
894         break;
895
896      case META_DIBCREATEPATTERNBRUSH:
897         /*  *(mr->rdParm) may be BS_PATTERN or BS_DIBPATTERN: but there's no difference */
898         TRACE(metafile,"%d\n",*(mr->rdParm));
899         s1 = mr->rdSize * 2 - sizeof(METARECORD) - 2;
900         hndl = GlobalAlloc16(GMEM_MOVEABLE, s1);
901         ptr = GlobalLock16(hndl);
902         memcpy(ptr, mr->rdParm + 2, s1);
903         GlobalUnlock16(hndl);
904         MF_AddHandle(ht, nHandles,CreateDIBPatternBrush16(hndl, *(mr->rdParm + 1)));
905         GlobalFree16(hndl);
906         break;
907
908      case META_DIBBITBLT:
909         {
910                 /*In practice ive found that theres two layout for META_DIBBITBLT,
911                 one (the first here) is the usual one when a src dc is actually passed
912                 int, the second occurs when the src dc is passed in as NULL to
913                 the creating BitBlt.
914                 as the second case has no dib, a size check will suffice to distinguish.
915
916
917                 Caolan.McNamara@ul.ie
918                 */
919                 if (mr->rdSize > 12)
920                 {
921                     LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]);
922                     LPSTR bits = (LPSTR)info + DIB_BitmapInfoSize( info, mr->rdParm[0] );
923                     StretchDIBits16(hdc,mr->rdParm[7],mr->rdParm[6],mr->rdParm[5],
924                                     mr->rdParm[4],mr->rdParm[3],mr->rdParm[2],
925                                     mr->rdParm[5],mr->rdParm[4],bits,info,
926                                     DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1]));
927                 }
928                 else    /*equivalent to a PatBlt*/
929                 {
930                     PatBlt16(hdc, mr->rdParm[8], mr->rdParm[7],
931                              mr->rdParm[6], mr->rdParm[5],
932                              MAKELONG(*(mr->rdParm), *(mr->rdParm + 1)));
933                 }
934         }
935         break;  
936        
937      case META_SETTEXTCHAREXTRA:
938             SetTextCharacterExtra16(hdc, (INT16)*(mr->rdParm));
939             break;
940
941      case META_SETTEXTJUSTIFICATION:
942         SetTextJustification(hdc, *(mr->rdParm + 1), *(mr->rdParm));
943         break;
944
945     case META_EXTFLOODFILL:
946         ExtFloodFill(hdc, (INT16)*(mr->rdParm + 4), (INT16)*(mr->rdParm + 3),
947                      MAKELONG(*(mr->rdParm+1), *(mr->rdParm + 2)),*(mr->rdParm));
948         break;
949
950 #define META_UNIMP(x) case x: FIXME(metafile, "PlayMetaFileRecord:record type "#x" not implemented.\n");break;
951     META_UNIMP(META_FRAMEREGION)
952     META_UNIMP(META_DRAWTEXT)
953     META_UNIMP(META_SETDIBTODEV)
954     META_UNIMP(META_ANIMATEPALETTE)
955     META_UNIMP(META_SETPALENTRIES)
956     META_UNIMP(META_RESIZEPALETTE)
957     META_UNIMP(META_RESETDC)
958     META_UNIMP(META_STARTDOC)
959     META_UNIMP(META_STARTPAGE)
960     META_UNIMP(META_ENDPAGE)
961     META_UNIMP(META_ABORTDOC)
962     META_UNIMP(META_ENDDOC)
963     META_UNIMP(META_CREATEBRUSH)
964     META_UNIMP(META_CREATEBITMAPINDIRECT)
965     META_UNIMP(META_CREATEBITMAP)
966 #undef META_UNIMP
967
968     default:
969         WARN(metafile, "PlayMetaFileRecord: Unknown record type %x\n",
970                                               mr->rdFunction);
971     }
972 }
973
974
975 BOOL WINAPI PlayMetaFileRecord( 
976      HDC hdc, 
977      HANDLETABLE *handletable, 
978      METARECORD *metarecord, 
979      UINT handles  
980     )
981 {
982   HANDLETABLE16 * ht = (void *)GlobalAlloc(GPTR, 
983                                handles*sizeof(HANDLETABLE16));
984   int i = 0;
985   TRACE(metafile, "(%08x,%p,%p,%d)\n", hdc, handletable, metarecord, handles); 
986   for (i=0; i<handles; i++)  
987     ht->objectHandle[i] =  handletable->objectHandle[i];
988   PlayMetaFileRecord16(hdc, ht, metarecord, handles);
989   for (i=0; i<handles; i++) 
990     handletable->objectHandle[i] = ht->objectHandle[i];
991   GlobalFree((HGLOBAL)ht);
992   return TRUE;
993 }
994
995 /******************************************************************
996  *         GetMetaFileBits   (GDI.159)
997  *
998  * Trade in a metafile object handle for a handle to the metafile memory.
999  *
1000  */
1001
1002 HGLOBAL16 WINAPI GetMetaFileBits16(
1003                                  HMETAFILE16 hmf /* metafile handle */
1004                                  )
1005 {
1006     TRACE(metafile,"hMem out: %04x\n", hmf);
1007     return hmf;
1008 }
1009
1010 /******************************************************************
1011  *         SetMetaFileBits   (GDI.160)
1012  *
1013  * Trade in a metafile memory handle for a handle to a metafile object.
1014  * The memory region should hold a proper metafile, otherwise
1015  * problems will occur when it is used. Validity of the memory is not
1016  * checked. The function is essentially just the identity function.
1017  */
1018 HMETAFILE16 WINAPI SetMetaFileBits16( 
1019                                    HGLOBAL16 hMem 
1020                         /* handle to a memory region holding a metafile */
1021 )
1022 {
1023     TRACE(metafile,"hmf out: %04x\n", hMem);
1024
1025     return hMem;
1026 }
1027
1028 /******************************************************************
1029  *         SetMetaFileBitsBetter   (GDI.196)
1030  *
1031  * Trade in a metafile memory handle for a handle to a metafile object,
1032  * making a cursory check (using IsValidMetaFile()) that the memory
1033  * handle points to a valid metafile.
1034  *
1035  * RETURNS
1036  *  Handle to a metafile on success, NULL on failure..
1037  */
1038 HMETAFILE16 WINAPI SetMetaFileBitsBetter16( HMETAFILE16 hMeta )
1039 {
1040    if( IsValidMetaFile16( hMeta ) )
1041        return (HMETAFILE16)GlobalReAlloc16( hMeta, 0, 
1042                            GMEM_SHARE | GMEM_NODISCARD | GMEM_MODIFY);
1043    return (HMETAFILE16)0;
1044 }
1045
1046 /******************************************************************
1047  *         SetMetaFileBitsEx    (GDI32.323)
1048  * 
1049  *  Create a metafile from raw data. No checking of the data is performed.
1050  *  Use _GetMetaFileBitsEx_ to get raw data from a metafile.
1051  */
1052 HMETAFILE WINAPI SetMetaFileBitsEx( 
1053      UINT size, /* size of metafile, in bytes */
1054      const BYTE *lpData /* pointer to metafile data */  
1055     )
1056 {
1057   HMETAFILE hmf = GlobalAlloc16(GHND, size);
1058   BYTE *p = GlobalLock16(hmf) ;
1059   TRACE(metafile, "(%d,%p) returning %08x\n", size, lpData, hmf);
1060   if (!hmf || !p) return 0;
1061   memcpy(p, lpData, size);
1062   GlobalUnlock16(hmf);
1063   return hmf;
1064 }
1065
1066 /*****************************************************************
1067  *  GetMetaFileBitsEx     (GDI32.198)  Get raw metafile data
1068  * 
1069  *  Copies the data from metafile _hmf_ into the buffer _buf_.
1070  *  If _buf_ is zero, returns size of buffer required. Otherwise,
1071  *  returns number of bytes copied.
1072  */
1073 UINT WINAPI GetMetaFileBitsEx( 
1074      HMETAFILE hmf, /* metafile */
1075      UINT nSize, /* size of buf */ 
1076      LPVOID buf   /* buffer to receive raw metafile data */  
1077 ) {
1078   METAHEADER *h = GlobalLock16(hmf);
1079   UINT mfSize;
1080
1081   TRACE(metafile, "(%08x,%d,%p)\n", hmf, nSize, buf);
1082   if (!h) return 0;  /* FIXME: error code */
1083   mfSize = h->mtSize * 2;
1084   if (!buf) {
1085     GlobalUnlock16(hmf);
1086     TRACE(metafile,"returning size %d\n", mfSize);
1087     return mfSize;
1088   }
1089   if(mfSize > nSize) mfSize = nSize;
1090   memmove(buf, h, mfSize);
1091   GlobalUnlock16(hmf);
1092   return mfSize;
1093 }
1094
1095 /******************************************************************
1096  *         GetWinMetaFileBits [GDI32.241]
1097  */
1098 UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf,
1099                                 UINT cbBuffer, LPBYTE lpbBuffer,
1100                                 INT fnMapMode, HDC hdcRef)
1101 {
1102   FIXME(metafile, "(%d,%d,%p,%d,%d): stub\n",
1103         hemf, cbBuffer, lpbBuffer, fnMapMode, hdcRef);
1104   return 0;
1105 }
1106
1107 /******************************************************************
1108  *         MF_Meta_CreateRegion
1109  *
1110  *  Handles META_CREATEREGION for PlayMetaFileRecord().
1111  */
1112
1113 /*
1114  *      The layout of the record looks something like this:
1115  *       
1116  *       rdParm meaning
1117  *       0              Always 0?
1118  *       1              Always 6?
1119  *       2              Looks like a handle? - not constant
1120  *       3              0 or 1 ??
1121  *       4              Total number of bytes
1122  *       5              No. of seperate bands = n [see below]
1123  *       6              Largest number of x co-ords in a band
1124  *       7-10           Bounding box x1 y1 x2 y2
1125  *       11-...         n bands
1126  *
1127  *       Regions are divided into bands that are uniform in the
1128  *       y-direction. Each band consists of pairs of on/off x-coords and is
1129  *       written as
1130  *              m y0 y1 x1 x2 x3 ... xm m
1131  *       into successive rdParm[]s.
1132  *
1133  *       This is probably just a dump of the internal RGNOBJ?
1134  *
1135  *       HDMD - 18/12/97
1136  *
1137  */
1138
1139 static BOOL MF_Meta_CreateRegion( METARECORD *mr, HRGN hrgn )
1140 {
1141     WORD band, pair;
1142     WORD *start, *end;
1143     INT16 y0, y1;
1144     HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 );
1145
1146     for(band  = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5];
1147                                                 band++, start = end + 1) {
1148         if(*start / 2 != (*start + 1) / 2) {
1149             WARN(metafile, "Delimiter not even.\n");
1150             DeleteObject( hrgn2 );
1151             return FALSE;
1152         }
1153
1154         end = start + *start + 3;
1155         if(end > (WORD *)mr + mr->rdSize) {
1156             WARN(metafile, "End points outside record.\n");
1157             DeleteObject( hrgn2 );
1158             return FALSE;
1159         }
1160
1161         if(*start != *end) {
1162             WARN(metafile, "Mismatched delimiters.\n");
1163             DeleteObject( hrgn2 );
1164             return FALSE;
1165         }
1166
1167         y0 = *(INT16 *)(start + 1);
1168         y1 = *(INT16 *)(start + 2);
1169         for(pair = 0; pair < *start / 2; pair++) {
1170             SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0,
1171                                  *(INT16 *)(start + 4 + 2*pair), y1 );
1172             CombineRgn(hrgn, hrgn, hrgn2, RGN_OR);
1173         }
1174     }
1175     DeleteObject( hrgn2 );
1176     return TRUE;
1177  }
1178  
1179
1180 /******************************************************************
1181  *         MF_WriteRecord
1182  *
1183  * Warning: this function can change the metafile handle.
1184  */
1185
1186 static BOOL MF_WriteRecord( DC *dc, METARECORD *mr, DWORD rlen)
1187 {
1188     DWORD len;
1189     METAHEADER *mh;
1190     METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
1191
1192     switch(physDev->mh->mtType)
1193     {
1194     case METAFILE_MEMORY:
1195         len = physDev->mh->mtSize * 2 + rlen;
1196         mh = HeapReAlloc( SystemHeap, 0, physDev->mh, len );
1197         if (!mh) return FALSE;
1198         physDev->mh = mh;
1199         memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
1200         break;
1201     case METAFILE_DISK:
1202         TRACE(metafile,"Writing record to disk\n");
1203         if (_lwrite(physDev->mh->mtNoParameters, (char *)mr, rlen) == -1)
1204             return FALSE;
1205         break;
1206     default:
1207         ERR(metafile, "Unknown metafile type %d\n", physDev->mh->mtType );
1208         return FALSE;
1209     }
1210
1211     physDev->mh->mtSize += rlen / 2;
1212     physDev->mh->mtMaxRecord = MAX(physDev->mh->mtMaxRecord, rlen / 2);
1213     return TRUE;
1214 }
1215
1216
1217 /******************************************************************
1218  *         MF_MetaParam0
1219  */
1220
1221 BOOL MF_MetaParam0(DC *dc, short func)
1222 {
1223     char buffer[8];
1224     METARECORD *mr = (METARECORD *)&buffer;
1225     
1226     mr->rdSize = 3;
1227     mr->rdFunction = func;
1228     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1229 }
1230
1231
1232 /******************************************************************
1233  *         MF_MetaParam1
1234  */
1235 BOOL MF_MetaParam1(DC *dc, short func, short param1)
1236 {
1237     char buffer[8];
1238     METARECORD *mr = (METARECORD *)&buffer;
1239     
1240     mr->rdSize = 4;
1241     mr->rdFunction = func;
1242     *(mr->rdParm) = param1;
1243     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1244 }
1245
1246
1247 /******************************************************************
1248  *         MF_MetaParam2
1249  */
1250 BOOL MF_MetaParam2(DC *dc, short func, short param1, short param2)
1251 {
1252     char buffer[10];
1253     METARECORD *mr = (METARECORD *)&buffer;
1254     
1255     mr->rdSize = 5;
1256     mr->rdFunction = func;
1257     *(mr->rdParm) = param2;
1258     *(mr->rdParm + 1) = param1;
1259     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1260 }
1261
1262
1263 /******************************************************************
1264  *         MF_MetaParam4
1265  */
1266
1267 BOOL MF_MetaParam4(DC *dc, short func, short param1, short param2, 
1268                    short param3, short param4)
1269 {
1270     char buffer[14];
1271     METARECORD *mr = (METARECORD *)&buffer;
1272     
1273     mr->rdSize = 7;
1274     mr->rdFunction = func;
1275     *(mr->rdParm) = param4;
1276     *(mr->rdParm + 1) = param3;
1277     *(mr->rdParm + 2) = param2;
1278     *(mr->rdParm + 3) = param1;
1279     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1280 }
1281
1282
1283 /******************************************************************
1284  *         MF_MetaParam6
1285  */
1286
1287 BOOL MF_MetaParam6(DC *dc, short func, short param1, short param2, 
1288                    short param3, short param4, short param5, short param6)
1289 {
1290     char buffer[18];
1291     METARECORD *mr = (METARECORD *)&buffer;
1292     
1293     mr->rdSize = 9;
1294     mr->rdFunction = func;
1295     *(mr->rdParm) = param6;
1296     *(mr->rdParm + 1) = param5;
1297     *(mr->rdParm + 2) = param4;
1298     *(mr->rdParm + 3) = param3;
1299     *(mr->rdParm + 4) = param2;
1300     *(mr->rdParm + 5) = param1;
1301     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1302 }
1303
1304
1305 /******************************************************************
1306  *         MF_MetaParam8
1307  */
1308 BOOL MF_MetaParam8(DC *dc, short func, short param1, short param2, 
1309                    short param3, short param4, short param5,
1310                    short param6, short param7, short param8)
1311 {
1312     char buffer[22];
1313     METARECORD *mr = (METARECORD *)&buffer;
1314     
1315     mr->rdSize = 11;
1316     mr->rdFunction = func;
1317     *(mr->rdParm) = param8;
1318     *(mr->rdParm + 1) = param7;
1319     *(mr->rdParm + 2) = param6;
1320     *(mr->rdParm + 3) = param5;
1321     *(mr->rdParm + 4) = param4;
1322     *(mr->rdParm + 5) = param3;
1323     *(mr->rdParm + 6) = param2;
1324     *(mr->rdParm + 7) = param1;
1325     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1326 }
1327
1328
1329 /******************************************************************
1330  *         MF_CreateBrushIndirect
1331  */
1332
1333 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1334 {
1335     int index;
1336     char buffer[sizeof(METARECORD) - 2 + sizeof(*logbrush)];
1337     METARECORD *mr = (METARECORD *)&buffer;
1338
1339     mr->rdSize = (sizeof(METARECORD) + sizeof(*logbrush) - 2) / 2;
1340     mr->rdFunction = META_CREATEBRUSHINDIRECT;
1341     memcpy(&(mr->rdParm), logbrush, sizeof(*logbrush));
1342     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1343
1344     mr->rdSize = sizeof(METARECORD) / 2;
1345     mr->rdFunction = META_SELECTOBJECT;
1346
1347     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1348     *(mr->rdParm) = index;
1349     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1350 }
1351
1352
1353 /******************************************************************
1354  *         MF_CreatePatternBrush
1355  */
1356
1357 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH16 hBrush, LOGBRUSH16 *logbrush)
1358 {
1359     DWORD len, bmSize, biSize;
1360     METARECORD *mr;
1361     BITMAPINFO *info;
1362     int index;
1363     char buffer[sizeof(METARECORD)];
1364
1365     switch (logbrush->lbStyle)
1366     {
1367     case BS_PATTERN:
1368         {
1369             BITMAP bm;
1370             BYTE *bits;
1371
1372             GetObjectA(logbrush->lbHatch, sizeof(bm), &bm);
1373             if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
1374                 FIXME(metafile, "Trying to store a colour pattern brush\n");
1375                 return FALSE;
1376             }
1377
1378             bmSize = bm.bmHeight * DIB_GetDIBWidthBytes(bm.bmWidth, 1);
1379
1380             len = sizeof(METARECORD) +  sizeof(WORD) + sizeof(BITMAPINFO) + 
1381               sizeof(RGBQUAD) + bmSize;
1382              
1383             mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
1384             if(!mr) return FALSE;
1385             mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1386             mr->rdSize = len / 2;
1387             mr->rdParm[0] = BS_PATTERN;
1388             mr->rdParm[1] = DIB_RGB_COLORS;
1389             info = (BITMAPINFO *)(mr->rdParm + 2);
1390
1391             info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1392             info->bmiHeader.biWidth = bm.bmWidth;
1393             info->bmiHeader.biHeight = bm.bmHeight;
1394             info->bmiHeader.biPlanes = 1;
1395             info->bmiHeader.biBitCount = 1;
1396             bits = ((BYTE *)info) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
1397
1398             GetDIBits(dc->hSelf, logbrush->lbHatch, 0, bm.bmHeight, bits,
1399                       info, DIB_RGB_COLORS);
1400             *(DWORD *)info->bmiColors = 0;
1401             *(DWORD *)(info->bmiColors + 1) = 0xffffff;
1402             break;
1403         }
1404
1405     case BS_DIBPATTERN:
1406         info = (BITMAPINFO *)GlobalLock16((HGLOBAL16)logbrush->lbHatch);
1407         if (info->bmiHeader.biCompression)
1408             bmSize = info->bmiHeader.biSizeImage;
1409         else
1410             bmSize = DIB_GetDIBWidthBytes(info->bmiHeader.biWidth,
1411                                           info->bmiHeader.biBitCount) 
1412                        * info->bmiHeader.biHeight;
1413         biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush->lbColor)); 
1414         len = sizeof(METARECORD) + biSize + bmSize + 2;
1415         mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
1416         if(!mr) return FALSE;
1417         mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
1418         mr->rdSize = len / 2;
1419         *(mr->rdParm) = logbrush->lbStyle;
1420         *(mr->rdParm + 1) = LOWORD(logbrush->lbColor);
1421         memcpy(mr->rdParm + 2, info, biSize + bmSize);
1422         break;
1423     default:
1424         return FALSE;
1425     }
1426     if (!(MF_WriteRecord(dc, mr, len)))
1427     {
1428         HeapFree(GetProcessHeap(), 0, mr);
1429         return FALSE;
1430     }
1431
1432     HeapFree(GetProcessHeap(), 0, mr);
1433     
1434     mr = (METARECORD *)&buffer;
1435     mr->rdSize = sizeof(METARECORD) / 2;
1436     mr->rdFunction = META_SELECTOBJECT;
1437
1438     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1439     *(mr->rdParm) = index;
1440     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1441 }
1442
1443
1444 /******************************************************************
1445  *         MF_CreatePenIndirect
1446  */
1447
1448 BOOL MF_CreatePenIndirect(DC *dc, HPEN16 hPen, LOGPEN16 *logpen)
1449 {
1450     int index;
1451     char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
1452     METARECORD *mr = (METARECORD *)&buffer;
1453
1454     mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
1455     mr->rdFunction = META_CREATEPENINDIRECT;
1456     memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
1457     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1458
1459     mr->rdSize = sizeof(METARECORD) / 2;
1460     mr->rdFunction = META_SELECTOBJECT;
1461
1462     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1463     *(mr->rdParm) = index;
1464     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1465 }
1466
1467
1468 /******************************************************************
1469  *         MF_CreateFontIndirect
1470  */
1471
1472 BOOL MF_CreateFontIndirect(DC *dc, HFONT16 hFont, LOGFONT16 *logfont)
1473 {
1474     int index;
1475     char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
1476     METARECORD *mr = (METARECORD *)&buffer;
1477
1478     mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
1479     mr->rdFunction = META_CREATEFONTINDIRECT;
1480     memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
1481     if (!(MF_WriteRecord( dc, mr, mr->rdSize * 2))) return FALSE;
1482
1483     mr->rdSize = sizeof(METARECORD) / 2;
1484     mr->rdFunction = META_SELECTOBJECT;
1485
1486     if ((index = MF_AddHandleDC( dc )) == -1) return FALSE;
1487     *(mr->rdParm) = index;
1488     return MF_WriteRecord( dc, mr, mr->rdSize * 2);
1489 }
1490
1491
1492 /******************************************************************
1493  *         MF_TextOut
1494  */
1495 BOOL MF_TextOut(DC *dc, short x, short y, LPCSTR str, short count)
1496 {
1497     BOOL ret;
1498     DWORD len;
1499     HGLOBAL16 hmr;
1500     METARECORD *mr;
1501
1502     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 4;
1503     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1504         return FALSE;
1505     mr = (METARECORD *)GlobalLock16(hmr);
1506     memset(mr, 0, len);
1507
1508     mr->rdSize = len / 2;
1509     mr->rdFunction = META_TEXTOUT;
1510     *(mr->rdParm) = count;
1511     memcpy(mr->rdParm + 1, str, count);
1512     *(mr->rdParm + ((count + 1) >> 1) + 1) = y;
1513     *(mr->rdParm + ((count + 1) >> 1) + 2) = x;
1514     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1515     GlobalFree16(hmr);
1516     return ret;
1517 }
1518
1519 /******************************************************************
1520  *         MF_ExtTextOut
1521  */
1522 BOOL MF_ExtTextOut(DC*dc, short x, short y, UINT16 flags, const RECT16 *rect,
1523                      LPCSTR str, short count, const INT16 *lpDx)
1524 {
1525     BOOL ret;
1526     DWORD len;
1527     HGLOBAL16 hmr;
1528     METARECORD *mr;
1529     
1530     if((!flags && rect) || (flags && !rect))
1531         WARN(metafile, "Inconsistent flags and rect\n");
1532     len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
1533             + sizeof(UINT16);
1534     if(rect)
1535         len += sizeof(RECT16);
1536     if (lpDx)
1537      len+=count*sizeof(INT16);
1538     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1539         return FALSE;
1540     mr = (METARECORD *)GlobalLock16(hmr);
1541     memset(mr, 0, len);
1542
1543     mr->rdSize = len / 2;
1544     mr->rdFunction = META_EXTTEXTOUT;
1545     *(mr->rdParm) = y;
1546     *(mr->rdParm + 1) = x;
1547     *(mr->rdParm + 2) = count;
1548     *(mr->rdParm + 3) = flags;
1549     if (rect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
1550     memcpy(mr->rdParm + (rect ? 8 : 4), str, count);
1551     if (lpDx)
1552      memcpy(mr->rdParm + (rect ? 8 : 4) + ((count + 1) >> 1),lpDx,
1553       count*sizeof(INT16));
1554     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1555     GlobalFree16(hmr);
1556     return ret;
1557 }
1558
1559 /******************************************************************
1560  *         MF_MetaPoly - implements Polygon and Polyline
1561  */
1562 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT16 pt, short count)
1563 {
1564     BOOL ret;
1565     DWORD len;
1566     HGLOBAL16 hmr;
1567     METARECORD *mr;
1568
1569     len = sizeof(METARECORD) + (count * 4); 
1570     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1571         return FALSE;
1572     mr = (METARECORD *)GlobalLock16(hmr);
1573     memset(mr, 0, len);
1574
1575     mr->rdSize = len / 2;
1576     mr->rdFunction = func;
1577     *(mr->rdParm) = count;
1578     memcpy(mr->rdParm + 1, pt, count * 4);
1579     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2);
1580     GlobalFree16(hmr);
1581     return ret;
1582 }
1583
1584
1585 /******************************************************************
1586  *         MF_BitBlt
1587  */
1588 BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
1589                  short height, DC *dcSrc, short xSrc, short ySrc, DWORD rop)
1590 {
1591     BOOL ret;
1592     DWORD len;
1593     HGLOBAL16 hmr;
1594     METARECORD *mr;
1595     BITMAP16  BM;
1596
1597     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1598     len = sizeof(METARECORD) + 12 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1599     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1600         return FALSE;
1601     mr = (METARECORD *)GlobalLock16(hmr);
1602     mr->rdFunction = META_BITBLT;
1603     *(mr->rdParm + 7) = BM.bmWidth;
1604     *(mr->rdParm + 8) = BM.bmHeight;
1605     *(mr->rdParm + 9) = BM.bmWidthBytes;
1606     *(mr->rdParm +10) = BM.bmPlanes;
1607     *(mr->rdParm +11) = BM.bmBitsPixel;
1608     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1609     if (GetBitmapBits(dcSrc->w.hBitmap,BM.bmWidthBytes * BM.bmHeight,
1610                         mr->rdParm +12))
1611     {
1612       mr->rdSize = len / sizeof(INT16);
1613       *(mr->rdParm) = HIWORD(rop);
1614       *(mr->rdParm + 1) = ySrc;
1615       *(mr->rdParm + 2) = xSrc;
1616       *(mr->rdParm + 3) = height;
1617       *(mr->rdParm + 4) = width;
1618       *(mr->rdParm + 5) = yDest;
1619       *(mr->rdParm + 6) = xDest;
1620       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1621     }  
1622     else
1623         ret = FALSE;
1624     GlobalFree16(hmr);
1625     return ret;
1626 }
1627
1628
1629 /**********************************************************************
1630  *         MF_StretchBlt         
1631  * this function contains TWO ways for procesing StretchBlt in metafiles,
1632  * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
1633  * via #define STRETCH_VIA_DIB
1634  */
1635 #define STRETCH_VIA_DIB
1636 #undef  STRETCH_VIA_DIB
1637 BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
1638                      short heightDest, DC *dcSrc, short xSrc, short ySrc, 
1639                      short widthSrc, short heightSrc, DWORD rop)
1640 {
1641     BOOL ret;
1642     DWORD len;
1643     HGLOBAL16 hmr;
1644     METARECORD *mr;
1645     BITMAP16  BM;
1646 #ifdef STRETCH_VIA_DIB    
1647     LPBITMAPINFOHEADER lpBMI;
1648     WORD nBPP;
1649 #endif  
1650     GetObject16(dcSrc->w.hBitmap, sizeof(BITMAP16), &BM);
1651 #ifdef STRETCH_VIA_DIB
1652     nBPP = BM.bmPlanes * BM.bmBitsPixel;
1653     len = sizeof(METARECORD) + 10 * sizeof(INT16) 
1654             + sizeof(BITMAPINFOHEADER) + (nBPP != 24 ? 1 << nBPP: 0) * sizeof(RGBQUAD) 
1655               + ((BM.bmWidth * nBPP + 31) / 32) * 4 * BM.bmHeight;
1656     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1657         return FALSE;
1658     mr = (METARECORD *)GlobalLock16(hmr);
1659     mr->rdFunction = META_DIBSTRETCHBLT;
1660     lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
1661     lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
1662     lpBMI->biWidth     = BM.bmWidth;
1663     lpBMI->biHeight    = BM.bmHeight;
1664     lpBMI->biPlanes    = 1;
1665     lpBMI->biBitCount  = nBPP;                              /* 1,4,8 or 24 */
1666     lpBMI->biClrUsed   = nBPP != 24 ? 1 << nBPP : 0;
1667     lpBMI->biSizeImage = ((lpBMI->biWidth * nBPP + 31) / 32) * 4 * lpBMI->biHeight;
1668     lpBMI->biCompression = BI_RGB;
1669     lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
1670     lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
1671     lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
1672
1673     TRACE(metafile,"MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
1674                len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(hdcSrc,LOGPIXELSY));
1675     if (GetDIBits(hdcSrc,dcSrc->w.hBitmap,0,(UINT)lpBMI->biHeight,
1676                   (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
1677                                                      DIB_RGB_COLORS ),
1678                   (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
1679 #else
1680     len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
1681     if (!(hmr = GlobalAlloc16(GMEM_MOVEABLE, len)))
1682         return FALSE;
1683     mr = (METARECORD *)GlobalLock16(hmr);
1684     mr->rdFunction = META_STRETCHBLT;
1685     *(mr->rdParm +10) = BM.bmWidth;
1686     *(mr->rdParm +11) = BM.bmHeight;
1687     *(mr->rdParm +12) = BM.bmWidthBytes;
1688     *(mr->rdParm +13) = BM.bmPlanes;
1689     *(mr->rdParm +14) = BM.bmBitsPixel;
1690     TRACE(metafile,"MF_StretchBlt->len = %ld  rop=%lx  \n",len,rop);
1691     if (GetBitmapBits( dcSrc->w.hBitmap, BM.bmWidthBytes * BM.bmHeight,
1692                          mr->rdParm +15))
1693 #endif    
1694     {
1695       mr->rdSize = len / sizeof(INT16);
1696       *(mr->rdParm) = LOWORD(rop);
1697       *(mr->rdParm + 1) = HIWORD(rop);
1698       *(mr->rdParm + 2) = heightSrc;
1699       *(mr->rdParm + 3) = widthSrc;
1700       *(mr->rdParm + 4) = ySrc;
1701       *(mr->rdParm + 5) = xSrc;
1702       *(mr->rdParm + 6) = heightDest;
1703       *(mr->rdParm + 7) = widthDest;
1704       *(mr->rdParm + 8) = yDest;
1705       *(mr->rdParm + 9) = xDest;
1706       ret = MF_WriteRecord( dcDest, mr, mr->rdSize * 2);
1707     }  
1708     else
1709         ret = FALSE;
1710     GlobalFree16(hmr);
1711     return ret;
1712 }
1713
1714
1715 /******************************************************************
1716  *         MF_CreateRegion
1717  */
1718 INT16 MF_CreateRegion(DC *dc, HRGN hrgn)
1719 {
1720     DWORD len;
1721     METARECORD *mr;
1722     RGNDATA *rgndata;
1723     RECT *pCurRect, *pEndRect;
1724     WORD Bands = 0, MaxBands = 0;
1725     WORD *Param, *StartBand;
1726     BOOL ret;
1727
1728     len = GetRegionData( hrgn, 0, NULL );
1729     if( !(rgndata = HeapAlloc( SystemHeap, 0, len )) ) {
1730         WARN(metafile, "MF_CreateRegion: can't alloc rgndata buffer\n");
1731         return -1;
1732     }
1733     GetRegionData( hrgn, len, rgndata );
1734
1735     /* Overestimate of length:
1736      * Assume every rect is a separate band -> 6 WORDs per rect
1737      */
1738     len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
1739     if( !(mr = HeapAlloc( SystemHeap, 0, len )) ) {
1740         WARN(metafile, "MF_CreateRegion: can't alloc METARECORD buffer\n");
1741         HeapFree( SystemHeap, 0, rgndata );
1742         return -1;
1743     }
1744
1745     memset(mr, 0, len);
1746         
1747     Param = mr->rdParm + 11;
1748     StartBand = NULL;
1749
1750     pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
1751     for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
1752     {
1753         if( StartBand && pCurRect->top == *(StartBand + 1) )
1754         {
1755             *Param++ = pCurRect->left;
1756             *Param++ = pCurRect->right;
1757         }
1758         else
1759         {
1760             if(StartBand)
1761             {
1762                 *StartBand = Param - StartBand - 3;
1763                 *Param++ = *StartBand;
1764                 if(*StartBand > MaxBands)
1765                     MaxBands = *StartBand;
1766                 Bands++;
1767             }
1768             StartBand = Param++;
1769             *Param++ = pCurRect->top;
1770             *Param++ = pCurRect->bottom;
1771             *Param++ = pCurRect->left;
1772             *Param++ = pCurRect->right;
1773         }
1774     }
1775     len = Param - (WORD *)mr;
1776     
1777     mr->rdParm[0] = 0;
1778     mr->rdParm[1] = 6;
1779     mr->rdParm[2] = 0x1234;
1780     mr->rdParm[3] = 0;
1781     mr->rdParm[4] = len * 2;
1782     mr->rdParm[5] = Bands;
1783     mr->rdParm[6] = MaxBands;
1784     mr->rdParm[7] = rgndata->rdh.rcBound.left;
1785     mr->rdParm[8] = rgndata->rdh.rcBound.top;
1786     mr->rdParm[9] = rgndata->rdh.rcBound.right;
1787     mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
1788     mr->rdFunction = META_CREATEREGION;
1789     mr->rdSize = len / 2;
1790     ret = MF_WriteRecord( dc, mr, mr->rdSize * 2 );     
1791     HeapFree( SystemHeap, 0, mr );
1792     HeapFree( SystemHeap, 0, rgndata );
1793     if(!ret) 
1794     {
1795         WARN(metafile, "MF_CreateRegion: MF_WriteRecord failed\n");
1796         return -1;
1797     }
1798     return MF_AddHandleDC( dc );
1799 }