GDI: Merge the enhmfdrv into one .c file.

Dimitrie O. Paun dpaun at rogers.com
Thu Apr 1 19:44:15 CST 2004


    Merge the entire enhmfdrv into one .c file.
    It's not big, and it's the way we usually do
    things in wine (e.g. dlls/comctl32/*.c).
    Moreover, we get rid of the extra dir in
    dlls/gdi/, and gets us closer to a flat
    dlls/*/ namespace.

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

ChangeLog
    Merge the enhmfdrv into one .c file.

--- orig/dlls/gdi/Makefile.in
+++ mod/dlls/gdi/Makefile.in
@@ -33,12 +33,7 @@
 	bidi.c \
 	bitblt.c \
 	driver.c \
-	enhmfdrv/bitblt.c \
-	enhmfdrv/dc.c \
-	enhmfdrv/graphics.c \
-	enhmfdrv/init.c \
-	enhmfdrv/mapping.c \
-	enhmfdrv/objects.c \
+	enhmfdrv.c \
 	freetype.c \
 	gdi_main.c \
 	icm.c \
@@ -68,7 +63,6 @@
 
 EXTRASUBDIRS = \
 	$(TOPOBJDIR)/objects \
-	enhmfdrv \
 	mfdrv
 
 @MAKE_DLL_RULES@



--- /dev/null	2003-01-30 05:24:37.000000000 -0500
+++ dlls/gdi/enhmfdrv.c	2004-04-01 12:04:38.000000000 -0500
@@ -0,0 +1,2387 @@
+/*
+ * Enhanced MetaFile driver definitions
+ *
+ * Copyright 1999 Huw D M Davies
+ *
+ * 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 "gdi_private.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile);
+
+/* Enhanced Metafile driver physical DC */
+
+typedef struct
+{
+    HDC             hdc;
+    DC             *dc;
+    ENHMETAHEADER  *emh;           /* Pointer to enhanced metafile header */
+    UINT       handles_size, cur_handles;
+    HGDIOBJ   *handles;
+    HANDLE     hFile;              /* Handle for disk based MetaFile */
+    INT        horzres, vertres;
+    INT        horzsize, vertsize;
+    INT        logpixelsx, logpixelsy;
+    INT        bitspixel;
+    INT        textcaps;
+    INT        rastercaps;
+    INT        technology;
+    INT        planes;
+} EMFDRV_PDEVICE;
+
+
+extern BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr );
+extern void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect );
+extern DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush );
+
+#define HANDLE_LIST_INC 20
+
+/********************/
+/* BitBlt functions */
+/********************/
+
+BOOL EMFDRV_PatBlt( PHYSDEV dev, INT left, INT top,
+                    INT width, INT height, DWORD rop )
+{
+    EMRBITBLT emr;
+    BOOL ret;
+
+    emr.emr.iType = EMR_BITBLT;
+    emr.emr.nSize = sizeof(emr);
+    emr.rclBounds.left = left;
+    emr.rclBounds.top = top;
+    emr.rclBounds.right = left + width - 1;
+    emr.rclBounds.bottom = top + height - 1;
+    emr.xDest = left;
+    emr.yDest = top;
+    emr.cxDest = width;
+    emr.cyDest = height;
+    emr.dwRop = rop;
+    emr.xSrc = 0;
+    emr.ySrc = 0;
+    emr.xformSrc.eM11 = 1.0;
+    emr.xformSrc.eM12 = 0.0;
+    emr.xformSrc.eM21 = 0.0;
+    emr.xformSrc.eM22 = 1.0;
+    emr.xformSrc.eDx = 0.0;
+    emr.xformSrc.eDy = 0.0;
+    emr.crBkColorSrc = 0;
+    emr.iUsageSrc = 0;
+    emr.offBmiSrc = 0;
+    emr.cbBmiSrc = 0;
+    emr.offBitsSrc = 0;
+    emr.cbBitsSrc = 0;
+
+    ret = EMFDRV_WriteRecord( dev, &emr.emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr.rclBounds );
+    return ret;
+}
+
+/* Utilitarian function used by EMFDRV_BitBlt and EMFDRV_StretchBlt */
+
+static BOOL EMFDRV_BitBlockTransfer( 
+    PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst,  
+    PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop,
+    DWORD emrType)
+{
+    BOOL ret;
+    PEMRBITBLT pEMR;
+    UINT emrSize;
+    UINT bmiSize;
+    UINT bitsSize;
+    UINT size;
+    BITMAP  BM;
+    WORD nBPP;
+    LPBITMAPINFOHEADER lpBmiH;
+    EMFDRV_PDEVICE* physDevSrc = (EMFDRV_PDEVICE*)devSrc;
+    HBITMAP hBitmap = GetCurrentObject(physDevSrc->hdc, OBJ_BITMAP);
+
+    if (emrType == EMR_BITBLT)
+        emrSize = sizeof(EMRBITBLT);
+    else if (emrType == EMR_STRETCHBLT)
+        emrSize = sizeof(EMRSTRETCHBLT);
+    else
+        return FALSE;
+
+    GetObjectW(hBitmap, sizeof(BITMAP), &BM);
+
+    nBPP = BM.bmPlanes * BM.bmBitsPixel;
+    if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */
+
+    bitsSize = DIB_GetDIBWidthBytes(BM.bmWidth, nBPP) * BM.bmHeight;
+    bmiSize = sizeof(BITMAPINFOHEADER) + 
+        (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD);
+    size = emrSize + bmiSize + bitsSize;
+
+    pEMR = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!pEMR) return FALSE;
+
+    /* Initialize EMR */
+    pEMR->emr.iType = emrType;
+    pEMR->emr.nSize = size;
+    pEMR->rclBounds.left = xDst;
+    pEMR->rclBounds.top = yDst;
+    pEMR->rclBounds.right = xDst + widthDst - 1;
+    pEMR->rclBounds.bottom = yDst + heightDst - 1;
+    pEMR->xDest = xDst;
+    pEMR->yDest = yDst;
+    pEMR->cxDest = widthDst;
+    pEMR->cyDest = heightDst;
+    pEMR->dwRop = rop;
+    pEMR->xSrc = xSrc;
+    pEMR->ySrc = ySrc;
+    pEMR->xformSrc.eM11 = 1.0;  /** FIXME:           */
+    pEMR->xformSrc.eM12 = 0.0;  /** Setting default  */
+    pEMR->xformSrc.eM21 = 0.0;  /** value.           */
+    pEMR->xformSrc.eM22 = 1.0;  /** Where should we  */
+    pEMR->xformSrc.eDx = 0.0;   /** get that info    */
+    pEMR->xformSrc.eDy = 0.0;   /** ????             */
+    pEMR->crBkColorSrc = GetBkColor(physDevSrc->hdc);
+    pEMR->iUsageSrc = DIB_RGB_COLORS;
+    pEMR->offBmiSrc = emrSize;
+    pEMR->cbBmiSrc = bmiSize;
+    pEMR->offBitsSrc = emrSize + bmiSize;
+    pEMR->cbBitsSrc = bitsSize;
+    if (emrType == EMR_STRETCHBLT) 
+    {
+        PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR;
+        pEMRStretch->cxSrc = widthSrc;
+        pEMRStretch->cySrc = heightSrc;
+    }
+
+    /* Initialize BITMAPINFO structure */
+    lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc);
+
+    lpBmiH->biSize = sizeof(BITMAPINFOHEADER); 
+    lpBmiH->biWidth =  BM.bmWidth;
+    lpBmiH->biHeight = BM.bmHeight;
+    lpBmiH->biPlanes = BM.bmPlanes;
+    lpBmiH->biBitCount = nBPP;
+    /* Assume the bitmap isn't compressed and set the BI_RGB flag. */
+    lpBmiH->biCompression = BI_RGB;
+    lpBmiH->biSizeImage = bitsSize;
+    lpBmiH->biYPelsPerMeter = /* 1 meter  = 39.37 inch */
+        MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSX),3937,100);
+    lpBmiH->biXPelsPerMeter = 
+        MulDiv(GetDeviceCaps(physDevSrc->hdc,LOGPIXELSY),3937,100);
+    lpBmiH->biClrUsed   = nBPP <= 8 ? 1 << nBPP : 0;
+    /* Set biClrImportant to 0, indicating that all of the 
+       device colors are important. */
+    lpBmiH->biClrImportant = 0; 
+
+    /* Initiliaze bitmap bits */
+    if (GetDIBits(physDevSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight,
+                  (BYTE*)pEMR + pEMR->offBitsSrc,
+                  (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS))
+    {
+        ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR);
+        if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds));
+    } 
+    else
+        ret = FALSE;
+
+    HeapFree( GetProcessHeap(), 0, pEMR);
+    return ret;
+}
+
+BOOL EMFDRV_BitBlt( 
+    PHYSDEV devDst, INT xDst, INT yDst, INT width, INT height,
+    PHYSDEV devSrc, INT xSrc, INT ySrc, DWORD rop)
+{
+    return EMFDRV_BitBlockTransfer( devDst, xDst, yDst, width, height,  
+                                    devSrc, xSrc, ySrc, width, height, 
+                                    rop, EMR_BITBLT );
+}
+
+BOOL EMFDRV_StretchBlt( 
+    PHYSDEV devDst, INT xDst, INT yDst, INT widthDst, INT heightDst,  
+    PHYSDEV devSrc, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, DWORD rop )
+{
+    return EMFDRV_BitBlockTransfer( devDst, xDst, yDst, widthDst, heightDst,  
+                                    devSrc, xSrc, ySrc, widthSrc, heightSrc, 
+                                    rop, EMR_STRETCHBLT );
+}
+
+INT EMFDRV_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 )
+{
+    EMRSTRETCHDIBITS *emr;
+    BOOL ret;
+    UINT bmi_size=0, bits_size, emr_size;
+    
+    bits_size = DIB_GetDIBImageBytes(info->bmiHeader.biWidth,
+                                     info->bmiHeader.biHeight,
+                                     info->bmiHeader.biBitCount);
+
+    /* calculate the size of the colour table */
+    bmi_size = DIB_BitmapInfoSize(info, wUsage);
+
+    emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + bits_size;
+    emr = HeapAlloc(GetProcessHeap(), 0, emr_size );
+    if (!emr) return 0;
+
+    /* write a bitmap info header (with colours) to the record */
+    memcpy( &emr[1], info, bmi_size);
+
+    /* write bitmap bits to the record */
+    memcpy ( ( (BYTE *) (&emr[1]) ) + bmi_size, bits, bits_size);
+
+    /* fill in the EMR header at the front of our piece of memory */
+    emr->emr.iType = EMR_STRETCHDIBITS;
+    emr->emr.nSize = emr_size;
+
+    emr->xDest     = xDst;
+    emr->yDest     = yDst;
+    emr->cxDest    = widthDst;
+    emr->cyDest    = heightDst;
+    emr->dwRop     = dwRop;
+    emr->xSrc      = xSrc; /* FIXME: only save the piece of the bitmap needed */
+    emr->ySrc      = ySrc;
+
+    emr->iUsageSrc    = wUsage;
+    emr->offBmiSrc    = sizeof (EMRSTRETCHDIBITS);
+    emr->cbBmiSrc     = bmi_size;
+    emr->offBitsSrc   = emr->offBmiSrc + bmi_size; 
+    emr->cbBitsSrc    = bits_size;
+
+    emr->cxSrc = widthSrc;
+    emr->cySrc = heightSrc;
+
+    emr->rclBounds.left   = xDst;
+    emr->rclBounds.top    = yDst;
+    emr->rclBounds.right  = xDst + widthDst;
+    emr->rclBounds.bottom = yDst + heightDst;
+
+    /* save the record we just created */
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+
+    HeapFree(GetProcessHeap(), 0, emr);
+
+    return ret;
+}
+
+INT EMFDRV_SetDIBitsToDevice( 
+    PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height,
+    INT xSrc, INT ySrc, UINT startscan, UINT lines,
+    LPCVOID bits, const BITMAPINFO *info, UINT wUsage )
+{
+    EMRSETDIBITSTODEVICE* pEMR;
+    DWORD size, bmiSize, bitsSize;
+
+    bmiSize = DIB_BitmapInfoSize(info, wUsage);
+    bitsSize = DIB_GetDIBImageBytes( info->bmiHeader.biWidth,
+                                     info->bmiHeader.biHeight,
+                                     info->bmiHeader.biBitCount );
+    size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + bitsSize;
+
+    pEMR = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!pEMR) return 0;
+
+    pEMR->emr.iType = EMR_SETDIBITSTODEVICE;
+    pEMR->emr.nSize = size;
+    pEMR->rclBounds.left = xDst;
+    pEMR->rclBounds.top = yDst;
+    pEMR->rclBounds.right = xDst + width - 1;
+    pEMR->rclBounds.bottom = yDst + height - 1;
+    pEMR->xDest = xDst;
+    pEMR->yDest = yDst;
+    pEMR->xSrc = xSrc;
+    pEMR->ySrc = ySrc;
+    pEMR->cxSrc = width;
+    pEMR->cySrc = height;
+    pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE);
+    pEMR->cbBmiSrc = bmiSize;
+    pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize;
+    pEMR->cbBitsSrc = bitsSize;
+    pEMR->iUsageSrc = wUsage;
+    pEMR->iStartScan = startscan;
+    pEMR->cScans = lines;
+    memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize);
+    memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, bitsSize);
+
+    if (EMFDRV_WriteRecord(dev, (EMR*)pEMR))
+        EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds));
+
+    HeapFree( GetProcessHeap(), 0, pEMR);
+    return lines;
+}
+
+/**********************/
+/* DC value functions */
+/**********************/
+
+INT EMFDRV_SaveDC( PHYSDEV dev )
+{
+    EMRSAVEDC emr;
+    emr.emr.iType = EMR_SAVEDC;
+    emr.emr.nSize = sizeof(emr);
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_RestoreDC( PHYSDEV dev, INT level )
+{
+    EMFDRV_PDEVICE* physDev = (EMFDRV_PDEVICE*)dev;
+    EMRRESTOREDC emr;
+
+    emr.emr.iType = EMR_RESTOREDC;
+    emr.emr.nSize = sizeof(emr);
+    emr.iRelative = -1;
+    if (level == -1) 
+        return EMFDRV_WriteRecord( dev, &emr.emr );
+    else if (level > 0 && level <= physDev->dc->saveLevel) 
+    {
+        while (level >= physDev->dc->saveLevel) 
+        {
+            EMFDRV_WriteRecord( dev, &emr.emr );
+            level--;
+        }
+        return TRUE;
+    }
+    return FALSE;
+}
+
+UINT EMFDRV_SetTextAlign( PHYSDEV dev, UINT align )
+{
+    EMRSETTEXTALIGN emr;
+    emr.emr.iType = EMR_SETTEXTALIGN;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = align;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_SetTextJustification(PHYSDEV dev, INT nBreakExtra, INT nBreakCount)
+{
+    EMRSETTEXTJUSTIFICATION emr;
+    emr.emr.iType = EMR_SETTEXTJUSTIFICATION;
+    emr.emr.nSize = sizeof(emr);
+    emr.nBreakExtra = nBreakExtra;
+    emr.nBreakCount = nBreakCount;
+    return EMFDRV_WriteRecord(dev, &emr.emr);
+}
+
+INT EMFDRV_SetBkMode( PHYSDEV dev, INT mode )
+{
+    EMRSETBKMODE emr;
+    emr.emr.iType = EMR_SETBKMODE;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = mode;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetROP2( PHYSDEV dev, INT rop )
+{
+    EMRSETROP2 emr;
+    emr.emr.iType = EMR_SETROP2;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = rop;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetPolyFillMode( PHYSDEV dev, INT mode )
+{
+    EMRSETPOLYFILLMODE emr;
+    emr.emr.iType = EMR_SETPOLYFILLMODE;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = mode;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetStretchBltMode( PHYSDEV dev, INT mode )
+{
+    EMRSETSTRETCHBLTMODE emr;
+    emr.emr.iType = EMR_SETSTRETCHBLTMODE;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = mode;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
+{
+    EMREXCLUDECLIPRECT emr;
+    emr.emr.iType      = EMR_EXCLUDECLIPRECT;
+    emr.emr.nSize      = sizeof(emr);
+    emr.rclClip.left   = left;
+    emr.rclClip.top    = top;
+    emr.rclClip.right  = right;
+    emr.rclClip.bottom = bottom;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom)
+{
+    EMRINTERSECTCLIPRECT emr;
+    emr.emr.iType      = EMR_INTERSECTCLIPRECT;
+    emr.emr.nSize      = sizeof(emr);
+    emr.rclClip.left   = left;
+    emr.rclClip.top    = top;
+    emr.rclClip.right  = right;
+    emr.rclClip.bottom = bottom;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y )
+{
+    EMROFFSETCLIPRGN emr;
+    emr.emr.iType   = EMR_OFFSETCLIPRGN;
+    emr.emr.nSize   = sizeof(emr);
+    emr.ptlOffset.x = x;
+    emr.ptlOffset.y = y;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode )
+{
+    EMREXTSELECTCLIPRGN *emr;
+    DWORD size, rgnsize;
+    BOOL ret;
+
+    if (!hrgn)
+    {
+        if (mode != RGN_COPY) return ERROR;
+        rgnsize = 0;
+    }
+    else rgnsize = GetRegionData( hrgn, 0, NULL );
+
+    size = rgnsize + offsetof(EMREXTSELECTCLIPRGN,RgnData);
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+    if (rgnsize) GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
+
+    emr->emr.iType = EMR_EXTSELECTCLIPRGN;
+    emr->emr.nSize = size;
+    emr->cbRgnData = rgnsize;
+    emr->iMode     = mode;
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret ? SIMPLEREGION : ERROR;
+}
+
+DWORD EMFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags )
+{
+    EMRSETMAPPERFLAGS emr;
+
+    emr.emr.iType = EMR_SETMAPPERFLAGS;
+    emr.emr.nSize = sizeof(emr);
+    emr.dwFlags   = flags;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_AbortPath( PHYSDEV dev )
+{
+    EMRABORTPATH emr;
+
+    emr.emr.iType = EMR_ABORTPATH;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_BeginPath( PHYSDEV dev )
+{
+    EMRBEGINPATH emr;
+
+    emr.emr.iType = EMR_BEGINPATH;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_CloseFigure( PHYSDEV dev )
+{
+    EMRCLOSEFIGURE emr;
+
+    emr.emr.iType = EMR_CLOSEFIGURE;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_EndPath( PHYSDEV dev )
+{
+    EMRENDPATH emr;
+
+    emr.emr.iType = EMR_ENDPATH;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_FillPath( PHYSDEV dev )
+{
+    EMRFILLPATH emr;
+
+    emr.emr.iType = EMR_FILLPATH;
+    emr.emr.nSize = sizeof(emr);
+    FIXME("Bounds\n");
+    emr.rclBounds.left = 0;
+    emr.rclBounds.top = 0;
+    emr.rclBounds.right = 0;
+    emr.rclBounds.bottom = 0;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_FlattenPath( PHYSDEV dev )
+{
+    EMRFLATTENPATH emr;
+
+    emr.emr.iType = EMR_FLATTENPATH;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_SelectClipPath( PHYSDEV dev, INT iMode )
+{
+    EMRSELECTCLIPPATH emr;
+
+    emr.emr.iType = EMR_SELECTCLIPPATH;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = iMode;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_StrokeAndFillPath( PHYSDEV dev )
+{
+    EMRSTROKEANDFILLPATH emr;
+
+    emr.emr.iType = EMR_STROKEANDFILLPATH;
+    emr.emr.nSize = sizeof(emr);
+    FIXME("Bounds\n");
+    emr.rclBounds.left = 0;
+    emr.rclBounds.top = 0;
+    emr.rclBounds.right = 0;
+    emr.rclBounds.bottom = 0;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_StrokePath( PHYSDEV dev )
+{
+    EMRSTROKEPATH emr;
+
+    emr.emr.iType = EMR_STROKEPATH;
+    emr.emr.nSize = sizeof(emr);
+    FIXME("Bounds\n");
+    emr.rclBounds.left = 0;
+    emr.rclBounds.top = 0;
+    emr.rclBounds.right = 0;
+    emr.rclBounds.bottom = 0;
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_WidenPath( PHYSDEV dev )
+{
+    EMRWIDENPATH emr;
+
+    emr.emr.iType = EMR_WIDENPATH;
+    emr.emr.nSize = sizeof(emr);
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_GetDeviceCaps(PHYSDEV dev, INT cap)
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
+
+    switch(cap) {
+
+    case HORZRES:
+        return physDev->horzres;
+    case VERTRES:
+        return physDev->vertres;
+    case LOGPIXELSX:
+        return physDev->logpixelsx;
+    case LOGPIXELSY:
+        return physDev->logpixelsy;
+    case HORZSIZE:
+        return physDev->horzsize;
+    case VERTSIZE:
+        return physDev->vertsize;
+    case BITSPIXEL:
+        return physDev->bitspixel;
+    case TEXTCAPS:
+        return physDev->textcaps;
+    case RASTERCAPS:
+        return physDev->rastercaps;
+    case TECHNOLOGY:
+        return physDev->technology;
+    case PLANES:
+        return physDev->planes;
+
+    default:
+        FIXME("Unimplemented cap %d\n", cap);
+	return 0;
+
+    }
+}
+
+/**********************/
+/* Graphics functions */
+/**********************/
+
+/**********************************************************************
+ *	     EMFDRV_MoveTo
+ */
+BOOL
+EMFDRV_MoveTo(PHYSDEV dev, INT x, INT y)
+{
+    EMRMOVETOEX emr;
+
+    emr.emr.iType = EMR_MOVETOEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptl.x = x;
+    emr.ptl.y = y;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+/***********************************************************************
+ *           EMFDRV_LineTo
+ */
+BOOL
+EMFDRV_LineTo( PHYSDEV dev, INT x, INT y )
+{
+    POINT pt;
+    EMRLINETO emr;
+    RECTL bounds;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    emr.emr.iType = EMR_LINETO;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptl.x = x;
+    emr.ptl.y = y;
+
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+    	return FALSE;
+
+    GetCurrentPositionEx(physDev->hdc, &pt);
+
+    bounds.left   = min(x, pt.x);
+    bounds.top    = min(y, pt.y);
+    bounds.right  = max(x, pt.x);
+    bounds.bottom = max(y, pt.y);
+
+    EMFDRV_UpdateBBox( dev, &bounds );
+
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           EMFDRV_ArcChordPie
+ */
+static BOOL
+EMFDRV_ArcChordPie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+		    INT xstart, INT ystart, INT xend, INT yend, DWORD iType )
+{
+    INT temp, xCentre, yCentre, i;
+    double angleStart, angleEnd;
+    double xinterStart, yinterStart, xinterEnd, yinterEnd;
+    EMRARC emr;
+    RECTL bounds;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    if(left == right || top == bottom) return FALSE;
+
+    if(left > right) {temp = left; left = right; right = temp;}
+    if(top > bottom) {temp = top; top = bottom; bottom = temp;}
+
+    if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
+        right--;
+	bottom--;
+    }
+
+    emr.emr.iType     = iType;
+    emr.emr.nSize     = sizeof(emr);
+    emr.rclBox.left   = left;
+    emr.rclBox.top    = top;
+    emr.rclBox.right  = right;
+    emr.rclBox.bottom = bottom;
+    emr.ptlStart.x    = xstart;
+    emr.ptlStart.y    = ystart;
+    emr.ptlEnd.x      = xend;
+    emr.ptlEnd.x      = yend;
+
+
+    /* Now calculate the BBox */
+    xCentre = (left + right + 1) / 2;
+    yCentre = (top + bottom + 1) / 2;
+
+    xstart -= xCentre;
+    ystart -= yCentre;
+    xend   -= xCentre;
+    yend   -= yCentre;
+
+    /* invert y co-ords to get angle anti-clockwise from x-axis */
+    angleStart = atan2( -(double)ystart, (double)xstart);
+    angleEnd   = atan2( -(double)yend, (double)xend);
+
+    /* These are the intercepts of the start/end lines with the arc */
+
+    xinterStart = (right - left + 1)/2 * cos(angleStart) + xCentre;
+    yinterStart = -(bottom - top + 1)/2 * sin(angleStart) + yCentre;
+    xinterEnd   = (right - left + 1)/2 * cos(angleEnd) + xCentre;
+    yinterEnd   = -(bottom - top + 1)/2 * sin(angleEnd) + yCentre;
+
+    if(angleStart < 0) angleStart += 2 * M_PI;
+    if(angleEnd < 0) angleEnd += 2 * M_PI;
+    if(angleEnd < angleStart) angleEnd += 2 * M_PI;
+
+    bounds.left   = min(xinterStart, xinterEnd);
+    bounds.top    = min(yinterStart, yinterEnd);
+    bounds.right  = max(xinterStart, xinterEnd);
+    bounds.bottom = max(yinterStart, yinterEnd);
+
+    for(i = 0; i <= 8; i++) {
+        if(i * M_PI / 2 < angleStart) /* loop until we're past start */
+	    continue;
+	if(i * M_PI / 2 > angleEnd)   /* if we're past end we're finished */
+	    break;
+
+	/* the arc touches the rectangle at the start of quadrant i, so adjust
+	   BBox to reflect this. */
+
+	switch(i % 4) {
+	case 0:
+	    bounds.right = right;
+	    break;
+	case 1:
+	    bounds.top = top;
+	    break;
+	case 2:
+	    bounds.left = left;
+	    break;
+	case 3:
+	    bounds.bottom = bottom;
+	    break;
+	}
+    }
+
+    /* If we're drawing a pie then make sure we include the centre */
+    if(iType == EMR_PIE) {
+        if(bounds.left > xCentre) bounds.left = xCentre;
+	else if(bounds.right < xCentre) bounds.right = xCentre;
+	if(bounds.top > yCentre) bounds.top = yCentre;
+	else if(bounds.bottom < yCentre) bounds.right = yCentre;
+    }
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        return FALSE;
+    EMFDRV_UpdateBBox( dev, &bounds );
+    return TRUE;
+}
+
+
+/***********************************************************************
+ *           EMFDRV_Arc
+ */
+BOOL
+EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+	    INT xstart, INT ystart, INT xend, INT yend )
+{
+    return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
+			       xend, yend, EMR_ARC );
+}
+
+/***********************************************************************
+ *           EMFDRV_Pie
+ */
+BOOL
+EMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+	    INT xstart, INT ystart, INT xend, INT yend )
+{
+    return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
+			       xend, yend, EMR_PIE );
+}
+
+
+/***********************************************************************
+ *           EMFDRV_Chord
+ */
+BOOL
+EMFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom,
+             INT xstart, INT ystart, INT xend, INT yend )
+{
+    return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart,
+			       xend, yend, EMR_CHORD );
+}
+
+/***********************************************************************
+ *           EMFDRV_Ellipse
+ */
+BOOL
+EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom )
+{
+    EMRELLIPSE emr;
+    INT temp;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    TRACE("%d,%d - %d,%d\n", left, top, right, bottom);
+
+    if(left == right || top == bottom) return FALSE;
+
+    if(left > right) {temp = left; left = right; right = temp;}
+    if(top > bottom) {temp = top; top = bottom; bottom = temp;}
+
+    if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
+        right--;
+	bottom--;
+    }
+
+    emr.emr.iType     = EMR_ELLIPSE;
+    emr.emr.nSize     = sizeof(emr);
+    emr.rclBox.left   = left;
+    emr.rclBox.top    = top;
+    emr.rclBox.right  = right;
+    emr.rclBox.bottom = bottom;
+
+    EMFDRV_UpdateBBox( dev, &emr.rclBox );
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+/***********************************************************************
+ *           EMFDRV_Rectangle
+ */
+BOOL
+EMFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom)
+{
+    EMRRECTANGLE emr;
+    INT temp;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    TRACE("%d,%d - %d,%d\n", left, top, right, bottom);
+
+    if(left == right || top == bottom) return FALSE;
+
+    if(left > right) {temp = left; left = right; right = temp;}
+    if(top > bottom) {temp = top; top = bottom; bottom = temp;}
+
+    if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
+        right--;
+	bottom--;
+    }
+
+    emr.emr.iType     = EMR_RECTANGLE;
+    emr.emr.nSize     = sizeof(emr);
+    emr.rclBox.left   = left;
+    emr.rclBox.top    = top;
+    emr.rclBox.right  = right;
+    emr.rclBox.bottom = bottom;
+
+    EMFDRV_UpdateBBox( dev, &emr.rclBox );
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+/***********************************************************************
+ *           EMFDRV_RoundRect
+ */
+BOOL
+EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right,
+		  INT bottom, INT ell_width, INT ell_height )
+{
+    EMRROUNDRECT emr;
+    INT temp;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    if(left == right || top == bottom) return FALSE;
+
+    if(left > right) {temp = left; left = right; right = temp;}
+    if(top > bottom) {temp = top; top = bottom; bottom = temp;}
+
+    if(GetGraphicsMode(physDev->hdc) == GM_COMPATIBLE) {
+        right--;
+	bottom--;
+    }
+
+    emr.emr.iType     = EMR_ROUNDRECT;
+    emr.emr.nSize     = sizeof(emr);
+    emr.rclBox.left   = left;
+    emr.rclBox.top    = top;
+    emr.rclBox.right  = right;
+    emr.rclBox.bottom = bottom;
+    emr.szlCorner.cx  = ell_width;
+    emr.szlCorner.cy  = ell_height;
+
+    EMFDRV_UpdateBBox( dev, &emr.rclBox );
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+/***********************************************************************
+ *           EMFDRV_SetPixel
+ */
+COLORREF
+EMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color )
+{
+    EMRSETPIXELV emr;
+
+    emr.emr.iType  = EMR_SETPIXELV;
+    emr.emr.nSize  = sizeof(emr);
+    emr.ptlPixel.x = x;
+    emr.ptlPixel.y = y;
+    emr.crColor = color;
+
+    if (EMFDRV_WriteRecord( dev, &emr.emr )) {
+        RECTL bounds;
+        bounds.left = bounds.right = x;
+        bounds.top = bounds.bottom = y;
+        EMFDRV_UpdateBBox( dev, &bounds );
+        return color;
+    }
+    return -1;
+}
+
+/**********************************************************************
+ *          EMFDRV_Polylinegon
+ *
+ * Helper for EMFDRV_Poly{line|gon}
+ */
+static BOOL
+EMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType )
+{
+    EMRPOLYLINE *emr;
+    DWORD size;
+    INT i;
+    BOOL ret;
+
+    size = sizeof(EMRPOLYLINE) + sizeof(POINTL) * (count - 1);
+
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+    emr->emr.iType = iType;
+    emr->emr.nSize = size;
+
+    emr->rclBounds.left = emr->rclBounds.right = pt[0].x;
+    emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y;
+
+    for(i = 1; i < count; i++) {
+        if(pt[i].x < emr->rclBounds.left)
+	    emr->rclBounds.left = pt[i].x;
+	else if(pt[i].x > emr->rclBounds.right)
+	    emr->rclBounds.right = pt[i].x;
+	if(pt[i].y < emr->rclBounds.top)
+	    emr->rclBounds.top = pt[i].y;
+	else if(pt[i].y > emr->rclBounds.bottom)
+	    emr->rclBounds.bottom = pt[i].y;
+    }
+
+    emr->cptl = count;
+    memcpy(emr->aptl, pt, count * sizeof(POINTL));
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          EMFDRV_Polylinegon16
+ *
+ * Helper for EMFDRV_Poly{line|gon}
+ *
+ *  This is not a legacy function!
+ *  We are using SHORT integers to save space.
+ */
+static BOOL
+EMFDRV_Polylinegon16( PHYSDEV dev, const POINT* pt, INT count, DWORD iType )
+{
+    EMRPOLYLINE16 *emr;
+    DWORD size;
+    INT i;
+    BOOL ret;
+
+    /* check whether all points fit in the SHORT int POINT structure */
+    for(i = 0; i < count; i++) {
+        if( ((pt[i].x+0x8000) & ~0xffff ) || 
+            ((pt[i].y+0x8000) & ~0xffff ) )
+            return FALSE;
+    }
+
+    size = sizeof(EMRPOLYLINE16) + sizeof(POINTS) * (count - 1);
+
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+    emr->emr.iType = iType;
+    emr->emr.nSize = size;
+
+    emr->rclBounds.left = emr->rclBounds.right = pt[0].x;
+    emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y;
+
+    for(i = 1; i < count; i++) {
+        if(pt[i].x < emr->rclBounds.left)
+	    emr->rclBounds.left = pt[i].x;
+	else if(pt[i].x > emr->rclBounds.right)
+	    emr->rclBounds.right = pt[i].x;
+	if(pt[i].y < emr->rclBounds.top)
+	    emr->rclBounds.top = pt[i].y;
+	else if(pt[i].y > emr->rclBounds.bottom)
+	    emr->rclBounds.bottom = pt[i].y;
+    }
+
+    emr->cpts = count;
+    for(i = 0; i < count; i++ ) {
+        emr->apts[i].x = pt[i].x;
+        emr->apts[i].y = pt[i].y;
+    }
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+
+
+/**********************************************************************
+ *          EMFDRV_Polyline
+ */
+BOOL
+EMFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count )
+{
+    if( EMFDRV_Polylinegon16( dev, pt, count, EMR_POLYLINE16 ) )
+        return TRUE;
+    return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYLINE );
+}
+
+/**********************************************************************
+ *          EMFDRV_Polygon
+ */
+BOOL
+EMFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count )
+{
+    if(count < 2) return FALSE;
+    return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYGON );
+}
+
+
+/**********************************************************************
+ *          EMFDRV_PolyPolylinegon
+ *
+ * Helper for EMFDRV_PolyPoly{line|gon}
+ */
+static BOOL
+EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys,
+			DWORD iType)
+{
+    EMRPOLYPOLYLINE *emr;
+    DWORD cptl = 0, poly, size, point;
+    RECTL bounds;
+    const POINT *pts;
+    BOOL ret;
+
+    bounds.left = bounds.right = pt[0].x;
+    bounds.top = bounds.bottom = pt[0].y;
+
+    pts = pt;
+    for(poly = 0; poly < polys; poly++) {
+        cptl += counts[poly];
+	for(point = 0; point < counts[poly]; point++) {
+	    if(bounds.left > pts->x) bounds.left = pts->x;
+	    else if(bounds.right < pts->x) bounds.right = pts->x;
+	    if(bounds.top > pts->y) bounds.top = pts->y;
+	    else if(bounds.bottom < pts->y) bounds.bottom = pts->y;
+	    pts++;
+	}
+    }
+
+    size = sizeof(EMRPOLYPOLYLINE) + (polys - 1) * sizeof(DWORD) +
+      (cptl - 1) * sizeof(POINTL);
+
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+
+    emr->emr.iType = iType;
+    emr->emr.nSize = size;
+    emr->rclBounds = bounds;
+    emr->nPolys = polys;
+    emr->cptl = cptl;
+    memcpy(emr->aPolyCounts, counts, polys * sizeof(DWORD));
+    memcpy(emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL));
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+
+/**********************************************************************
+ *          EMFDRV_PolyPolyline
+ */
+BOOL
+EMFDRV_PolyPolyline(PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polys)
+{
+    return EMFDRV_PolyPolylinegon( dev, pt, (INT *)counts, polys,
+				   EMR_POLYPOLYLINE );
+}
+
+/**********************************************************************
+ *          EMFDRV_PolyPolygon
+ */
+BOOL
+EMFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys )
+{
+    return EMFDRV_PolyPolylinegon( dev, pt, counts, polys, EMR_POLYPOLYGON );
+}
+
+
+/**********************************************************************
+ *          EMFDRV_ExtFloodFill
+ */
+BOOL
+EMFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType )
+{
+    EMREXTFLOODFILL emr;
+
+    emr.emr.iType = EMR_EXTFLOODFILL;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptlStart.x = x;
+    emr.ptlStart.y = y;
+    emr.crColor = color;
+    emr.iMode = fillType;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+
+/*********************************************************************
+ *          EMFDRV_FillRgn
+ */
+BOOL EMFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush )
+{
+    EMRFILLRGN *emr;
+    DWORD size, rgnsize, index;
+    BOOL ret;
+
+    index = EMFDRV_CreateBrushIndirect( dev, hbrush );
+    if(!index) return FALSE;
+
+    rgnsize = GetRegionData( hrgn, 0, NULL );
+    size = rgnsize + offsetof(EMRFILLRGN,RgnData);
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+
+    GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
+
+    emr->emr.iType = EMR_FILLRGN;
+    emr->emr.nSize = size;
+    emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
+    emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
+    emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
+    emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
+    emr->cbRgnData = rgnsize;
+    emr->ihBrush = index;
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+/*********************************************************************
+ *          EMFDRV_FrameRgn
+ */
+BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height )
+{
+    EMRFRAMERGN *emr;
+    DWORD size, rgnsize, index;
+    BOOL ret;
+
+    index = EMFDRV_CreateBrushIndirect( dev, hbrush );
+    if(!index) return FALSE;
+
+    rgnsize = GetRegionData( hrgn, 0, NULL );
+    size = rgnsize + offsetof(EMRFRAMERGN,RgnData);
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+
+    GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
+
+    emr->emr.iType = EMR_FRAMERGN;
+    emr->emr.nSize = size;
+    emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
+    emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
+    emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
+    emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
+    emr->cbRgnData = rgnsize;
+    emr->ihBrush = index;
+    emr->szlStroke.cx = width;
+    emr->szlStroke.cy = height;
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+
+/*********************************************************************
+ *          EMFDRV_PaintInvertRgn
+ *
+ * Helper for EMFDRV_{Paint|Invert}Rgn
+ */
+static BOOL EMFDRV_PaintInvertRgn( PHYSDEV dev, HRGN hrgn, DWORD iType )
+{
+    EMRINVERTRGN *emr;
+    DWORD size, rgnsize;
+    BOOL ret;
+
+
+    rgnsize = GetRegionData( hrgn, 0, NULL );
+    size = rgnsize + offsetof(EMRINVERTRGN,RgnData);
+    emr = HeapAlloc( GetProcessHeap(), 0, size );
+
+    GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData );
+
+    emr->emr.iType = iType;
+    emr->emr.nSize = size;
+    emr->rclBounds.left   = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left;
+    emr->rclBounds.top    = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top;
+    emr->rclBounds.right  = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1;
+    emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1;
+    emr->cbRgnData = rgnsize;
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &emr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, emr );
+    return ret;
+}
+
+/**********************************************************************
+ *          EMFDRV_PaintRgn
+ */
+BOOL
+EMFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn )
+{
+    return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_PAINTRGN );
+}
+
+/**********************************************************************
+ *          EMFDRV_InvertRgn
+ */
+BOOL
+EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn )
+{
+    return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_INVERTRGN );
+}
+
+/**********************************************************************
+ *          EMFDRV_SetBkColor
+ */
+COLORREF
+EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color )
+{
+    EMRSETBKCOLOR emr;
+
+    emr.emr.iType = EMR_SETBKCOLOR;
+    emr.emr.nSize = sizeof(emr);
+    emr.crColor = color;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
+}
+
+
+/**********************************************************************
+ *          EMFDRV_SetTextColor
+ */
+COLORREF
+EMFDRV_SetTextColor( PHYSDEV dev, COLORREF color )
+{
+    EMRSETTEXTCOLOR emr;
+
+    emr.emr.iType = EMR_SETTEXTCOLOR;
+    emr.emr.nSize = sizeof(emr);
+    emr.crColor = color;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID;
+}
+
+/**********************************************************************
+ *          EMFDRV_ExtTextOut
+ */
+BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags,
+			const RECT *lprect, LPCWSTR str, UINT count,
+			const INT *lpDx, INT breakExtra )
+{
+    EMREXTTEXTOUTW *pemr;
+    DWORD nSize;
+    BOOL ret;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
+    int textHeight = 0;
+    int textWidth = 0;
+    const UINT textAlign = GetTextAlign(physDev->hdc);
+
+    nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT);
+
+    TRACE("%s count %d nSize = %ld\n", debugstr_wn(str, count), count, nSize);
+    pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize);
+
+    pemr->emr.iType = EMR_EXTTEXTOUTW;
+    pemr->emr.nSize = nSize;
+
+    pemr->iGraphicsMode = GetGraphicsMode(physDev->hdc);
+    pemr->exScale = pemr->eyScale = 1.0; /* FIXME */
+
+    pemr->emrtext.ptlReference.x = x;
+    pemr->emrtext.ptlReference.y = y;
+    pemr->emrtext.nChars = count;
+    pemr->emrtext.offString = sizeof(*pemr);
+    memcpy((char*)pemr + pemr->emrtext.offString, str, count * sizeof(WCHAR));
+    pemr->emrtext.fOptions = flags;
+    if(!lprect) {
+        pemr->emrtext.rcl.left = pemr->emrtext.rcl.top = 0;
+        pemr->emrtext.rcl.right = pemr->emrtext.rcl.bottom = -1;
+    } else {
+        pemr->emrtext.rcl.left = lprect->left;
+        pemr->emrtext.rcl.top = lprect->top;
+        pemr->emrtext.rcl.right = lprect->right;
+        pemr->emrtext.rcl.bottom = lprect->bottom;
+    }
+
+    pemr->emrtext.offDx = pemr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR);
+    if(lpDx) {
+        UINT i;
+        SIZE strSize;
+        memcpy((char*)pemr + pemr->emrtext.offDx, lpDx, count * sizeof(INT));
+        for (i = 0; i < count; i++) {
+            textWidth += lpDx[i];
+        }
+        GetTextExtentPoint32W(physDev->hdc, str, count, &strSize);
+        textHeight = strSize.cy;
+    }
+    else {
+        UINT i;
+        INT *dx = (INT *)((char*)pemr + pemr->emrtext.offDx);
+        SIZE charSize;
+        for (i = 0; i < count; i++) {
+            GetTextExtentPoint32W(physDev->hdc, str + i, 1, &charSize);
+            dx[i] = charSize.cx;
+            textWidth += charSize.cx;
+            textHeight = max(textHeight, charSize.cy);
+        }
+    }
+
+    switch (textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER)) {
+    case TA_CENTER: {
+        pemr->rclBounds.left  = x - (textWidth / 2) - 1;
+        pemr->rclBounds.right = x + (textWidth / 2) + 1;
+        break;
+    }
+    case TA_RIGHT: {
+        pemr->rclBounds.left  = x - textWidth - 1;
+        pemr->rclBounds.right = x;
+        break;
+    }
+    default: { /* TA_LEFT */
+        pemr->rclBounds.left  = x;
+        pemr->rclBounds.right = x + textWidth + 1;
+    }
+    }
+
+    switch (textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE)) {
+    case TA_BASELINE: {
+        TEXTMETRICW tm;
+        GetTextMetricsW(physDev->hdc, &tm);
+        /* Play safe here... it's better to have a bounding box */
+        /* that is too big than too small. */
+        pemr->rclBounds.top    = y - textHeight - 1;
+        pemr->rclBounds.bottom = y + tm.tmDescent + 1;
+        break;
+    }
+    case TA_BOTTOM: {
+        pemr->rclBounds.top    = y - textHeight - 1;
+        pemr->rclBounds.bottom = y;
+        break;
+    }
+    default: { /* TA_TOP */
+        pemr->rclBounds.top    = y;
+        pemr->rclBounds.bottom = y + textHeight + 1;
+    }
+    }
+
+    ret = EMFDRV_WriteRecord( dev, &pemr->emr );
+    if(ret)
+        EMFDRV_UpdateBBox( dev, &pemr->rclBounds );
+    HeapFree( GetProcessHeap(), 0, pemr );
+    return ret;
+}
+
+/**********************************************************************
+ *          EMFDRV_SetArcDirection
+ */
+INT EMFDRV_SetArcDirection(PHYSDEV dev, INT arcDirection)
+{
+    EMRSETARCDIRECTION emr;
+
+    emr.emr.iType = EMR_SETARCDIRECTION;
+    emr.emr.nSize = sizeof(emr);
+    emr.iArcDirection = arcDirection;
+
+    EMFDRV_WriteRecord(dev, &emr.emr);
+
+    /* We don't know the old arc direction and we don't care... */ 
+    return 0;
+}
+
+/*********************/
+/* Mapping functions */
+/*********************/
+
+INT EMFDRV_SetMapMode( PHYSDEV dev, INT mode )
+{
+    EMRSETMAPMODE emr;
+    emr.emr.iType = EMR_SETMAPMODE;
+    emr.emr.nSize = sizeof(emr);
+    emr.iMode = mode;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetViewportExt( PHYSDEV dev, INT cx, INT cy )
+{
+    EMRSETVIEWPORTEXTEX emr;
+
+    emr.emr.iType = EMR_SETVIEWPORTEXTEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.szlExtent.cx = cx;
+    emr.szlExtent.cy = cy;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetWindowExt( PHYSDEV dev, INT cx, INT cy )
+{
+    EMRSETWINDOWEXTEX emr;
+
+    emr.emr.iType = EMR_SETWINDOWEXTEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.szlExtent.cx = cx;
+    emr.szlExtent.cy = cy;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetViewportOrg( PHYSDEV dev, INT x, INT y )
+{
+    EMRSETVIEWPORTORGEX emr;
+
+    emr.emr.iType = EMR_SETVIEWPORTORGEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptlOrigin.x = x;
+    emr.ptlOrigin.y = y;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_SetWindowOrg( PHYSDEV dev, INT x, INT y )
+{
+    EMRSETWINDOWORGEX emr;
+
+    emr.emr.iType = EMR_SETWINDOWORGEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptlOrigin.x = x;
+    emr.ptlOrigin.y = y;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_ScaleViewportExt( PHYSDEV dev, INT xNum, INT xDenom, INT yNum,
+			     INT yDenom )
+{
+    EMRSCALEVIEWPORTEXTEX emr;
+
+    emr.emr.iType = EMR_SCALEVIEWPORTEXTEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.xNum      = xNum;
+    emr.xDenom    = xDenom;
+    emr.yNum      = yNum;
+    emr.yDenom    = yDenom;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_ScaleWindowExt( PHYSDEV dev, INT xNum, INT xDenom, INT yNum,
+			   INT yDenom )
+{
+    EMRSCALEWINDOWEXTEX emr;
+
+    emr.emr.iType = EMR_SCALEWINDOWEXTEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.xNum      = xNum;
+    emr.xDenom    = xDenom;
+    emr.yNum      = yNum;
+    emr.yDenom    = yDenom;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_SetWorldTransform( PHYSDEV dev, const XFORM *xform)
+{
+    EMRSETWORLDTRANSFORM emr;
+
+    emr.emr.iType = EMR_SETWORLDTRANSFORM;
+    emr.emr.nSize = sizeof(emr);
+    emr.xform = *xform;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+BOOL EMFDRV_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, INT mode)
+{
+    EMRMODIFYWORLDTRANSFORM emr;
+
+    emr.emr.iType = EMR_MODIFYWORLDTRANSFORM;
+    emr.emr.nSize = sizeof(emr);
+    emr.xform = *xform;
+    emr.iMode = mode;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_OffsetViewportOrg( PHYSDEV dev, INT x, INT y )
+{
+    POINT pt;
+    EMRSETVIEWPORTORGEX emr;
+    EMFDRV_PDEVICE* physDev = (EMFDRV_PDEVICE*)dev;
+
+    GetViewportOrgEx(physDev->hdc, &pt);
+
+    emr.emr.iType = EMR_SETVIEWPORTORGEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptlOrigin.x = pt.x + x;
+    emr.ptlOrigin.y = pt.y + y;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+INT EMFDRV_OffsetWindowOrg( PHYSDEV dev, INT x, INT y )
+{
+    POINT pt;
+    EMRSETWINDOWORGEX emr;
+    EMFDRV_PDEVICE* physDev = (EMFDRV_PDEVICE*)dev;
+
+    GetWindowOrgEx(physDev->hdc, &pt);
+
+    emr.emr.iType = EMR_SETWINDOWORGEX;
+    emr.emr.nSize = sizeof(emr);
+    emr.ptlOrigin.x = pt.x + x;
+    emr.ptlOrigin.y = pt.y + y;
+
+    return EMFDRV_WriteRecord( dev, &emr.emr );
+}
+
+/**********************/
+/* Object functions */
+/**********************/
+
+
+/******************************************************************
+ *         EMFDRV_AddHandle
+ */
+static UINT EMFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+    UINT 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->emh->nHandles)
+        physDev->emh->nHandles++;
+
+    return index + 1; /* index 0 is reserved for the hmf, so we increment everything by 1 */
+}
+
+/******************************************************************
+ *         EMFDRV_FindObject
+ */
+static UINT EMFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
+    UINT index;
+
+    for(index = 0; index < physDev->handles_size; index++)
+        if(physDev->handles[index] == obj) break;
+
+    if(index == physDev->handles_size) return 0;
+
+    return index + 1;
+}
+
+
+/******************************************************************
+ *         EMFDRV_DeleteObject
+ */
+BOOL EMFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj )
+{
+    EMRDELETEOBJECT emr;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev;
+    UINT index;
+    BOOL ret = TRUE;
+
+    if(!(index = EMFDRV_FindObject(dev, obj))) return 0;
+
+    emr.emr.iType = EMR_DELETEOBJECT;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihObject = index;
+
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        ret = FALSE;
+
+    physDev->handles[index - 1] = 0;
+    physDev->cur_handles--;
+    return ret;
+}
+
+  
+/***********************************************************************
+ *           EMFDRV_SelectBitmap
+ */
+HBITMAP EMFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap )
+{
+    return 0;
+}
+
+
+/***********************************************************************
+ *           EMFDRV_CreateBrushIndirect
+ */
+DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush )
+{
+    DWORD index = 0;
+    LOGBRUSH logbrush;
+
+    if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0;
+
+    switch (logbrush.lbStyle) {
+    case BS_SOLID:
+    case BS_HATCHED:
+    case BS_NULL:
+      {
+	EMRCREATEBRUSHINDIRECT emr;
+	emr.emr.iType = EMR_CREATEBRUSHINDIRECT;
+	emr.emr.nSize = sizeof(emr);
+	emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush );
+	emr.lb = logbrush;
+
+	if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+	    index = 0;
+      }
+      break;
+    case BS_DIBPATTERN:
+      {
+	EMRCREATEDIBPATTERNBRUSHPT *emr;
+	DWORD bmSize, biSize, size;
+	BITMAPINFO *info = GlobalLock16(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(EMRCREATEDIBPATTERNBRUSHPT) + biSize + bmSize;
+	emr = HeapAlloc( GetProcessHeap(), 0, size );
+	if(!emr) break;
+	emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT;
+	emr->emr.nSize = size;
+	emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush );
+	emr->iUsage = LOWORD(logbrush.lbColor);
+	emr->offBmi = sizeof(EMRCREATEDIBPATTERNBRUSHPT);
+	emr->cbBmi = biSize;
+	emr->offBits = sizeof(EMRCREATEDIBPATTERNBRUSHPT) + biSize;
+	emr->cbBits = bmSize;
+	memcpy((char *)emr + sizeof(EMRCREATEDIBPATTERNBRUSHPT), info,
+	       biSize + bmSize );
+
+	if(!EMFDRV_WriteRecord( dev, &emr->emr ))
+	    index = 0;
+	HeapFree( GetProcessHeap(), 0, emr );
+	GlobalUnlock16(logbrush.lbHatch);
+      }
+      break;
+
+    case BS_PATTERN:
+        FIXME("Unsupported style %x\n",
+	      logbrush.lbStyle);
+        break;
+    default:
+        FIXME("Unknown style %x\n", logbrush.lbStyle);
+	break;
+    }
+    return index;
+}
+
+
+/***********************************************************************
+ *           EMFDRV_SelectBrush
+ */
+HBRUSH EMFDRV_SelectBrush(PHYSDEV dev, HBRUSH hBrush )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev;
+    EMRSELECTOBJECT emr;
+    DWORD index;
+    int i;
+
+    /* If the object is a stock brush object, do not need to create it.
+     * See definitions in  wingdi.h for range of stock brushes.
+     * We do however have to handle setting the higher order bit to
+     * designate that this is a stock object.
+     */
+    for (i = WHITE_BRUSH; i <= NULL_BRUSH; i++)
+    {
+        if (hBrush == GetStockObject(i))
+        {
+            index = i | 0x80000000;
+            goto found;
+        }
+    }
+    if((index = EMFDRV_FindObject(dev, hBrush)) != 0)
+        goto found;
+
+    if (!(index = EMFDRV_CreateBrushIndirect(dev, hBrush ))) return 0;
+    GDI_hdc_using_object(hBrush, physDev->hdc);
+
+ found:
+    emr.emr.iType = EMR_SELECTOBJECT;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihObject = index;
+    return EMFDRV_WriteRecord( dev, &emr.emr ) ? hBrush : 0;
+}
+
+
+/******************************************************************
+ *         EMFDRV_CreateFontIndirect
+ */
+static BOOL EMFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont )
+{
+    DWORD index = 0;
+    EMREXTCREATEFONTINDIRECTW emr;
+    int i;
+
+    if (!GetObjectW( hFont, sizeof(emr.elfw.elfLogFont), &emr.elfw.elfLogFont )) return 0;
+
+    emr.emr.iType = EMR_EXTCREATEFONTINDIRECTW;
+    emr.emr.nSize = (sizeof(emr) + 3) / 4 * 4;
+    emr.ihFont = index = EMFDRV_AddHandle( dev, hFont );
+    emr.elfw.elfFullName[0] = '\0';
+    emr.elfw.elfStyle[0]    = '\0';
+    emr.elfw.elfVersion     = 0;
+    emr.elfw.elfStyleSize   = 0;
+    emr.elfw.elfMatch       = 0;
+    emr.elfw.elfReserved    = 0;
+    for(i = 0; i < ELF_VENDOR_SIZE; i++)
+        emr.elfw.elfVendorId[i] = 0;
+    emr.elfw.elfCulture                 = PAN_CULTURE_LATIN;
+    emr.elfw.elfPanose.bFamilyType      = PAN_NO_FIT;
+    emr.elfw.elfPanose.bSerifStyle      = PAN_NO_FIT;
+    emr.elfw.elfPanose.bWeight          = PAN_NO_FIT;
+    emr.elfw.elfPanose.bProportion      = PAN_NO_FIT;
+    emr.elfw.elfPanose.bContrast        = PAN_NO_FIT;
+    emr.elfw.elfPanose.bStrokeVariation = PAN_NO_FIT;
+    emr.elfw.elfPanose.bArmStyle        = PAN_NO_FIT;
+    emr.elfw.elfPanose.bLetterform      = PAN_NO_FIT;
+    emr.elfw.elfPanose.bMidline         = PAN_NO_FIT;
+    emr.elfw.elfPanose.bXHeight         = PAN_NO_FIT;
+
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        index = 0;
+    return index;
+}
+
+
+/***********************************************************************
+ *           EMFDRV_SelectFont
+ */
+HFONT EMFDRV_SelectFont( PHYSDEV dev, HFONT hFont, HANDLE gdiFont )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev;
+    EMRSELECTOBJECT emr;
+    DWORD index;
+    int i;
+
+    /* If the object is a stock font object, do not need to create it.
+     * See definitions in  wingdi.h for range of stock fonts.
+     * We do however have to handle setting the higher order bit to
+     * designate that this is a stock object.
+     */
+
+    for (i = OEM_FIXED_FONT; i <= DEFAULT_GUI_FONT; i++)
+    {
+        if (i != DEFAULT_PALETTE && hFont == GetStockObject(i))
+        {
+            index = i | 0x80000000;
+            goto found;
+        }
+    }
+
+    if((index = EMFDRV_FindObject(dev, hFont)) != 0)
+        goto found;
+
+    if (!(index = EMFDRV_CreateFontIndirect(dev, hFont ))) return HGDI_ERROR;
+    GDI_hdc_using_object(hFont, physDev->hdc);
+
+ found:
+    emr.emr.iType = EMR_SELECTOBJECT;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihObject = index;
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        return HGDI_ERROR;
+    return 0;
+}
+
+
+
+/******************************************************************
+ *         EMFDRV_CreatePenIndirect
+ */
+static HPEN EMFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen )
+{
+    EMRCREATEPEN emr;
+    DWORD index = 0;
+
+    if (!GetObjectA( hPen, sizeof(emr.lopn), &emr.lopn )) return 0;
+
+    emr.emr.iType = EMR_CREATEPEN;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihPen = index = EMFDRV_AddHandle( dev, hPen );
+
+    if(!EMFDRV_WriteRecord( dev, &emr.emr ))
+        index = 0;
+    return (HPEN)index;
+}
+
+/******************************************************************
+ *         EMFDRV_SelectPen
+ */
+HPEN EMFDRV_SelectPen(PHYSDEV dev, HPEN hPen )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev;
+    EMRSELECTOBJECT emr;
+    DWORD index;
+    int i;
+
+    /* If the object is a stock pen object, do not need to create it.
+     * See definitions in  wingdi.h for range of stock pens.
+     * We do however have to handle setting the higher order bit to
+     * designate that this is a stock object.
+     */
+
+    for (i = WHITE_PEN; i <= NULL_PEN; i++)
+    {
+        if (hPen == GetStockObject(i))
+        {
+            index = i | 0x80000000;
+            goto found;
+        }
+    }
+    if((index = EMFDRV_FindObject(dev, hPen)) != 0)
+        goto found;
+
+    if (!(index = (DWORD)EMFDRV_CreatePenIndirect(dev, hPen ))) return 0;
+    GDI_hdc_using_object(hPen, physDev->hdc);
+
+ found:
+    emr.emr.iType = EMR_SELECTOBJECT;
+    emr.emr.nSize = sizeof(emr);
+    emr.ihObject = index;
+    return EMFDRV_WriteRecord( dev, &emr.emr ) ? hPen : 0;
+}
+
+
+/******************************************************************
+ *         EMFDRV_GdiComment
+ */
+BOOL EMFDRV_GdiComment(PHYSDEV dev, UINT bytes, CONST BYTE *buffer)
+{
+    EMRGDICOMMENT *emr;
+    UINT total, rounded_size;
+    BOOL ret;
+
+    rounded_size = (bytes+3) & ~3;
+    total = offsetof(EMRGDICOMMENT,Data) + rounded_size;
+
+    emr = HeapAlloc(GetProcessHeap(), 0, total);
+    emr->emr.iType = EMR_GDICOMMENT;
+    emr->emr.nSize = total;
+    emr->cbData = bytes;
+    memset(&emr->Data[bytes], 0, rounded_size - bytes);
+    memcpy(&emr->Data[0], buffer, bytes);
+
+    ret = EMFDRV_WriteRecord( dev, &emr->emr );
+
+    HeapFree(GetProcessHeap(), 0, emr);
+
+    return ret;
+}
+
+/****************************/
+/* Initialisation functions */
+/****************************/
+
+static const DC_FUNCTIONS EMFDRV_Funcs =
+{
+    NULL,                            /* pAbortDoc */
+    EMFDRV_AbortPath,                /* pAbortPath */
+    NULL,                            /* pAngleArc */
+    EMFDRV_Arc,                      /* pArc */
+    NULL,                            /* pArcTo */
+    EMFDRV_BeginPath,                /* pBeginPath */
+    EMFDRV_BitBlt,                   /* pBitBlt */
+    NULL,                            /* pChoosePixelFormat */
+    EMFDRV_Chord,                    /* pChord */
+    EMFDRV_CloseFigure,              /* pCloseFigure */
+    NULL,                            /* pCreateBitmap */
+    NULL,                            /* pCreateDC */
+    NULL,                            /* pCreateDIBSection */
+    NULL,                            /* pDeleteBitmap */
+    NULL,                            /* pDeleteDC */
+    EMFDRV_DeleteObject,             /* pDeleteObject */
+    NULL,                            /* pDescribePixelFormat */
+    NULL,                            /* pDeviceCapabilities */
+    EMFDRV_Ellipse,                  /* pEllipse */
+    NULL,                            /* pEndDoc */
+    NULL,                            /* pEndPage */
+    EMFDRV_EndPath,                  /* pEndPath */
+    NULL,                            /* pEnumDeviceFonts */
+    EMFDRV_ExcludeClipRect,          /* pExcludeClipRect */
+    NULL,                            /* pExtDeviceMode */
+    NULL,                            /* pExtEscape */
+    EMFDRV_ExtFloodFill,             /* pExtFloodFill */
+    EMFDRV_ExtSelectClipRgn,         /* pExtSelectClipRgn */
+    EMFDRV_ExtTextOut,               /* pExtTextOut */
+    EMFDRV_FillPath,                 /* pFillPath */
+    EMFDRV_FillRgn,                  /* pFillRgn */
+    EMFDRV_FlattenPath,              /* pFlattenPath */
+    EMFDRV_FrameRgn,                 /* pFrameRgn */
+    EMFDRV_GdiComment,               /* pGdiComment */
+    NULL,                            /* pGetBitmapBits */
+    NULL,                            /* pGetCharWidth */
+    NULL,                            /* pGetDCOrgEx */
+    NULL,                            /* pGetDIBColorTable */
+    NULL,                            /* pGetDIBits */
+    EMFDRV_GetDeviceCaps,            /* pGetDeviceCaps */
+    NULL,                            /* pGetDeviceGammaRamp */
+    NULL,                            /* pGetNearestColor */
+    NULL,                            /* pGetPixel */
+    NULL,                            /* pGetPixelFormat */
+    NULL,                            /* pGetSystemPaletteEntries */
+    NULL,                            /* pGetTextExtentPoint */
+    NULL,                            /* pGetTextMetrics */
+    EMFDRV_IntersectClipRect,        /* pIntersectClipRect */
+    EMFDRV_InvertRgn,                /* pInvertRgn */
+    EMFDRV_LineTo,                   /* pLineTo */
+    EMFDRV_ModifyWorldTransform,     /* pModifyWorldTransform */
+    EMFDRV_MoveTo,                   /* pMoveTo */
+    EMFDRV_OffsetClipRgn,            /* pOffsetClipRgn */
+    EMFDRV_OffsetViewportOrg,        /* pOffsetViewportOrg */
+    EMFDRV_OffsetWindowOrg,          /* pOffsetWindowOrg */
+    EMFDRV_PaintRgn,                 /* pPaintRgn */
+    EMFDRV_PatBlt,                   /* pPatBlt */
+    EMFDRV_Pie,                      /* pPie */
+    NULL,                            /* pPolyBezier */
+    NULL,                            /* pPolyBezierTo */
+    NULL,                            /* pPolyDraw */
+    EMFDRV_PolyPolygon,              /* pPolyPolygon */
+    EMFDRV_PolyPolyline,             /* pPolyPolyline */
+    EMFDRV_Polygon,                  /* pPolygon */
+    EMFDRV_Polyline,                 /* pPolyline */
+    NULL,                            /* pPolylineTo */
+    NULL,                            /* pRealizeDefaultPalette */
+    NULL,                            /* pRealizePalette */
+    EMFDRV_Rectangle,                /* pRectangle */
+    NULL,                            /* pResetDC */
+    EMFDRV_RestoreDC,                /* pRestoreDC */
+    EMFDRV_RoundRect,                /* pRoundRect */
+    EMFDRV_SaveDC,                   /* pSaveDC */
+    EMFDRV_ScaleViewportExt,         /* pScaleViewportExt */
+    EMFDRV_ScaleWindowExt,           /* pScaleWindowExt */
+    EMFDRV_SelectBitmap,             /* pSelectBitmap */
+    EMFDRV_SelectBrush,              /* pSelectBrush */
+    EMFDRV_SelectClipPath,           /* pSelectClipPath */
+    EMFDRV_SelectFont,               /* pSelectFont */
+    NULL,                            /* pSelectPalette */
+    EMFDRV_SelectPen,                /* pSelectPen */
+    EMFDRV_SetArcDirection,          /* pSetArcDirection */
+    NULL,                            /* pSetBitmapBits */
+    EMFDRV_SetBkColor,               /* pSetBkColor */
+    EMFDRV_SetBkMode,                /* pSetBkMode */
+    NULL,                            /* pSetDCBrushColor */
+    NULL,                            /* pSetDCOrg */
+    NULL,                            /* pSetDCPenColor */
+    NULL,                            /* pSetDIBColorTable */
+    NULL,                            /* pSetDIBits */
+    EMFDRV_SetDIBitsToDevice,        /* pSetDIBitsToDevice */
+    NULL,                            /* pSetDeviceClipping */
+    NULL,                            /* pSetDeviceGammaRamp */
+    EMFDRV_SetMapMode,               /* pSetMapMode */
+    EMFDRV_SetMapperFlags,           /* pSetMapperFlags */
+    NULL,                            /* pSetPixel */
+    NULL,                            /* pSetPixelFormat */
+    EMFDRV_SetPolyFillMode,          /* pSetPolyFillMode */
+    EMFDRV_SetROP2,                  /* pSetROP2 */
+    NULL,                            /* pSetRelAbs */
+    EMFDRV_SetStretchBltMode,        /* pSetStretchBltMode */
+    EMFDRV_SetTextAlign,             /* pSetTextAlign */
+    NULL,                            /* pSetTextCharacterExtra */
+    EMFDRV_SetTextColor,             /* pSetTextColor */
+    EMFDRV_SetTextJustification,     /* pSetTextJustification */ 
+    EMFDRV_SetViewportExt,           /* pSetViewportExt */
+    EMFDRV_SetViewportOrg,           /* pSetViewportOrg */
+    EMFDRV_SetWindowExt,             /* pSetWindowExt */
+    EMFDRV_SetWindowOrg,             /* pSetWindowOrg */
+    EMFDRV_SetWorldTransform,        /* pSetWorldTransform */
+    NULL,                            /* pStartDoc */
+    NULL,                            /* pStartPage */
+    EMFDRV_StretchBlt,               /* pStretchBlt */
+    EMFDRV_StretchDIBits,            /* pStretchDIBits */
+    EMFDRV_StrokeAndFillPath,        /* pStrokeAndFillPath */
+    EMFDRV_StrokePath,               /* pStrokePath */
+    NULL,                            /* pSwapBuffers */
+    EMFDRV_WidenPath                 /* pWidenPath */
+};
+
+
+/**********************************************************************
+ *	     EMFDRV_DeleteDC
+ */
+static BOOL EMFDRV_DeleteDC( PHYSDEV dev )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+    DC *dc = physDev->dc;
+    UINT index;
+
+    if (physDev->emh) HeapFree( GetProcessHeap(), 0, physDev->emh );
+    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;
+}
+
+
+/******************************************************************
+ *         EMFDRV_WriteRecord
+ *
+ * Warning: this function can change the pointer to the metafile header.
+ */
+BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr )
+{
+    DWORD len;
+    ENHMETAHEADER *emh;
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+
+    physDev->emh->nBytes += emr->nSize;
+    physDev->emh->nRecords++;
+
+    if(physDev->hFile) {
+        TRACE("Writing record to disk\n");
+	if (!WriteFile(physDev->hFile, (char *)emr, emr->nSize, NULL, NULL))
+	    return FALSE;
+    } else {
+        DWORD nEmfSize = HeapSize(GetProcessHeap(), 0, physDev->emh);
+        len = physDev->emh->nBytes;
+        if (len > nEmfSize) {
+            nEmfSize += (nEmfSize / 2) + emr->nSize;
+            emh = HeapReAlloc(GetProcessHeap(), 0, physDev->emh, nEmfSize);
+            if (!emh) return FALSE;
+            physDev->emh = emh;
+        }
+        memcpy((CHAR *)physDev->emh + physDev->emh->nBytes - emr->nSize, emr,
+               emr->nSize);
+    }
+    return TRUE;
+}
+
+
+/******************************************************************
+ *         EMFDRV_UpdateBBox
+ */
+void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect )
+{
+    EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev;
+    RECTL *bounds = &physDev->emh->rclBounds;
+    RECTL vportRect = *rect;
+
+    LPtoDP(physDev->hdc, (LPPOINT)&vportRect, 2);
+
+    if(bounds->left > bounds->right) {/* first rect */
+	*bounds = vportRect;
+	return;
+    }
+    bounds->left   = min(bounds->left,   vportRect.left);
+    bounds->top    = min(bounds->top,    vportRect.top);
+    bounds->right  = max(bounds->right,  vportRect.right);
+    bounds->bottom = max(bounds->bottom, vportRect.bottom);
+    return;
+}
+
+/**********************************************************************
+ *          CreateEnhMetaFileA   (GDI32.@)
+ */
+HDC WINAPI CreateEnhMetaFileA(
+    HDC hdc,           /* [in] optional reference DC */
+    LPCSTR filename,   /* [in] optional filename for disk metafiles */
+    const RECT *rect,  /* [in] optional bounding rectangle */
+    LPCSTR description /* [in] optional description */
+    )
+{
+    LPWSTR filenameW = NULL;
+    LPWSTR descriptionW = NULL;
+    HDC hReturnDC;
+    DWORD len1, len2, total;
+
+    if(filename)
+    {
+        total = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 );
+        filenameW = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) );
+        MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, total );
+    }
+    if(description) {
+        len1 = strlen(description);
+	len2 = strlen(description + len1 + 1);
+        total = MultiByteToWideChar( CP_ACP, 0, description, len1 + len2 + 3, NULL, 0 );
+	descriptionW = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) );
+        MultiByteToWideChar( CP_ACP, 0, description, len1 + len2 + 3, descriptionW, total );
+    }
+
+    hReturnDC = CreateEnhMetaFileW(hdc, filenameW, rect, descriptionW);
+
+    if(filenameW)
+        HeapFree( GetProcessHeap(), 0, filenameW );
+    if(descriptionW)
+        HeapFree( GetProcessHeap(), 0, descriptionW );
+
+    return hReturnDC;
+}
+
+/**********************************************************************
+ *          CreateEnhMetaFileW   (GDI32.@)
+ */
+HDC WINAPI CreateEnhMetaFileW(
+    HDC           hdc,        /* [in] optional reference DC */
+    LPCWSTR       filename,   /* [in] optional filename for disk metafiles */
+    const RECT*   rect,       /* [in] optional bounding rectangle */
+    LPCWSTR       description /* [in] optional description */
+    )
+{
+    static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0};
+    HDC ret;
+    DC *dc;
+    HDC hRefDC = hdc ? hdc : CreateDCW(displayW,NULL,NULL,NULL); 
+        /* If no ref, use current display */
+    EMFDRV_PDEVICE *physDev;
+    HANDLE hFile;
+    DWORD size = 0, length = 0;
+
+    TRACE("%s\n", debugstr_w(filename) );
+
+    if (!(dc = DC_AllocDC( &EMFDRV_Funcs, ENHMETAFILE_DC_MAGIC ))) return 0;
+
+    physDev = (EMFDRV_PDEVICE *)HeapAlloc(GetProcessHeap(),0,sizeof(*physDev));
+    if (!physDev) {
+        GDI_FreeObject( dc->hSelf, dc );
+        return 0;
+    }
+    dc->physDev = (PHYSDEV)physDev;
+    physDev->hdc = dc->hSelf;
+    physDev->dc = dc;
+
+    if(description) { /* App name\0Title\0\0 */
+        length = lstrlenW(description);
+	length += lstrlenW(description + length + 1);
+	length += 3;
+	length *= 2;
+    }
+    size = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4;
+
+    if (!(physDev->emh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size))) {
+        HeapFree( GetProcessHeap(), 0, physDev );
+        GDI_FreeObject( dc->hSelf, dc );
+        return 0;
+    }
+
+    physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0]));
+    physDev->handles_size = HANDLE_LIST_INC;
+    physDev->cur_handles = 1;
+    physDev->hFile = 0;
+
+    physDev->horzres = GetDeviceCaps(hRefDC, HORZRES);
+    physDev->vertres = GetDeviceCaps(hRefDC, VERTRES);
+    physDev->logpixelsx = GetDeviceCaps(hRefDC, LOGPIXELSX);
+    physDev->logpixelsy = GetDeviceCaps(hRefDC, LOGPIXELSY);
+    physDev->horzsize = GetDeviceCaps(hRefDC, HORZSIZE);
+    physDev->vertsize = GetDeviceCaps(hRefDC, VERTSIZE);
+    physDev->bitspixel = GetDeviceCaps(hRefDC, BITSPIXEL);
+    physDev->textcaps = GetDeviceCaps(hRefDC, TEXTCAPS);
+    physDev->rastercaps = GetDeviceCaps(hRefDC, RASTERCAPS);
+    physDev->technology = GetDeviceCaps(hRefDC, TECHNOLOGY);
+    physDev->planes = GetDeviceCaps(hRefDC, PLANES);
+
+    physDev->emh->iType = EMR_HEADER;
+    physDev->emh->nSize = size;
+
+    physDev->emh->rclBounds.left = physDev->emh->rclBounds.top = 0;
+    physDev->emh->rclBounds.right = physDev->emh->rclBounds.bottom = -1;
+
+    if(rect) {
+        physDev->emh->rclFrame.left   = rect->left;
+	physDev->emh->rclFrame.top    = rect->top;
+	physDev->emh->rclFrame.right  = rect->right;
+	physDev->emh->rclFrame.bottom = rect->bottom;
+    } else {  /* Set this to {0,0 - -1,-1} and update it at the end */
+        physDev->emh->rclFrame.left = physDev->emh->rclFrame.top = 0;
+	physDev->emh->rclFrame.right = physDev->emh->rclFrame.bottom = -1;
+    }
+
+    physDev->emh->dSignature = ENHMETA_SIGNATURE;
+    physDev->emh->nVersion = 0x10000;
+    physDev->emh->nBytes = physDev->emh->nSize;
+    physDev->emh->nRecords = 1;
+    physDev->emh->nHandles = 1;
+
+    physDev->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */
+    physDev->emh->nDescription = length / 2;
+
+    physDev->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0;
+
+    physDev->emh->nPalEntries = 0; /* I guess this should start at 0 */
+
+    /* Size in pixels */
+    physDev->emh->szlDevice.cx = physDev->horzres;
+    physDev->emh->szlDevice.cy = physDev->vertres;
+
+    /* Size in millimeters */
+    physDev->emh->szlMillimeters.cx = physDev->horzsize;
+    physDev->emh->szlMillimeters.cy = physDev->vertsize;
+
+    /* Size in micrometers */
+    physDev->emh->szlMicrometers.cx = physDev->horzsize * 1000;
+    physDev->emh->szlMicrometers.cy = physDev->vertsize * 1000;
+
+    memcpy((char *)physDev->emh + sizeof(ENHMETAHEADER), description, length);
+
+    if (filename)  /* disk based metafile */
+    {
+        if ((hFile = CreateFileW(filename, GENERIC_WRITE | GENERIC_READ, 0,
+				 NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) {
+            EMFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+        if (!WriteFile( hFile, (LPSTR)physDev->emh, size, NULL, NULL )) {
+            EMFDRV_DeleteDC( dc->physDev );
+            return 0;
+	}
+	physDev->hFile = hFile;
+    }
+
+    TRACE("returning %p\n", dc->hSelf);
+    ret = dc->hSelf;
+    GDI_ReleaseObj( dc->hSelf );
+
+    if( !hdc )
+      DeleteDC( hRefDC );
+
+    return ret;
+}
+
+/******************************************************************
+ *             CloseEnhMetaFile (GDI32.@)
+ */
+HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */
+{
+    HENHMETAFILE hmf;
+    EMFDRV_PDEVICE *physDev;
+    DC *dc;
+    EMREOF emr;
+    HANDLE hMapping = 0;
+
+    TRACE("(%p)\n", hdc );
+
+    if (!(dc = (DC *) GDI_GetObjPtr( hdc, ENHMETAFILE_DC_MAGIC ))) return 0;
+    physDev = (EMFDRV_PDEVICE *)dc->physDev;
+
+    emr.emr.iType = EMR_EOF;
+    emr.emr.nSize = sizeof(emr);
+    emr.nPalEntries = 0;
+    emr.offPalEntries = 0;
+    emr.nSizeLast = emr.emr.nSize;
+    EMFDRV_WriteRecord( dc->physDev, &emr.emr );
+
+    /* Update rclFrame if not initialized in CreateEnhMetaFile */
+    if(physDev->emh->rclFrame.left > physDev->emh->rclFrame.right) {
+        physDev->emh->rclFrame.left = physDev->emh->rclBounds.left *
+	  physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx;
+        physDev->emh->rclFrame.top = physDev->emh->rclBounds.top *
+	  physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy;
+        physDev->emh->rclFrame.right = physDev->emh->rclBounds.right *
+	  physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx;
+        physDev->emh->rclFrame.bottom = physDev->emh->rclBounds.bottom *
+	  physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy;
+    }
+
+    if (physDev->hFile)  /* disk based metafile */
+    {
+        if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0)
+        {
+            CloseHandle( physDev->hFile );
+            EMFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+
+        if (!WriteFile(physDev->hFile, (LPSTR)physDev->emh,
+                       sizeof(*physDev->emh), NULL, NULL))
+        {
+            CloseHandle( physDev->hFile );
+            EMFDRV_DeleteDC( dc->physDev );
+            return 0;
+        }
+	HeapFree( GetProcessHeap(), 0, physDev->emh );
+        hMapping = CreateFileMappingA(physDev->hFile, NULL, PAGE_READONLY, 0,
+				      0, NULL);
+	TRACE("hMapping = %p\n", hMapping );
+	physDev->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
+	TRACE("view = %p\n", physDev->emh );
+        CloseHandle( hMapping );
+        CloseHandle( physDev->hFile );
+    }
+
+    hmf = EMF_Create_HENHMETAFILE( physDev->emh, (physDev->hFile != 0) );
+    physDev->emh = NULL;  /* So it won't be deleted */
+    EMFDRV_DeleteDC( dc->physDev );
+    return hmf;
+}


-- 
Dimi.




More information about the wine-patches mailing list