GDI: Merge the mfdrv into one .c file.

Dimitrie O. Paun dpaun at rogers.com
Thu Apr 1 19:47:16 CST 2004


Identical rationale as for the enhmfdrv one.

Remove dlls/gdi/mfdrv/*:
    $ cvs rm -f dlls/gdi/mfdrv/*.[hc]

ChangeLog
    Merge the mfdrv into one .c file.

--- orig/dlls/gdi/Makefile.in
+++ mod/dlls/gdi/Makefile.in
@@ -38,13 +38,7 @@
 	gdi_main.c \
 	icm.c \
 	mapping.c \
-	mfdrv/bitblt.c \
-	mfdrv/dc.c \
-	mfdrv/graphics.c \
-	mfdrv/init.c \
-	mfdrv/mapping.c \
-	mfdrv/objects.c \
-	mfdrv/text.c \
+	mfdrv.c \
 	painting.c \
 	path.c \
 	printdrv.c
@@ -61,9 +55,7 @@
 
 SUBDIRS = tests
 
-EXTRASUBDIRS = \
-	$(TOPOBJDIR)/objects \
-	mfdrv
+EXTRASUBDIRS = $(TOPOBJDIR)/objects
 
 @MAKE_DLL_RULES@
 
--- /dev/null	2003-01-30 05:24:37.000000000 -0500
+++ dlls/gdi/mfdrv.c	2004-04-01 17:15:39.000000000 -0500
@@ -0,0 +1,2004 @@
+/*
+ * Metafile driver
+ *
+ * Copyright 1996 Alexandre Julliard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "gdi.h"
+#include "wownt32.h"
+#include "gdi_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(metafile);
+
+/* Metafile driver physical DC */
+
+typedef struct
+{
+    HDC         hdc;
+    DC         *dc;
+    METAHEADER *mh;           /* Pointer to metafile header */
+    UINT        handles_size, cur_handles;
+    HGDIOBJ    *handles;
+    HANDLE      hFile;          /* Handle for disk based MetaFile */
+} METAFILEDRV_PDEVICE;
+
+#define HANDLE_LIST_INC 20
+
+
+extern BOOL MFDRV_MetaParam0(PHYSDEV dev, short func);
+extern BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1);
+extern BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2);
+extern BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2,
+                             short param3, short param4);
+extern BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2,
+                             short param3, short param4, short param5,
+                             short param6);
+extern BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2,
+                             short param3, short param4, short param5,
+                             short param6, short param7, short param8);
+extern BOOL MFDRV_WriteRecord(PHYSDEV dev, METARECORD *mr, DWORD rlen);
+extern UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj );
+extern INT16 MFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush );
+
+extern INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data,
+                            INT cbOutput, LPVOID out_data );
+extern INT MFDRV_GetDeviceCaps( PHYSDEV dev , INT cap );
+extern BOOL MFDRV_StretchBlt( PHYSDEV devDst, INT xDst, INT yDst, INT widthDst,
+                              INT heightDst, PHYSDEV devSrc, INT xSrc, INT ySrc,
+                              INT widthSrc, INT heightSrc, DWORD rop );
+/*********************/
+/* Bitblt operations */
+/*********************/
+
+/***********************************************************************
+ *           MFDRV_PatBlt
+ */
+BOOL MFDRV_PatBlt( PHYSDEV dev, INT left, INT top, INT width, INT height, DWORD rop )
+{
+    MFDRV_MetaParam6( dev, META_PATBLT, left, top, width, height, HIWORD(rop), LOWORD(rop) );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           MFDRV_BitBlt
+ */
+BOOL MFDRV_BitBlt( PHYSDEV devDst, INT xDst, INT yDst, INT width, INT height,
+		   PHYSDEV devSrc, INT xSrc, INT ySrc, DWORD rop )
+{
+    return MFDRV_StretchBlt(devDst, xDst, yDst, width, height, devSrc,
+                            xSrc, ySrc, width, height, rop);
+}
+
+
+
+/***********************************************************************
+ *           MFDRV_StretchBlt
+ * this function contains TWO ways for procesing StretchBlt in metafiles,
+ * decide between rdFunction values  META_STRETCHBLT or META_DIBSTRETCHBLT
+ * via #define STRETCH_VIA_DIB
+ */
+#define STRETCH_VIA_DIB
+
+BOOL MFDRV_StretchBlt( PHYSDEV devDst, INT xDst, INT yDst, INT widthDst,
+		       INT heightDst, PHYSDEV devSrc, INT xSrc, INT ySrc,
+		       INT widthSrc, INT heightSrc, DWORD rop )
+{
+    BOOL ret;
+    DWORD len;
+    METARECORD *mr;
+    BITMAP BM;
+    METAFILEDRV_PDEVICE *physDevSrc = (METAFILEDRV_PDEVICE *)devSrc;
+    DC *dcSrc = physDevSrc->dc;
+#ifdef STRETCH_VIA_DIB
+    LPBITMAPINFOHEADER lpBMI;
+    WORD nBPP;
+#endif
+    GetObjectA(dcSrc->hBitmap, sizeof(BITMAP), &BM);
+#ifdef STRETCH_VIA_DIB
+    nBPP = BM.bmPlanes * BM.bmBitsPixel;
+    if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */
+    len = sizeof(METARECORD) + 10 * sizeof(INT16)
+            + sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP: 0) * sizeof(RGBQUAD)
+              + DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * BM.bmHeight;
+    if (!(mr = HeapAlloc( GetProcessHeap(), 0, len)))
+	return FALSE;
+    mr->rdFunction = META_DIBSTRETCHBLT;
+    lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10);
+    lpBMI->biSize      = sizeof(BITMAPINFOHEADER);
+    lpBMI->biWidth     = BM.bmWidth;
+    lpBMI->biHeight    = BM.bmHeight;
+    lpBMI->biPlanes    = 1;
+    lpBMI->biBitCount  = nBPP;
+    lpBMI->biSizeImage = DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * lpBMI->biHeight;
+    lpBMI->biClrUsed   = nBPP <= 8 ? 1 << nBPP : 0;
+    lpBMI->biCompression = BI_RGB;
+    lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSX),3937,100);
+    lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(dcSrc->hSelf,LOGPIXELSY),3937,100);
+    lpBMI->biClrImportant  = 0;                          /* 1 meter  = 39.37 inch */
+
+    TRACE("MF_StretchBltViaDIB->len = %ld  rop=%lx  PixYPM=%ld Caps=%d\n",
+	  len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(dcSrc->hSelf,
+						       LOGPIXELSY));
+    if (GetDIBits(dcSrc->hSelf,dcSrc->hBitmap,0,(UINT)lpBMI->biHeight,
+                  (LPSTR)lpBMI + DIB_BitmapInfoSize( (BITMAPINFO *)lpBMI,
+                                                     DIB_RGB_COLORS ),
+                  (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS))
+#else
+    len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight;
+    if (!(mr = HeapAlloc( GetProcessHeap(), 0, len )))
+	return FALSE;
+    mr->rdFunction = META_STRETCHBLT;
+    *(mr->rdParm +10) = BM.bmWidth;
+    *(mr->rdParm +11) = BM.bmHeight;
+    *(mr->rdParm +12) = BM.bmWidthBytes;
+    *(mr->rdParm +13) = BM.bmPlanes;
+    *(mr->rdParm +14) = BM.bmBitsPixel;
+    TRACE("len = %ld  rop=%lx  \n",len,rop);
+    if (GetBitmapBits( dcSrc->hBitmap, BM.bmWidthBytes * BM.bmHeight,
+                         mr->rdParm +15))
+#endif
+    {
+      mr->rdSize = len / sizeof(INT16);
+      *(mr->rdParm) = LOWORD(rop);
+      *(mr->rdParm + 1) = HIWORD(rop);
+      *(mr->rdParm + 2) = heightSrc;
+      *(mr->rdParm + 3) = widthSrc;
+      *(mr->rdParm + 4) = ySrc;
+      *(mr->rdParm + 5) = xSrc;
+      *(mr->rdParm + 6) = heightDst;
+      *(mr->rdParm + 7) = widthDst;
+      *(mr->rdParm + 8) = yDst;
+      *(mr->rdParm + 9) = xDst;
+      ret = MFDRV_WriteRecord( devDst, mr, mr->rdSize * 2);
+    }
+    else
+        ret = FALSE;
+    HeapFree( GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+/***********************************************************************
+ *           MFDRV_StretchDIBits
+ */
+INT MFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst,
+			 INT heightDst, INT xSrc, INT ySrc, INT widthSrc,
+			 INT heightSrc, const void *bits,
+			 const BITMAPINFO *info, UINT wUsage, DWORD dwRop )
+{
+    DWORD len, infosize, imagesize;
+    METARECORD *mr;
+
+    infosize = DIB_BitmapInfoSize(info, wUsage);
+    imagesize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth,
+				      info->bmiHeader.biHeight,
+				      info->bmiHeader.biBitCount );
+
+    len = sizeof(METARECORD) + 10 * sizeof(WORD) + infosize + imagesize;
+    mr = (METARECORD *)HeapAlloc( GetProcessHeap(), 0, len );
+    if(!mr) return 0;
+
+    mr->rdSize = len / 2;
+    mr->rdFunction = META_STRETCHDIB;
+    mr->rdParm[0] = LOWORD(dwRop);
+    mr->rdParm[1] = HIWORD(dwRop);
+    mr->rdParm[2] = wUsage;
+    mr->rdParm[3] = (INT16)heightSrc;
+    mr->rdParm[4] = (INT16)widthSrc;
+    mr->rdParm[5] = (INT16)ySrc;
+    mr->rdParm[6] = (INT16)xSrc;
+    mr->rdParm[7] = (INT16)heightDst;
+    mr->rdParm[8] = (INT16)widthDst;
+    mr->rdParm[9] = (INT16)yDst;
+    mr->rdParm[10] = (INT16)xDst;
+    memcpy(mr->rdParm + 11, info, infosize);
+    memcpy(mr->rdParm + 11 + infosize / 2, bits, imagesize);
+    MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
+    HeapFree( GetProcessHeap(), 0, mr );
+    return heightSrc;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SetDIBitsToDeivce
+ */
+INT MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD cx,
+			     DWORD cy, INT xSrc, INT ySrc, UINT startscan,
+			     UINT lines, LPCVOID bits, const BITMAPINFO *info,
+			     UINT coloruse )
+
+{
+    DWORD len, infosize, imagesize;
+    METARECORD *mr;
+
+    infosize = DIB_BitmapInfoSize(info, coloruse);
+    imagesize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth,
+				      info->bmiHeader.biHeight,
+				      info->bmiHeader.biBitCount );
+
+    len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + imagesize;
+    mr = (METARECORD *)HeapAlloc( GetProcessHeap(), 0, len );
+    if(!mr) return 0;
+
+    mr->rdSize = len / 2;
+    mr->rdFunction = META_SETDIBTODEV;
+    mr->rdParm[0] = coloruse;
+    mr->rdParm[1] = lines;
+    mr->rdParm[2] = startscan;
+    mr->rdParm[3] = (INT16)ySrc;
+    mr->rdParm[4] = (INT16)xSrc;
+    mr->rdParm[5] = (INT16)cy;
+    mr->rdParm[6] = (INT16)cx;
+    mr->rdParm[7] = (INT16)yDst;
+    mr->rdParm[8] = (INT16)xDst;
+    memcpy(mr->rdParm + 9, info, infosize);
+    memcpy(mr->rdParm + 9 + infosize / 2, bits, imagesize);
+    MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
+    HeapFree( GetProcessHeap(), 0, mr );
+    return lines;
+}
+
+/**********************/
+/* DC value functions */
+/**********************/
+
+INT MFDRV_SaveDC( PHYSDEV dev )
+{
+    return MFDRV_MetaParam0( dev, META_SAVEDC );
+}
+
+BOOL MFDRV_RestoreDC( PHYSDEV dev, INT level )
+{
+    if(level != -1) return FALSE;
+    return MFDRV_MetaParam1( dev, META_RESTOREDC, level );
+}
+
+UINT MFDRV_SetTextAlign( PHYSDEV dev, UINT align )
+{
+    return MFDRV_MetaParam2( dev, META_SETTEXTALIGN, HIWORD(align), LOWORD(align));
+}
+
+INT MFDRV_SetBkMode( PHYSDEV dev, INT mode )
+{
+    return MFDRV_MetaParam1( dev, META_SETBKMODE, (WORD)mode);
+}
+
+INT MFDRV_SetROP2( PHYSDEV dev, INT rop )
+{
+    return MFDRV_MetaParam1( dev, META_SETROP2, (WORD)rop);
+}
+
+INT MFDRV_SetRelAbs( PHYSDEV dev, INT mode )
+{
+    return MFDRV_MetaParam1( dev, META_SETRELABS, (WORD)mode);
+}
+
+INT MFDRV_SetPolyFillMode( PHYSDEV dev, INT mode )
+{
+    return MFDRV_MetaParam1( dev, META_SETPOLYFILLMODE, (WORD)mode);
+}
+
+INT MFDRV_SetStretchBltMode( PHYSDEV dev, INT mode )
+{
+    return MFDRV_MetaParam1( dev, META_SETSTRETCHBLTMODE, (WORD)mode);
+}
+
+INT MFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
+{
+    return MFDRV_MetaParam4( dev, META_INTERSECTCLIPRECT, left, top, right,
+			     bottom );
+}
+
+INT MFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
+{
+    return MFDRV_MetaParam4( dev, META_EXCLUDECLIPRECT, left, top, right,
+			     bottom );
+}
+
+INT MFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y )
+{
+    return MFDRV_MetaParam2( dev, META_OFFSETCLIPRGN, x, y );
+}
+
+INT MFDRV_SetTextJustification( PHYSDEV dev, INT extra, INT breaks )
+{
+    return MFDRV_MetaParam2( dev, META_SETTEXTJUSTIFICATION, extra, breaks );
+}
+
+INT MFDRV_SetTextCharacterExtra( PHYSDEV dev, INT extra )
+{
+    if(!MFDRV_MetaParam1( dev, META_SETTEXTCHAREXTRA, extra ))
+        return 0x80000000;
+    return TRUE;
+}
+
+DWORD MFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags )
+{
+    return MFDRV_MetaParam2( dev, META_SETMAPPERFLAGS, HIWORD(flags),
+			     LOWORD(flags) );
+}
+
+BOOL MFDRV_AbortPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_BeginPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_CloseFigure( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_EndPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_FillPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_FlattenPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_SelectClipPath( PHYSDEV dev, INT iMode )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_StrokeAndFillPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_StrokePath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+BOOL MFDRV_WidenPath( PHYSDEV dev )
+{
+    return FALSE;
+}
+
+/**********************/
+/* Graphics functions */
+/**********************/
+
+/**********************************************************************
+ *	     MFDRV_MoveTo
+ */
+BOOL
+MFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
+{
+    return MFDRV_MetaParam2(dev,META_MOVETO,x,y);
+}
+
+/***********************************************************************
+ *           MFDRV_LineTo
+ */
+BOOL
+MFDRV_LineTo( PHYSDEV dev, INT x, INT y )
+{
+     return MFDRV_MetaParam2(dev, META_LINETO, x, y);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Arc
+ */
+BOOL
+MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+           INT xstart, INT ystart, INT xend, INT yend )
+{
+     return MFDRV_MetaParam8(dev, META_ARC, left, top, right, bottom,
+			     xstart, ystart, xend, yend);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Pie
+ */
+BOOL
+MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+           INT xstart, INT ystart, INT xend, INT yend )
+{
+    return MFDRV_MetaParam8(dev, META_PIE, left, top, right, bottom,
+			    xstart, ystart, xend, yend);
+}
+
+
+/***********************************************************************
+ *           MFDRV_Chord
+ */
+BOOL
+MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+             INT xstart, INT ystart, INT xend, INT yend )
+{
+    return MFDRV_MetaParam8(dev, META_CHORD, left, top, right, bottom,
+			    xstart, ystart, xend, yend);
+}
+
+/***********************************************************************
+ *           MFDRV_Ellipse
+ */
+BOOL
+MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
+{
+    return MFDRV_MetaParam4(dev, META_ELLIPSE, left, top, right, bottom);
+}
+
+/***********************************************************************
+ *           MFDRV_Rectangle
+ */
+BOOL
+MFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
+{
+    return MFDRV_MetaParam4(dev, META_RECTANGLE, left, top, right, bottom);
+}
+
+/***********************************************************************
+ *           MFDRV_RoundRect
+ */
+BOOL
+MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
+                 INT bottom, INT ell_width, INT ell_height )
+{
+    return MFDRV_MetaParam6(dev, META_ROUNDRECT, left, top, right, bottom,
+			    ell_width, ell_height);
+}
+
+/***********************************************************************
+ *           MFDRV_SetPixel
+ */
+COLORREF
+MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
+{
+    return MFDRV_MetaParam4(dev, META_SETPIXEL, x, y,HIWORD(color),
+			    LOWORD(color));
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaPoly - implements Polygon and Polyline
+ */
+static BOOL MFDRV_MetaPoly(PHYSDEV dev, short func, LPPOINT16 pt, short count)
+{
+    BOOL ret;
+    DWORD len;
+    METARECORD *mr;
+
+    len = sizeof(METARECORD) + (count * 4);
+    if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )))
+	return FALSE;
+
+    mr->rdSize = len / 2;
+    mr->rdFunction = func;
+    *(mr->rdParm) = count;
+    memcpy(mr->rdParm + 1, pt, count * 4);
+    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+    HeapFree( GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_Polyline
+ */
+BOOL
+MFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
+{
+    register int i;
+    LPPOINT16	pt16;
+    BOOL16	ret;
+
+    pt16 = (LPPOINT16)HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
+    if(!pt16) return FALSE;
+    for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
+    ret = MFDRV_MetaPoly(dev, META_POLYLINE, pt16, count);
+
+    HeapFree( GetProcessHeap(), 0, pt16 );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_Polygon
+ */
+BOOL
+MFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
+{
+    register int i;
+    LPPOINT16	pt16;
+    BOOL16	ret;
+
+    pt16 = (LPPOINT16) HeapAlloc( GetProcessHeap(), 0, sizeof(POINT16)*count );
+    if(!pt16) return FALSE;
+    for (i=count;i--;) CONV_POINT32TO16(&(pt[i]),&(pt16[i]));
+    ret = MFDRV_MetaPoly(dev, META_POLYGON, pt16, count);
+
+    HeapFree( GetProcessHeap(), 0, pt16 );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_PolyPolygon
+ */
+BOOL
+MFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons)
+{
+    BOOL ret;
+    DWORD len;
+    METARECORD *mr;
+    int       i,j;
+    LPPOINT16 pt16;
+    INT16 totalpoint16 = 0;
+    INT16 * pointcounts;
+
+    for (i=0;i<polygons;i++) {
+         totalpoint16 += counts[i];
+    }
+
+    /* allocate space for all points */
+    pt16=(LPPOINT16)HeapAlloc( GetProcessHeap(), 0,
+                                     sizeof(POINT16) * totalpoint16 );
+    pointcounts = (INT16*)HeapAlloc( GetProcessHeap(), 0,
+                                     sizeof(INT16) * totalpoint16 );
+
+    /* copy point counts */
+    for (i=0;i<polygons;i++) {
+          pointcounts[i] = counts[i];
+    }
+
+    /* convert all points */
+    for (j = totalpoint16; j--;){
+         CONV_POINT32TO16(&(pt[j]),&(pt16[j]));
+    }
+
+    len = sizeof(METARECORD) + sizeof(WORD) + polygons*sizeof(INT16) + totalpoint16*sizeof(POINT16);
+
+    if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) {
+         HeapFree( GetProcessHeap(), 0, pt16 );
+         HeapFree( GetProcessHeap(), 0, pointcounts );
+         return FALSE;
+    }
+
+    mr->rdSize = len /2;
+    mr->rdFunction = META_POLYPOLYGON;
+    *(mr->rdParm) = polygons;
+    memcpy(mr->rdParm + 1, pointcounts, polygons*sizeof(INT16));
+    memcpy(mr->rdParm + 1+polygons, pt16 , totalpoint16*sizeof(POINT16));
+    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+
+    HeapFree( GetProcessHeap(), 0, pt16 );
+    HeapFree( GetProcessHeap(), 0, pointcounts );
+    HeapFree( GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_ExtFloodFill
+ */
+BOOL
+MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
+{
+    return MFDRV_MetaParam4(dev,META_FLOODFILL,x,y,HIWORD(color),
+			    LOWORD(color));
+}
+
+
+/******************************************************************
+ *         MFDRV_CreateRegion
+ *
+ * For explanation of the format of the record see MF_Play_MetaCreateRegion in
+ * objects/metafile.c
+ */
+static INT16 MFDRV_CreateRegion(PHYSDEV dev, HRGN hrgn)
+{
+    DWORD len;
+    METARECORD *mr;
+    RGNDATA *rgndata;
+    RECT *pCurRect, *pEndRect;
+    WORD Bands = 0, MaxBands = 0;
+    WORD *Param, *StartBand;
+    BOOL ret;
+
+    if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1;
+    if( !(rgndata = HeapAlloc( GetProcessHeap(), 0, len )) ) {
+        WARN("Can't alloc rgndata buffer\n");
+	return -1;
+    }
+    GetRegionData( hrgn, len, rgndata );
+
+    /* Overestimate of length:
+     * Assume every rect is a separate band -> 6 WORDs per rect
+     */
+    len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12);
+    if( !(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )) ) {
+        WARN("Can't alloc METARECORD buffer\n");
+	HeapFree( GetProcessHeap(), 0, rgndata );
+	return -1;
+    }
+
+    Param = mr->rdParm + 11;
+    StartBand = NULL;
+
+    pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount;
+    for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++)
+    {
+        if( StartBand && pCurRect->top == *(StartBand + 1) )
+        {
+	    *Param++ = pCurRect->left;
+	    *Param++ = pCurRect->right;
+	}
+	else
+	{
+	    if(StartBand)
+	    {
+	        *StartBand = Param - StartBand - 3;
+		*Param++ = *StartBand;
+		if(*StartBand > MaxBands)
+		    MaxBands = *StartBand;
+		Bands++;
+	    }
+	    StartBand = Param++;
+	    *Param++ = pCurRect->top;
+	    *Param++ = pCurRect->bottom;
+	    *Param++ = pCurRect->left;
+	    *Param++ = pCurRect->right;
+	}
+    }
+    len = Param - (WORD *)mr;
+
+    mr->rdParm[0] = 0;
+    mr->rdParm[1] = 6;
+    mr->rdParm[2] = 0x1234;
+    mr->rdParm[3] = 0;
+    mr->rdParm[4] = len * 2;
+    mr->rdParm[5] = Bands;
+    mr->rdParm[6] = MaxBands;
+    mr->rdParm[7] = rgndata->rdh.rcBound.left;
+    mr->rdParm[8] = rgndata->rdh.rcBound.top;
+    mr->rdParm[9] = rgndata->rdh.rcBound.right;
+    mr->rdParm[10] = rgndata->rdh.rcBound.bottom;
+    mr->rdFunction = META_CREATEREGION;
+    mr->rdSize = len / 2;
+    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 );
+    HeapFree( GetProcessHeap(), 0, mr );
+    HeapFree( GetProcessHeap(), 0, rgndata );
+    if(!ret)
+    {
+        WARN("MFDRV_WriteRecord failed\n");
+	return -1;
+    }
+    return MFDRV_AddHandle( dev, hrgn );
+}
+
+
+/**********************************************************************
+ *          MFDRV_PaintRgn
+ */
+BOOL
+MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
+{
+    INT16 index;
+    index = MFDRV_CreateRegion( dev, hrgn );
+    if(index == -1)
+        return FALSE;
+    return MFDRV_MetaParam1( dev, META_PAINTREGION, index );
+}
+
+
+/**********************************************************************
+ *          MFDRV_InvertRgn
+ */
+BOOL
+MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
+{
+    INT16 index;
+    index = MFDRV_CreateRegion( dev, hrgn );
+    if(index == -1)
+        return FALSE;
+    return MFDRV_MetaParam1( dev, META_INVERTREGION, index );
+}
+
+
+/**********************************************************************
+ *          MFDRV_FillRgn
+ */
+BOOL
+MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
+{
+    INT16 iRgn, iBrush;
+    iRgn = MFDRV_CreateRegion( dev, hrgn );
+    if(iRgn == -1)
+        return FALSE;
+    iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
+    if(!iBrush)
+        return FALSE;
+    return MFDRV_MetaParam2( dev, META_FILLREGION, iRgn, iBrush );
+}
+
+/**********************************************************************
+ *          MFDRV_FrameRgn
+ */
+BOOL
+MFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT x, INT y )
+{
+    INT16 iRgn, iBrush;
+    iRgn = MFDRV_CreateRegion( dev, hrgn );
+    if(iRgn == -1)
+        return FALSE;
+    iBrush = MFDRV_CreateBrushIndirect( dev, hbrush );
+    if(!iBrush)
+        return FALSE;
+    return MFDRV_MetaParam4( dev, META_FRAMEREGION, iRgn, iBrush, x, y );
+}
+
+
+/**********************************************************************
+ *          MFDRV_ExtSelectClipRgn
+ */
+INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode )
+{
+    INT16 iRgn;
+    INT ret;
+
+    if (mode != RGN_COPY) return ERROR;
+    if (!hrgn) return NULLREGION;
+    iRgn = MFDRV_CreateRegion( dev, hrgn );
+    if(iRgn == -1) return ERROR;
+    ret = MFDRV_MetaParam1( dev, META_SELECTCLIPREGION, iRgn ) ? NULLREGION : ERROR;
+    MFDRV_MetaParam1( dev, META_DELETEOBJECT, iRgn );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          MFDRV_SetBkColor
+ */
+COLORREF
+MFDRV_SetBkColor( PHYSDEV dev, COLORREF color )
+{
+    return MFDRV_MetaParam2(dev, META_SETBKCOLOR, HIWORD(color),
+                            LOWORD(color)) ? color : CLR_INVALID;
+}
+
+
+/**********************************************************************
+ *          MFDRV_SetTextColor
+ */
+COLORREF
+MFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
+{
+    return MFDRV_MetaParam2(dev, META_SETTEXTCOLOR, HIWORD(color),
+                            LOWORD(color)) ? color : CLR_INVALID;
+}
+
+
+/**********************************************************************
+ *          MFDRV_PolyBezier
+ * Since MetaFiles don't record Beziers and they don't even record
+ * approximations to them using lines, we need this stub function.
+ */
+BOOL
+MFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count )
+{
+    return FALSE;
+}
+
+/**********************************************************************
+ *          MFDRV_PolyBezierTo
+ * Since MetaFiles don't record Beziers and they don't even record
+ * approximations to them using lines, we need this stub function.
+ */
+BOOL
+MFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count )
+{
+    return FALSE;
+}
+
+/**************************/
+/* Mapping mode functions */
+/**************************/
+
+/***********************************************************************
+ *           MFDRV_SetMapMode
+ */
+INT MFDRV_SetMapMode( PHYSDEV dev, INT mode )
+{
+    if(!MFDRV_MetaParam1( dev, META_SETMAPMODE, mode ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SetViewportExt
+ */
+INT MFDRV_SetViewportExt( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_SETVIEWPORTEXT, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SetViewportOrg
+ */
+INT MFDRV_SetViewportOrg( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_SETVIEWPORTORG, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SetWindowExt
+ */
+INT MFDRV_SetWindowExt( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_SETWINDOWEXT, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SetWindowOrg
+ */
+INT MFDRV_SetWindowOrg( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_SETWINDOWORG, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_OffsetViewportOrg
+ */
+INT MFDRV_OffsetViewportOrg( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_OFFSETVIEWPORTORG, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_OffsetWindowOrg
+ */
+INT MFDRV_OffsetWindowOrg( PHYSDEV dev, INT x, INT y )
+{
+    if(!MFDRV_MetaParam2( dev, META_OFFSETWINDOWORG, x, y ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_ScaleViewportExt
+ */
+INT MFDRV_ScaleViewportExt( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom )
+{
+    if(!MFDRV_MetaParam4( dev, META_SCALEVIEWPORTEXT, xNum, xDenom, yNum, yDenom ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+
+/***********************************************************************
+ *           MFDRV_ScaleWindowExt
+ */
+INT MFDRV_ScaleWindowExt( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom )
+{
+    if(!MFDRV_MetaParam4( dev, META_SCALEWINDOWEXT, xNum, xDenom, yNum, yDenom ))
+        return FALSE;
+    return GDI_NO_MORE_WORK;
+}
+
+/***************/
+/* GDI objects */
+/***************/
+
+/******************************************************************
+ *         MFDRV_AddHandle
+ */
+UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    INT16 index;
+
+    for(index = 0; index < physDev->handles_size; index++)
+        if(physDev->handles[index] == 0) break; 
+    if(index == physDev->handles_size) {
+        physDev->handles_size += HANDLE_LIST_INC;
+        physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                                       physDev->handles,
+                                       physDev->handles_size * sizeof(physDev->handles[0]));
+    }
+    physDev->handles[index] = obj;
+
+    physDev->cur_handles++; 
+    if(physDev->cur_handles > physDev->mh->mtNoObjects)
+        physDev->mh->mtNoObjects++;
+
+    return index ; /* index 0 is not reserved for metafiles */
+}
+
+/******************************************************************
+ *         MFDRV_FindObject
+ */
+static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    INT16 index;
+
+    for(index = 0; index < physDev->handles_size; index++)
+        if(physDev->handles[index] == obj) break;
+
+    if(index == physDev->handles_size) return -1;
+
+    return index ;
+}
+
+
+/******************************************************************
+ *         MFDRV_DeleteObject
+ */
+BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
+{   
+    METARECORD mr;
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    INT16 index;
+    BOOL ret = TRUE;
+
+    index = MFDRV_FindObject(dev, obj);
+    if( index < 0 )
+        return 0;
+
+    mr.rdSize = sizeof mr / 2;
+    mr.rdFunction = META_DELETEOBJECT;
+    mr.rdParm[0] = index;
+
+    if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ))
+        ret = FALSE;
+
+    physDev->handles[index] = 0;
+    physDev->cur_handles--;
+    return ret;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectObject
+ */
+static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index)
+{
+    METARECORD mr;
+
+    mr.rdSize = sizeof mr / 2;
+    mr.rdFunction = META_SELECTOBJECT;
+    mr.rdParm[0] = index;
+
+    return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 );
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectBitmap
+ */
+HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
+{
+    return 0;
+}
+
+
+/******************************************************************
+ *         MFDRV_CreateBrushIndirect
+ */
+
+INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush )
+{
+    DWORD size;
+    METARECORD *mr;
+    LOGBRUSH logbrush;
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    BOOL r;
+
+    if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1;
+
+    switch(logbrush.lbStyle)
+    {
+    case BS_SOLID:
+    case BS_NULL:
+    case BS_HATCHED:
+        {
+	    LOGBRUSH16 lb16;
+
+	    lb16.lbStyle = logbrush.lbStyle;
+	    lb16.lbColor = logbrush.lbColor;
+	    lb16.lbHatch = logbrush.lbHatch;
+	    size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2;
+	    mr = HeapAlloc( GetProcessHeap(), 0, size );
+	    mr->rdSize = size / 2;
+	    mr->rdFunction = META_CREATEBRUSHINDIRECT;
+	    memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16));
+	    break;
+	}
+    case BS_PATTERN:
+        {
+	    BITMAP bm;
+	    BYTE *bits;
+	    BITMAPINFO *info;
+	    DWORD bmSize;
+
+	    GetObjectA((HANDLE)logbrush.lbHatch, sizeof(bm), &bm);
+	    if(bm.bmBitsPixel != 1 || bm.bmPlanes != 1) {
+	        FIXME("Trying to store a colour pattern brush\n");
+		goto done;
+	    }
+
+	    bmSize = DIB_GetDIBImageBytes(bm.bmWidth, bm.bmHeight, 1);
+
+	    size = sizeof(METARECORD) + sizeof(WORD) + sizeof(BITMAPINFO) +
+	      sizeof(RGBQUAD) + bmSize;
+
+	    mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+	    if(!mr) goto done;
+	    mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
+	    mr->rdSize = size / 2;
+	    mr->rdParm[0] = BS_PATTERN;
+	    mr->rdParm[1] = DIB_RGB_COLORS;
+	    info = (BITMAPINFO *)(mr->rdParm + 2);
+
+	    info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+	    info->bmiHeader.biWidth = bm.bmWidth;
+	    info->bmiHeader.biHeight = bm.bmHeight;
+	    info->bmiHeader.biPlanes = 1;
+	    info->bmiHeader.biBitCount = 1;
+	    bits = ((BYTE *)info) + sizeof(BITMAPINFO) + sizeof(RGBQUAD);
+
+	    GetDIBits(physDev->hdc, (HANDLE)logbrush.lbHatch, 0, bm.bmHeight,
+		      bits, info, DIB_RGB_COLORS);
+	    *(DWORD *)info->bmiColors = 0;
+	    *(DWORD *)(info->bmiColors + 1) = 0xffffff;
+	    break;
+	}
+
+    case BS_DIBPATTERN:
+        {
+	      BITMAPINFO *info;
+	      DWORD bmSize, biSize;
+
+	      info = GlobalLock16((HGLOBAL16)logbrush.lbHatch);
+	      if (info->bmiHeader.biCompression)
+		  bmSize = info->bmiHeader.biSizeImage;
+	      else
+		  bmSize = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
+						info->bmiHeader.biHeight,
+						info->bmiHeader.biBitCount);
+	      biSize = DIB_BitmapInfoSize(info, LOWORD(logbrush.lbColor));
+	      size = sizeof(METARECORD) + biSize + bmSize + 2;
+	      mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
+	      if(!mr) goto done;
+	      mr->rdFunction = META_DIBCREATEPATTERNBRUSH;
+	      mr->rdSize = size / 2;
+	      *(mr->rdParm) = logbrush.lbStyle;
+	      *(mr->rdParm + 1) = LOWORD(logbrush.lbColor);
+	      memcpy(mr->rdParm + 2, info, biSize + bmSize);
+	      break;
+	}
+	default:
+	    FIXME("Unkonwn brush style %x\n", logbrush.lbStyle);
+	    return 0;
+    }
+    r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+    HeapFree(GetProcessHeap(), 0, mr);
+    if( !r )
+        return -1;
+done:
+    return MFDRV_AddHandle( dev, hBrush );
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectBrush
+ */
+HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    INT16 index;
+
+    index = MFDRV_FindObject(dev, hbrush);
+    if( index < 0 )
+    {
+        index = MFDRV_CreateBrushIndirect( dev, hbrush );
+        if( index < 0 )
+            return 0;
+        GDI_hdc_using_object(hbrush, physDev->hdc);
+    }
+    return MFDRV_SelectObject( dev, index ) ? hbrush : HGDI_ERROR;
+}
+
+/******************************************************************
+ *         MFDRV_CreateFontIndirect
+ */
+
+static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, LOGFONT16 *logfont)
+{
+    char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2;
+    mr->rdFunction = META_CREATEFONTINDIRECT;
+    memcpy(&(mr->rdParm), logfont, sizeof(LOGFONT16));
+    if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
+        return 0;
+    return MFDRV_AddHandle( dev, hFont );
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectFont
+ */
+HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, HANDLE gdiFont )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    LOGFONT16 lf16;
+    INT16 index;
+
+    index = MFDRV_FindObject(dev, hfont);
+    if( index < 0 )
+    {
+        if (!GetObject16( HFONT_16(hfont), sizeof(lf16), &lf16 ))
+            return HGDI_ERROR;
+        index = MFDRV_CreateFontIndirect(dev, hfont, &lf16);
+        if( index < 0 )
+            return HGDI_ERROR;
+        GDI_hdc_using_object(hfont, physDev->hdc);
+    }
+    return MFDRV_SelectObject( dev, index ) ? hfont : HGDI_ERROR;
+}
+
+/******************************************************************
+ *         MFDRV_CreatePenIndirect
+ */
+static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen)
+{
+    char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2;
+    mr->rdFunction = META_CREATEPENINDIRECT;
+    memcpy(&(mr->rdParm), logpen, sizeof(*logpen));
+    if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2)))
+        return 0;
+    return MFDRV_AddHandle( dev, hPen );
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectPen
+ */
+HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    LOGPEN16 logpen;
+    INT16 index;
+
+    index = MFDRV_FindObject(dev, hpen);
+    if( index < 0 )
+    {
+        if (!GetObject16( HPEN_16(hpen), sizeof(logpen), &logpen ))
+            return 0;
+        index = MFDRV_CreatePenIndirect( dev, hpen, &logpen );
+        if( index < 0 )
+            return 0;
+        GDI_hdc_using_object(hpen, physDev->hdc);
+    }
+    return MFDRV_SelectObject( dev, index ) ? hpen : HGDI_ERROR;
+}
+
+
+/******************************************************************
+ *         MFDRV_CreatePalette
+ */
+static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette)
+{
+    int index;
+    BOOL ret;
+    METARECORD *mr;
+
+    mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) );
+    mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD);
+    mr->rdFunction = META_CREATEPALETTE;
+    memcpy(&(mr->rdParm), logPalette, sizeofPalette);
+    if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD))))
+    {
+        HeapFree(GetProcessHeap(), 0, mr);
+        return FALSE;
+    }
+
+    mr->rdSize = sizeof(METARECORD) / sizeof(WORD);
+    mr->rdFunction = META_SELECTPALETTE;
+
+    if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE;
+    else
+    {
+        *(mr->rdParm) = index;
+        ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD));
+    }
+    HeapFree(GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+/***********************************************************************
+ *           MFDRV_SelectPalette
+ */
+HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground )
+{
+#define PALVERSION 0x0300
+
+    PLOGPALETTE logPalette;
+    WORD        wNumEntries = 0;
+    BOOL        creationSucceed;
+    int         sizeofPalette;
+
+    GetObjectA(hPalette, sizeof(WORD), (LPSTR) &wNumEntries);
+
+    if (wNumEntries == 0) return 0;
+
+    sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY));
+    logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette );
+
+    if (logPalette == NULL) return 0;
+
+    logPalette->palVersion = PALVERSION;
+    logPalette->palNumEntries = wNumEntries;
+
+    GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry);
+
+    creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette );
+
+    HeapFree( GetProcessHeap(), 0, logPalette );
+
+    if (creationSucceed)
+        return hPalette;
+
+    return 0;
+}
+
+/***********************************************************************
+ *           MFDRV_RealizePalette
+ */
+UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy)
+{
+    char buffer[sizeof(METARECORD) - sizeof(WORD)];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD);
+    mr->rdFunction = META_REALIZEPALETTE;
+
+    if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0;
+
+    /* The return value is suppose to be the number of entries
+       in the logical palette mapped to the system palette or 0
+       if the function failed. Since it's not trivial here to
+       get that kind of information and since it's of little
+       use in the case of metafiles, we'll always return 1. */
+    return 1;
+}
+
+/******************/
+/* Text functions */
+/******************/
+
+/******************************************************************
+ *         MFDRV_MetaExtTextOut
+ */
+static BOOL MFDRV_MetaExtTextOut( PHYSDEV dev, short x, short y, UINT16 flags,
+				 const RECT16 *rect, LPCSTR str, short count,
+				 const INT16 *lpDx)
+{
+    BOOL ret;
+    DWORD len;
+    METARECORD *mr;
+    BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE);
+
+    len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short)
+	    + sizeof(UINT16);
+    if (isrect)
+        len += sizeof(RECT16);
+    if (lpDx)
+     len+=count*sizeof(INT16);
+    if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len)))
+	return FALSE;
+
+    mr->rdSize = len / 2;
+    mr->rdFunction = META_EXTTEXTOUT;
+    *(mr->rdParm) = y;
+    *(mr->rdParm + 1) = x;
+    *(mr->rdParm + 2) = count;
+    *(mr->rdParm + 3) = flags;
+    if (isrect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16));
+    memcpy(mr->rdParm + (isrect ? 8 : 4), str, count);
+    if (lpDx)
+     memcpy(mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1),lpDx,
+      count*sizeof(INT16));
+    ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+    HeapFree( GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+
+/***********************************************************************
+ *           MFDRV_ExtTextOut
+ */
+BOOL
+MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
+                  const RECT *lprect, LPCWSTR str, UINT count,
+                  const INT *lpDx, INT breakExtra )
+{
+    RECT16	rect16;
+    LPINT16	lpdx16 = NULL;
+    BOOL	ret;
+    int		i, j;
+    LPSTR       ascii;
+    DWORD len;
+    CHARSETINFO csi;
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    int charset = GetTextCharset(physDev->hdc);
+    UINT cp = CP_ACP;
+
+    if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
+        cp = csi.ciACP;
+    else {
+        switch(charset) {
+	case OEM_CHARSET:
+	    cp = GetOEMCP();
+	    break;
+	case DEFAULT_CHARSET:
+	    cp = GetACP();
+	    break;
+
+	case VISCII_CHARSET:
+	case TCVN_CHARSET:
+	case KOI8_CHARSET:
+	case ISO3_CHARSET:
+	case ISO4_CHARSET:
+	case ISO10_CHARSET:
+	case CELTIC_CHARSET:
+	  /* FIXME: These have no place here, but because x11drv
+	     enumerates fonts with these (made up) charsets some apps
+	     might use them and then the FIXME below would become
+	     annoying.  Now we could pick the intended codepage for
+	     each of these, but since it's broken anyway we'll just
+	     use CP_ACP and hope it'll go away...
+	  */
+	    cp = CP_ACP;
+	    break;
+
+
+	default:
+	    FIXME("Can't find codepage for charset %d\n", charset);
+	    break;
+	}
+    }
+
+
+    TRACE("cp == %d\n", cp);
+    len = WideCharToMultiByte(cp, 0, str, count, NULL, 0, NULL, NULL);
+    ascii = HeapAlloc(GetProcessHeap(), 0, len);
+    WideCharToMultiByte(cp, 0, str, count, ascii, len, NULL, NULL);
+    TRACE("mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len));
+
+
+    if (lprect)	CONV_RECT32TO16(lprect,&rect16);
+
+    if(lpDx) {
+        lpdx16 = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16)*len );
+	for(i = j = 0; i < len; )
+	    if(IsDBCSLeadByteEx(cp, ascii[i])) {
+	        lpdx16[i++] = lpDx[j++];
+		lpdx16[i++] = 0;
+	    } else
+	        lpdx16[i++] = lpDx[j++];
+    }
+
+    ret = MFDRV_MetaExtTextOut(dev,x,y,flags,lprect?&rect16:NULL,ascii,len,lpdx16);
+    HeapFree( GetProcessHeap(), 0, ascii );
+    if (lpdx16)	HeapFree( GetProcessHeap(), 0, lpdx16 );
+    return ret;
+}
+
+/****************************/
+/* Initialisation functions */
+/****************************/
+
+static const DC_FUNCTIONS MFDRV_Funcs =
+{
+    NULL,                            /* pAbortDoc */
+    MFDRV_AbortPath,                 /* pAbortPath */
+    NULL,                            /* pAngleArc */
+    MFDRV_Arc,                       /* pArc */
+    NULL,                            /* pArcTo */
+    MFDRV_BeginPath,                 /* pBeginPath */
+    MFDRV_BitBlt,                    /* pBitBlt */
+    NULL,                            /* pChoosePixelFormat */
+    MFDRV_Chord,                     /* pChord */
+    MFDRV_CloseFigure,               /* pCloseFigure */
+    NULL,                            /* pCreateBitmap */
+    NULL,                            /* pCreateDC */
+    NULL,                            /* pCreateDIBSection */
+    NULL,                            /* pDeleteBitmap */
+    NULL,                            /* pDeleteDC */
+    MFDRV_DeleteObject,              /* pDeleteObject */
+    NULL,                            /* pDescribePixelFormat */
+    NULL,                            /* pDeviceCapabilities */
+    MFDRV_Ellipse,                   /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
+    MFDRV_EndPath,                   /* pEndPath */
+    NULL,                            /* pEnumDeviceFonts */
+    MFDRV_ExcludeClipRect,           /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
+    MFDRV_ExtEscape,                 /* pExtEscape */
+    MFDRV_ExtFloodFill,              /* pExtFloodFill */
+    MFDRV_ExtSelectClipRgn,          /* pExtSelectClipRgn */
+    MFDRV_ExtTextOut,                /* pExtTextOut */
+    MFDRV_FillPath,                  /* pFillPath */
+    MFDRV_FillRgn,                   /* pFillRgn */
+    MFDRV_FlattenPath,               /* pFlattenPath */
+    MFDRV_FrameRgn,                  /* pFrameRgn */
+    NULL,                            /* pGdiComment */
+    NULL,                            /* pGetBitmapBits */
+    NULL,                            /* pGetCharWidth */
+    NULL,                            /* pGetDCOrgEx */
+    NULL,                            /* pGetDIBColorTable */
+    NULL,                            /* pGetDIBits */
+    MFDRV_GetDeviceCaps,             /* pGetDeviceCaps */
+    NULL,                            /* pGetDeviceGammaRamp */
+    NULL,                            /* pGetNearestColor */
+    NULL,                            /* pGetPixel */
+    NULL,                            /* pGetPixelFormat */
+    NULL,                            /* pGetSystemPaletteEntries */
+    NULL,                            /* pGetTextExtentPoint */
+    NULL,                            /* pGetTextMetrics */
+    MFDRV_IntersectClipRect,         /* pIntersectClipRect */
+    MFDRV_InvertRgn,                 /* pInvertRgn */
+    MFDRV_LineTo,                    /* pLineTo */
+    NULL,                            /* pModifyWorldTransform */
+    MFDRV_MoveTo,                    /* pMoveTo */
+    MFDRV_OffsetClipRgn,             /* pOffsetClipRgn */
+    MFDRV_OffsetViewportOrg,         /* pOffsetViewportOrg */
+    MFDRV_OffsetWindowOrg,           /* pOffsetWindowOrg */
+    MFDRV_PaintRgn,                  /* pPaintRgn */
+    MFDRV_PatBlt,                    /* pPatBlt */
+    MFDRV_Pie,                       /* pPie */
+    MFDRV_PolyBezier,                /* pPolyBezier */
+    MFDRV_PolyBezierTo,              /* pPolyBezierTo */
+    NULL,                            /* pPolyDraw */
+    MFDRV_PolyPolygon,               /* pPolyPolygon */
+    NULL,                            /* pPolyPolyline */
+    MFDRV_Polygon,                   /* pPolygon */
+    MFDRV_Polyline,                  /* pPolyline */
+    NULL,                            /* pPolylineTo */
+    NULL,                            /* pRealizeDefaultPalette */
+    MFDRV_RealizePalette,            /* pRealizePalette */
+    MFDRV_Rectangle,                 /* pRectangle */
+    NULL,                            /* pResetDC */
+    MFDRV_RestoreDC,                 /* pRestoreDC */
+    MFDRV_RoundRect,                 /* pRoundRect */
+    MFDRV_SaveDC,                    /* pSaveDC */
+    MFDRV_ScaleViewportExt,          /* pScaleViewportExt */
+    MFDRV_ScaleWindowExt,            /* pScaleWindowExt */
+    MFDRV_SelectBitmap,              /* pSelectBitmap */
+    MFDRV_SelectBrush,               /* pSelectBrush */
+    MFDRV_SelectClipPath,            /* pSelectClipPath */
+    MFDRV_SelectFont,                /* pSelectFont */
+    MFDRV_SelectPalette,             /* pSelectPalette */
+    MFDRV_SelectPen,                 /* pSelectPen */
+    NULL,                            /* pSetArcDirection */
+    NULL,                            /* pSetBitmapBits */
+    MFDRV_SetBkColor,                /* pSetBkColor */
+    MFDRV_SetBkMode,                 /* pSetBkMode */
+    NULL,                            /* pSetDCBrushColor*/
+    NULL,                            /* pSetDCOrg */
+    NULL,                            /* pSetDCPenColor*/
+    NULL,                            /* pSetDIBColorTable */
+    NULL,                            /* pSetDIBits */
+    MFDRV_SetDIBitsToDevice,         /* pSetDIBitsToDevice */
+    NULL,                            /* pSetDeviceClipping */
+    NULL,                            /* pSetDeviceGammaRamp */
+    MFDRV_SetMapMode,                /* pSetMapMode */
+    MFDRV_SetMapperFlags,            /* pSetMapperFlags */
+    MFDRV_SetPixel,                  /* pSetPixel */
+    NULL,                            /* pSetPixelFormat */
+    MFDRV_SetPolyFillMode,           /* pSetPolyFillMode */
+    MFDRV_SetROP2,                   /* pSetROP2 */
+    MFDRV_SetRelAbs,                 /* pSetRelAbs */
+    MFDRV_SetStretchBltMode,         /* pSetStretchBltMode */
+    MFDRV_SetTextAlign,              /* pSetTextAlign */
+    MFDRV_SetTextCharacterExtra,     /* pSetTextCharacterExtra */
+    MFDRV_SetTextColor,              /* pSetTextColor */
+    MFDRV_SetTextJustification,      /* pSetTextJustification */
+    MFDRV_SetViewportExt,            /* pSetViewportExt */
+    MFDRV_SetViewportOrg,            /* pSetViewportOrg */
+    MFDRV_SetWindowExt,              /* pSetWindowExt */
+    MFDRV_SetWindowOrg,              /* pSetWindowOrg */
+    NULL,                            /* pSetWorldTransform */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
+    MFDRV_StretchBlt,                /* pStretchBlt */
+    MFDRV_StretchDIBits,             /* pStretchDIBits */
+    MFDRV_StrokeAndFillPath,         /* pStrokeAndFillPath */
+    MFDRV_StrokePath,                /* pStrokePath */
+    NULL,                            /* pSwapBuffers */
+    MFDRV_WidenPath                  /* pWidenPath */
+};
+
+
+
+/**********************************************************************
+ *	     MFDRV_AllocMetaFile
+ */
+static DC *MFDRV_AllocMetaFile(void)
+{
+    DC *dc;
+    METAFILEDRV_PDEVICE *physDev;
+
+    if (!(dc = DC_AllocDC( &MFDRV_Funcs, METAFILE_DC_MAGIC ))) return NULL;
+
+    physDev = (METAFILEDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
+    if (!physDev)
+    {
+        GDI_FreeObject( dc->hSelf, dc );
+        return NULL;
+    }
+    dc->physDev = (PHYSDEV)physDev;
+    physDev->hdc = dc->hSelf;
+    physDev->dc = dc;
+
+    if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) )))
+    {
+        HeapFree( GetProcessHeap(), 0, physDev );
+        GDI_FreeObject( dc->hSelf, dc );
+        return NULL;
+    }
+
+    physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0]));
+    physDev->handles_size = HANDLE_LIST_INC;
+    physDev->cur_handles = 0;
+
+    physDev->hFile = 0;
+
+    physDev->mh->mtHeaderSize   = sizeof(METAHEADER) / sizeof(WORD);
+    physDev->mh->mtVersion      = 0x0300;
+    physDev->mh->mtSize         = physDev->mh->mtHeaderSize;
+    physDev->mh->mtNoObjects    = 0;
+    physDev->mh->mtMaxRecord    = 0;
+    physDev->mh->mtNoParameters = 0;
+
+    return dc;
+}
+
+
+/**********************************************************************
+ *	     MFDRV_DeleteDC
+ */
+static BOOL MFDRV_DeleteDC( PHYSDEV dev )
+{
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+    DC *dc = physDev->dc;
+    DWORD index;
+
+    if (physDev->mh) HeapFree( GetProcessHeap(), 0, physDev->mh );
+    for(index = 0; index < physDev->handles_size; index++)
+        if(physDev->handles[index])
+            GDI_hdc_not_using_object(physDev->handles[index], physDev->hdc);
+    HeapFree( GetProcessHeap(), 0, physDev->handles );
+    HeapFree( GetProcessHeap(), 0, physDev );
+    dc->physDev = NULL;
+    GDI_FreeObject( dc->hSelf, dc );
+    return TRUE;
+}
+
+
+/**********************************************************************
+ *	     CreateMetaFileW   (GDI32.@)
+ *
+ *  Create a new DC and associate it with a metafile. Pass a filename
+ *  to create a disk-based metafile, NULL to create a memory metafile.
+ *
+ * RETURNS
+ *  A handle to the metafile DC if successful, NULL on failure.
+ */
+HDC WINAPI CreateMetaFileW( LPCWSTR filename ) /* [in] Filename of disk metafile */
+{
+    HDC ret;
+    DC *dc;
+    METAFILEDRV_PDEVICE *physDev;
+    HANDLE hFile;
+
+    TRACE("'%s'\n", debugstr_w(filename) );
+
+    if (!(dc = MFDRV_AllocMetaFile())) return 0;
+    physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
+
+    if (filename)  /* disk based metafile */
+    {
+        physDev->mh->mtType = METAFILE_DISK;
+        if ((hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL,
+				CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
+            MFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+        if (!WriteFile( hFile, physDev->mh, sizeof(*physDev->mh), NULL,
+			NULL )) {
+            MFDRV_DeleteDC( dc->physDev );
+            return 0;
+	}
+	physDev->hFile = hFile;
+
+	/* Grow METAHEADER to include filename */
+	physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename, TRUE);
+    }
+    else  /* memory based metafile */
+	physDev->mh->mtType = METAFILE_MEMORY;
+
+    TRACE("returning %p\n", dc->hSelf);
+    ret = dc->hSelf;
+    GDI_ReleaseObj( dc->hSelf );
+    return ret;
+}
+
+/**********************************************************************
+ *          CreateMetaFileA   (GDI32.@)
+ */
+HDC WINAPI CreateMetaFileA(LPCSTR filename)
+{
+    LPWSTR filenameW;
+    DWORD len;
+    HDC hReturnDC;
+
+    if (!filename) return CreateMetaFileW(NULL);
+
+    len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
+    filenameW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
+    MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len );
+
+    hReturnDC = CreateMetaFileW(filenameW);
+
+    HeapFree( GetProcessHeap(), 0, filenameW );
+
+    return hReturnDC;
+}
+
+
+/**********************************************************************
+ *          MFDRV_CloseMetaFile
+ */
+static DC *MFDRV_CloseMetaFile( HDC hdc )
+{
+    DC *dc;
+    METAFILEDRV_PDEVICE *physDev;
+
+    TRACE("(%p)\n", hdc );
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC ))) return 0;
+    physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
+
+    /* Construct the end of metafile record - this is documented
+     * in SDK Knowledgebase Q99334.
+     */
+
+    if (!MFDRV_MetaParam0(dc->physDev, META_EOF))
+    {
+        MFDRV_DeleteDC( dc->physDev );
+	return 0;
+    }
+
+    if (physDev->mh->mtType == METAFILE_DISK)  /* disk based metafile */
+    {
+        if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) {
+            MFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+
+	physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */
+        if (!WriteFile(physDev->hFile, (LPSTR)physDev->mh,
+                       sizeof(*physDev->mh), NULL, NULL)) {
+            MFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+        CloseHandle(physDev->hFile);
+	physDev->mh->mtType = METAFILE_DISK;
+    }
+
+    return dc;
+}
+
+/******************************************************************
+ *	     CloseMetaFile     (GDI.126)
+ */
+HMETAFILE16 WINAPI CloseMetaFile16(
+				   HDC16 hdc /* [in] Metafile DC to close */
+)
+{
+    HMETAFILE16 hmf;
+    METAFILEDRV_PDEVICE *physDev;
+    DC *dc = MFDRV_CloseMetaFile(HDC_32(hdc));
+    if (!dc) return 0;
+    physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
+
+    /* Now allocate a global handle for the metafile */
+
+    hmf = MF_Create_HMETAFILE16( physDev->mh );
+
+    physDev->mh = NULL;  /* So it won't be deleted */
+    MFDRV_DeleteDC( dc->physDev );
+    return hmf;
+}
+
+/******************************************************************
+ *	     CloseMetaFile   (GDI32.@)
+ *
+ *  Stop recording graphics operations in metafile associated with
+ *  hdc and retrieve metafile.
+ *
+ * RETURNS
+ *  Handle of newly created metafile on success, NULL on failure.
+ */
+HMETAFILE WINAPI CloseMetaFile(
+				   HDC hdc /* [in] Metafile DC to close */
+)
+{
+    HMETAFILE hmf;
+    METAFILEDRV_PDEVICE *physDev;
+    DC *dc = MFDRV_CloseMetaFile(hdc);
+    if (!dc) return 0;
+    physDev = (METAFILEDRV_PDEVICE *)dc->physDev;
+
+    /* Now allocate a global handle for the metafile */
+
+    hmf = MF_Create_HMETAFILE( physDev->mh );
+
+    physDev->mh = NULL;  /* So it won't be deleted */
+    MFDRV_DeleteDC( dc->physDev );
+    return hmf;
+}
+
+
+/******************************************************************
+ *         MFDRV_WriteRecord
+ *
+ * Warning: this function can change the pointer to the metafile header.
+ */
+BOOL MFDRV_WriteRecord( PHYSDEV dev, METARECORD *mr, DWORD rlen)
+{
+    DWORD len, size;
+    METAHEADER *mh;
+    METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev;
+
+    switch(physDev->mh->mtType)
+    {
+    case METAFILE_MEMORY:
+	len = physDev->mh->mtSize * 2 + rlen;
+	/* reallocate memory if needed */
+        size = HeapSize( GetProcessHeap(), 0, physDev->mh );
+        if (len > size)
+        {
+            /*expand size*/
+            size += size / 2 + rlen;
+            mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, size);
+            if (!mh) return FALSE;
+            physDev->mh = mh;
+            TRACE("Reallocated metafile: new size is %ld\n",size);
+        }
+	memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen);
+        break;
+    case METAFILE_DISK:
+        TRACE("Writing record to disk\n");
+	if (!WriteFile(physDev->hFile, (char *)mr, rlen, NULL, NULL))
+	    return FALSE;
+        break;
+    default:
+        ERR("Unknown metafile type %d\n", physDev->mh->mtType );
+        return FALSE;
+    }
+
+    physDev->mh->mtSize += rlen / 2;
+    physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2);
+    return TRUE;
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam0
+ */
+
+BOOL MFDRV_MetaParam0(PHYSDEV dev, short func)
+{
+    char buffer[8];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 3;
+    mr->rdFunction = func;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam1
+ */
+BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1)
+{
+    char buffer[8];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 4;
+    mr->rdFunction = func;
+    *(mr->rdParm) = param1;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam2
+ */
+BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2)
+{
+    char buffer[10];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 5;
+    mr->rdFunction = func;
+    *(mr->rdParm) = param2;
+    *(mr->rdParm + 1) = param1;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam4
+ */
+
+BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2,
+		      short param3, short param4)
+{
+    char buffer[14];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 7;
+    mr->rdFunction = func;
+    *(mr->rdParm) = param4;
+    *(mr->rdParm + 1) = param3;
+    *(mr->rdParm + 2) = param2;
+    *(mr->rdParm + 3) = param1;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam6
+ */
+
+BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2,
+		      short param3, short param4, short param5, short param6)
+{
+    char buffer[18];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 9;
+    mr->rdFunction = func;
+    *(mr->rdParm) = param6;
+    *(mr->rdParm + 1) = param5;
+    *(mr->rdParm + 2) = param4;
+    *(mr->rdParm + 3) = param3;
+    *(mr->rdParm + 4) = param2;
+    *(mr->rdParm + 5) = param1;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/******************************************************************
+ *         MFDRV_MetaParam8
+ */
+BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2,
+		      short param3, short param4, short param5,
+		      short param6, short param7, short param8)
+{
+    char buffer[22];
+    METARECORD *mr = (METARECORD *)&buffer;
+
+    mr->rdSize = 11;
+    mr->rdFunction = func;
+    *(mr->rdParm) = param8;
+    *(mr->rdParm + 1) = param7;
+    *(mr->rdParm + 2) = param6;
+    *(mr->rdParm + 3) = param5;
+    *(mr->rdParm + 4) = param4;
+    *(mr->rdParm + 5) = param3;
+    *(mr->rdParm + 6) = param2;
+    *(mr->rdParm + 7) = param1;
+    return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2);
+}
+
+
+/**********************************************************************
+ *           MFDRV_ExtEscape
+ */
+INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data,
+                     INT cbOutput, LPVOID out_data )
+{
+    METARECORD *mr;
+    DWORD len;
+    INT ret;
+
+    len = sizeof(*mr) + sizeof(WORD) + ((cbInput + 1) & ~1);
+    mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
+    mr->rdSize = len / 2;
+    mr->rdFunction = META_ESCAPE;
+    mr->rdParm[0] = nEscape;
+    mr->rdParm[1] = cbInput;
+    memcpy(&(mr->rdParm[2]), in_data, cbInput);
+    ret = MFDRV_WriteRecord( dev, mr, len);
+    HeapFree(GetProcessHeap(), 0, mr);
+    return ret;
+}
+
+
+/******************************************************************
+ *         MFDRV_GetDeviceCaps
+ *
+ *A very simple implementation that returns DT_METAFILE
+ */
+INT MFDRV_GetDeviceCaps(PHYSDEV dev, INT cap)
+{
+    switch(cap)
+    {
+    case TECHNOLOGY:
+        return DT_METAFILE;
+    case TEXTCAPS:
+        return 0;
+    default:
+        TRACE(" unsupported capability %d, will return 0\n", cap );
+    }
+    return 0;
+}

-- 
Dimi.




More information about the wine-patches mailing list