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