mirror of
https://github.com/reactos/reactos.git
synced 2024-11-07 07:00:19 +00:00
333b8f19a4
Patch by : Akihiro Sagawa : Implement GetCharWidthInfo().
1128587fd2
1311 lines
52 KiB
C
1311 lines
52 KiB
C
|
|
#include <precomp.h>
|
|
#include "gdi_private.h"
|
|
#undef SetWorldTransform
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
WINEDC *get_nulldrv_dc( PHYSDEV dev );
|
|
|
|
BOOL nulldrv_BeginPath( PHYSDEV dev );
|
|
BOOL nulldrv_EndPath( PHYSDEV dev );
|
|
BOOL nulldrv_AbortPath( PHYSDEV dev );
|
|
BOOL nulldrv_CloseFigure( PHYSDEV dev );
|
|
BOOL nulldrv_SelectClipPath( PHYSDEV dev, INT mode );
|
|
BOOL nulldrv_FillPath( PHYSDEV dev );
|
|
BOOL nulldrv_StrokeAndFillPath( PHYSDEV dev );
|
|
BOOL nulldrv_StrokePath( PHYSDEV dev );
|
|
BOOL nulldrv_FlattenPath( PHYSDEV dev );
|
|
BOOL nulldrv_WidenPath( PHYSDEV dev );
|
|
|
|
static INT i = 0;
|
|
|
|
static
|
|
INT_PTR
|
|
NULL_Unused()
|
|
{
|
|
DPRINT1("NULL_Unused %d\n",i);
|
|
// __debugbreak();
|
|
return 0;
|
|
}
|
|
|
|
static INT NULL_SaveDC(PHYSDEV dev) { return 1; }
|
|
static BOOL NULL_RestoreDC(PHYSDEV dev, INT level) { return TRUE; }
|
|
static INT NULL_SetMapMode(PHYSDEV dev, INT iMode) { return 1; }
|
|
static HFONT NULL_SelectFont(PHYSDEV dev, HFONT hFont, UINT *aa_flags) { return NULL; }
|
|
static BOOL NULL_SetWindowExtEx(PHYSDEV dev, INT cx, INT cy, SIZE *size) { return TRUE; }
|
|
static BOOL NULL_SetViewportExtEx(PHYSDEV dev, INT cx, INT cy, SIZE *size) { return TRUE; }
|
|
static BOOL NULL_SetWindowOrgEx(PHYSDEV dev, INT x, INT y, POINT *pt) { return TRUE; }
|
|
static BOOL NULL_SetViewportOrgEx(PHYSDEV dev, INT x, INT y, POINT *pt) { return TRUE; }
|
|
static INT NULL_ExtSelectClipRgn(PHYSDEV dev, HRGN hrgn, INT iMode) { return 1; }
|
|
static INT NULL_IntersectClipRect(PHYSDEV dev, INT left, INT top, INT right, INT bottom) { return 1; }
|
|
static INT NULL_OffsetClipRgn(PHYSDEV dev, INT x, INT y) { return SIMPLEREGION; }
|
|
static INT NULL_ExcludeClipRect(PHYSDEV dev, INT left, INT top, INT right, INT bottom) { return 1; }
|
|
static BOOL NULL_ExtTextOutW(PHYSDEV dev, INT x, INT y, UINT fuOptions, const RECT *lprc, LPCWSTR lpString, UINT cwc, const INT *lpDx) { return TRUE; }
|
|
static BOOL NULL_ModifyWorldTransform( PHYSDEV dev, const XFORM* xform, DWORD mode ) { return TRUE; }
|
|
static BOOL NULL_SetWorldTransform( PHYSDEV dev, const XFORM* xform ) { return TRUE; }
|
|
static BOOL NULL_PolyPolyline(PHYSDEV dev, const POINT *pt, const DWORD *lpt, DWORD cw) { return TRUE; }
|
|
|
|
static const struct gdi_dc_funcs DummyPhysDevFuncs =
|
|
{
|
|
(PVOID)NULL_Unused, //INT (*pAbortDoc)(PHYSDEV);
|
|
nulldrv_AbortPath, //BOOL (*pAbortPath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pAlphaBlend)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,BLENDFUNCTION);
|
|
(PVOID)NULL_Unused, //BOOL (*pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT);
|
|
(PVOID)NULL_Unused, //BOOL (*pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
|
|
nulldrv_BeginPath, //BOOL (*pBeginPath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //DWORD (*pBlendImage)(PHYSDEV,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,BLENDFUNCTION);
|
|
(PVOID)NULL_Unused, //BOOL (*pChord)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
|
|
nulldrv_CloseFigure, //BOOL (*pCloseFigure)(PHYSDEV);
|
|
|
|
(PVOID)NULL_Unused, //BOOL (*pCreateCompatibleDC)(PHYSDEV,PHYSDEV*);
|
|
(PVOID)NULL_Unused, //BOOL (*pCreateDC)(PHYSDEV*,LPCWSTR,LPCWSTR,LPCWSTR,const DEVMODEW*);
|
|
(PVOID)NULL_Unused, //BOOL (*pDeleteDC)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pDeleteObject)(PHYSDEV,HGDIOBJ);
|
|
(PVOID)NULL_Unused, //DWORD (*pDeviceCapabilities)(LPSTR,LPCSTR,LPCSTR,WORD,LPSTR,LPDEVMODEA);
|
|
(PVOID)NULL_Unused, //BOOL (*pEllipse)(PHYSDEV,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //INT (*pEndDoc)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //INT (*pEndPage)(PHYSDEV);
|
|
nulldrv_EndPath, //BOOL (*pEndPath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pEnumFonts)(PHYSDEV,LPLOGFONTW,FONTENUMPROCW,LPARAM);
|
|
|
|
(PVOID)NULL_Unused, //INT (*pEnumICMProfiles)(PHYSDEV,ICMENUMPROCW,LPARAM);
|
|
NULL_ExcludeClipRect, //INT (*pExcludeClipRect)(PHYSDEV,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //INT (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD);
|
|
(PVOID)NULL_Unused, //INT (*pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID);
|
|
(PVOID)NULL_Unused, //BOOL (*pExtFloodFill)(PHYSDEV,INT,INT,COLORREF,UINT);
|
|
NULL_ExtSelectClipRgn, //INT (*pExtSelectClipRgn)(PHYSDEV,HRGN,INT);
|
|
NULL_ExtTextOutW, //BOOL (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
|
|
nulldrv_FillPath, //BOOL (*pFillPath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pFillRgn)(PHYSDEV,HRGN,HBRUSH);
|
|
nulldrv_FlattenPath, //BOOL (*pFlattenPath)(PHYSDEV);
|
|
|
|
(PVOID)NULL_Unused, //BOOL (*pFontIsLinked)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pFrameRgn)(PHYSDEV,HRGN,HBRUSH,INT,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pGdiComment)(PHYSDEV,UINT,const BYTE*);
|
|
(PVOID)NULL_Unused, //UINT (*pGetBoundsRect)(PHYSDEV,RECT*,UINT);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetCharABCWidths)(PHYSDEV,UINT,UINT,LPABC);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetCharABCWidthsI)(PHYSDEV,UINT,UINT,WORD*,LPABC);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetCharWidth)(PHYSDEV,UINT,UINT,LPINT);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetCharWidthInfo)(PHYSDEV,void*);
|
|
(PVOID)NULL_Unused, //INT (*pGetDeviceCaps)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetDeviceGammaRamp)(PHYSDEV,LPVOID);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetFontData)(PHYSDEV,DWORD,DWORD,LPVOID,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetFontRealizationInfo)(PHYSDEV,void*);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetFontUnicodeRanges)(PHYSDEV,LPGLYPHSET);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetGlyphIndices)(PHYSDEV,LPCWSTR,INT,LPWORD,DWORD);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetGlyphOutline)(PHYSDEV,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetICMProfile)(PHYSDEV,LPDWORD,LPWSTR);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetImage)(PHYSDEV,BITMAPINFO*,struct gdi_image_bits*,struct bitblt_coords*);
|
|
(PVOID)NULL_Unused, //DWORD (*pGetKerningPairs)(PHYSDEV,DWORD,LPKERNINGPAIR);
|
|
(PVOID)NULL_Unused, //COLORREF (*pGetNearestColor)(PHYSDEV,COLORREF);
|
|
(PVOID)NULL_Unused, //UINT (*pGetOutlineTextMetrics)(PHYSDEV,UINT,LPOUTLINETEXTMETRICW);
|
|
(PVOID)NULL_Unused, //COLORREF (*pGetPixel)(PHYSDEV,INT,INT);
|
|
(PVOID)NULL_Unused, //UINT (*pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY);
|
|
(PVOID)NULL_Unused, //UINT (*pGetTextCharsetInfo)(PHYSDEV,LPFONTSIGNATURE,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,LPINT);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetTextExtentExPointI)(PHYSDEV,const WORD*,INT,LPINT);
|
|
(PVOID)NULL_Unused, //INT (*pGetTextFace)(PHYSDEV,INT,LPWSTR);
|
|
(PVOID)NULL_Unused, //BOOL (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*);
|
|
(PVOID)NULL_Unused, //BOOL (*pGradientFill)(PHYSDEV,TRIVERTEX*,ULONG,void*,ULONG,ULONG);
|
|
NULL_IntersectClipRect, //INT (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pInvertRgn)(PHYSDEV,HRGN);
|
|
(PVOID)NULL_Unused, //BOOL (*pLineTo)(PHYSDEV,INT,INT);
|
|
NULL_ModifyWorldTransform, //BOOL (*pModifyWorldTransform)(PHYSDEV,const XFORM*,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pMoveTo)(PHYSDEV,INT,INT);
|
|
NULL_OffsetClipRgn, //INT (*pOffsetClipRgn)(PHYSDEV,INT,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pOffsetViewportOrgEx)(PHYSDEV,INT,INT,POINT*);
|
|
(PVOID)NULL_Unused, //BOOL (*pOffsetWindowOrgEx)(PHYSDEV,INT,INT,POINT*);
|
|
(PVOID)NULL_Unused, //BOOL (*pPaintRgn)(PHYSDEV,HRGN);
|
|
(PVOID)NULL_Unused, //BOOL (*pPatBlt)(PHYSDEV,struct bitblt_coords*,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pPie)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolyBezier)(PHYSDEV,const POINT*,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolyBezierTo)(PHYSDEV,const POINT*,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolyDraw)(PHYSDEV,const POINT*,const BYTE *,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolyPolygon)(PHYSDEV,const POINT*,const INT*,UINT);
|
|
NULL_PolyPolyline, //BOOL (*pPolyPolyline)(PHYSDEV,const POINT*,const DWORD*,DWORD);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolygon)(PHYSDEV,const POINT*,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolyline)(PHYSDEV,const POINT*,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pPolylineTo)(PHYSDEV,const POINT*,INT);
|
|
(PVOID)NULL_Unused, //DWORD (*pPutImage)(PHYSDEV,HRGN,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,DWORD);
|
|
(PVOID)NULL_Unused, //UINT (*pRealizeDefaultPalette)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //UINT (*pRealizePalette)(PHYSDEV,HPALETTE,BOOL);
|
|
(PVOID)NULL_Unused, //BOOL (*pRectangle)(PHYSDEV,INT,INT,INT,INT);
|
|
(PVOID)NULL_Unused, //HDC (*pResetDC)(PHYSDEV,const DEVMODEW*);
|
|
NULL_RestoreDC, //BOOL (*pRestoreDC)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //BOOL (*pRoundRect)(PHYSDEV,INT,INT,INT,INT,INT,INT);
|
|
NULL_SaveDC, //INT (*pSaveDC)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pScaleViewportExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
|
|
(PVOID)NULL_Unused, //BOOL (*pScaleWindowExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*);
|
|
(PVOID)NULL_Unused, //HBITMAP (*pSelectBitmap)(PHYSDEV,HBITMAP);
|
|
(PVOID)NULL_Unused, //HBRUSH (*pSelectBrush)(PHYSDEV,HBRUSH,const struct brush_pattern*);
|
|
nulldrv_SelectClipPath, //BOOL (*pSelectClipPath)(PHYSDEV,INT);
|
|
NULL_SelectFont, //HFONT (*pSelectFont)(PHYSDEV,HFONT,UINT*);
|
|
(PVOID)NULL_Unused, //HPALETTE (*pSelectPalette)(PHYSDEV,HPALETTE,BOOL);
|
|
(PVOID)NULL_Unused, //HPEN (*pSelectPen)(PHYSDEV,HPEN,const struct brush_pattern*);
|
|
(PVOID)NULL_Unused, //INT (*pSetArcDirection)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //COLORREF (*pSetBkColor)(PHYSDEV,COLORREF);
|
|
(PVOID)NULL_Unused, //INT (*pSetBkMode)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //UINT (*pSetBoundsRect)(PHYSDEV,RECT*,UINT);
|
|
(PVOID)NULL_Unused, //COLORREF (*pSetDCBrushColor)(PHYSDEV, COLORREF);
|
|
(PVOID)NULL_Unused, //COLORREF (*pSetDCPenColor)(PHYSDEV, COLORREF);
|
|
(PVOID)NULL_Unused, //INT (*pSetDIBitsToDevice)(PHYSDEV,INT,INT,DWORD,DWORD,INT,INT,UINT,UINT,LPCVOID,BITMAPINFO*,UINT);
|
|
(PVOID)NULL_Unused, //VOID (*pSetDeviceClipping)(PHYSDEV,HRGN);
|
|
(PVOID)NULL_Unused, //BOOL (*pSetDeviceGammaRamp)(PHYSDEV,LPVOID);
|
|
(PVOID)NULL_Unused, //DWORD (*pSetLayout)(PHYSDEV,DWORD);
|
|
NULL_SetMapMode, //INT (*pSetMapMode)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //DWORD (*pSetMapperFlags)(PHYSDEV,DWORD);
|
|
(PVOID)NULL_Unused, //COLORREF (*pSetPixel)(PHYSDEV,INT,INT,COLORREF);
|
|
(PVOID)NULL_Unused, //INT (*pSetPolyFillMode)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //INT (*pSetROP2)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //INT (*pSetRelAbs)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //INT (*pSetStretchBltMode)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //UINT (*pSetTextAlign)(PHYSDEV,UINT);
|
|
(PVOID)NULL_Unused, //INT (*pSetTextCharacterExtra)(PHYSDEV,INT);
|
|
(PVOID)NULL_Unused, //COLORREF (*pSetTextColor)(PHYSDEV,COLORREF);
|
|
(PVOID)NULL_Unused, //BOOL (*pSetTextJustification)(PHYSDEV,INT,INT);
|
|
NULL_SetViewportExtEx, //BOOL (*pSetViewportExtEx)(PHYSDEV,INT,INT,SIZE*);
|
|
NULL_SetViewportOrgEx, //BOOL (*pSetViewportOrgEx)(PHYSDEV,INT,INT,POINT*);
|
|
NULL_SetWindowExtEx, //BOOL (*pSetWindowExtEx)(PHYSDEV,INT,INT,SIZE*);
|
|
NULL_SetWindowOrgEx, //BOOL (*pSetWindowOrgEx)(PHYSDEV,INT,INT,POINT*);
|
|
NULL_SetWorldTransform, //BOOL (*pSetWorldTransform)(PHYSDEV,const XFORM*);
|
|
(PVOID)NULL_Unused, //INT (*pStartDoc)(PHYSDEV,const DOCINFOW*);
|
|
(PVOID)NULL_Unused, //INT (*pStartPage)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pStretchBlt)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,DWORD);
|
|
(PVOID)NULL_Unused, //INT (*pStretchDIBits)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT,const void*,BITMAPINFO*,UINT,DWORD);
|
|
nulldrv_StrokeAndFillPath, //BOOL (*pStrokeAndFillPath)(PHYSDEV);
|
|
nulldrv_StrokePath, //BOOL (*pStrokePath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //BOOL (*pUnrealizePalette)(HPALETTE);
|
|
nulldrv_WidenPath, //BOOL (*pWidenPath)(PHYSDEV);
|
|
(PVOID)NULL_Unused, //struct opengl_funcs * (*wine_get_wgl_driver)(PHYSDEV,UINT);
|
|
0 // UINT priority;
|
|
};
|
|
|
|
WINEDC *get_nulldrv_dc( PHYSDEV dev )
|
|
{
|
|
return CONTAINING_RECORD( dev, WINEDC, NullPhysDev );
|
|
}
|
|
|
|
WINEDC* get_physdev_dc( PHYSDEV dev )
|
|
{
|
|
while (dev->funcs != &DummyPhysDevFuncs)
|
|
dev = dev->next;
|
|
return get_nulldrv_dc( dev );
|
|
}
|
|
|
|
static
|
|
GDILOOBJTYPE
|
|
ConvertObjectType(
|
|
WORD wType)
|
|
{
|
|
/* Get the GDI object type */
|
|
switch (wType)
|
|
{
|
|
case OBJ_PEN: return GDILoObjType_LO_PEN_TYPE;
|
|
case OBJ_BRUSH: return GDILoObjType_LO_BRUSH_TYPE;
|
|
case OBJ_DC: return GDILoObjType_LO_DC_TYPE;
|
|
case OBJ_METADC: return GDILoObjType_LO_METADC16_TYPE;
|
|
case OBJ_PAL: return GDILoObjType_LO_PALETTE_TYPE;
|
|
case OBJ_FONT: return GDILoObjType_LO_FONT_TYPE;
|
|
case OBJ_BITMAP: return GDILoObjType_LO_BITMAP_TYPE;
|
|
case OBJ_REGION: return GDILoObjType_LO_REGION_TYPE;
|
|
case OBJ_METAFILE: return GDILoObjType_LO_METAFILE16_TYPE;
|
|
case OBJ_MEMDC: return GDILoObjType_LO_DC_TYPE;
|
|
case OBJ_EXTPEN: return GDILoObjType_LO_EXTPEN_TYPE;
|
|
case OBJ_ENHMETADC: return GDILoObjType_LO_ALTDC_TYPE;
|
|
case OBJ_ENHMETAFILE: return GDILoObjType_LO_METAFILE_TYPE;
|
|
case OBJ_COLORSPACE: return GDILoObjType_LO_ICMLCS_TYPE;
|
|
default: return 0;
|
|
}
|
|
}
|
|
|
|
HGDIOBJ
|
|
alloc_gdi_handle(
|
|
PVOID pvObject,
|
|
WORD wType,
|
|
const struct gdi_obj_funcs *funcs)
|
|
{
|
|
GDILOOBJTYPE eObjType;
|
|
|
|
/* Get the GDI object type */
|
|
eObjType = ConvertObjectType(wType);
|
|
if ((eObjType != GDILoObjType_LO_METAFILE_TYPE) &&
|
|
(eObjType != GDILoObjType_LO_METAFILE16_TYPE) &&
|
|
(eObjType != GDILoObjType_LO_METADC16_TYPE))
|
|
{
|
|
/* This is not supported! */
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
/* Insert the client object */
|
|
return GdiCreateClientObj(pvObject, eObjType);
|
|
}
|
|
|
|
PVOID
|
|
free_gdi_handle(HGDIOBJ hobj)
|
|
{
|
|
/* Should be a client object */
|
|
return GdiDeleteClientObj(hobj);
|
|
}
|
|
|
|
PVOID
|
|
GDI_GetObjPtr(
|
|
HGDIOBJ hobj,
|
|
WORD wType)
|
|
{
|
|
GDILOOBJTYPE eObjType;
|
|
|
|
/* Check if the object type matches */
|
|
eObjType = ConvertObjectType(wType);
|
|
if ((eObjType == 0) || (GDI_HANDLE_GET_TYPE(hobj) != eObjType))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Check if we have an ALTDC */
|
|
if (eObjType == GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
/* Object is stored as LDC */
|
|
return GdiGetLDC(hobj);
|
|
}
|
|
|
|
/* Check for client objects */
|
|
if ((eObjType == GDILoObjType_LO_METAFILE_TYPE) ||
|
|
(eObjType == GDILoObjType_LO_METAFILE16_TYPE) ||
|
|
(eObjType == GDILoObjType_LO_METADC16_TYPE))
|
|
{
|
|
return GdiGetClientObjLink(hobj);
|
|
}
|
|
|
|
/* This should never happen! */
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
GDI_ReleaseObj(HGDIOBJ hobj)
|
|
{
|
|
/* We don't do any reference-counting */
|
|
}
|
|
|
|
WINEDC*
|
|
alloc_dc_ptr(WORD magic)
|
|
{
|
|
WINEDC* pWineDc;
|
|
|
|
/* Allocate the Wine DC */
|
|
pWineDc = HeapAlloc(GetProcessHeap(), 0, sizeof(*pWineDc));
|
|
if (pWineDc == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ZeroMemory(pWineDc, sizeof(*pWineDc));
|
|
pWineDc->refcount = 1;
|
|
pWineDc->hFont = GetStockObject(SYSTEM_FONT);
|
|
pWineDc->hBrush = GetStockObject(WHITE_BRUSH);
|
|
pWineDc->hPen = GetStockObject(BLACK_PEN);
|
|
pWineDc->hPalette = GetStockObject(DEFAULT_PALETTE);
|
|
|
|
if (magic == OBJ_ENHMETADC)
|
|
{
|
|
/* We create a metafile DC, but we ignore the reference DC, this is
|
|
handled by the wine code */
|
|
pWineDc->hdc = NtGdiCreateMetafileDC(NULL);
|
|
if (pWineDc->hdc == NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pWineDc);
|
|
return NULL;
|
|
}
|
|
|
|
pWineDc->iType = LDC_EMFLDC;
|
|
|
|
/* Set the Wine DC as LDC */
|
|
GdiSetLDC(pWineDc->hdc, pWineDc);
|
|
}
|
|
else if (magic == OBJ_METADC)
|
|
{
|
|
pWineDc->hdc = GdiCreateClientObj(pWineDc, GDILoObjType_LO_METADC16_TYPE);
|
|
if (pWineDc->hdc == NULL)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, pWineDc);
|
|
return NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// nothing else supported!
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
pWineDc->physDev = &pWineDc->NullPhysDev;
|
|
pWineDc->NullPhysDev.funcs = &DummyPhysDevFuncs;
|
|
pWineDc->NullPhysDev.next = NULL;
|
|
|
|
pWineDc->NullPhysDev.hdc = pWineDc->hdc;
|
|
return pWineDc;
|
|
}
|
|
|
|
VOID
|
|
free_dc_ptr(WINEDC* pWineDc)
|
|
{
|
|
/* Invoke the DeleteDC callback to clean up the DC */
|
|
pWineDc->physDev->funcs->pDeleteDC(pWineDc->physDev);
|
|
|
|
/* FIXME */
|
|
if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
/* Get rid of the LDC */
|
|
ASSERT((WINEDC*)GdiGetLDC(pWineDc->hdc) == pWineDc);
|
|
GdiSetLDC(pWineDc->hdc, NULL);
|
|
|
|
/* Free the DC */
|
|
NtGdiDeleteObjectApp(pWineDc->hdc);
|
|
}
|
|
else if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_METADC16_TYPE)
|
|
{
|
|
GdiDeleteClientObj(pWineDc->hdc);
|
|
}
|
|
|
|
/* Free the Wine DC */
|
|
HeapFree(GetProcessHeap(), 0, pWineDc);
|
|
}
|
|
|
|
WINEDC*
|
|
get_dc_ptr(HDC hdc)
|
|
{
|
|
/* Check for EMF DC */
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
/* The Wine DC is stored as the LDC */
|
|
return (WINEDC*)GdiGetLDC(hdc);
|
|
}
|
|
|
|
/* Check for METADC16 */
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
|
|
{
|
|
return GdiGetClientObjLink(hdc);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
VOID
|
|
release_dc_ptr(WINEDC* dc)
|
|
{
|
|
/* We don't do any reference-counting */
|
|
}
|
|
|
|
void
|
|
push_dc_driver_ros(
|
|
PHYSDEV *dev,
|
|
PHYSDEV physdev,
|
|
const struct gdi_dc_funcs *funcs)
|
|
{
|
|
while ((*dev)->funcs->priority > funcs->priority) dev = &(*dev)->next;
|
|
physdev->funcs = funcs;
|
|
physdev->next = *dev;
|
|
physdev->hdc = CONTAINING_RECORD(dev, WINEDC, physDev)->hdc;
|
|
*dev = physdev;
|
|
}
|
|
|
|
VOID
|
|
GDI_hdc_using_object(
|
|
HGDIOBJ hobj,
|
|
HDC hdc)
|
|
{
|
|
/* Record that we have an object in use by a METADC. We simply link the
|
|
object to the HDC that we use. Wine API does not give us a way to
|
|
respond to failure, so we silently ignore it */
|
|
if (!GdiCreateClientObjLink(hobj, hdc))
|
|
{
|
|
/* Ignore failure, and return */
|
|
DPRINT1("Failed to create link for selected METADC object.\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
GDI_hdc_not_using_object(
|
|
HGDIOBJ hobj,
|
|
HDC hdc)
|
|
{
|
|
HDC hdcLink;
|
|
|
|
/* Remove the HDC link for the object */
|
|
hdcLink = GdiRemoveClientObjLink(hobj);
|
|
ASSERT(hdcLink == hdc);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* bitmap_info_size
|
|
*
|
|
* Return the size of the bitmap info structure including color table.
|
|
*/
|
|
int
|
|
bitmap_info_size(
|
|
const BITMAPINFO * info,
|
|
WORD coloruse)
|
|
{
|
|
unsigned int colors, size, masks = 0;
|
|
|
|
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
|
{
|
|
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
|
|
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
|
|
return sizeof(BITMAPCOREHEADER) + colors *
|
|
((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
|
|
}
|
|
else /* assume BITMAPINFOHEADER */
|
|
{
|
|
if (info->bmiHeader.biClrUsed) colors = min( info->bmiHeader.biClrUsed, 256 );
|
|
else colors = info->bmiHeader.biBitCount > 8 ? 0 : 1 << info->bmiHeader.biBitCount;
|
|
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
|
|
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
|
|
return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
get_brush_bitmap_info(
|
|
HBRUSH hbr,
|
|
PBITMAPINFO pbmi,
|
|
PVOID *ppvBits,
|
|
PUINT puUsage)
|
|
{
|
|
HBITMAP hbmp;
|
|
HDC hdc;
|
|
|
|
/* Call win32k to get the bitmap handle and color usage */
|
|
hbmp = NtGdiGetObjectBitmapHandle(hbr, puUsage);
|
|
if (hbmp == NULL)
|
|
return FALSE;
|
|
|
|
hdc = GetDC(NULL);
|
|
if (hdc == NULL)
|
|
return FALSE;
|
|
|
|
/* Initialize the BITMAPINFO */
|
|
ZeroMemory(pbmi, sizeof(*pbmi));
|
|
pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
|
|
/* Retrieve information about the bitmap */
|
|
if (!GetDIBits(hdc, hbmp, 0, 0, NULL, pbmi, *puUsage))
|
|
return FALSE;
|
|
|
|
/* Now allocate a buffer for the bits */
|
|
*ppvBits = HeapAlloc(GetProcessHeap(), 0, pbmi->bmiHeader.biSizeImage);
|
|
if (*ppvBits == NULL)
|
|
return FALSE;
|
|
|
|
/* Retrieve the bitmap bits */
|
|
if (!GetDIBits(hdc, hbmp, 0, pbmi->bmiHeader.biHeight, *ppvBits, pbmi, *puUsage))
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, *ppvBits);
|
|
*ppvBits = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
/* GetDIBits doesn't set biClrUsed, but wine code needs it, so we set it */
|
|
if (pbmi->bmiHeader.biBitCount <= 8)
|
|
{
|
|
pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
SetVirtualResolution(
|
|
HDC hdc,
|
|
DWORD cxVirtualDevicePixel,
|
|
DWORD cyVirtualDevicePixel,
|
|
DWORD cxVirtualDeviceMm,
|
|
DWORD cyVirtualDeviceMm)
|
|
{
|
|
return NtGdiSetVirtualResolution(hdc,
|
|
cxVirtualDevicePixel,
|
|
cyVirtualDevicePixel,
|
|
cxVirtualDeviceMm,
|
|
cyVirtualDeviceMm);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
DeleteColorSpace(
|
|
HCOLORSPACE hcs)
|
|
{
|
|
return NtGdiDeleteColorSpace(hcs);
|
|
}
|
|
#if 0
|
|
BOOL
|
|
WINAPI
|
|
SetWorldTransformForMetafile(
|
|
_In_ HDC hdc,
|
|
_Out_ CONST XFORM *pxform)
|
|
{
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE)
|
|
{
|
|
#if 0
|
|
//HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, MWT_SET);
|
|
/* Get the physdev */
|
|
physdev = GetPhysDev(hdc);
|
|
if (physdev == NULL)
|
|
{
|
|
DPRINT1("Failed to get physdev for meta DC %p\n", hdc);
|
|
return FALSE;
|
|
}
|
|
|
|
physdev->funcs->pSetWorldTransform(physdev, pxform);
|
|
#endif
|
|
// HACK!!!
|
|
return TRUE;
|
|
}
|
|
|
|
return SetWorldTransform(hdc, pxform);
|
|
}
|
|
#endif
|
|
void
|
|
__cdecl
|
|
_assert (
|
|
const char *exp,
|
|
const char *file,
|
|
unsigned line)
|
|
{
|
|
DbgRaiseAssertionFailure();
|
|
}
|
|
|
|
/******************************************************************************/
|
|
|
|
static
|
|
VOID
|
|
InitBitBltCoords(
|
|
struct bitblt_coords *coords,
|
|
HDC hdc,
|
|
int x,
|
|
int y,
|
|
int cx,
|
|
int cy)
|
|
{
|
|
coords->log_x = x;
|
|
coords->log_y = y;
|
|
coords->log_width = cx;
|
|
coords->log_height = cy;
|
|
coords->layout = GetLayout(hdc);
|
|
}
|
|
|
|
static
|
|
PHYSDEV
|
|
GetPhysDev(
|
|
HDC hdc)
|
|
{
|
|
WINEDC *pWineDc;
|
|
|
|
pWineDc = get_dc_ptr(hdc);
|
|
if (pWineDc == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return pWineDc->physDev;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
DRIVER_PatBlt(
|
|
_In_ PHYSDEV physdev,
|
|
_In_ HDC hdc,
|
|
_In_ INT xLeft,
|
|
_In_ INT yTop,
|
|
_In_ INT cx,
|
|
_In_ INT cy,
|
|
_In_ DWORD dwRop)
|
|
{
|
|
struct bitblt_coords coords;
|
|
|
|
InitBitBltCoords(&coords, hdc, xLeft, yTop, cx, cy);
|
|
|
|
return physdev->funcs->pPatBlt(physdev, &coords, dwRop);
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
DRIVER_StretchBlt(
|
|
_In_ PHYSDEV physdev,
|
|
_In_ HDC hdcDst,
|
|
_In_ INT xDst,
|
|
_In_ INT yDst,
|
|
_In_ INT cxDst,
|
|
_In_ INT cyDst,
|
|
_In_opt_ HDC hdcSrc,
|
|
_In_ INT xSrc,
|
|
_In_ INT ySrc,
|
|
_In_ INT cxSrc,
|
|
_In_ INT cySrc,
|
|
_In_ DWORD dwRop)
|
|
{
|
|
struct bitblt_coords coordsDst, coordsSrc;
|
|
struct gdi_physdev physdevSrc = {0};
|
|
|
|
/* Source cannot be a metafile */
|
|
if (GDI_HANDLE_GET_TYPE(hdcSrc) != GDILoObjType_LO_DC_TYPE)
|
|
return FALSE;
|
|
|
|
/* Source physdev uses only hdc and func */
|
|
physdevSrc.hdc = hdcSrc;
|
|
|
|
InitBitBltCoords(&coordsDst, hdcDst, xDst, yDst, cxDst, cyDst);
|
|
InitBitBltCoords(&coordsSrc, hdcSrc, xSrc, ySrc, cxSrc, cySrc);
|
|
|
|
return physdev->funcs->pStretchBlt(physdev, &coordsDst, &physdevSrc, &coordsSrc, dwRop);
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
DRIVER_RestoreDC(PHYSDEV physdev, INT level)
|
|
{
|
|
WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
|
|
|
|
if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
/* The Restore DC function needs the save level to be set correctly.
|
|
Note that wine's level is 0 based, while our's is (like win) 1 based. */
|
|
pWineDc->saveLevel = GetDCDWord(physdev->hdc, GdiGetEMFRestorDc, 0) - 1;
|
|
|
|
/* Fail if the level is not valid */
|
|
if ((abs(level) > pWineDc->saveLevel) || (level == 0))
|
|
return FALSE;
|
|
}
|
|
|
|
return physdev->funcs->pRestoreDC(physdev,level);
|
|
}
|
|
|
|
static
|
|
HFONT
|
|
DRIVER_SelectFont(PHYSDEV physdev, HFONT hFont, UINT *aa_flags)
|
|
{
|
|
WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
|
|
HFONT hOldFont;
|
|
|
|
if (!physdev->funcs->pSelectFont(physdev, hFont, aa_flags))
|
|
return 0;
|
|
|
|
hOldFont = pWineDc->hFont;
|
|
pWineDc->hFont = hFont;
|
|
return hOldFont;
|
|
}
|
|
|
|
static
|
|
HPEN
|
|
DRIVER_SelectPen(PHYSDEV physdev, HPEN hpen, const struct brush_pattern *pattern)
|
|
{
|
|
WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
|
|
HPEN hOldPen;
|
|
|
|
if (!physdev->funcs->pSelectPen(physdev, hpen, pattern))
|
|
return 0;
|
|
|
|
hOldPen = pWineDc->hPen;
|
|
pWineDc->hPen = hpen;
|
|
return hOldPen;
|
|
}
|
|
|
|
static
|
|
HBRUSH
|
|
DRIVER_SelectBrush(PHYSDEV physdev, HBRUSH hbrush, const struct brush_pattern *pattern)
|
|
{
|
|
WINEDC *pWineDc = get_dc_ptr(physdev->hdc);
|
|
HBRUSH hOldBrush;
|
|
|
|
if (!physdev->funcs->pSelectBrush(physdev, hbrush, pattern))
|
|
return 0;
|
|
|
|
hOldBrush = pWineDc->hBrush;
|
|
pWineDc->hBrush = hbrush;
|
|
return hOldBrush;
|
|
}
|
|
|
|
static
|
|
HRGN
|
|
DRIVER_PathToRegion(PHYSDEV physdev)
|
|
{
|
|
DPRINT1("DRIVER_PathToRegion\n");
|
|
return (HRGN)(ULONG_PTR)physdev->funcs->pAbortPath( physdev );
|
|
}
|
|
|
|
|
|
static
|
|
DWORD_PTR
|
|
DRIVER_Dispatch(
|
|
_In_ PHYSDEV physdev,
|
|
_In_ DCFUNC eFunction,
|
|
_In_ va_list argptr)
|
|
{
|
|
UINT aa_flags = 0;
|
|
|
|
/* Note that this is a hack that relies on some assumptions regarding the
|
|
Windows ABI. It relies on the fact that all vararg functions put their
|
|
parameters on the stack in the correct order. Additionally it relies
|
|
on the fact that none of the functions we handle here, pass any 64
|
|
bit arguments on a 32 bit architecture. */
|
|
#define _va_arg_n(p,t,i) (*(t*)((intptr_t*)(p) + i))
|
|
|
|
switch (eFunction)
|
|
{
|
|
case DCFUNC_AbortPath:
|
|
return physdev->funcs->pAbortPath(physdev);
|
|
case DCFUNC_Arc:
|
|
return physdev->funcs->pArc(physdev,
|
|
_va_arg_n(argptr, INT, 0), // left
|
|
_va_arg_n(argptr, INT, 1), // top
|
|
_va_arg_n(argptr, INT, 2), // right
|
|
_va_arg_n(argptr, INT, 3), // bottom
|
|
_va_arg_n(argptr, INT, 4), // xstart
|
|
_va_arg_n(argptr, INT, 5), // ystart
|
|
_va_arg_n(argptr, INT, 6), // xend
|
|
_va_arg_n(argptr, INT, 7)); // yend
|
|
case DCFUNC_BeginPath:
|
|
return physdev->funcs->pBeginPath(physdev);
|
|
case DCFUNC_Chord:
|
|
return physdev->funcs->pChord(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, INT, 4),
|
|
_va_arg_n(argptr, INT, 5),
|
|
_va_arg_n(argptr, INT, 6),
|
|
_va_arg_n(argptr, INT, 7));
|
|
case DCFUNC_CloseFigure:
|
|
return physdev->funcs->pCloseFigure(physdev);
|
|
case DCFUNC_Ellipse:
|
|
return physdev->funcs->pEllipse(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3));
|
|
case DCFUNC_EndPath:
|
|
return physdev->funcs->pEndPath(physdev);
|
|
case DCFUNC_ExcludeClipRect:
|
|
return physdev->funcs->pExcludeClipRect(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3));
|
|
case DCFUNC_ExtEscape:
|
|
ASSERT(physdev->funcs->pExtEscape != NULL);
|
|
return physdev->funcs->pExtEscape(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, LPCVOID, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, LPVOID, 4));
|
|
case DCFUNC_ExtFloodFill:
|
|
return physdev->funcs->pExtFloodFill(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, COLORREF, 2),
|
|
_va_arg_n(argptr, UINT, 3));
|
|
case DCFUNC_ExtSelectClipRgn:
|
|
return physdev->funcs->pExtSelectClipRgn(physdev,
|
|
_va_arg_n(argptr, HRGN, 0), // hrgn
|
|
_va_arg_n(argptr, INT, 1)); // iMode
|
|
case DCFUNC_ExtTextOut:
|
|
return physdev->funcs->pExtTextOut(physdev,
|
|
_va_arg_n(argptr, INT, 0),// x
|
|
_va_arg_n(argptr, INT, 1),// y
|
|
_va_arg_n(argptr, UINT, 2),// fuOptions
|
|
_va_arg_n(argptr, const RECT *, 3),// lprc,
|
|
_va_arg_n(argptr, LPCWSTR, 4),// lpString,
|
|
_va_arg_n(argptr, UINT, 5),// cchString,
|
|
_va_arg_n(argptr, const INT *, 6));// lpDx);
|
|
case DCFUNC_FillPath:
|
|
return physdev->funcs->pFillPath(physdev);
|
|
case DCFUNC_FillRgn:
|
|
return physdev->funcs->pFillRgn(physdev,
|
|
_va_arg_n(argptr, HRGN, 0),
|
|
_va_arg_n(argptr, HBRUSH, 1));
|
|
case DCFUNC_FlattenPath:
|
|
return physdev->funcs->pFlattenPath(physdev);
|
|
case DCFUNC_FrameRgn:
|
|
return physdev->funcs->pFrameRgn(physdev,
|
|
_va_arg_n(argptr, HRGN, 0),
|
|
_va_arg_n(argptr, HBRUSH, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3));
|
|
case DCFUNC_GetDeviceCaps:
|
|
return physdev->funcs->pGetDeviceCaps(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_GdiComment:
|
|
return physdev->funcs->pGdiComment(physdev,
|
|
_va_arg_n(argptr, UINT, 0),
|
|
_va_arg_n(argptr, const BYTE*, 1));
|
|
case DCFUNC_IntersectClipRect:
|
|
return physdev->funcs->pIntersectClipRect(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3));
|
|
case DCFUNC_InvertRgn:
|
|
return physdev->funcs->pInvertRgn(physdev,
|
|
va_arg(argptr, HRGN));
|
|
case DCFUNC_LineTo:
|
|
return physdev->funcs->pLineTo(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_ModifyWorldTransform:
|
|
return physdev->funcs->pModifyWorldTransform(physdev,
|
|
_va_arg_n(argptr, const XFORM*, 0),
|
|
_va_arg_n(argptr, DWORD, 1));
|
|
case DCFUNC_MoveTo:
|
|
return physdev->funcs->pMoveTo(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_OffsetClipRgn:
|
|
return physdev->funcs->pOffsetClipRgn(physdev,
|
|
_va_arg_n(argptr, INT, 0), // hrgn
|
|
_va_arg_n(argptr, INT, 1)); // iMode
|
|
case DCFUNC_OffsetViewportOrgEx:
|
|
return physdev->funcs->pOffsetViewportOrgEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // X
|
|
_va_arg_n(argptr, INT, 1), // Y
|
|
_va_arg_n(argptr, LPPOINT, 2)); // lpPoint
|
|
case DCFUNC_OffsetWindowOrgEx:
|
|
return physdev->funcs->pOffsetWindowOrgEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // X
|
|
_va_arg_n(argptr, INT, 1), // Y
|
|
_va_arg_n(argptr, LPPOINT, 2)); // lpPoint
|
|
case DCFUNC_PatBlt:
|
|
return DRIVER_PatBlt(physdev,
|
|
physdev->hdc,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, DWORD, 4));
|
|
case DCFUNC_Pie:
|
|
return physdev->funcs->pPie(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, INT, 4),
|
|
_va_arg_n(argptr, INT, 5),
|
|
_va_arg_n(argptr, INT, 6),
|
|
_va_arg_n(argptr, INT, 7));
|
|
case DCFUNC_PolyBezier:
|
|
return physdev->funcs->pPolyBezier(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, DWORD, 1));
|
|
case DCFUNC_PolyBezierTo:
|
|
return physdev->funcs->pPolyBezierTo(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, DWORD, 1));
|
|
case DCFUNC_PolyDraw:
|
|
return physdev->funcs->pPolyDraw(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, const BYTE*, 1),
|
|
_va_arg_n(argptr, DWORD, 2));
|
|
case DCFUNC_Polygon:
|
|
return physdev->funcs->pPolygon(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_Polyline:
|
|
return physdev->funcs->pPolyline(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_PolylineTo:
|
|
return physdev->funcs->pPolylineTo(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_PolyPolygon:
|
|
return physdev->funcs->pPolyPolygon(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, const INT*, 1),
|
|
_va_arg_n(argptr, DWORD, 2));
|
|
case DCFUNC_PolyPolyline:
|
|
return physdev->funcs->pPolyPolyline(physdev,
|
|
_va_arg_n(argptr, const POINT*, 0),
|
|
_va_arg_n(argptr, const DWORD*, 1),
|
|
_va_arg_n(argptr, DWORD, 2));
|
|
case DCFUNC_RealizePalette:
|
|
if (GDI_HANDLE_GET_TYPE(physdev->hdc) != GDILoObjType_LO_METADC16_TYPE)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return GDI_ERROR;
|
|
}
|
|
return physdev->funcs->pRealizePalette(physdev, NULL, FALSE);
|
|
case DCFUNC_Rectangle:
|
|
return physdev->funcs->pRectangle(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3));
|
|
case DCFUNC_RestoreDC:
|
|
return DRIVER_RestoreDC(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_RoundRect:
|
|
return physdev->funcs->pRoundRect(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, INT, 4),
|
|
_va_arg_n(argptr, INT, 5));
|
|
|
|
case DCFUNC_SaveDC:
|
|
return physdev->funcs->pSaveDC(physdev);
|
|
case DCFUNC_ScaleViewportExtEx:
|
|
return physdev->funcs->pScaleViewportExtEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // xNum
|
|
_va_arg_n(argptr, INT, 1), // xDenom
|
|
_va_arg_n(argptr, INT, 2), // yNum
|
|
_va_arg_n(argptr, INT, 3), // yDenom
|
|
_va_arg_n(argptr, LPSIZE, 4)); // lpSize
|
|
case DCFUNC_ScaleWindowExtEx:
|
|
return physdev->funcs->pScaleWindowExtEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // xNum
|
|
_va_arg_n(argptr, INT, 1), // xDenom
|
|
_va_arg_n(argptr, INT, 2), // yNum
|
|
_va_arg_n(argptr, INT, 3), // yDenom
|
|
_va_arg_n(argptr, LPSIZE, 4)); // lpSize
|
|
case DCFUNC_SelectBrush:
|
|
return (DWORD_PTR)DRIVER_SelectBrush(physdev, va_arg(argptr, HBRUSH), NULL);
|
|
case DCFUNC_SelectClipPath:
|
|
return physdev->funcs->pSelectClipPath(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SelectFont:
|
|
return (DWORD_PTR)DRIVER_SelectFont(physdev, va_arg(argptr, HFONT), &aa_flags);
|
|
case DCFUNC_SelectPalette:
|
|
return (DWORD_PTR)physdev->funcs->pSelectPalette(physdev,
|
|
_va_arg_n(argptr, HPALETTE, 0),
|
|
_va_arg_n(argptr, BOOL, 1));
|
|
case DCFUNC_SelectPen:
|
|
return (DWORD_PTR)DRIVER_SelectPen(physdev, va_arg(argptr, HPEN), NULL);
|
|
case DCFUNC_SetDCBrushColor:
|
|
return physdev->funcs->pSetDCBrushColor(physdev, va_arg(argptr, COLORREF));
|
|
case DCFUNC_SetDCPenColor:
|
|
return physdev->funcs->pSetDCPenColor(physdev, va_arg(argptr, COLORREF));
|
|
case DCFUNC_SetDIBitsToDevice:
|
|
return physdev->funcs->pSetDIBitsToDevice(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, DWORD, 2),
|
|
_va_arg_n(argptr, DWORD, 3),
|
|
_va_arg_n(argptr, INT, 4),
|
|
_va_arg_n(argptr, INT, 5),
|
|
_va_arg_n(argptr, UINT, 6),
|
|
_va_arg_n(argptr, UINT, 7),
|
|
_va_arg_n(argptr, LPCVOID, 8),
|
|
_va_arg_n(argptr, BITMAPINFO*, 9),
|
|
_va_arg_n(argptr, UINT, 10));
|
|
case DCFUNC_SetBkColor:
|
|
return physdev->funcs->pSetBkColor(physdev, va_arg(argptr, COLORREF));
|
|
case DCFUNC_SetBkMode:
|
|
return physdev->funcs->pSetBkMode(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetLayout:
|
|
// FIXME: MF16 is UNIMPLEMENTED
|
|
return physdev->funcs->pSetLayout(physdev,
|
|
_va_arg_n(argptr, DWORD, 0));
|
|
//case DCFUNC_SetMapMode:
|
|
// return physdev->funcs->pSetMapMode(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetPixel:
|
|
return physdev->funcs->pSetPixel(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, COLORREF, 2));
|
|
case DCFUNC_SetPolyFillMode:
|
|
return physdev->funcs->pSetPolyFillMode(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetROP2:
|
|
return physdev->funcs->pSetROP2(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetStretchBltMode:
|
|
return physdev->funcs->pSetStretchBltMode(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetTextAlign:
|
|
return physdev->funcs->pSetTextAlign(physdev, va_arg(argptr, UINT));
|
|
case DCFUNC_SetTextCharacterExtra:
|
|
return physdev->funcs->pSetTextCharacterExtra(physdev, va_arg(argptr, INT));
|
|
case DCFUNC_SetTextColor:
|
|
return physdev->funcs->pSetTextColor(physdev, va_arg(argptr, COLORREF));
|
|
case DCFUNC_SetTextJustification:
|
|
return physdev->funcs->pSetTextJustification(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1));
|
|
case DCFUNC_SetViewportExtEx:
|
|
return physdev->funcs->pSetViewportExtEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // nXExtent
|
|
_va_arg_n(argptr, INT, 1), // nYExtent
|
|
_va_arg_n(argptr, LPSIZE, 2)); // lpSize
|
|
case DCFUNC_SetViewportOrgEx:
|
|
return physdev->funcs->pSetViewportOrgEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // X
|
|
_va_arg_n(argptr, INT, 1), // Y
|
|
_va_arg_n(argptr, LPPOINT, 2)); // lpPoint
|
|
case DCFUNC_SetWindowExtEx:
|
|
return physdev->funcs->pSetWindowExtEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // nXExtent
|
|
_va_arg_n(argptr, INT, 1), // nYExtent
|
|
_va_arg_n(argptr, LPSIZE, 2)); // lpSize
|
|
case DCFUNC_SetWindowOrgEx:
|
|
return physdev->funcs->pSetWindowOrgEx(physdev,
|
|
_va_arg_n(argptr, INT, 0), // X
|
|
_va_arg_n(argptr, INT, 1), // Y
|
|
_va_arg_n(argptr, LPPOINT, 2)); // lpPoint
|
|
|
|
case DCFUNC_SetWorldTransform:
|
|
return physdev->funcs->pSetWorldTransform(physdev,
|
|
va_arg(argptr, const XFORM*));
|
|
|
|
case DCFUNC_StretchBlt:
|
|
return DRIVER_StretchBlt(physdev,
|
|
physdev->hdc,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, HDC, 4),
|
|
_va_arg_n(argptr, INT, 5),
|
|
_va_arg_n(argptr, INT, 6),
|
|
_va_arg_n(argptr, INT, 7),
|
|
_va_arg_n(argptr, INT, 8),
|
|
_va_arg_n(argptr, DWORD, 9));
|
|
case DCFUNC_StrokeAndFillPath:
|
|
return physdev->funcs->pStrokeAndFillPath(physdev);
|
|
case DCFUNC_StrokePath:
|
|
return physdev->funcs->pStrokePath(physdev);
|
|
case DCFUNC_WidenPath:
|
|
return physdev->funcs->pWidenPath(physdev);
|
|
case DCFUNC_AngleArc:
|
|
return physdev->funcs->pAngleArc(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, DWORD, 2),
|
|
_va_arg_n(argptr, FLOAT, 3),
|
|
_va_arg_n(argptr, FLOAT, 4 ));
|
|
case DCFUNC_ArcTo:
|
|
return physdev->funcs->pArcTo(physdev,
|
|
_va_arg_n(argptr, INT, 0),
|
|
_va_arg_n(argptr, INT, 1),
|
|
_va_arg_n(argptr, INT, 2),
|
|
_va_arg_n(argptr, INT, 3),
|
|
_va_arg_n(argptr, INT, 4),
|
|
_va_arg_n(argptr, INT, 5),
|
|
_va_arg_n(argptr, INT, 6),
|
|
_va_arg_n(argptr, INT, 7));
|
|
case DCFUNC_GradientFill:
|
|
return physdev->funcs->pGradientFill(physdev,
|
|
_va_arg_n(argptr, TRIVERTEX *, 0),
|
|
_va_arg_n(argptr, ULONG, 1),
|
|
_va_arg_n(argptr, void *, 2),
|
|
_va_arg_n(argptr, ULONG , 3),
|
|
_va_arg_n(argptr, ULONG , 4));
|
|
case DCFUNC_PathToRegion:
|
|
return (DWORD_PTR)DRIVER_PathToRegion(physdev);
|
|
|
|
/* These are not implemented in wine */
|
|
case DCFUNC_AlphaBlend:
|
|
case DCFUNC_MaskBlt:
|
|
case DCFUNC_PlgBlt:
|
|
case DCFUNC_TransparentBlt:
|
|
UNIMPLEMENTED;
|
|
return 0;
|
|
|
|
default:
|
|
__debugbreak();
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
METADC_Dispatch(
|
|
_In_ DCFUNC eFunction,
|
|
_Out_ PDWORD_PTR pdwResult,
|
|
_In_ DWORD_PTR dwError,
|
|
_In_ HDC hdc,
|
|
...)
|
|
{
|
|
PHYSDEV physdev;
|
|
va_list argptr;
|
|
|
|
/* Handle only METADC16 and ALTDC */
|
|
if ((GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) &&
|
|
(GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_METADC16_TYPE))
|
|
{
|
|
/* Let the caller handle it */
|
|
return FALSE;
|
|
}
|
|
|
|
// See if this is other than a METADATA issue.
|
|
if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
WINEDC* pwdc = (WINEDC*)GdiGetLDC(hdc);
|
|
if (pwdc && pwdc->iType != LDC_EMFLDC)
|
|
{
|
|
/* Let the caller handle it */
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
physdev = GetPhysDev(hdc);
|
|
if (physdev == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
*pdwResult = dwError;
|
|
return TRUE;
|
|
}
|
|
|
|
i = eFunction;
|
|
va_start(argptr, hdc);
|
|
*pdwResult = DRIVER_Dispatch(physdev, eFunction, argptr);
|
|
va_end(argptr);
|
|
i = 0;
|
|
|
|
/* Return TRUE to indicate that we want to return from the parent */
|
|
return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
|
|
(*pdwResult == dwError));
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
METADC_GetAndSetDCDWord(
|
|
_Out_ DWORD* pdwResult,
|
|
_In_ HDC hdc,
|
|
_In_ UINT uFunction,
|
|
_In_ DWORD dwIn,
|
|
_In_ ULONG ulMFId,
|
|
_In_ USHORT usMF16Id,
|
|
_In_ DWORD dwError)
|
|
{
|
|
PHYSDEV physdev;
|
|
|
|
/* Ignore these, we let wine code handle this */
|
|
UNREFERENCED_PARAMETER(ulMFId);
|
|
UNREFERENCED_PARAMETER(usMF16Id);
|
|
|
|
physdev = GetPhysDev(hdc);
|
|
if (physdev == NULL)
|
|
{
|
|
SetLastError(ERROR_INVALID_HANDLE);
|
|
*pdwResult = dwError;
|
|
return TRUE;
|
|
}
|
|
|
|
/* Check the function */
|
|
switch (uFunction)
|
|
{
|
|
case GdiGetSetMapMode:
|
|
*pdwResult = physdev->funcs->pSetMapMode(physdev, dwIn);
|
|
break;
|
|
|
|
case GdiGetSetArcDirection:
|
|
if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE)
|
|
*pdwResult = 0;
|
|
else
|
|
*pdwResult = physdev->funcs->pSetArcDirection(physdev, dwIn);
|
|
break;
|
|
|
|
case GdiGetSetRelAbs:
|
|
if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE)
|
|
*pdwResult = physdev->funcs->pSetRelAbs(physdev, dwIn);
|
|
else
|
|
{
|
|
UNIMPLEMENTED;
|
|
*pdwResult = 0;
|
|
}
|
|
break;
|
|
|
|
|
|
default:
|
|
__debugbreak();
|
|
}
|
|
|
|
/* Return TRUE to indicate that we want to return from the parent */
|
|
return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) ||
|
|
(*pdwResult == dwError));
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
METADC_DeleteObject(HGDIOBJ hobj)
|
|
{
|
|
GDILOOBJTYPE eObjectType;
|
|
HDC hdc;
|
|
PHYSDEV physdev;
|
|
|
|
/* Check for one of the types we actually handle here */
|
|
eObjectType = GDI_HANDLE_GET_TYPE(hobj);
|
|
if ((eObjectType != GDILoObjType_LO_BRUSH_TYPE) &&
|
|
(eObjectType != GDILoObjType_LO_PEN_TYPE) &&
|
|
(eObjectType != GDILoObjType_LO_EXTPEN_TYPE) &&
|
|
(eObjectType != GDILoObjType_LO_PALETTE_TYPE) &&
|
|
(eObjectType != GDILoObjType_LO_FONT_TYPE))
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Check if we have a client object link and remove it if it was found.
|
|
The link is the HDC that the object was selected into. */
|
|
hdc = GdiRemoveClientObjLink(hobj);
|
|
if (hdc == NULL)
|
|
{
|
|
/* The link was not found, so we are not handling this object here */
|
|
return;
|
|
}
|
|
|
|
/* Get the physdev */
|
|
physdev = GetPhysDev(hdc);
|
|
if (physdev == NULL)
|
|
{
|
|
/* This happens, when the METADC is already closed, when we delete
|
|
the object. Simply ignore it */
|
|
DPRINT1("METADC was already closed, cannot delete object. Ignoring.\n");
|
|
return;
|
|
}
|
|
|
|
physdev->funcs->pDeleteObject(physdev, hobj);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
METADC_DeleteDC(
|
|
_In_ HDC hdc)
|
|
{
|
|
/* Only ALTDCs are supported */
|
|
if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE)
|
|
{
|
|
DPRINT1("Trying to delete METADC %p\n", hdc);
|
|
return FALSE;
|
|
}
|
|
// FIXME call the driver?
|
|
return NtGdiDeleteObjectApp(hdc);
|
|
}
|
|
|
|
INT
|
|
WINAPI
|
|
METADC16_Escape(
|
|
_In_ HDC hdc,
|
|
_In_ INT nEscape,
|
|
_In_ INT cbInput,
|
|
_In_ LPCSTR lpvInData,
|
|
_Out_ LPVOID lpvOutData)
|
|
{
|
|
DWORD_PTR dwResult;
|
|
|
|
/* Do not record MFCOMMENT */
|
|
if (nEscape == MFCOMMENT)
|
|
{
|
|
// HACK required by wine code...
|
|
//return 1;
|
|
}
|
|
|
|
METADC_Dispatch(DCFUNC_ExtEscape,
|
|
&dwResult,
|
|
SP_ERROR,
|
|
hdc,
|
|
nEscape,
|
|
cbInput,
|
|
lpvInData,
|
|
lpvOutData);
|
|
|
|
return (INT)dwResult;
|
|
}
|