diff --git a/sdk/include/psdk/wingdi.h b/sdk/include/psdk/wingdi.h index 3cbfb75069d..00a0bf8cb71 100644 --- a/sdk/include/psdk/wingdi.h +++ b/sdk/include/psdk/wingdi.h @@ -215,6 +215,7 @@ extern "C" { #define META_SETPOLYFILLMODE 0x106 #define META_SETSTRETCHBLTMODE 0x107 #define META_SETTEXTCHAREXTRA 0x108 +#define META_SETLAYOUT 0x149 #define META_SETTEXTCOLOR 0x209 #define META_SETTEXTJUSTIFICATION 0x20A #define META_SETWINDOWORG 0x20B diff --git a/win32ss/gdi/gdi32/include/gdi32p.h b/win32ss/gdi/gdi32/include/gdi32p.h index a9eb00b89ef..b5f29b7c5e6 100644 --- a/win32ss/gdi/gdi32/include/gdi32p.h +++ b/win32ss/gdi/gdi32/include/gdi32p.h @@ -563,21 +563,14 @@ extern ULONG gcClientObj; VOID WINAPI -METADC_DeleteObject(HGDIOBJ hobj); +METADC_RosGlueDeleteObject(HGDIOBJ hobj); BOOL WINAPI -METADC_DeleteDC( +METADC_RosGlueDeleteDC( _In_ HDC hdc); -INT -WINAPI -METADC16_Escape( - _In_ HDC hdc, - _In_ INT nEscape, - _In_ INT cbInput, - _In_ LPCSTR lpvInData, - _Out_ LPVOID lpvOutData); +BOOL METADC_DeleteDC( HDC hdc ); BOOL WINAPI @@ -591,155 +584,323 @@ METADC_ExtTextOutW( UINT cchString, const INT *lpDx); -BOOL -WINAPI -METADC_PatBlt( - _In_ HDC hdc, - _In_ INT xLeft, - _In_ INT yTop, - _In_ INT nWidth, - _In_ INT nHeight, - _In_ DWORD dwRop); - /* The following METADC_* functions follow this pattern: */ -#define HANDLE_METADC0P(_RetType, _Func, dwError, hdc, ...) \ - if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ - { \ - DWORD_PTR dwResult; \ - if (METADC_Dispatch(DCFUNC_##_Func, &dwResult, (DWORD_PTR)dwError, hdc)) \ - { \ - return (_RetType)dwResult; \ - } \ - } - #define HANDLE_METADC(_RetType, _Func, dwError, hdc, ...) \ if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ { \ - DWORD_PTR dwResult = 1; \ - if (METADC_Dispatch(DCFUNC_##_Func, &dwResult, (DWORD_PTR)dwError, hdc, __VA_ARGS__)) \ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ { \ - return (_RetType)dwResult; \ + return (_RetType)METADC_##_Func(hdc, __VA_ARGS__); \ + } \ + else \ + { \ + PLDC pLDC = GdiGetLDC(hdc); \ + _RetType _Ret = dwError; \ + if ( !pLDC ) \ + { \ + SetLastError(ERROR_INVALID_HANDLE); \ + return (_RetType)_Ret; \ + } \ + if ( pLDC->iType == LDC_EMFLDC && !(_Ret = (_RetType)EMFDC_##_Func(pLDC, __VA_ARGS__)) ) \ + { \ + return (_RetType)_Ret; \ + } \ + /* Fall through to support information DC's.*/ \ } \ } - -typedef enum _DCFUNC -{ - //DCFUNC_AbortDoc, - DCFUNC_AbortPath, - DCFUNC_AlphaBlend, // UNIMPLEMENTED - DCFUNC_AngleArc, // UNIMPLEMENTED - DCFUNC_Arc, - DCFUNC_ArcTo, // UNIMPLEMENTED - DCFUNC_BeginPath, - //DCFUNC_BitBlt, - DCFUNC_Chord, - DCFUNC_CloseFigure, - DCFUNC_Ellipse, - DCFUNC_EndPath, - DCFUNC_ExcludeClipRect, - DCFUNC_ExtEscape, - DCFUNC_ExtFloodFill, - DCFUNC_ExtSelectClipRgn, - DCFUNC_ExtTextOut, - DCFUNC_FillPath, - DCFUNC_FillRgn, - DCFUNC_FlattenPath, - DCFUNC_FrameRgn, - DCFUNC_GetDeviceCaps, - DCFUNC_GdiComment, - DCFUNC_GradientFill, // UNIMPLEMENTED - DCFUNC_IntersectClipRect, - DCFUNC_InvertRgn, - DCFUNC_LineTo, - DCFUNC_MaskBlt, // UNIMPLEMENTED - DCFUNC_ModifyWorldTransform, - DCFUNC_MoveTo, - DCFUNC_OffsetClipRgn, - DCFUNC_OffsetViewportOrgEx, - DCFUNC_OffsetWindowOrgEx, - DCFUNC_PathToRegion, // UNIMPLEMENTED - DCFUNC_PatBlt, - DCFUNC_Pie, - DCFUNC_PlgBlt, // UNIMPLEMENTED - DCFUNC_PolyBezier, - DCFUNC_PolyBezierTo, - DCFUNC_PolyDraw, - DCFUNC_Polygon, - DCFUNC_Polyline, - DCFUNC_PolylineTo, - DCFUNC_PolyPolygon, - DCFUNC_PolyPolyline, - DCFUNC_RealizePalette, - DCFUNC_Rectangle, - DCFUNC_RestoreDC, - DCFUNC_RoundRect, - DCFUNC_SaveDC, - DCFUNC_ScaleViewportExtEx, - DCFUNC_ScaleWindowExtEx, - DCFUNC_SelectBrush, - DCFUNC_SelectClipPath, - DCFUNC_SelectFont, - DCFUNC_SelectPalette, - DCFUNC_SelectPen, - DCFUNC_SetDCBrushColor, - DCFUNC_SetDCPenColor, - DCFUNC_SetDIBitsToDevice, - DCFUNC_SetBkColor, - DCFUNC_SetBkMode, - DCFUNC_SetLayout, - //DCFUNC_SetMapMode, - DCFUNC_SetPixel, - DCFUNC_SetPolyFillMode, - DCFUNC_SetROP2, - DCFUNC_SetStretchBltMode, - DCFUNC_SetTextAlign, - DCFUNC_SetTextCharacterExtra, - DCFUNC_SetTextColor, - DCFUNC_SetTextJustification, - DCFUNC_SetViewportExtEx, - DCFUNC_SetViewportOrgEx, - DCFUNC_SetWindowExtEx, - DCFUNC_SetWindowOrgEx, - DCFUNC_SetWorldTransform, - DCFUNC_StretchBlt, - DCFUNC_StrokeAndFillPath, - DCFUNC_StrokePath, - DCFUNC_TransparentBlt, // UNIMPLEMENTED - DCFUNC_WidenPath, - -} DCFUNC; - -BOOL -METADC_Dispatch( - _In_ DCFUNC eFunction, - _Out_ PDWORD_PTR pdwResult, - _In_ DWORD_PTR dwError, - _In_ HDC hdc, - ...); - -#define HANDLE_METADC2(_RetType, _Func, hdc, ...) \ +#define HANDLE_METADC16(_RetType, _Func, dwError, hdc, ...) \ if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ { \ - _RetType result; \ - if (METADC_##_Func(&result, hdc, __VA_ARGS__)) \ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ { \ - return result; \ + return METADC_##_Func(hdc, __VA_ARGS__); \ } \ } -BOOL -WINAPI -METADC_GetAndSetDCDWord( - _Out_ PDWORD pdwResult, - _In_ HDC hdc, - _In_ UINT u, - _In_ DWORD dwIn, - _In_ ULONG ulMFId, - _In_ USHORT usMF16Id, - _In_ DWORD dwError); +#define HANDLE_METADC0P(_RetType, _Func, dwError, hdc, ...) \ + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ + { \ + PLDC pLDC = NULL; \ + _RetType _Ret = dwError; \ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ + { \ + return (_RetType)_Ret; \ + } \ + pLDC = GdiGetLDC(hdc); \ + if ( !pLDC ) \ + { \ + SetLastError(ERROR_INVALID_HANDLE); \ + return (_RetType)_Ret; \ + } \ + if ( pLDC->iType == LDC_EMFLDC && !(_Ret = (_RetType)EMFDC_##_Func(pLDC)) ) \ + { \ + return (_RetType)_Ret; \ + } \ + /* Fall through to support information DC's.*/ \ + } + +#define HANDLE_EMETAFDC(_RetType, _Func, dwError, hdc, ...) \ + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ + { \ + PLDC pLDC = NULL; \ + _RetType _Ret = dwError; \ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ + { \ + return (_RetType)_Ret; \ + } \ + pLDC = GdiGetLDC(hdc); \ + if ( !pLDC ) \ + { \ + SetLastError(ERROR_INVALID_HANDLE); \ + return (_RetType)_Ret; \ + } \ + if ( pLDC->iType == LDC_EMFLDC && !(_Ret = EMFDC_##_Func(pLDC, __VA_ARGS__)) ) \ + { \ + return (_RetType)_Ret; \ + } \ + /* Fall through to support information DC's.*/ \ + } + +#define HANDLE_METADC1P(_RetType, _Func, dwError, hdc, ...) \ + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ + { \ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ + { \ + return (_RetType)METADC_##_Func(hdc); \ + } \ + else \ + { \ + PLDC pLDC = GdiGetLDC(hdc); \ + _RetType _Ret = dwError; \ + if ( !pLDC ) \ + { \ + SetLastError(ERROR_INVALID_HANDLE); \ + return (_RetType)_Ret; \ + } \ + if ( pLDC->iType == LDC_EMFLDC && !(_Ret = (_RetType)EMFDC_##_Func(pLDC)) ) \ + { \ + return (_RetType)_Ret; \ + } \ + /* Fall through to support information DC's.*/ \ + } \ + } + + +BOOL WINAPI METADC_SetD(_In_ HDC hdc,_In_ DWORD dwIn,_In_ USHORT usMF16Id); +BOOL WINAPI EMFDC_SetD(_In_ PLDC pldc,_In_ DWORD dwIn,_In_ ULONG ulMFId); HDC WINAPI GdiConvertAndCheckDC(HDC hdc); +HENHMETAFILE WINAPI SetEnhMetaFileBitsAlt( PDWORD pdw, LPWSTR FilePart, HANDLE hFile, LARGE_INTEGER li); + +/* meta dc files */ +extern BOOL METADC_Arc( HDC hdc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL METADC_BitBlt( HDC hdc_dst, INT x_dst, INT y_dst, INT width, INT height, + HDC hdc_src, INT x_src, INT y_src, DWORD rop ); +extern BOOL METADC_Chord( HDC hdc, INT left, INT top, INT right, INT bottom, INT xstart, + INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL METADC_Ellipse( HDC hdc, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL METADC_ExcludeClipRect( HDC hdc, INT left, INT top, INT right, + INT bottom ) DECLSPEC_HIDDEN; +extern BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, LPCSTR input, INT output_size, LPVOID output ) DECLSPEC_HIDDEN; +extern BOOL METADC_ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, + UINT fill_type ) DECLSPEC_HIDDEN; +extern BOOL METADC_ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT mode ) DECLSPEC_HIDDEN; +extern BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *rect, + const WCHAR *str, UINT count, const INT *dx ) DECLSPEC_HIDDEN; +extern BOOL METADC_FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush ) DECLSPEC_HIDDEN; +extern BOOL METADC_FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, INT x, INT y ) DECLSPEC_HIDDEN; +extern INT METADC_GetDeviceCaps( HDC hdc, INT cap ); +extern BOOL METADC_IntersectClipRect( HDC hdc, INT left, INT top, INT right, + INT bottom ) DECLSPEC_HIDDEN; +extern BOOL METADC_InvertRgn( HDC hdc, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL METADC_LineTo( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_MoveTo( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_OffsetClipRgn( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_OffsetViewportOrgEx( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_OffsetWindowOrgEx( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_PaintRgn( HDC hdc, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL METADC_PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop ); +extern BOOL METADC_Pie( HDC hdc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL METADC_PolyPolygon( HDC hdc, const POINT *points, const INT *counts, + UINT polygons ) DECLSPEC_HIDDEN; +extern BOOL METADC_Polygon( HDC hdc, const POINT *points, INT count ) DECLSPEC_HIDDEN; +extern BOOL METADC_Polyline( HDC hdc, const POINT *points,INT count) DECLSPEC_HIDDEN; +extern BOOL METADC_RealizePalette( HDC hdc ) DECLSPEC_HIDDEN; +extern BOOL METADC_Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN; +extern BOOL METADC_RestoreDC( HDC hdc, INT level ) DECLSPEC_HIDDEN; +extern BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right, INT bottom, + INT ell_width, INT ell_height ) DECLSPEC_HIDDEN; +extern BOOL METADC_SaveDC( HDC hdc ) DECLSPEC_HIDDEN; +extern BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, + INT y_denom ) DECLSPEC_HIDDEN; +extern BOOL METADC_ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, + INT y_denom ) DECLSPEC_HIDDEN; +extern HGDIOBJ METADC_SelectObject( HDC hdc, HGDIOBJ obj ) DECLSPEC_HIDDEN; +extern BOOL METADC_SelectPalette( HDC hdc, HPALETTE palette ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetBkColor( HDC hdc, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetBkMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN; +extern INT METADC_SetDIBitsToDevice( HDC hdc, INT x_dest, INT y_dest, DWORD width, DWORD height, + INT x_src, INT y_src, UINT startscan, UINT lines, + const void *bits, const BITMAPINFO *info, + UINT coloruse ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetLayout( HDC hdc, DWORD layout ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetMapMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetMapperFlags( HDC hdc, DWORD flags ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetPixel( HDC hdc, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetPolyFillMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetRelAbs( HDC hdc, INT mode ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetROP2( HDC hdc, INT rop ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetStretchBltMode( HDC hdc, INT mode ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetTextAlign( HDC hdc, UINT align ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetTextColor( HDC hdc, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetTextJustification( HDC hdc, INT extra, INT breaks ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetViewportExtEx( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetViewportOrgEx( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetWindowExtEx( HDC hdc, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_SetWindowOrgEx( HDC, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL METADC_StretchBlt( HDC hdc_dst, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop ); +extern INT METADC_StretchDIBits( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + INT x_src, INT y_src, INT width_src, INT height_src, + const void *bits, const BITMAPINFO *info, UINT coloruse, + DWORD rop ) DECLSPEC_HIDDEN; +/* enhanced metafiles */ +extern BOOL EMFDC_AbortPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_AlphaBlend( LDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + BLENDFUNCTION blend_function ); +extern BOOL EMFDC_AngleArc( LDC *dc_attr, INT x, INT y, DWORD radius, FLOAT start, + FLOAT sweep ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ArcChordPie( LDC *dc_attr, INT left, INT top, INT right, + INT bottom, INT xstart, INT ystart, INT xend, + INT yend, DWORD type ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_BeginPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_BitBlt( LDC *dc_attr, INT x_dst, INT y_dst, INT width, INT height, + HDC hdc_src, INT x_src, INT y_src, DWORD rop ); +extern BOOL EMFDC_CloseFigure( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern void EMFDC_DeleteDC( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_Ellipse( LDC *dc_attr, INT left, INT top, INT right, + INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_EndPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ExcludeClipRect( LDC *dc_attr, INT left, INT top, INT right, + INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ExtFloodFill( LDC *dc_attr, INT x, INT y, COLORREF color, + UINT fill_type ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ExtSelectClipRgn( LDC *dc_attr, HRGN hrgn, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ExtTextOut( LDC *dc_attr, INT x, INT y, UINT flags, const RECT *rect, + const WCHAR *str, UINT count, const INT *dx ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_FillPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_FillRgn( LDC *dc_attr, HRGN hrgn, HBRUSH hbrush ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_FlattenPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_FrameRgn( LDC *dc_attr, HRGN hrgn, HBRUSH hbrush, INT width, + INT height ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_GradientFill( LDC *dc_attr, TRIVERTEX *vert_array, ULONG nvert, + void *grad_array, ULONG ngrad, ULONG mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_IntersectClipRect( LDC *dc_attr, INT left, INT top, INT right, + INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_InvertRgn( LDC *dc_attr, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_LineTo( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ModifyWorldTransform( LDC *dc_attr, const XFORM *xform, + DWORD mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_MoveTo( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_OffsetClipRgn( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PaintRgn( LDC *dc_attr, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PatBlt( LDC *dc_attr, INT left, INT top, INT width, INT height, DWORD rop ); +extern BOOL EMFDC_PolyBezier( LDC *dc_attr, const POINT *points, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PolyBezierTo( LDC *dc_attr, const POINT *points, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PolyDraw( LDC *dc_attr, const POINT *points, const BYTE *types, + DWORD count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PolyPolyline( LDC *dc_attr, const POINT *points, const DWORD *counts, + DWORD polys ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PolyPolygon( LDC *dc_attr, const POINT *points, const INT *counts, + UINT polys ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_Polygon( LDC *dc_attr, const POINT *points, INT count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_Polyline( LDC *dc_attr, const POINT *points, INT count) DECLSPEC_HIDDEN; +extern BOOL EMFDC_PolylineTo( LDC *dc_attr, const POINT *points, INT count ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_Rectangle( LDC *dc_attr, INT left, INT top, INT right, + INT bottom) DECLSPEC_HIDDEN; +extern BOOL EMFDC_RestoreDC( LDC *dc_attr, INT level ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_RoundRect( LDC *dc_attr, INT left, INT top, INT right, INT bottom, + INT ell_width, INT ell_height ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SaveDC( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ScaleViewportExtEx( LDC *dc_attr, INT x_num, INT x_denom, INT y_num, + INT y_denom ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_ScaleWindowExtEx( LDC *dc_attr, INT x_num, INT x_denom, INT y_num, + INT y_denom ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SelectClipPath( LDC *dc_attr, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SelectObject( LDC *dc_attr, HGDIOBJ obj ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SelectPalette( LDC *dc_attr, HPALETTE palette ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetArcDirection( LDC *dc_attr, INT dir ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetBkColor( LDC *dc_attr, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetBkMode( LDC *dc_attr, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetDCBrushColor( LDC *dc_attr, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetDCPenColor( LDC *dc_attr, COLORREF color ) DECLSPEC_HIDDEN; +extern INT EMFDC_SetDIBitsToDevice( LDC *dc_attr, INT x_dest, INT y_dest, DWORD width, + DWORD height, INT x_src, INT y_src, UINT startscan, + UINT lines, const void *bits, const BITMAPINFO *info, + UINT coloruse ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetLayout( LDC *dc_attr, DWORD layout ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetMapMode( LDC *dc_attr, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetMapperFlags( LDC *dc_attr, DWORD flags ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetPixel( LDC *dc_attr, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetPolyFillMode( LDC *dc_attr, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetROP2( LDC *dc_attr, INT rop ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetStretchBltMode( LDC *dc_attr, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetTextAlign( LDC *dc_attr, UINT align ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetTextColor( LDC *dc_attr, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetTextJustification( LDC *dc_attr, INT extra, INT breaks ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetViewportExtEx( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetViewportOrgEx( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetWindowExtEx( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetWindowOrgEx( LDC *dc_attr, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_SetWorldTransform( LDC *dc_attr, const XFORM *xform ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_StretchBlt( LDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop ); +extern BOOL EMFDC_StretchDIBits( LDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, + INT height_dst, INT x_src, INT y_src, INT width_src, + INT height_src, const void *bits, const BITMAPINFO *info, + UINT coloruse, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_StrokeAndFillPath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_StrokePath( LDC *dc_attr ) DECLSPEC_HIDDEN; +extern BOOL EMFDC_WidenPath( LDC *dc_attr ) DECLSPEC_HIDDEN; + + +BOOL EMFDC_MaskBlt( LDC *dc_attr, INT xDest, INT yDest, INT cx, INT cy, HDC hdcSrc, INT xSrc, INT ySrc, HBITMAP hbmMask, INT xMask, INT yMask, DWORD dwRop); +BOOL EMFDC_PlgBlt( LDC *dc_attr, const POINT * ppt, HDC hdcSrc, INT xSrc, INT ySrc, INT cx, INT cy, HBITMAP hbmMask, INT xMask, INT yMask); +BOOL EMFDC_TransparentBlt( LDC *dc_attr, INT xDst, INT yDst, INT cxDst, INT cyDst, HDC hdcSrc, INT xSrc, INT ySrc, INT cxSrc, INT cySrc, UINT crTransparent); +BOOL EMFDC_SetBrushOrg( LDC *dc_attr, INT x, INT y); +BOOL EMFDC_SetMetaRgn( LDC *dc_attr ); +INT EMFDC_WriteNamedEscape( LDC *dc_attr, PWCHAR pDriver, INT nEscape, INT cbInput, LPCSTR lpszInData); +INT EMFDC_WriteEscape( LDC *dc_attr, INT nEscape, INT cbInput, LPSTR lpszInData, DWORD emrType); + + +FORCEINLINE BOOL EMFDC_Arc( PLDC dc_attr, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDC_ArcChordPie( dc_attr, left, top, right, bottom, xstart, ystart, xend, yend, EMR_ARC ); +} + +FORCEINLINE BOOL EMFDC_ArcTo( PLDC dc_attr, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) +{ +return EMFDC_ArcChordPie( dc_attr, left, top, right, bottom, xstart, ystart, xend, yend, EMR_ARCTO ); +} +FORCEINLINE BOOL EMFDC_Chord( PLDC dc_attr, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) +{ +return EMFDC_ArcChordPie( dc_attr, left, top, right, bottom, xstart, ystart, xend, yend, EMR_CHORD ); +} + +FORCEINLINE BOOL EMFDC_Pie( PLDC dc_attr, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ) +{ +return EMFDC_ArcChordPie( dc_attr, left, top, right, bottom, xstart, ystart, xend, yend, EMR_PIE ); +} + +BOOL WINAPI EMFDC_GdiComment( HDC hdc, UINT bytes, const BYTE *buffer ); + /* EOF */ diff --git a/win32ss/gdi/gdi32/misc/misc.c b/win32ss/gdi/gdi32/misc/misc.c index d977d6c3080..f753e9bde0f 100644 --- a/win32ss/gdi/gdi32/misc/misc.c +++ b/win32ss/gdi/gdi32/misc/misc.c @@ -66,7 +66,7 @@ Escape( if (ulObjType == GDILoObjType_LO_METADC16_TYPE) { - return METADC16_Escape(hdc, nEscape, cbInput, lpvInData, lpvOutData); + return METADC_ExtEscape(hdc, nEscape, cbInput, lpvInData, 0, lpvOutData); } switch (nEscape) diff --git a/win32ss/gdi/gdi32/objects/arc.c b/win32ss/gdi/gdi32/objects/arc.c index 444b05a295b..f689b05ab4d 100644 --- a/win32ss/gdi/gdi32/objects/arc.c +++ b/win32ss/gdi/gdi32/objects/arc.c @@ -54,15 +54,15 @@ AngleArc( _In_ FLOAT eStartAngle, _In_ FLOAT eSweepAngle) { - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, AngleArc, FALSE, hdc, x, y, dwRadius, - RCAST(DWORD, eStartAngle), - RCAST(DWORD, eSweepAngle)); + eStartAngle, + eSweepAngle); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -87,7 +87,7 @@ ArcTo( _In_ INT xRadial2, _In_ INT yRadial2) { - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, ArcTo, FALSE, hdc, diff --git a/win32ss/gdi/gdi32/objects/bitmap.c b/win32ss/gdi/gdi32/objects/bitmap.c index f290b546617..438521f69e9 100644 --- a/win32ss/gdi/gdi32/objects/bitmap.c +++ b/win32ss/gdi/gdi32/objects/bitmap.c @@ -811,7 +811,7 @@ StretchDIBits( BOOL Hit = FALSE; DPRINT("StretchDIBits %p : %p : %u\n", lpBits, lpBitsInfo, iUsage); -#if 0 + HANDLE_METADC( int, StretchDIBits, 0, @@ -828,11 +828,10 @@ StretchDIBits( lpBitsInfo, iUsage, dwRop ); -#endif + if ( GdiConvertAndCheckDC(hdc) == NULL ) return 0; - pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, &ConvertedInfoSize, - FALSE); + pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, &ConvertedInfoSize, FALSE); if (!pConvertedInfo) { return 0; @@ -878,10 +877,22 @@ StretchDIBits( (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ { - LinesCopied = NtGdiStretchDIBitsInternal(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc, - YSrc, nSrcWidth, nSrcHeight, pvSafeBits, pConvertedInfo, (DWORD) iUsage, dwRop, - ConvertedInfoSize, cjBmpScanSize, - NULL); + LinesCopied = NtGdiStretchDIBitsInternal( hdc, + XDest, + YDest, + nDestWidth, + nDestHeight, + XSrc, + YSrc, + nSrcWidth, + nSrcHeight, + pvSafeBits, + pConvertedInfo, + (DWORD) iUsage, + dwRop, + ConvertedInfoSize, + cjBmpScanSize, + NULL ); } if (pvSafeBits) RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); diff --git a/win32ss/gdi/gdi32/objects/coord.c b/win32ss/gdi/gdi32/objects/coord.c index b27711ca1e3..49c16bf93e7 100644 --- a/win32ss/gdi/gdi32/objects/coord.c +++ b/win32ss/gdi/gdi32/objects/coord.c @@ -142,7 +142,7 @@ SetMapMode( /* Handle METADC16 here, since we don't have a DCATTR. */ if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) \ { - return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0 ); + return METADC_SetMapMode(hdc, iMode); } /* Get the DC attribute */ @@ -157,7 +157,7 @@ SetMapMode( if ((iMode != pdcattr->iMapMode) || (iMode == MM_ISOTROPIC)) { pdcattr->ulDirty_ &= ~SLOW_WIDTHS; - return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0 ); + return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, EMR_SETMAPMODE, 0, 0 ); } return pdcattr->iMapMode; @@ -323,11 +323,11 @@ ModifyWorldTransform( if (dwMode == MWT_SET) { - HANDLE_METADC(BOOL, SetWorldTransform, FALSE, hdc, pxform); + HANDLE_EMETAFDC(BOOL, SetWorldTransform, FALSE, hdc, pxform); } else { - HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode); + HANDLE_EMETAFDC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode); } /* Get the DC attribute */ @@ -470,7 +470,7 @@ SetViewportExtEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize); + HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -537,7 +537,7 @@ SetWindowOrgEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y, lpPoint); + HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -589,7 +589,7 @@ SetWindowExtEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize); + HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent); /* Get the DC attr */ pdcattr = GdiGetDcAttr(hdc); @@ -660,7 +660,7 @@ SetViewportOrgEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y, lpPoint); + HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -707,7 +707,7 @@ ScaleViewportExtEx( _In_ INT yDenom, _Out_ LPSIZE lpSize) { - HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize); + HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom); if (!GdiGetDcAttr(hdc)) { @@ -731,7 +731,7 @@ ScaleWindowExtEx( _In_ INT yDenom, _Out_ LPSIZE lpSize) { - HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize); + HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom); if (!GdiGetDcAttr(hdc)) { @@ -863,7 +863,7 @@ OffsetViewportOrgEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint); + HANDLE_METADC16(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -895,6 +895,9 @@ OffsetViewportOrgEx( pdcattr->ptlViewportOrg.x += nXOffset; pdcattr->ptlViewportOrg.y += nYOffset; } + + HANDLE_EMETAFDC(BOOL, SetViewportOrgEx, FALSE, hdc, pdcattr->ptlViewportOrg.x, pdcattr->ptlViewportOrg.y); + return TRUE; // return NtGdiOffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint); @@ -914,7 +917,7 @@ OffsetWindowOrgEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint); + HANDLE_METADC16(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -946,6 +949,9 @@ OffsetWindowOrgEx( pdcattr->ptlWindowOrg.y += nYOffset; pdcattr->lWindowOrgx += nXOffset; } + + HANDLE_EMETAFDC(BOOL, SetWindowOrgEx, FALSE, hdc, pdcattr->ptlWindowOrg.x, pdcattr->ptlWindowOrg.y); + return TRUE; // return NtGdiOffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint); diff --git a/win32ss/gdi/gdi32/objects/dc.c b/win32ss/gdi/gdi32/objects/dc.c index 91df2a90984..f929dfdd011 100644 --- a/win32ss/gdi/gdi32/objects/dc.c +++ b/win32ss/gdi/gdi32/objects/dc.c @@ -281,47 +281,34 @@ BOOL WINAPI DeleteDC(HDC hdc) { - BOOL bResult = TRUE; - PLDC pLDC = NULL; - HANDLE hPrinter = NULL; ULONG hType = GDI_HANDLE_GET_TYPE(hdc); - pLDC = GdiGetLDC(hdc); - if (hType != GDILoObjType_LO_DC_TYPE) { - return METADC_DeleteDC(hdc); + return METADC_RosGlueDeleteDC(hdc); } - bResult = NtGdiDeleteObjectApp(hdc); + //if ( ghICM || pdcattr->pvLIcm ) + // IcmDeleteLocalDC( hdc, pdcattr, NULL ); - if (bResult && pLDC) - { - DPRINT1("Delete the Local DC structure\n"); - LocalFree( pLDC ); - } - - if (hPrinter) - fpClosePrinter(hPrinter); - - return bResult; + return NtGdiDeleteObjectApp(hdc); } /* - * @unimplemented + * @implemented */ INT WINAPI SaveDC(IN HDC hdc) { - HANDLE_METADC0P(INT, SaveDC, 0, hdc); + HANDLE_METADC1P(INT, SaveDC, 0, hdc); return NtGdiSaveDC(hdc); } /* - * @unimplemented + * @implemented */ BOOL WINAPI @@ -381,7 +368,7 @@ SetArcDirection( _In_ HDC hdc, _In_ INT nDirection) { - return GetAndSetDCDWord(hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0); + return GetAndSetDCDWord(hdc, GdiGetSetArcDirection, nDirection, EMR_SETARCDIRECTION, 0, 0); } /* @@ -565,21 +552,43 @@ GetDeviceCaps( _In_ int nIndex) { PDC_ATTR pdcattr; + PLDC pldc; + ULONG hType = GDI_HANDLE_GET_TYPE(hdc); PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities. DPRINT("Device CAPS1\n"); - HANDLE_METADC(INT, GetDeviceCaps, 0, hdc, nIndex); + HANDLE_METADC16(INT, GetDeviceCaps, 0, hdc, nIndex); - /* Get the DC attribute */ - pdcattr = GdiGetDcAttr(hdc); - if (pdcattr == NULL) + if ( hType != GDILoObjType_LO_DC_TYPE && hType != GDILoObjType_LO_METADC16_TYPE ) { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + pldc = GdiGetLDC(hdc); + if ( !pldc ) + { + SetLastError(ERROR_INVALID_HANDLE); + return 0; + } + if (!(pldc->Flags & LDC_DEVCAPS) ) + { + if (!NtGdiGetDeviceCapsAll(hdc, &pldc->DevCaps) ) + SetLastError(ERROR_INVALID_PARAMETER); - if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY)) - return NtGdiGetDeviceCaps(hdc, nIndex); + pldc->Flags |= LDC_DEVCAPS; + } + pDevCaps = &pldc->DevCaps; + } + else + { + /* Get the DC attribute */ + pdcattr = GdiGetDcAttr(hdc); + if ( pdcattr == NULL ) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; + } + + if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY)) + return NtGdiGetDeviceCaps(hdc, nIndex); + } switch (nIndex) { @@ -725,7 +734,7 @@ SetRelAbs( HDC hdc, INT Mode) { - return GetAndSetDCDWord(hdc, GdiGetSetRelAbs, Mode, 0, 0, 0); + return GetAndSetDCDWord(hdc, GdiGetSetRelAbs, Mode, 0, META_SETRELABS, 0); } @@ -743,9 +752,22 @@ GetAndSetDCDWord( _In_ DWORD dwError) { DWORD dwResult; + PLDC pldc; - /* This is a special API, handle it appropriately */ - HANDLE_METADC2(DWORD, GetAndSetDCDWord, hdc, u, dwIn, ulMFId, usMF16Id, dwError); + if ( GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE && + ulMFId != EMR_MAX + 1 ) + { + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + { + return METADC_SetD( hdc, dwIn, usMF16Id ); + } + pldc = GdiGetLDC(hdc); + if ( pldc->iType == LDC_EMFLDC) + { + if (!EMFDC_SetD( pldc, dwIn, ulMFId )) + return 0; + } + } /* Call win32k to do the real work */ if (!NtGdiGetAndSetDCDword(hdc, u, dwIn, &dwResult)) @@ -896,7 +918,7 @@ SetDCBrushColor( } /* We handle only enhanced meta DCs here */ - HANDLE_METADC(COLORREF, SetDCBrushColor, CLR_INVALID, hdc, crColor); + HANDLE_EMETAFDC(COLORREF, SetDCBrushColor, CLR_INVALID, hdc, crColor); /* Get old color and store the new */ crOldColor = pdcattr->ulBrushClr; @@ -932,7 +954,7 @@ SetDCPenColor( } /* We handle only enhanced meta DCs here */ - HANDLE_METADC(COLORREF, SetDCPenColor, CLR_INVALID, hdc, crColor); + HANDLE_EMETAFDC(COLORREF, SetDCPenColor, CLR_INVALID, hdc, crColor); /* Get old color and store the new */ crOldColor = pdcattr->ulPenClr; @@ -1292,7 +1314,7 @@ SelectPalette( HPALETTE hpal, BOOL bForceBackground) { - HANDLE_METADC(HPALETTE, SelectPalette, NULL, hdc, hpal, bForceBackground); + HANDLE_METADC(HPALETTE, SelectPalette, NULL, hdc, hpal); return NtUserSelectPalette(hdc, hpal, bForceBackground); } @@ -1392,7 +1414,7 @@ GdiSelectBrush( PDC_ATTR pdcattr; HBRUSH hbrOld; - HANDLE_METADC(HBRUSH, SelectBrush, NULL, hdc, hbr); + HANDLE_METADC(HBRUSH, SelectObject, NULL, hdc, hbr); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -1422,7 +1444,7 @@ GdiSelectPen( PDC_ATTR pdcattr; HPEN hpenOld; - HANDLE_METADC(HPEN, SelectPen, NULL, hdc, hpen); + HANDLE_METADC(HPEN, SelectObject, NULL, hdc, hpen); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -1452,7 +1474,7 @@ GdiSelectFont( PDC_ATTR pdcattr; HFONT hfontOld; - HANDLE_METADC(HFONT, SelectFont, NULL, hdc, hfont); + HANDLE_METADC(HFONT, SelectObject, NULL, hdc, hfont); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); diff --git a/win32ss/gdi/gdi32/objects/enhmfile.c b/win32ss/gdi/gdi32/objects/enhmfile.c index a7d168dc20a..c1c58d4867d 100644 --- a/win32ss/gdi/gdi32/objects/enhmfile.c +++ b/win32ss/gdi/gdi32/objects/enhmfile.c @@ -6,35 +6,31 @@ /* * @unimplemented */ -DWORD +BOOL WINAPI IsValidEnhMetaRecord( - DWORD a0, - DWORD a1 -) + PVOID pv0, + PVOID pv1) { UNIMPLEMENTED; SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - + return FALSE; } /* * @unimplemented */ -DWORD +BOOL WINAPI IsValidEnhMetaRecordOffExt( - DWORD a0, - DWORD a1, - DWORD a2, - DWORD a3 -) + PVOID pv0, + PVOID pv1, + DWORD dwOffset, + DWORD dwExtends ) { UNIMPLEMENTED; SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; - + return FALSE; } /* @@ -136,9 +132,7 @@ GdiComment( if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) return TRUE; - HANDLE_METADC(BOOL, GdiComment, FALSE, hdc, cbSize, lpData); - - return TRUE; + return EMFDC_GdiComment( hdc, cbSize, lpData ); } /* @@ -147,10 +141,9 @@ GdiComment( UINT WINAPI GetEnhMetaFilePixelFormat( - HENHMETAFILE hemf, - UINT cbBuffer, - PIXELFORMATDESCRIPTOR *ppfd -) + HENHMETAFILE hemf, + UINT cbBuffer, + PIXELFORMATDESCRIPTOR *ppfd ) { ENHMETAHEADER pemh; diff --git a/win32ss/gdi/gdi32/objects/gdiobj.c b/win32ss/gdi/gdi32/objects/gdiobj.c index ecd5d50f5e6..96617881fc4 100644 --- a/win32ss/gdi/gdi32/objects/gdiobj.c +++ b/win32ss/gdi/gdi32/objects/gdiobj.c @@ -323,14 +323,15 @@ DeleteObject(HGDIOBJ hObject) if ((DWORD_PTR)hObject & GDI_HANDLE_STOCK_MASK) { /* Ignore the attempt to delete a stock object */ - DPRINT("Trying to delete system object 0x%p\n", hObject); + DPRINT1("Trying to delete system object 0x%p\n", hObject); return TRUE; } /* If we have any METAFILE objects, we need to check them */ if (gcClientObj > 0) { - METADC_DeleteObject(hObject); + DPRINT("Going Glue\n"); + METADC_RosGlueDeleteObject(hObject); } /* Switch by object type */ @@ -349,16 +350,7 @@ DeleteObject(HGDIOBJ hObject) case GDILoObjType_LO_REGION_TYPE: return DeleteRegion(hObject); -#if 0 - case GDI_OBJECT_TYPE_METADC: - return MFDRV_DeleteObject( hObject ); - case GDI_OBJECT_TYPE_EMF: - { - PLDC pLDC = GdiGetLDC(hObject); - if ( !pLDC ) return FALSE; - return EMFDRV_DeleteObject( hObject ); - } -#endif + case GDILoObjType_LO_BRUSH_TYPE: case GDILoObjType_LO_PEN_TYPE: case GDILoObjType_LO_EXTPEN_TYPE: diff --git a/win32ss/gdi/gdi32/objects/metafile.c b/win32ss/gdi/gdi32/objects/metafile.c index 42bd22ec93c..f59d6ce40d6 100644 --- a/win32ss/gdi/gdi32/objects/metafile.c +++ b/win32ss/gdi/gdi32/objects/metafile.c @@ -17,19 +17,15 @@ */ BOOL WINAPI -GdiIsPlayMetafileDC(HDC hDC) +GdiIsPlayMetafileDC(HDC hdc) { -#if 0 - PLDC pLDC = GdiGetLDC(hDC); - if ( pLDC ) + PDC_ATTR pdcattr = GdiGetDcAttr(hdc); + + if ( pdcattr ) { - if ( pLDC->Flags & LDC_PLAY_MFDC ) return TRUE; + return !!( pdcattr->ulDirty_ & DC_PLAYMETAFILE ); } return FALSE; -#else - UNIMPLEMENTED; - return FALSE; -#endif } /* @@ -49,17 +45,13 @@ GdiIsMetaFileDC(HDC hdc) if (ulObjType == GDILoObjType_LO_ALTDC_TYPE) { -#if 0 PLDC pLDC = GdiGetLDC(hdc); if ( !pLDC ) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - if ( pLDC->iType == LDC_EMFLDC) return TRUE; - return FALSE; -#endif - return TRUE; + return !!( pLDC->iType == LDC_EMFLDC ); } return FALSE; @@ -70,29 +62,26 @@ GdiIsMetaFileDC(HDC hdc) */ BOOL WINAPI -GdiIsMetaPrintDC(HDC hDC) +GdiIsMetaPrintDC(HDC hdc) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) + ULONG hType = GDI_HANDLE_GET_TYPE(hdc); + + if ( hType != GDILoObjType_LO_DC_TYPE ) { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) + if ( hType == GDILoObjType_LO_METADC16_TYPE ) return FALSE; else { - PLDC pLDC = GdiGetLDC(hDC); + PLDC pLDC = GdiGetLDC(hdc); if ( !pLDC ) { SetLastError(ERROR_INVALID_HANDLE); return FALSE; } - if ( pLDC->Flags & LDC_META_PRINT) return TRUE; + return !!( pLDC->Flags & LDC_META_PRINT ); } } return FALSE; -#else - UNIMPLEMENTED; - return FALSE; -#endif } // NOTE: I wanna use GdiCreateLocalMetaFilePict and GdiConvertMetaFilePict diff --git a/win32ss/gdi/gdi32/objects/painting.c b/win32ss/gdi/gdi32/objects/painting.c index 17f64b8b384..9790111e55b 100644 --- a/win32ss/gdi/gdi32/objects/painting.c +++ b/win32ss/gdi/gdi32/objects/painting.c @@ -29,7 +29,7 @@ MoveToEx( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, MoveTo, FALSE, hdc, x, y, ppt); + HANDLE_METADC(BOOL, MoveTo, FALSE, hdc, x, y); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -265,7 +265,7 @@ PolyBezier( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { - HANDLE_METADC(BOOL, PolyBezier, FALSE, hdc, apt, cpt); + HANDLE_EMETAFDC(BOOL, PolyBezier, FALSE, hdc, apt, cpt); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -283,7 +283,7 @@ PolyBezierTo( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { - HANDLE_METADC(BOOL, PolyBezierTo, FALSE, hdc, apt, cpt); + HANDLE_EMETAFDC(BOOL, PolyBezierTo, FALSE, hdc, apt, cpt); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -302,7 +302,7 @@ PolyDraw( _In_reads_(cpt) const BYTE *aj, _In_ INT cpt) { - HANDLE_METADC(BOOL, PolyDraw, FALSE, hdc, apt, aj, cpt); + HANDLE_EMETAFDC(BOOL, PolyDraw, FALSE, hdc, apt, aj, cpt); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -356,7 +356,7 @@ PolylineTo( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { - HANDLE_METADC(BOOL, PolylineTo, FALSE, hdc, apt, cpt); + HANDLE_EMETAFDC(BOOL, PolylineTo, FALSE, hdc, apt, cpt); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -397,7 +397,7 @@ PolyPolyline( if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) return FALSE; - HANDLE_METADC(BOOL, PolyPolyline, FALSE, hdc, apt, asz, csz); + HANDLE_EMETAFDC(BOOL, PolyPolyline, FALSE, hdc, apt, asz, csz); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -461,9 +461,9 @@ BitBlt( return PatBlt(hdcDest, xDest, yDest, cx, cy, dwRop); } - /* For meta DCs we use StretchBlt */ + /* For meta DCs we use StretchBlt via emfdc.c */ HANDLE_METADC(BOOL, - StretchBlt, + BitBlt, FALSE, hdcDest, xDest, @@ -473,8 +473,6 @@ BitBlt( hdcSrc, xSrc, ySrc, - cx, - cy, dwRop); if ( GdiConvertAndCheckDC(hdcDest) == NULL ) return FALSE; @@ -494,7 +492,7 @@ PatBlt( { PDC_ATTR pdcattr; - HANDLE_METADC(BOOL, PatBlt, FALSE, hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop); + HANDLE_EMETAFDC(BOOL, PatBlt, FALSE, hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; @@ -686,7 +684,7 @@ MaskBlt( _In_ INT yMask, _In_ DWORD dwRop) { - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, MaskBlt, FALSE, hdcDest, @@ -737,7 +735,7 @@ PlgBlt( _In_ INT xMask, _In_ INT yMask) { - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, PlgBlt, FALSE, hdcDest, @@ -785,7 +783,7 @@ GdiAlphaBlend( if (GDI_HANDLE_GET_TYPE(hdcSrc) == GDI_OBJECT_TYPE_METADC) return FALSE; - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, AlphaBlend, FALSE, hdcDst, @@ -835,7 +833,7 @@ GdiTransparentBlt( _In_ INT cySrc, _In_ UINT crTransparent) { - HANDLE_METADC(BOOL, + HANDLE_EMETAFDC(BOOL, TransparentBlt, FALSE, hdcDst, @@ -868,7 +866,9 @@ GdiGradientFill( _In_ ULONG nCount, _In_ ULONG ulMode) { - HANDLE_METADC(BOOL, GradientFill, FALSE, hdc, pVertex, nVertex, pMesh, nCount, ulMode); + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) return TRUE; + + HANDLE_EMETAFDC(BOOL, GradientFill, FALSE, hdc, pVertex, nVertex, pMesh, nCount, ulMode); if ( GdiConvertAndCheckDC(hdc) == NULL ) return FALSE; diff --git a/win32ss/gdi/gdi32/objects/palette.c b/win32ss/gdi/gdi32/objects/palette.c index 3c7afd74339..c79ca27308f 100644 --- a/win32ss/gdi/gdi32/objects/palette.c +++ b/win32ss/gdi/gdi32/objects/palette.c @@ -138,7 +138,10 @@ WINAPI RealizePalette( _In_ HDC hdc) /* [in] Handle of device context */ { - HANDLE_METADC0P(UINT, RealizePalette, GDI_ERROR, hdc); + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + { + return METADC_RealizePalette(hdc); + } if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) { diff --git a/win32ss/gdi/gdi32/objects/path.c b/win32ss/gdi/gdi32/objects/path.c index 01ba886c3ae..26922f46350 100644 --- a/win32ss/gdi/gdi32/objects/path.c +++ b/win32ss/gdi/gdi32/objects/path.c @@ -120,7 +120,7 @@ WINAPI PathToRegion( HDC hdc) { - HANDLE_METADC0P(HRGN, PathToRegion, NULL, hdc); + HANDLE_METADC0P(HRGN, AbortPath, NULL, hdc); return NtGdiPathToRegion(hdc); } @@ -192,6 +192,6 @@ SelectClipPath( HDC hdc, int iMode) { - HANDLE_METADC(BOOL, SelectClipPath, FALSE, hdc, iMode); + HANDLE_EMETAFDC(BOOL, SelectClipPath, FALSE, hdc, iMode); return NtGdiSelectClipPath(hdc, iMode); } diff --git a/win32ss/gdi/gdi32/objects/region.c b/win32ss/gdi/gdi32/objects/region.c index d7d2c330f73..17b500af01d 100644 --- a/win32ss/gdi/gdi32/objects/region.c +++ b/win32ss/gdi/gdi32/objects/region.c @@ -1086,20 +1086,22 @@ int WINAPI SetMetaRgn(HDC hDC) { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC) - return NtGdiSetMetaRgn(hDC); -#if 0 - PLDC pLDC = GdiGetLDC(hDC); - if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_METADC ) + if (GDI_HANDLE_GET_TYPE(hDC) != GDILoObjType_LO_DC_TYPE) { - if (pLDC->iType == LDC_EMFLDC || EMFDRV_SetMetaRgn(hDC)) + PLDC pLDC = GdiGetLDC(hDC); + if ( pLDC && GDI_HANDLE_GET_TYPE(hDC) != GDILoObjType_LO_METADC16_TYPE ) { - return NtGdiSetMetaRgn(hDC); + if (pLDC->iType == LDC_EMFLDC && !EMFDC_SetMetaRgn( pLDC )) + { + return ERROR; + } } else + { SetLastError(ERROR_INVALID_HANDLE); + return ERROR; + } } -#endif - return ERROR; + return NtGdiSetMetaRgn(hDC); } diff --git a/win32ss/gdi/gdi32/objects/text.c b/win32ss/gdi/gdi32/objects/text.c index 9a08ec56d16..799c20f5f72 100644 --- a/win32ss/gdi/gdi32/objects/text.c +++ b/win32ss/gdi/gdi32/objects/text.c @@ -782,10 +782,7 @@ SetTextCharacterExtra( return 0x80000000; } - if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) - { - HANDLE_METADC(INT, SetTextCharacterExtra, 0x80000000, hdc, nCharExtra); - } + HANDLE_METADC16(INT, SetTextCharacterExtra, 0x80000000, hdc, nCharExtra); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -935,10 +932,7 @@ SetTextJustification( { PDC_ATTR pdcattr; - if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) - { - HANDLE_METADC(BOOL, SetTextJustification, FALSE, hdc, nBreakExtra, nBreakCount); - } + HANDLE_METADC16(BOOL, SetTextJustification, FALSE, hdc, nBreakExtra, nBreakCount); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); diff --git a/win32ss/gdi/gdi32/wine/CMakeLists.txt b/win32ss/gdi/gdi32/wine/CMakeLists.txt index 4f70a336d05..387b224e4c8 100644 --- a/win32ss/gdi/gdi32/wine/CMakeLists.txt +++ b/win32ss/gdi/gdi32/wine/CMakeLists.txt @@ -6,20 +6,11 @@ include_directories( .) list(APPEND SOURCE + emfdc.c + emfdrv.c enhmetafile.c + metadc.c metafile.c - path.c - enhmfdrv/bitblt.c - enhmfdrv/dc.c - enhmfdrv/graphics.c - enhmfdrv/init.c - enhmfdrv/objects.c - mfdrv/bitblt.c - mfdrv/dc.c - mfdrv/graphics.c - mfdrv/init.c - mfdrv/objects.c - mfdrv/text.c rosglue.c) add_library(winegdi ${SOURCE}) diff --git a/win32ss/gdi/gdi32/wine/emfdc.c b/win32ss/gdi/gdi32/wine/emfdc.c new file mode 100644 index 00000000000..b300e0efea8 --- /dev/null +++ b/win32ss/gdi/gdi32/wine/emfdc.c @@ -0,0 +1,2569 @@ +/* + * Enhanced MetaFile recording functions + * + * Copyright 1999 Huw D M Davies + * Copyright 2016 Alexandre Julliard + * Copyright 2021 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include "config.h" + +#include +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winnls.h" +#include "winerror.h" +#include "gdi_private.h" +#include "wine/wingdi16.h" +#include "wine/debug.h" +#ifdef __REACTOS__ +#include "wine/winternl.h" +#else +#include "winternl.h" +#endif + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +struct emf +{ + ENHMETAHEADER *emh; + WINEDC *dc_attr; + UINT handles_size, cur_handles; + HGDIOBJ *handles; + HANDLE file; + HBRUSH dc_brush; + HPEN dc_pen; + BOOL path; +}; + +#define HANDLE_LIST_INC 20 +static const RECTL empty_bounds = { 0, 0, -1, -1 }; + +static BOOL emfdc_record( struct emf *emf, EMR *emr ) +{ + DWORD len, size; + ENHMETAHEADER *emh; + + TRACE( "record %d, size %d\n", emr->iType, emr->nSize ); + + assert( !(emr->nSize & 3) ); + + emf->emh->nBytes += emr->nSize; + emf->emh->nRecords++; + + size = HeapSize( GetProcessHeap(), 0, emf->emh ); + len = emf->emh->nBytes; + if (len > size) + { + size += (size / 2) + emr->nSize; + emh = HeapReAlloc( GetProcessHeap(), 0, emf->emh, size ); + if (!emh) return FALSE; + emf->emh = emh; + } + memcpy( (char *)emf->emh + emf->emh->nBytes - emr->nSize, emr, emr->nSize ); + return TRUE; +} + +static void emfdc_update_bounds( struct emf *emf, RECTL *rect ) +{ + RECTL *bounds = &emf->dc_attr->emf_bounds; + RECTL vport_rect = *rect; + + LPtoDP( emf->dc_attr->hdc, (POINT *)&vport_rect, 2 ); + + /* The coordinate systems may be mirrored + (LPtoDP handles points, not rectangles) */ + if (vport_rect.left > vport_rect.right) + { + LONG temp = vport_rect.right; + vport_rect.right = vport_rect.left; + vport_rect.left = temp; + } + if (vport_rect.top > vport_rect.bottom) + { + LONG temp = vport_rect.bottom; + vport_rect.bottom = vport_rect.top; + vport_rect.top = temp; + } + + if (bounds->left > bounds->right) + { + /* first bounding rectangle */ + *bounds = vport_rect; + } + else + { + bounds->left = min(bounds->left, vport_rect.left); + bounds->top = min(bounds->top, vport_rect.top); + bounds->right = max(bounds->right, vport_rect.right); + bounds->bottom = max(bounds->bottom, vport_rect.bottom); + } +} + +static UINT get_bitmap_info( HDC *hdc, HBITMAP *bitmap, BITMAPINFO *info ) +{ + HBITMAP blit_bitmap; + HDC blit_dc; + UINT info_size, bpp; + DIBSECTION dib; + + if (!(info_size = GetObjectW( *bitmap, sizeof(dib), &dib ))) return 0; + + if (info_size == sizeof(dib)) + { + blit_dc = *hdc; + blit_bitmap = *bitmap; + } + else + { + unsigned char dib_info_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *dib_info = (BITMAPINFO *)dib_info_buffer; + BITMAP bmp = dib.dsBm; + HPALETTE palette; + void *bits; + + assert( info_size == sizeof(BITMAP) ); + + dib_info->bmiHeader.biSize = sizeof(dib_info->bmiHeader); + dib_info->bmiHeader.biWidth = bmp.bmWidth; + dib_info->bmiHeader.biHeight = bmp.bmHeight; + dib_info->bmiHeader.biPlanes = 1; + dib_info->bmiHeader.biBitCount = bmp.bmBitsPixel; + dib_info->bmiHeader.biCompression = BI_RGB; + dib_info->bmiHeader.biSizeImage = 0; + dib_info->bmiHeader.biXPelsPerMeter = 0; + dib_info->bmiHeader.biYPelsPerMeter = 0; + dib_info->bmiHeader.biClrUsed = 0; + dib_info->bmiHeader.biClrImportant = 0; + switch (dib_info->bmiHeader.biBitCount) + { + case 16: + ((DWORD *)dib_info->bmiColors)[0] = 0xf800; + ((DWORD *)dib_info->bmiColors)[1] = 0x07e0; + ((DWORD *)dib_info->bmiColors)[2] = 0x001f; + break; + case 32: + ((DWORD *)dib_info->bmiColors)[0] = 0xff0000; + ((DWORD *)dib_info->bmiColors)[1] = 0x00ff00; + ((DWORD *)dib_info->bmiColors)[2] = 0x0000ff; + break; + default: + if (dib_info->bmiHeader.biBitCount > 8) break; + if (!(palette = GetCurrentObject( *hdc, OBJ_PAL ))) return FALSE; + if (!GetPaletteEntries( palette, 0, 256, (PALETTEENTRY *)dib_info->bmiColors )) + return FALSE; + } + + if (!(blit_dc = /*NtGdi*/CreateCompatibleDC( *hdc ))) return FALSE; + if (!(blit_bitmap = CreateDIBSection( blit_dc, dib_info, DIB_RGB_COLORS, &bits, NULL, 0 ))) + goto err; + if (!SelectObject( blit_dc, blit_bitmap )) goto err; + if (!BitBlt( blit_dc, 0, 0, bmp.bmWidth, bmp.bmHeight, *hdc, 0, 0, SRCCOPY )) + goto err; + } + if (!GetDIBits( blit_dc, blit_bitmap, 0, INT_MAX, NULL, info, DIB_RGB_COLORS )) + goto err; + + bpp = info->bmiHeader.biBitCount; + if (bpp <= 8) + return sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD); + else if (bpp == 16 || bpp == 32) + return sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD); + + return sizeof(BITMAPINFOHEADER); + +err: + if (blit_dc && blit_dc != *hdc) DeleteDC( blit_dc ); + if (blit_bitmap && blit_bitmap != *bitmap) DeleteObject( blit_bitmap ); + return 0; +} + +static UINT emfdc_add_handle( struct emf *emf, HGDIOBJ obj ) +{ + UINT index; + + for (index = 0; index < emf->handles_size; index++) + if (emf->handles[index] == 0) break; + + if (index == emf->handles_size) + { + emf->handles_size += HANDLE_LIST_INC; + emf->handles = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + emf->handles, + emf->handles_size * sizeof(emf->handles[0]) ); + } + emf->handles[index] = get_full_gdi_handle( obj ); + + emf->cur_handles++; + if (emf->cur_handles > emf->emh->nHandles) + emf->emh->nHandles++; + + return index + 1; /* index 0 is reserved for the hmf, so we increment everything by 1 */ +} + +static UINT emfdc_find_object( struct emf *emf, HGDIOBJ obj ) +{ + UINT index; + + for (index = 0; index < emf->handles_size; index++) + if (emf->handles[index] == obj) return index + 1; + + return 0; +} + +void emfdc_delete_object( HDC hdc, HGDIOBJ obj ) +{ + WINEDC *dc_attr = get_dc_ptr( hdc ); + struct emf *emf = dc_attr->emf; + EMRDELETEOBJECT emr; + UINT index; + + if(!(index = emfdc_find_object( emf, obj ))) return; + + emr.emr.iType = EMR_DELETEOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + + emfdc_record( emf, &emr.emr ); + + emf->handles[index - 1] = 0; + emf->cur_handles--; +} + +static DWORD emfdc_create_brush( struct emf *emf, HBRUSH brush ) +{ + DWORD index = 0; + LOGBRUSH logbrush; + + if (!GetObjectA( brush, 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 = emfdc_add_handle( emf, brush ); + emr.lb.lbStyle = logbrush.lbStyle; + emr.lb.lbColor = logbrush.lbColor; + emr.lb.lbHatch = logbrush.lbHatch; + + if(!emfdc_record( emf, &emr.emr )) + index = 0; + } + break; + case BS_PATTERN: + case BS_DIBPATTERN: + { + EMRCREATEDIBPATTERNBRUSHPT *emr; + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; + DWORD info_size; + UINT usage; + + if (!get_brush_bitmap_info( brush, info, NULL, &usage )) break; + info_size = get_dib_info_size( info, usage ); + + emr = HeapAlloc( GetProcessHeap(), 0, + sizeof(EMRCREATEDIBPATTERNBRUSHPT) + sizeof(DWORD) + + info_size+info->bmiHeader.biSizeImage ); + if(!emr) break; + + /* FIXME: There is an extra DWORD written by native before the BMI. + * Not sure what it's meant to contain. + */ + emr->offBmi = sizeof( EMRCREATEDIBPATTERNBRUSHPT ) + sizeof(DWORD); + *(DWORD *)(emr + 1) = 0x20000000; + + if (logbrush.lbStyle == BS_PATTERN && info->bmiHeader.biBitCount == 1) + { + /* Presumably to reduce the size of the written EMF, MS supports an + * undocumented iUsage value of 2, indicating a mono bitmap without the + * 8 byte 2 entry black/white palette. Stupidly, they could have saved + * over 20 bytes more by also ignoring the BITMAPINFO fields that are + * irrelevant/constant for monochrome bitmaps. + * FIXME: It may be that the DIB functions themselves accept this value. + */ + emr->emr.iType = EMR_CREATEMONOBRUSH; + usage = DIB_PAL_MONO; + emr->cbBmi = sizeof( BITMAPINFOHEADER ); + } + else + { + emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; + emr->cbBmi = info_size; + } + emr->ihBrush = index = emfdc_add_handle( emf, brush ); + emr->iUsage = usage; + emr->offBits = emr->offBmi + emr->cbBmi; + emr->cbBits = info->bmiHeader.biSizeImage; + emr->emr.nSize = emr->offBits + emr->cbBits; + + if (info->bmiHeader.biClrUsed == 1 << info->bmiHeader.biBitCount) + info->bmiHeader.biClrUsed = 0; + memcpy( (BYTE *)emr + emr->offBmi, info, emr->cbBmi ); + get_brush_bitmap_info( brush, NULL, (char *)emr + emr->offBits, NULL ); + + if (!emfdc_record( emf, &emr->emr )) index = 0; + HeapFree( GetProcessHeap(), 0, emr ); + } + break; + + default: + FIXME("Unknown style %x\n", logbrush.lbStyle); + break; + } + + return index; +} + +static BOOL emfdc_select_brush( WINEDC *dc_attr, HBRUSH brush ) +{ + struct emf *emf = dc_attr->emf; + EMRSELECTOBJECT emr; + DWORD index = 0; + 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 <= DC_BRUSH; i++) + { + if (brush == GetStockObject(i)) + { + index = i | 0x80000000; + break; + } + } + + if (!index && !(index = emfdc_find_object( emf, brush ))) + { + if (!(index = emfdc_create_brush( emf, brush ))) return 0; + GDI_hdc_using_object( brush, dc_attr->hdc);//, emfdc_delete_object ); + } + + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return emfdc_record( emf, &emr.emr ); +} + +static BOOL emfdc_create_font( struct emf *emf, HFONT font ) +{ + DWORD index = 0; + EMREXTCREATEFONTINDIRECTW emr; + int i; + + if (!GetObjectW( font, sizeof(emr.elfw.elfLogFont), &emr.elfw.elfLogFont )) return FALSE; + + emr.emr.iType = EMR_EXTCREATEFONTINDIRECTW; + emr.emr.nSize = (sizeof(emr) + 3) / 4 * 4; + emr.ihFont = index = emfdc_add_handle( emf, font ); + 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; + + return emfdc_record( emf, &emr.emr ) ? index : 0; +} + +static BOOL emfdc_select_font( WINEDC *dc_attr, HFONT font ) +{ + struct emf *emf = dc_attr->emf; + 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 && font == GetStockObject(i)) + { + index = i | 0x80000000; + goto found; + } + } + + if (!(index = emfdc_find_object( emf, font ))) + { + if (!(index = emfdc_create_font( emf, font ))) return FALSE; + GDI_hdc_using_object( font, dc_attr->hdc);//, emfdc_delete_object ); + } + + found: + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return emfdc_record( emf, &emr.emr ); +} + +static DWORD emfdc_create_pen( struct emf *emf, HPEN hPen ) +{ + EMRCREATEPEN emr; + DWORD index = 0; + + if (!GetObjectW( hPen, sizeof(emr.lopn), &emr.lopn )) + { + /* must be an extended pen */ + EXTLOGPEN *elp; + INT size = GetObjectW( hPen, 0, NULL ); + + if (!size) return 0; + + elp = HeapAlloc( GetProcessHeap(), 0, size ); + + GetObjectW( hPen, size, elp ); + /* FIXME: add support for user style pens */ + emr.lopn.lopnStyle = elp->elpPenStyle; + emr.lopn.lopnWidth.x = elp->elpWidth; + emr.lopn.lopnWidth.y = 0; + emr.lopn.lopnColor = elp->elpColor; + + HeapFree( GetProcessHeap(), 0, elp ); + } + + emr.emr.iType = EMR_CREATEPEN; + emr.emr.nSize = sizeof(emr); + emr.ihPen = index = emfdc_add_handle( emf, hPen ); + return emfdc_record( emf, &emr.emr ) ? index : 0; +} + +static BOOL emfdc_select_pen( WINEDC *dc_attr, HPEN pen ) +{ + struct emf *emf = dc_attr->emf; + EMRSELECTOBJECT emr; + DWORD index = 0; + 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 <= DC_PEN; i++) + { + if (pen == GetStockObject(i)) + { + index = i | 0x80000000; + break; + } + } + if (!index && !(index = emfdc_find_object( emf, pen ))) + { + if (!(index = emfdc_create_pen( emf, pen ))) return FALSE; + GDI_hdc_using_object( pen, dc_attr->hdc);//, emfdc_delete_object ); + } + + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return emfdc_record( emf, &emr.emr ); +} + +static DWORD emfdc_create_palette( struct emf *emf, HPALETTE hPal ) +{ + WORD i; + struct { + EMRCREATEPALETTE hdr; + PALETTEENTRY entry[255]; + } pal; + + memset( &pal, 0, sizeof(pal) ); + + if (!GetObjectW( hPal, sizeof(pal.hdr.lgpl) + sizeof(pal.entry), &pal.hdr.lgpl )) + return 0; + + for (i = 0; i < pal.hdr.lgpl.palNumEntries; i++) + pal.hdr.lgpl.palPalEntry[i].peFlags = 0; + + pal.hdr.emr.iType = EMR_CREATEPALETTE; + pal.hdr.emr.nSize = sizeof(pal.hdr) + pal.hdr.lgpl.palNumEntries * sizeof(PALETTEENTRY); + pal.hdr.ihPal = emfdc_add_handle( emf, hPal ); + + if (!emfdc_record( emf, &pal.hdr.emr )) + pal.hdr.ihPal = 0; + return pal.hdr.ihPal; +} + +BOOL EMFDC_SelectPalette( WINEDC *dc_attr, HPALETTE palette ) +{ + struct emf *emf = dc_attr->emf; + EMRSELECTPALETTE emr; + DWORD index = 0; + + if (palette == GetStockObject( DEFAULT_PALETTE )) + { + index = DEFAULT_PALETTE | 0x80000000; + } + else if (!(index = emfdc_find_object( emf, palette ))) + { + if (!(index = emfdc_create_palette( emf, palette ))) return 0; + GDI_hdc_using_object( palette, dc_attr->hdc);//, emfdc_delete_object ); + } + + emr.emr.iType = EMR_SELECTPALETTE; + emr.emr.nSize = sizeof(emr); + emr.ihPal = index; + return emfdc_record( emf, &emr.emr ); +} + +BOOL EMFDC_SelectObject( WINEDC *dc_attr, HGDIOBJ obj ) +{ + switch (GDI_HANDLE_GET_TYPE( obj )) + { + case GDILoObjType_LO_BRUSH_TYPE: + return emfdc_select_brush( dc_attr, obj ); + case GDILoObjType_LO_FONT_TYPE: + return emfdc_select_font( dc_attr, obj ); + case GDILoObjType_LO_PEN_TYPE: + case GDILoObjType_LO_EXTPEN_TYPE: + return emfdc_select_pen( dc_attr, obj ); + default: + return TRUE; + } +} + +/* determine if we can use 16-bit points to store all the input points */ +static BOOL can_use_short_points( const POINT *pts, UINT count ) +{ + UINT i; + + for (i = 0; i < count; i++) + if (((pts[i].x + 0x8000) & ~0xffff) || ((pts[i].y + 0x8000) & ~0xffff)) + return FALSE; + return TRUE; +} + +/* store points in either long or short format; return a pointer to the end of the stored data */ +static void *store_points( POINTL *dest, const POINT *pts, UINT count, BOOL short_points ) +{ + if (short_points) + { + UINT i; + POINTS *dest_short = (POINTS *)dest; + + for (i = 0; i < count; i++) + { + dest_short[i].x = pts[i].x; + dest_short[i].y = pts[i].y; + } + return dest_short + count; + } + else + { + memcpy( dest, pts, count * sizeof(*dest) ); + return dest + count; + } +} + +/* compute the bounds of an array of points, optionally including the current position */ +static void get_points_bounds( RECTL *bounds, const POINT *pts, UINT count, WINEDC *dc_attr ) +{ + UINT i; + + if (dc_attr) + { + POINT cur_pos; + GetCurrentPositionEx(dc_attr->hdc, &cur_pos); + bounds->left = bounds->right = cur_pos.x; + bounds->top = bounds->bottom = cur_pos.y; + } + else if (count) + { + bounds->left = bounds->right = pts[0].x; + bounds->top = bounds->bottom = pts[0].y; + } + else *bounds = empty_bounds; + + for (i = 0; i < count; i++) + { + bounds->left = min( bounds->left, pts[i].x ); + bounds->right = max( bounds->right, pts[i].x ); + bounds->top = min( bounds->top, pts[i].y ); + bounds->bottom = max( bounds->bottom, pts[i].y ); + } +} + +/* helper for path stroke and fill functions */ +#ifdef __REACTOS__ +static BOOL emfdrv_stroke_and_fill_path( struct emf *emf, INT type ) +{ + EMRSTROKEANDFILLPATH emr; + LPPOINT Points; + LPBYTE Types; + INT nSize; + + emr.emr.iType = type; + emr.emr.nSize = sizeof(emr); + + nSize = GetPath(emf->dc_attr->hdc, NULL, NULL, 0); + if (nSize != -1) + { + Points = HeapAlloc( GetProcessHeap(), 0, nSize*sizeof(POINT) ); + Types = HeapAlloc( GetProcessHeap(), 0, nSize*sizeof(BYTE) ); + + GetPath(emf->dc_attr->hdc, Points, Types, nSize); + get_points_bounds( &emr.rclBounds, Points, nSize, 0 ); + + HeapFree( GetProcessHeap(), 0, Points ); + HeapFree( GetProcessHeap(), 0, Types ); + + TRACE("GetBounds l %d t %d r %d b %d\n",emr.rclBounds.left, emr.rclBounds.top, emr.rclBounds.right, emr.rclBounds.bottom); + } + else emr.rclBounds = empty_bounds; + + if (!emfdc_record( emf, &emr.emr )) return FALSE; + if (nSize == -1 ) return FALSE; + emfdc_update_bounds( emf, &emr.rclBounds ); + return TRUE; +} +#else +static BOOL emfdrv_stroke_and_fill_path( struct emf *emf, INT type ) +{ + EMRSTROKEANDFILLPATH emr; + HRGN region; + + emr.emr.iType = type; + emr.emr.nSize = sizeof(emr); + emr.rclBounds = empty_bounds; + + if ((region = NtGdiPathToRegion( emf->dc_attr->hdc ))) // WTF are you doing? This removes path!!! + { + NtGdiGetRgnBox( region, (RECT *)&emr.rclBounds ); + DeleteObject( region ); + } + if (!emfdc_record( emf, &emr.emr )) return FALSE; + if (!region) return FALSE; + emfdc_update_bounds( emf, &emr.rclBounds ); + return TRUE; +} +#endif +BOOL EMFDC_MoveTo( WINEDC *dc_attr, INT x, INT y ) +{ + struct emf *emf = dc_attr->emf; + EMRMOVETOEX emr; + + emr.emr.iType = EMR_MOVETOEX; + emr.emr.nSize = sizeof(emr); + emr.ptl.x = x; + emr.ptl.y = y; + return emfdc_record( emf, &emr.emr ); +} + +BOOL EMFDC_LineTo( WINEDC *dc_attr, INT x, INT y ) +{ + EMRLINETO emr; + BOOL Ret; + + emr.emr.iType = EMR_LINETO; + emr.emr.nSize = sizeof(emr); + emr.ptl.x = x; + emr.ptl.y = y; + Ret = emfdc_record( dc_attr->emf, &emr.emr ); + EMFDRV_LineTo( dc_attr, x, y ); + return Ret; +} + +BOOL EMFDC_ArcChordPie( WINEDC *dc_attr, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend, DWORD type ) +{ + struct emf *emf = dc_attr->emf; + EMRARC emr; + INT temp; + BOOL Ret; + + 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(dc_attr->hdc) == GM_COMPATIBLE) + { + right--; + bottom--; + } + + emr.emr.iType = type; + 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.y = yend; + Ret = emfdc_record( emf, &emr.emr ); + EMFDRV_ArcChordPie( dc_attr, left, top, right, bottom, xstart, ystart, xend, yend, type ); + return Ret; +} + +BOOL EMFDC_AngleArc( WINEDC *dc_attr, INT x, INT y, DWORD radius, FLOAT start, FLOAT sweep ) +{ + EMRANGLEARC emr; + + emr.emr.iType = EMR_ANGLEARC; + emr.emr.nSize = sizeof( emr ); + emr.ptlCenter.x = x; + emr.ptlCenter.y = y; + emr.nRadius = radius; + emr.eStartAngle = start; + emr.eSweepAngle = sweep; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_Ellipse( WINEDC *dc_attr, INT left, INT top, INT right, INT bottom ) +{ + struct emf *emf = dc_attr->emf; + EMRELLIPSE emr; + BOOL Ret; + + if (left == right || top == bottom) return FALSE; + + emr.emr.iType = EMR_ELLIPSE; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = min( left, right ); + emr.rclBox.top = min( top, bottom ); + emr.rclBox.right = max( left, right ); + emr.rclBox.bottom = max( top, bottom ); + if (GetGraphicsMode(dc_attr->hdc) == GM_COMPATIBLE) + { + emr.rclBox.right--; + emr.rclBox.bottom--; + } + Ret = emfdc_record( emf, &emr.emr ); + EMFDRV_Ellipse( dc_attr, left, top, right, bottom ); + return Ret; +} + +BOOL EMFDC_Rectangle( WINEDC *dc_attr, INT left, INT top, INT right, INT bottom ) +{ + struct emf *emf = dc_attr->emf; + EMRRECTANGLE emr; + BOOL Ret; + + if(left == right || top == bottom) return FALSE; + + emr.emr.iType = EMR_RECTANGLE; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = min( left, right ); + emr.rclBox.top = min( top, bottom ); + emr.rclBox.right = max( left, right ); + emr.rclBox.bottom = max( top, bottom ); + if (GetGraphicsMode(dc_attr->hdc) == GM_COMPATIBLE) + { + emr.rclBox.right--; + emr.rclBox.bottom--; + } + Ret = emfdc_record( emf, &emr.emr ); + EMFDRV_Rectangle( dc_attr, left, top, right, bottom ); + return Ret; +} + +BOOL EMFDC_RoundRect( WINEDC *dc_attr, INT left, INT top, INT right, + INT bottom, INT ell_width, INT ell_height ) +{ + struct emf *emf = dc_attr->emf; + EMRROUNDRECT emr; + BOOL Ret; + + if (left == right || top == bottom) return FALSE; + + emr.emr.iType = EMR_ROUNDRECT; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = min( left, right ); + emr.rclBox.top = min( top, bottom ); + emr.rclBox.right = max( left, right ); + emr.rclBox.bottom = max( top, bottom ); + emr.szlCorner.cx = ell_width; + emr.szlCorner.cy = ell_height; + if (GetGraphicsMode(dc_attr->hdc) == GM_COMPATIBLE) + { + emr.rclBox.right--; + emr.rclBox.bottom--; + } + Ret = emfdc_record( emf, &emr.emr ); + EMFDRV_RoundRect( dc_attr, left, top, right, bottom, ell_width, ell_height ); + return Ret; +} + +BOOL EMFDC_SetPixel( WINEDC *dc_attr, INT x, INT y, COLORREF color ) +{ + EMRSETPIXELV emr; + BOOL Ret; + + emr.emr.iType = EMR_SETPIXELV; + emr.emr.nSize = sizeof(emr); + emr.ptlPixel.x = x; + emr.ptlPixel.y = y; + emr.crColor = color; + Ret = emfdc_record( dc_attr->emf, &emr.emr ); + EMFDRV_SetPixel( dc_attr, x, y, color ); + return Ret; +} + +static BOOL emfdc_polylinegon( WINEDC *dc_attr, const POINT *points, INT count, DWORD type ) +{ + struct emf *emf = dc_attr->emf; + EMRPOLYLINE *emr; + DWORD size; + BOOL ret, use_small_emr = can_use_short_points( points, count ); + + size = use_small_emr ? offsetof( EMRPOLYLINE16, apts[count] ) : offsetof( EMRPOLYLINE, aptl[count] ); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + emr->emr.iType = use_small_emr ? type + EMR_POLYLINE16 - EMR_POLYLINE : type; + emr->emr.nSize = size; + emr->cptl = count; + + store_points( emr->aptl, points, count, use_small_emr ); + + if (!emf->path) + get_points_bounds( &emr->rclBounds, points, count, + (type == EMR_POLYBEZIERTO || type == EMR_POLYLINETO) ? dc_attr : 0 ); + else + emr->rclBounds = empty_bounds; + + ret = emfdc_record( emf, &emr->emr ); + if (ret && !emf->path) emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_Polyline( WINEDC *dc_attr, const POINT *points, INT count ) +{ + return emfdc_polylinegon( dc_attr, points, count, EMR_POLYLINE ); +} + +BOOL EMFDC_PolylineTo( WINEDC *dc_attr, const POINT *points, INT count ) +{ + return emfdc_polylinegon( dc_attr, points, count, EMR_POLYLINETO ); +} + +BOOL EMFDC_Polygon( WINEDC *dc_attr, const POINT *pt, INT count ) +{ + if(count < 2) return FALSE; + return emfdc_polylinegon( dc_attr, pt, count, EMR_POLYGON ); +} + +BOOL EMFDC_PolyBezier( WINEDC *dc_attr, const POINT *pts, DWORD count ) +{ + return emfdc_polylinegon( dc_attr, pts, count, EMR_POLYBEZIER ); +} + +BOOL EMFDC_PolyBezierTo( WINEDC *dc_attr, const POINT *pts, DWORD count ) +{ + return emfdc_polylinegon( dc_attr, pts, count, EMR_POLYBEZIERTO ); +} + +static BOOL emfdc_poly_polylinegon( struct emf *emf, const POINT *pt, const INT *counts, + UINT polys, DWORD type) +{ + EMRPOLYPOLYLINE *emr; + DWORD cptl = 0, poly, size; + BOOL ret, use_small_emr, bounds_valid = TRUE; + + for(poly = 0; poly < polys; poly++) { + cptl += counts[poly]; + if(counts[poly] < 2) bounds_valid = FALSE; + } + if(!cptl) bounds_valid = FALSE; + use_small_emr = can_use_short_points( pt, cptl ); + + size = FIELD_OFFSET(EMRPOLYPOLYLINE, aPolyCounts[polys]); + if(use_small_emr) + size += cptl * sizeof(POINTS); + else + size += cptl * sizeof(POINTL); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + emr->emr.iType = type; + if(use_small_emr) emr->emr.iType += EMR_POLYPOLYLINE16 - EMR_POLYPOLYLINE; + + emr->emr.nSize = size; + if(bounds_valid && !emf->path) + get_points_bounds( &emr->rclBounds, pt, cptl, 0 ); + else + emr->rclBounds = empty_bounds; + emr->nPolys = polys; + emr->cptl = cptl; + + if(polys) + { + memcpy( emr->aPolyCounts, counts, polys * sizeof(DWORD) ); + store_points( (POINTL *)(emr->aPolyCounts + polys), pt, cptl, use_small_emr ); + } + + ret = emfdc_record( emf, &emr->emr ); + if(ret && !bounds_valid) + { + ret = FALSE; + SetLastError( ERROR_INVALID_PARAMETER ); + } + if(ret && !emf->path) + emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_PolyPolyline( WINEDC *dc_attr, const POINT *pt, const DWORD *counts, DWORD polys) +{ + return emfdc_poly_polylinegon( dc_attr->emf, pt, (const INT *)counts, polys, EMR_POLYPOLYLINE ); +} + +BOOL EMFDC_PolyPolygon( WINEDC *dc_attr, const POINT *pt, const INT *counts, UINT polys ) +{ + return emfdc_poly_polylinegon( dc_attr->emf, pt, counts, polys, EMR_POLYPOLYGON ); +} + +BOOL EMFDC_PolyDraw( WINEDC *dc_attr, const POINT *pts, const BYTE *types, DWORD count ) +{ + struct emf *emf = dc_attr->emf; + EMRPOLYDRAW *emr; + BOOL ret; + BYTE *types_dest; + BOOL use_small_emr = can_use_short_points( pts, count ); + DWORD size; + + size = use_small_emr ? offsetof( EMRPOLYDRAW16, apts[count] ) + : offsetof( EMRPOLYDRAW, aptl[count] ); + size += (count + 3) & ~3; + + if (!(emr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; + + emr->emr.iType = use_small_emr ? EMR_POLYDRAW16 : EMR_POLYDRAW; + emr->emr.nSize = size; + emr->cptl = count; + + types_dest = store_points( emr->aptl, pts, count, use_small_emr ); + memcpy( types_dest, types, count ); + if (count & 3) memset( types_dest + count, 0, 4 - (count & 3) ); + + if (!emf->path) + get_points_bounds( &emr->rclBounds, pts, count, 0 ); + else + emr->rclBounds = empty_bounds; + + ret = emfdc_record( emf, &emr->emr ); + if (ret && !emf->path) emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_ExtFloodFill( WINEDC *dc_attr, INT x, INT y, COLORREF color, UINT fill_type ) +{ + 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 = fill_type; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_FillRgn( WINEDC *dc_attr, HRGN hrgn, HBRUSH hbrush ) +{ + struct emf *emf = dc_attr->emf; + EMRFILLRGN *emr; + DWORD size, rgnsize, index; + BOOL ret; + + if (!(index = emfdc_create_brush( emf, hbrush ))) return FALSE; + + rgnsize = /*NtGdi*/GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRFILLRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + /*NtGdi*/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 = emfdc_record( emf, &emr->emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_FrameRgn( WINEDC *dc_attr, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) +{ + struct emf *emf = dc_attr->emf; + EMRFRAMERGN *emr; + DWORD size, rgnsize, index; + BOOL ret; + + index = emfdc_create_brush( emf, hbrush ); + if(!index) return FALSE; + + rgnsize = /*NtGdi*/GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRFRAMERGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + /*NtGdi*/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 = emfdc_record( emf, &emr->emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +static BOOL emfdc_paint_invert_region( struct emf *emf, HRGN hrgn, DWORD iType ) +{ + EMRINVERTRGN *emr; + DWORD size, rgnsize; + BOOL ret; + + rgnsize = /*NtGdi*/GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRINVERTRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + /*NtGdi*/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 = emfdc_record( emf, &emr->emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_PaintRgn( WINEDC *dc_attr, HRGN hrgn ) +{ + return emfdc_paint_invert_region( dc_attr->emf, hrgn, EMR_PAINTRGN ); +} + +BOOL EMFDC_InvertRgn( WINEDC *dc_attr, HRGN hrgn ) +{ + return emfdc_paint_invert_region( dc_attr->emf, hrgn, EMR_INVERTRGN ); +} + +BOOL EMFDC_ExtTextOut( WINEDC *dc_attr, INT x, INT y, UINT flags, const RECT *rect, + const WCHAR *str, UINT count, const INT *dx ) +{ + struct emf *emf = dc_attr->emf; + FLOAT ex_scale, ey_scale; + EMREXTTEXTOUTW *emr; + int text_height = 0; + int text_width = 0; + TEXTMETRICW tm; + DWORD size; + BOOL ret; + + if (count > INT_MAX) return FALSE; + + size = sizeof(*emr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT); + + TRACE( "%s %s count %d size = %d\n", debugstr_wn(str, count), + wine_dbgstr_rect(rect), count, size ); + emr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size ); + + if (GetGraphicsMode(dc_attr->hdc) == GM_COMPATIBLE) + { + const INT horzSize = GetDeviceCaps( dc_attr->hdc, HORZSIZE ); + const INT horzRes = GetDeviceCaps( dc_attr->hdc, HORZRES ); + const INT vertSize = GetDeviceCaps( dc_attr->hdc, VERTSIZE ); + const INT vertRes = GetDeviceCaps( dc_attr->hdc, VERTRES ); + SIZE wndext, vportext; + + GetViewportExtEx( dc_attr->hdc, &vportext ); + GetWindowExtEx( dc_attr->hdc, &wndext ); + ex_scale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) / + ((FLOAT)wndext.cx / (FLOAT)vportext.cx); + ey_scale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) / + ((FLOAT)wndext.cy / (FLOAT)vportext.cy); + } + else + { + ex_scale = 0.0; + ey_scale = 0.0; + } + + emr->emr.iType = EMR_EXTTEXTOUTW; + emr->emr.nSize = size; + emr->iGraphicsMode = GetGraphicsMode(dc_attr->hdc); + emr->exScale = ex_scale; + emr->eyScale = ey_scale; + emr->emrtext.ptlReference.x = x; + emr->emrtext.ptlReference.y = y; + emr->emrtext.nChars = count; + emr->emrtext.offString = sizeof(*emr); + memcpy( (char*)emr + emr->emrtext.offString, str, count * sizeof(WCHAR) ); + emr->emrtext.fOptions = flags; + if (!rect) + { + emr->emrtext.rcl.left = emr->emrtext.rcl.top = 0; + emr->emrtext.rcl.right = emr->emrtext.rcl.bottom = -1; + } + else + { + emr->emrtext.rcl.left = rect->left; + emr->emrtext.rcl.top = rect->top; + emr->emrtext.rcl.right = rect->right; + emr->emrtext.rcl.bottom = rect->bottom; + } + + emr->emrtext.offDx = emr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR); + if (dx) + { + UINT i; + SIZE str_size; + memcpy( (char*)emr + emr->emrtext.offDx, dx, count * sizeof(INT) ); + for (i = 0; i < count; i++) text_width += dx[i]; + if (GetTextExtentPoint32W( dc_attr->hdc, str, count, &str_size )) + text_height = str_size.cy; + } + else + { + UINT i; + INT *emf_dx = (INT *)((char*)emr + emr->emrtext.offDx); + SIZE charSize; + for (i = 0; i < count; i++) + { + if (GetTextExtentPoint32W( dc_attr->hdc, str + i, 1, &charSize )) + { + emf_dx[i] = charSize.cx; + text_width += charSize.cx; + text_height = max( text_height, charSize.cy ); + } + } + } + + if (emf->path) + { + emr->rclBounds.left = emr->rclBounds.top = 0; + emr->rclBounds.right = emr->rclBounds.bottom = -1; + goto no_bounds; + } + + /* FIXME: handle font escapement */ + switch (GetTextAlign(dc_attr->hdc) & (TA_LEFT | TA_RIGHT | TA_CENTER)) + { + case TA_CENTER: + emr->rclBounds.left = x - (text_width / 2) - 1; + emr->rclBounds.right = x + (text_width / 2) + 1; + break; + + case TA_RIGHT: + emr->rclBounds.left = x - text_width - 1; + emr->rclBounds.right = x; + break; + + default: /* TA_LEFT */ + emr->rclBounds.left = x; + emr->rclBounds.right = x + text_width + 1; + } + + switch (GetTextAlign(dc_attr->hdc) & (TA_TOP | TA_BOTTOM | TA_BASELINE)) + { + case TA_BASELINE: + if (!GetTextMetricsW( dc_attr->hdc, &tm )) tm.tmDescent = 0; + /* Play safe here... it's better to have a bounding box */ + /* that is too big than too small. */ + emr->rclBounds.top = y - text_height - 1; + emr->rclBounds.bottom = y + tm.tmDescent + 1; + break; + + case TA_BOTTOM: + emr->rclBounds.top = y - text_height - 1; + emr->rclBounds.bottom = y; + break; + + default: /* TA_TOP */ + emr->rclBounds.top = y; + emr->rclBounds.bottom = y + text_height + 1; + } + emfdc_update_bounds( emf, &emr->rclBounds ); + +no_bounds: + ret = emfdc_record( emf, &emr->emr ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_GradientFill( WINEDC *dc_attr, TRIVERTEX *vert_array, ULONG nvert, + void *grad_array, ULONG ngrad, ULONG mode ) +{ + EMRGRADIENTFILL *emr; + ULONG i, pt, size, num_pts = ngrad * (mode == GRADIENT_FILL_TRIANGLE ? 3 : 2); + const ULONG *pts = (const ULONG *)grad_array; + BOOL ret; + + size = FIELD_OFFSET(EMRGRADIENTFILL, Ver[nvert]) + num_pts * sizeof(pts[0]); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + if (!emr) return FALSE; + + for (i = 0; i < num_pts; i++) + { + pt = pts[i]; + + if (i == 0) + { + emr->rclBounds.left = emr->rclBounds.right = vert_array[pt].x; + emr->rclBounds.top = emr->rclBounds.bottom = vert_array[pt].y; + } + else + { + if (vert_array[pt].x < emr->rclBounds.left) + emr->rclBounds.left = vert_array[pt].x; + else if (vert_array[pt].x > emr->rclBounds.right) + emr->rclBounds.right = vert_array[pt].x; + if (vert_array[pt].y < emr->rclBounds.top) + emr->rclBounds.top = vert_array[pt].y; + else if (vert_array[pt].y > emr->rclBounds.bottom) + emr->rclBounds.bottom = vert_array[pt].y; + } + } + emr->rclBounds.right--; + emr->rclBounds.bottom--; + + emr->emr.iType = EMR_GRADIENTFILL; + emr->emr.nSize = size; + emr->nVer = nvert; + emr->nTri = ngrad; + emr->ulMode = mode; + memcpy( emr->Ver, vert_array, nvert * sizeof(vert_array[0]) ); + memcpy( emr->Ver + nvert, pts, num_pts * sizeof(pts[0]) ); + + emfdc_update_bounds( dc_attr->emf, &emr->rclBounds ); + ret = emfdc_record( dc_attr->emf, &emr->emr ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_FillPath( WINEDC *dc_attr ) +{ + return emfdrv_stroke_and_fill_path( dc_attr->emf, EMR_FILLPATH ); +} + +BOOL EMFDC_StrokeAndFillPath( WINEDC *dc_attr ) +{ + return emfdrv_stroke_and_fill_path( dc_attr->emf, EMR_STROKEANDFILLPATH ); +} + +BOOL EMFDC_StrokePath( WINEDC *dc_attr ) +{ + return emfdrv_stroke_and_fill_path( dc_attr->emf, EMR_STROKEPATH ); +} + +/* Generate an EMRBITBLT, EMRSTRETCHBLT or EMRALPHABLEND record depending on the type parameter */ +static BOOL emfdrv_stretchblt( struct emf *emf, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop, DWORD type ) +{ + BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }}; + UINT bmi_size, emr_size, size; + HBITMAP bitmap, blit_bitmap = NULL; + EMRBITBLT *emr = NULL; + BITMAPINFO *bmi; + HDC blit_dc; + BOOL ret = FALSE; + + if (hdc_src && GDI_HANDLE_GET_TYPE(hdc_src) == GDILoObjType_LO_ALTDC_TYPE) + { + WINEDC * pldc = get_dc_ptr(hdc_src); + + if (pldc->iType == LDC_EMFLDC) + { + return FALSE; + } + } + + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE; + + blit_dc = hdc_src; + blit_bitmap = bitmap; + if (!(bmi_size = get_bitmap_info( &blit_dc, &blit_bitmap, &src_info ))) return FALSE; + + /* EMRSTRETCHBLT and EMRALPHABLEND have the same structure */ + emr_size = type == EMR_BITBLT ? sizeof(EMRBITBLT) : sizeof(EMRSTRETCHBLT); + size = emr_size + bmi_size + src_info.bmiHeader.biSizeImage; + + if (!(emr = HeapAlloc(GetProcessHeap(), 0, size))) goto err; + + emr->emr.iType = type; + emr->emr.nSize = size; + emr->rclBounds.left = x_dst; + emr->rclBounds.top = y_dst; + emr->rclBounds.right = x_dst + width_dst - 1; + emr->rclBounds.bottom = y_dst + height_dst - 1; + emr->xDest = x_dst; + emr->yDest = y_dst; + emr->cxDest = width_dst; + emr->cyDest = height_dst; + emr->xSrc = x_src; + emr->ySrc = y_src; + if (type != EMR_BITBLT) + { + EMRSTRETCHBLT *emr_stretchblt = (EMRSTRETCHBLT *)emr; + emr_stretchblt->cxSrc = width_src; + emr_stretchblt->cySrc = height_src; + } + emr->dwRop = rop; + NtGdiGetTransform( hdc_src, GdiWorldSpaceToDeviceSpace, &emr->xformSrc ); + emr->crBkColorSrc = GetBkColor( hdc_src ); + emr->iUsageSrc = DIB_RGB_COLORS; + emr->offBmiSrc = emr_size; + emr->cbBmiSrc = bmi_size; + emr->offBitsSrc = emr_size + bmi_size; + emr->cbBitsSrc = src_info.bmiHeader.biSizeImage; + + bmi = (BITMAPINFO *)((BYTE *)emr + emr->offBmiSrc); + bmi->bmiHeader = src_info.bmiHeader; + ret = GetDIBits( blit_dc, blit_bitmap, 0, src_info.bmiHeader.biHeight, + (BYTE *)emr + emr->offBitsSrc, bmi, DIB_RGB_COLORS ); + + if (ret) + { + ret = emfdc_record( emf, (EMR *)emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + } + +err: + HeapFree( GetProcessHeap(), 0, emr ); + if (blit_bitmap != bitmap) DeleteObject( blit_bitmap ); + if (blit_dc != hdc_src) DeleteDC( blit_dc ); + return ret; +} + +BOOL EMFDC_AlphaBlend( WINEDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + BLENDFUNCTION blend_function ) +{ + return emfdrv_stretchblt( dc_attr->emf, x_dst, y_dst, width_dst, height_dst, hdc_src, + x_src, y_src, width_src, height_src, *(DWORD *)&blend_function, + EMR_ALPHABLEND ); +} + +BOOL EMFDC_PatBlt( WINEDC *dc_attr, INT left, INT top, INT width, INT height, DWORD rop ) +{ + struct emf *emf = dc_attr->emf; + 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 = emfdc_record( emf, &emr.emr ); + if (ret) emfdc_update_bounds( emf, &emr.rclBounds ); + return ret; +} + +static inline BOOL rop_uses_src( DWORD rop ) +{ + return ((rop >> 2) & 0x330000) != (rop & 0x330000); +} + +BOOL EMFDC_BitBlt( WINEDC *dc_attr, INT x_dst, INT y_dst, INT width, INT height, + HDC hdc_src, INT x_src, INT y_src, DWORD rop ) +{ + if (!rop_uses_src( rop )) return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width, height, rop ); + return emfdrv_stretchblt( dc_attr->emf, x_dst, y_dst, width, height, + hdc_src, x_src, y_src, width, height, rop, EMR_BITBLT ); +} + +BOOL EMFDC_StretchBlt( WINEDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop ) +{ + if (!rop_uses_src( rop )) return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, rop ); + return emfdrv_stretchblt( dc_attr->emf, x_dst, y_dst, width_dst, height_dst, + hdc_src, x_src, y_src, width_src, + height_src, rop, EMR_STRETCHBLT ); +} + +BOOL EMFDC_TransparentBlt( WINEDC *dc_attr, int x_dst, int y_dst, int width_dst, int height_dst, + HDC hdc_src, int x_src, int y_src, int width_src, int height_src, + UINT color ) +{ + return emfdrv_stretchblt( dc_attr->emf, x_dst, y_dst, width_dst, height_dst, + hdc_src, x_src, y_src, width_src, + height_src, color, EMR_TRANSPARENTBLT ); +} + +BOOL EMFDC_MaskBlt( WINEDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, HBITMAP mask, + INT x_mask, INT y_mask, DWORD rop ) +{ + unsigned char mask_info_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *mask_bits_info = (BITMAPINFO *)mask_info_buffer; + struct emf *emf = dc_attr->emf; + BITMAPINFO mask_info = {{ sizeof( mask_info.bmiHeader ) }}; + BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }}; + HBITMAP bitmap, blit_bitmap = NULL, mask_bitmap = NULL; + UINT bmi_size, size, mask_info_size = 0; + EMRMASKBLT *emr = NULL; + BITMAPINFO *bmi; + HDC blit_dc, mask_dc = NULL; + BOOL ret = FALSE; + + if (!rop_uses_src( rop )) + return EMFDC_PatBlt( dc_attr, x_dst, y_dst, width_dst, height_dst, rop ); + + if (hdc_src && GDI_HANDLE_GET_TYPE(hdc_src) == GDILoObjType_LO_ALTDC_TYPE) + { + WINEDC * pldc = get_dc_ptr(hdc_src); + + if (pldc->iType == LDC_EMFLDC) + { + return FALSE; + } + } + + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE; + blit_dc = hdc_src; + blit_bitmap = bitmap; + if (!(bmi_size = get_bitmap_info( &blit_dc, &blit_bitmap, &src_info ))) return FALSE; + + if (mask) + { + mask_dc = hdc_src; + mask_bitmap = mask; + if (!(mask_info_size = get_bitmap_info( &mask_dc, &mask_bitmap, &mask_info ))) goto err; + if (mask_info.bmiHeader.biBitCount == 1) + mask_info_size = sizeof(BITMAPINFOHEADER); /* don't include colors */ + } + else mask_info.bmiHeader.biSizeImage = 0; + + size = sizeof(*emr) + bmi_size + src_info.bmiHeader.biSizeImage + + mask_info_size + mask_info.bmiHeader.biSizeImage; + + if (!(emr = HeapAlloc(GetProcessHeap(), 0, size))) goto err; + + emr->emr.iType = EMR_MASKBLT; + emr->emr.nSize = size; + emr->rclBounds.left = x_dst; + emr->rclBounds.top = y_dst; + emr->rclBounds.right = x_dst + width_dst - 1; + emr->rclBounds.bottom = y_dst + height_dst - 1; + emr->xDest = x_dst; + emr->yDest = y_dst; + emr->cxDest = width_dst; + emr->cyDest = height_dst; + emr->dwRop = rop; + emr->xSrc = x_src; + emr->ySrc = y_src; + NtGdiGetTransform( hdc_src, GdiWorldSpaceToDeviceSpace, &emr->xformSrc ); + emr->crBkColorSrc = GetBkColor( hdc_src ); + emr->iUsageSrc = DIB_RGB_COLORS; + emr->offBmiSrc = sizeof(*emr); + emr->cbBmiSrc = bmi_size; + emr->offBitsSrc = emr->offBmiSrc + bmi_size; + emr->cbBitsSrc = src_info.bmiHeader.biSizeImage; + emr->xMask = x_mask; + emr->yMask = y_mask; + emr->iUsageMask = DIB_PAL_MONO; + emr->offBmiMask = mask_info_size ? emr->offBitsSrc + emr->cbBitsSrc : 0; + emr->cbBmiMask = mask_info_size; + emr->offBitsMask = emr->offBmiMask + emr->cbBmiMask; + emr->cbBitsMask = mask_info.bmiHeader.biSizeImage; + + bmi = (BITMAPINFO *)((char *)emr + emr->offBmiSrc); + bmi->bmiHeader = src_info.bmiHeader; + ret = GetDIBits( blit_dc, blit_bitmap, 0, src_info.bmiHeader.biHeight, + (char *)emr + emr->offBitsSrc, bmi, DIB_RGB_COLORS ); + if (!ret) goto err; + + if (mask_info_size) + { + mask_bits_info->bmiHeader = mask_info.bmiHeader; + ret = GetDIBits( blit_dc, mask_bitmap, 0, mask_info.bmiHeader.biHeight, + (char *)emr + emr->offBitsMask, mask_bits_info, DIB_RGB_COLORS ); + if (ret) memcpy( (char *)emr + emr->offBmiMask, mask_bits_info, mask_info_size ); + } + + if (ret) + { + ret = emfdc_record( emf, (EMR *)emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + } + +err: + HeapFree( GetProcessHeap(), 0, emr ); + if (mask_bitmap != mask) DeleteObject( mask_bitmap ); + if (mask_dc != hdc_src) DeleteObject( mask_dc ); + if (blit_bitmap != bitmap) DeleteObject( blit_bitmap ); + if (blit_dc != hdc_src) DeleteDC( blit_dc ); + return ret; +} + +BOOL EMFDC_PlgBlt( WINEDC *dc_attr, const POINT *points, HDC hdc_src, INT x_src, INT y_src, + INT width, INT height, HBITMAP mask, INT x_mask, INT y_mask ) +{ + unsigned char mask_info_buffer[FIELD_OFFSET(BITMAPINFO, bmiColors[256])]; + BITMAPINFO *mask_bits_info = (BITMAPINFO *)mask_info_buffer; + struct emf *emf = dc_attr->emf; + BITMAPINFO mask_info = {{ sizeof( mask_info.bmiHeader ) }}; + BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }}; + HBITMAP bitmap, blit_bitmap = NULL, mask_bitmap = NULL; + UINT bmi_size, size, mask_info_size = 0; + EMRPLGBLT *emr = NULL; + BITMAPINFO *bmi; + HDC blit_dc, mask_dc = NULL; + int x_min, y_min, x_max, y_max, i; + BOOL ret = FALSE; + + if (hdc_src && GDI_HANDLE_GET_TYPE(hdc_src) == GDILoObjType_LO_ALTDC_TYPE) + { + WINEDC * pldc = get_dc_ptr(hdc_src); + + if (pldc->iType == LDC_EMFLDC) + { + return FALSE; + } + } + + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE; + + blit_dc = hdc_src; + blit_bitmap = bitmap; + if (!(bmi_size = get_bitmap_info( &blit_dc, &blit_bitmap, &src_info ))) return FALSE; + + if (mask) + { + mask_dc = hdc_src; + mask_bitmap = mask; + if (!(mask_info_size = get_bitmap_info( &mask_dc, &mask_bitmap, &mask_info ))) goto err; + if (mask_info.bmiHeader.biBitCount == 1) + mask_info_size = sizeof(BITMAPINFOHEADER); /* don't include colors */ + } + else mask_info.bmiHeader.biSizeImage = 0; + + size = sizeof(*emr) + bmi_size + src_info.bmiHeader.biSizeImage + + mask_info_size + mask_info.bmiHeader.biSizeImage; + + if (!(emr = HeapAlloc(GetProcessHeap(), 0, size))) goto err; + + emr->emr.iType = EMR_PLGBLT; + emr->emr.nSize = size; + + /* FIXME: not exactly what native does */ + x_min = x_max = points[1].x + points[2].x - points[0].x; + y_min = y_max = points[1].y + points[2].y - points[0].y; + for (i = 0; i < ARRAYSIZE(emr->aptlDest); i++) + { + x_min = min( x_min, points[i].x ); + y_min = min( y_min, points[i].y ); + x_max = max( x_max, points[i].x ); + y_max = max( y_min, points[i].y ); + } + emr->rclBounds.left = x_min; + emr->rclBounds.top = y_min; + emr->rclBounds.right = x_max; + emr->rclBounds.bottom = y_max; + memcpy( emr->aptlDest, points, sizeof(emr->aptlDest) ); + emr->xSrc = x_src; + emr->ySrc = y_src; + emr->cxSrc = width; + emr->cySrc = height; + NtGdiGetTransform( hdc_src, GdiWorldSpaceToDeviceSpace, &emr->xformSrc ); + emr->crBkColorSrc = GetBkColor( hdc_src ); + emr->iUsageSrc = DIB_RGB_COLORS; + emr->offBmiSrc = sizeof(*emr); + emr->cbBmiSrc = bmi_size; + emr->offBitsSrc = emr->offBmiSrc + bmi_size; + emr->cbBitsSrc = src_info.bmiHeader.biSizeImage; + emr->xMask = x_mask; + emr->yMask = y_mask; + emr->iUsageMask = DIB_PAL_MONO; + emr->offBmiMask = mask_info_size ? emr->offBitsSrc + emr->cbBitsSrc : 0; + emr->cbBmiMask = mask_info_size; + emr->offBitsMask = emr->offBmiMask + emr->cbBmiMask; + emr->cbBitsMask = mask_info.bmiHeader.biSizeImage; + + bmi = (BITMAPINFO *)((char *)emr + emr->offBmiSrc); + bmi->bmiHeader = src_info.bmiHeader; + ret = GetDIBits( blit_dc, blit_bitmap, 0, src_info.bmiHeader.biHeight, + (char *)emr + emr->offBitsSrc, bmi, DIB_RGB_COLORS ); + if (!ret) goto err; + + if (mask_info_size) + { + mask_bits_info->bmiHeader = mask_info.bmiHeader; + ret = GetDIBits( blit_dc, mask_bitmap, 0, mask_info.bmiHeader.biHeight, + (char *)emr + emr->offBitsMask, mask_bits_info, DIB_RGB_COLORS ); + if (ret) memcpy( (char *)emr + emr->offBmiMask, mask_bits_info, mask_info_size ); + } + + if (ret) + { + ret = emfdc_record( emf, (EMR *)emr ); + if (ret) emfdc_update_bounds( emf, &emr->rclBounds ); + } + +err: + HeapFree( GetProcessHeap(), 0, emr ); + if (mask_bitmap != mask) DeleteObject( mask_bitmap ); + if (mask_dc != hdc_src) DeleteObject( mask_dc ); + if (blit_bitmap != bitmap) DeleteObject( blit_bitmap ); + if (blit_dc != hdc_src) DeleteDC( blit_dc ); + return ret; +} + +BOOL EMFDC_StretchDIBits( WINEDC *dc_attr, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + INT x_src, INT y_src, INT width_src, INT height_src, const void *bits, + const BITMAPINFO *info, UINT usage, DWORD rop ) +{ + EMRSTRETCHDIBITS *emr; + BOOL ret; + UINT bmi_size, emr_size; + + /* calculate the size of the colour table */ + bmi_size = get_dib_info_size( info, usage ); + + emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + info->bmiHeader.biSizeImage; + if (!(emr = HeapAlloc(GetProcessHeap(), 0, emr_size ))) 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, info->bmiHeader.biSizeImage ); + + /* 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 = x_dst; + emr->yDest = y_dst; + emr->cxDest = width_dst; + emr->cyDest = height_dst; + emr->dwRop = rop; + emr->xSrc = x_src; + emr->ySrc = y_src; + + emr->iUsageSrc = usage; + emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); + emr->cbBmiSrc = bmi_size; + emr->offBitsSrc = emr->offBmiSrc + bmi_size; + emr->cbBitsSrc = info->bmiHeader.biSizeImage; + + emr->cxSrc = width_src; + emr->cySrc = height_src; + + emr->rclBounds.left = x_dst; + emr->rclBounds.top = y_dst; + emr->rclBounds.right = x_dst + width_dst; + emr->rclBounds.bottom = y_dst + height_dst; + + /* save the record we just created */ + ret = emfdc_record( dc_attr->emf, &emr->emr ); + if (ret) emfdc_update_bounds( dc_attr->emf, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_SetDIBitsToDevice( WINEDC *dc_attr, INT x_dst, INT y_dst, DWORD width, DWORD height, + INT x_src, INT y_src, UINT startscan, UINT lines, + const void *bits, const BITMAPINFO *info, UINT usage ) +{ + EMRSETDIBITSTODEVICE *emr; + DWORD bmiSize = get_dib_info_size( info, usage ); + DWORD size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + info->bmiHeader.biSizeImage; + BOOL ret; + + if (!(emr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; + + emr->emr.iType = EMR_SETDIBITSTODEVICE; + emr->emr.nSize = size; + emr->rclBounds.left = x_dst; + emr->rclBounds.top = y_dst; + emr->rclBounds.right = x_dst + width - 1; + emr->rclBounds.bottom = y_dst + height - 1; + emr->xDest = x_dst; + emr->yDest = y_dst; + emr->xSrc = x_src; + emr->ySrc = y_src; + emr->cxSrc = width; + emr->cySrc = height; + emr->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); + emr->cbBmiSrc = bmiSize; + emr->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; + emr->cbBitsSrc = info->bmiHeader.biSizeImage; + emr->iUsageSrc = usage; + emr->iStartScan = startscan; + emr->cScans = lines; + memcpy( (BYTE*)emr + emr->offBmiSrc, info, bmiSize ); + memcpy( (BYTE*)emr + emr->offBitsSrc, bits, info->bmiHeader.biSizeImage ); + + if ((ret = emfdc_record( dc_attr->emf, (EMR*)emr ))) + emfdc_update_bounds( dc_attr->emf, &emr->rclBounds ); + + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_SetDCBrushColor( WINEDC *dc_attr, COLORREF color ) +{ + struct emf *emf = dc_attr->emf; + EMRSELECTOBJECT emr; + DWORD index; + + if (GetCurrentObject( dc_attr->hdc, OBJ_BRUSH ) != GetStockObject( DC_BRUSH )) return TRUE; + + if (emf->dc_brush) DeleteObject( emf->dc_brush ); + if (!(emf->dc_brush = CreateSolidBrush( color ))) return FALSE; + if (!(index = emfdc_create_brush( emf, emf->dc_brush ))) return FALSE; + GDI_hdc_using_object( emf->dc_brush, dc_attr->hdc);//, emfdc_delete_object ); + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return emfdc_record( emf, &emr.emr ); +} + +BOOL EMFDC_SetDCPenColor( WINEDC *dc_attr, COLORREF color ) +{ + struct emf *emf = dc_attr->emf; + EMRSELECTOBJECT emr; + DWORD index; + LOGPEN logpen = { PS_SOLID, { 0, 0 }, color }; + + if (GetCurrentObject( dc_attr->hdc, OBJ_PEN ) != GetStockObject( DC_PEN )) return TRUE; + + if (emf->dc_pen) DeleteObject( emf->dc_pen ); + if (!(emf->dc_pen = CreatePenIndirect( &logpen ))) return FALSE; + if (!(index = emfdc_create_pen( emf, emf->dc_pen ))) return FALSE; + GDI_hdc_using_object( emf->dc_pen, dc_attr->hdc);//, emfdc_delete_object ); + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return emfdc_record( emf, &emr.emr ); +} + +BOOL EMFDC_SaveDC( WINEDC *dc_attr ) +{ + EMRSAVEDC emr; + + emr.emr.iType = EMR_SAVEDC; + emr.emr.nSize = sizeof(emr); + return emfdc_record( dc_attr->emf, &emr.emr ); +} +#define GdiGetEMFRestorDc 5 +BOOL EMFDC_RestoreDC( WINEDC *dc_attr, INT level ) +{ + EMRRESTOREDC emr; + + /* 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. */ + dc_attr->save_level = GetDCDWord(dc_attr->hdc, GdiGetEMFRestorDc, 0) - 1; + + if (abs(level) > dc_attr->save_level || level == 0) return FALSE; + + emr.emr.iType = EMR_RESTOREDC; + emr.emr.nSize = sizeof(emr); + if (level < 0) + emr.iRelative = level; + else + emr.iRelative = level - dc_attr->save_level - 1; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetTextAlign( WINEDC *dc_attr, UINT align ) +{ + EMRSETTEXTALIGN emr; + + emr.emr.iType = EMR_SETTEXTALIGN; + emr.emr.nSize = sizeof(emr); + emr.iMode = align; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetTextJustification( WINEDC *dc_attr, INT extra, INT breaks ) +{ + EMRSETTEXTJUSTIFICATION emr; + + emr.emr.iType = EMR_SETTEXTJUSTIFICATION; + emr.emr.nSize = sizeof(emr); + emr.nBreakExtra = extra; + emr.nBreakCount = breaks; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetBkMode( WINEDC *dc_attr, INT mode ) +{ + EMRSETBKMODE emr; + + emr.emr.iType = EMR_SETBKMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetBkColor( WINEDC *dc_attr, COLORREF color ) +{ + EMRSETBKCOLOR emr; + + emr.emr.iType = EMR_SETBKCOLOR; + emr.emr.nSize = sizeof(emr); + emr.crColor = color; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetTextColor( WINEDC *dc_attr, COLORREF color ) +{ + EMRSETTEXTCOLOR emr; + + emr.emr.iType = EMR_SETTEXTCOLOR; + emr.emr.nSize = sizeof(emr); + emr.crColor = color; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetROP2( WINEDC *dc_attr, INT rop ) +{ + EMRSETROP2 emr; + + emr.emr.iType = EMR_SETROP2; + emr.emr.nSize = sizeof(emr); + emr.iMode = rop; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetPolyFillMode( WINEDC *dc_attr, INT mode ) +{ + EMRSETPOLYFILLMODE emr; + + emr.emr.iType = EMR_SETPOLYFILLMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetStretchBltMode( WINEDC *dc_attr, INT mode ) +{ + EMRSETSTRETCHBLTMODE emr; + + emr.emr.iType = EMR_SETSTRETCHBLTMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetArcDirection( WINEDC *dc_attr, INT dir ) +{ + EMRSETARCDIRECTION emr; + + emr.emr.iType = EMR_SETARCDIRECTION; + emr.emr.nSize = sizeof(emr); + emr.iArcDirection = dir; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +INT EMFDC_ExcludeClipRect( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_IntersectClipRect( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_OffsetClipRgn( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_ExtSelectClipRgn( WINEDC *dc_attr, HRGN hrgn, INT mode ) +{ + EMREXTSELECTCLIPRGN *emr; + DWORD size, rgnsize; + BOOL ret; + + if (!hrgn) + { + if (mode != RGN_COPY) return ERROR; + rgnsize = 0; + } + else rgnsize = /*NtGdi*/GetRegionData( hrgn, 0, NULL ); + + size = rgnsize + offsetof(EMREXTSELECTCLIPRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + if (rgnsize) /*NtGdi*/GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); + + emr->emr.iType = EMR_EXTSELECTCLIPRGN; + emr->emr.nSize = size; + emr->cbRgnData = rgnsize; + emr->iMode = mode; + + ret = emfdc_record( dc_attr->emf, &emr->emr ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +BOOL EMFDC_SetMapMode( WINEDC *dc_attr, INT mode ) +{ + EMRSETMAPMODE emr; + + emr.emr.iType = EMR_SETMAPMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetViewportExtEx( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetWindowExtEx( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetViewportOrgEx( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetWindowOrgEx( WINEDC *dc_attr, 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 emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_ScaleViewportExtEx( WINEDC *dc_attr, INT x_num, INT x_denom, INT y_num, INT y_denom ) +{ + EMRSCALEVIEWPORTEXTEX emr; + + emr.emr.iType = EMR_SCALEVIEWPORTEXTEX; + emr.emr.nSize = sizeof(emr); + emr.xNum = x_num; + emr.xDenom = x_denom; + emr.yNum = y_num; + emr.yDenom = y_denom; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_ScaleWindowExtEx( WINEDC *dc_attr, INT x_num, INT x_denom, INT y_num, INT y_denom ) +{ + EMRSCALEWINDOWEXTEX emr; + + emr.emr.iType = EMR_SCALEWINDOWEXTEX; + emr.emr.nSize = sizeof(emr); + emr.xNum = x_num; + emr.xDenom = x_denom; + emr.yNum = y_num; + emr.yDenom = y_denom; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetLayout( WINEDC *dc_attr, DWORD layout ) +{ + EMRSETLAYOUT emr; + + emr.emr.iType = EMR_SETLAYOUT; + emr.emr.nSize = sizeof(emr); + emr.iMode = layout; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetWorldTransform( WINEDC *dc_attr, const XFORM *xform ) +{ + EMRSETWORLDTRANSFORM emr; + + emr.emr.iType = EMR_SETWORLDTRANSFORM; + emr.emr.nSize = sizeof(emr); + emr.xform = *xform; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_ModifyWorldTransform( WINEDC *dc_attr, const XFORM *xform, DWORD mode ) +{ + EMRMODIFYWORLDTRANSFORM emr; + + emr.emr.iType = EMR_MODIFYWORLDTRANSFORM; + emr.emr.nSize = sizeof(emr); + if (mode == MWT_IDENTITY) + { + emr.xform.eM11 = 1.0f; + emr.xform.eM12 = 0.0f; + emr.xform.eM21 = 0.0f; + emr.xform.eM22 = 1.0f; + emr.xform.eDx = 0.0f; + emr.xform.eDy = 0.0f; + } + else + { + emr.xform = *xform; + } + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SetMapperFlags( WINEDC *dc_attr, DWORD flags ) +{ + EMRSETMAPPERFLAGS emr; + + emr.emr.iType = EMR_SETMAPPERFLAGS; + emr.emr.nSize = sizeof(emr); + emr.dwFlags = flags; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_AbortPath( WINEDC *dc_attr ) +{ + struct emf *emf = dc_attr->emf; + EMRABORTPATH emr; + + emr.emr.iType = EMR_ABORTPATH; + emr.emr.nSize = sizeof(emr); + + emf->path = FALSE; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_BeginPath( WINEDC *dc_attr ) +{ + struct emf *emf = dc_attr->emf; + EMRBEGINPATH emr; + + emr.emr.iType = EMR_BEGINPATH; + emr.emr.nSize = sizeof(emr); + if (!emfdc_record( emf, &emr.emr )) return FALSE; + + emf->path = TRUE; + return TRUE; +} + +BOOL EMFDC_CloseFigure( WINEDC *dc_attr ) +{ + EMRCLOSEFIGURE emr; + + emr.emr.iType = EMR_CLOSEFIGURE; + emr.emr.nSize = sizeof(emr); + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_EndPath( WINEDC *dc_attr ) +{ + struct emf *emf = dc_attr->emf; + EMRENDPATH emr; + + emf->path = FALSE; + + emr.emr.iType = EMR_ENDPATH; + emr.emr.nSize = sizeof(emr); + return emfdc_record( emf, &emr.emr ); +} + +BOOL EMFDC_FlattenPath( WINEDC *dc_attr ) +{ + EMRFLATTENPATH emr; + + emr.emr.iType = EMR_FLATTENPATH; + emr.emr.nSize = sizeof(emr); + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_SelectClipPath( WINEDC *dc_attr, INT mode ) +{ + EMRSELECTCLIPPATH emr; + + emr.emr.iType = EMR_SELECTCLIPPATH; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL EMFDC_WidenPath( WINEDC *dc_attr ) +{ + EMRWIDENPATH emr; + + emr.emr.iType = EMR_WIDENPATH; + emr.emr.nSize = sizeof(emr); + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +void EMFDC_DeleteDC( WINEDC *dc_attr ) +{ + struct emf *emf = dc_attr->emf; + UINT index; + + HeapFree( GetProcessHeap(), 0, emf->emh ); + for (index = 0; index < emf->handles_size; index++) + if (emf->handles[index]) + GDI_hdc_not_using_object( emf->handles[index], emf->dc_attr->hdc ); + HeapFree( GetProcessHeap(), 0, emf->handles ); +} + +// +// Waiting on wine support.... +// + + +// +// ReactOS Print Support +// +INT +EMFDC_WriteEscape( WINEDC *dc_attr, INT nEscape, INT cbInput, LPSTR lpszInData, DWORD emrType) +{ + PEMRESCAPE pemr; + UINT total, rounded_size; + INT ret; + + rounded_size = (cbInput+3) & ~3; + total = offsetof(EMRESCAPE,Data) + rounded_size; + + pemr = RtlAllocateHeap( GetProcessHeap(), 0, total ); + if ( !pemr ) + return 0; + + RtlZeroMemory( pemr, total ); + + pemr->emr.iType = emrType; + pemr->emr.nSize = total; + pemr->iEsc = nEscape; + pemr->cjIn = cbInput; + + RtlCopyMemory( &pemr->Data[0], lpszInData, cbInput ); + + ret = emfdc_record( dc_attr->emf, &pemr->emr ); + + RtlFreeHeap( GetProcessHeap(), 0, pemr ); + return ret; +} + +INT +EMFDC_WriteNamedEscape( WINEDC *dc_attr, PWCHAR pDriver, INT nEscape, INT cbInput, LPCSTR lpszInData) +{ + PEMRNAMEDESCAPE pemr; + UINT sizestr, total, rounded_size; + INT ret; + + rounded_size = (cbInput+3) & ~3; + total = offsetof(EMRNAMEDESCAPE,Data) + rounded_size; + + total += sizestr = (wcslen(pDriver) + 1 ) * sizeof(WCHAR); + + pemr = RtlAllocateHeap( GetProcessHeap(), 0, total ); + if ( !pemr ) + return 0; + + RtlZeroMemory( pemr, total ); + + pemr->emr.iType = EMR_NAMEDESCAPE; + pemr->emr.nSize = total; + pemr->iEsc = nEscape; + pemr->cjIn = cbInput; + + RtlCopyMemory( &pemr->Data[0], lpszInData, cbInput ); + // + // WARNING : + // Need to remember with wine, theses headers are relocatable. + RtlCopyMemory( &pemr->Data[rounded_size], pDriver, sizestr ); + + ret = emfdc_record( dc_attr->emf, &pemr->emr ); + + RtlFreeHeap( GetProcessHeap(), 0, pemr ); + return ret; +} + +BOOL +EMFDC_SetMetaRgn( WINEDC *dc_attr ) +{ + EMRSETMETARGN emr; + + emr.emr.iType = EMR_SETMETARGN; + emr.emr.nSize = sizeof(emr); + + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +BOOL +EMFDC_SetBrushOrg( WINEDC *dc_attr, INT x, INT y) +{ + EMRSETBRUSHORGEX emr; + + emr.emr.iType = EMR_SETBRUSHORGEX; + emr.emr.nSize = sizeof(emr); + emr.ptlOrigin.x = x; + emr.ptlOrigin.y = y; + + return emfdc_record( dc_attr->emf, &emr.emr ); +} + +/******************************************************************* + * GdiComment (GDI32.@) + */ +BOOL WINAPI EMFDC_GdiComment( HDC hdc, UINT bytes, const BYTE *buffer ) +{ + WINEDC *dc_attr; + EMRGDICOMMENT *emr; + UINT total, rounded_size; + BOOL ret; + + if (!(dc_attr = get_dc_ptr( hdc )) || !dc_attr->emf) return FALSE; + + 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 = emfdc_record( dc_attr->emf, &emr->emr ); + + HeapFree(GetProcessHeap(), 0, emr); + + return ret; +} + +/********************************************************************** + * CreateEnhMetaFileA (GDI32.@) + */ +HDC WINAPI CreateEnhMetaFileA( HDC hdc, const char *filename, const RECT *rect, + const char *description ) +{ + WCHAR *filenameW = NULL; + WCHAR *descriptionW = NULL; + DWORD len1, len2, total; + HDC ret; + + 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 ); + } + + ret = CreateEnhMetaFileW( hdc, filenameW, rect, descriptionW ); + + HeapFree( GetProcessHeap(), 0, filenameW ); + HeapFree( GetProcessHeap(), 0, descriptionW ); + return ret; +} + +/********************************************************************** + * CreateEnhMetaFileW (GDI32.@) + */ +HDC WINAPI CreateEnhMetaFileW( HDC hdc, const WCHAR *filename, const RECT *rect, + const WCHAR *description ) +{ + HDC ret; + struct emf *emf; + WINEDC *dc_attr; + HANDLE file; + DWORD size = 0, length = 0; + + TRACE( "(%p %s %s %s)\n", hdc, debugstr_w(filename), wine_dbgstr_rect(rect), + debugstr_w(description) ); + + //if (!(ret = NtGdiCreateMetafileDC( hdc ))) return 0; + if(!(dc_attr = alloc_dc_ptr(OBJ_ENHMETADC))) + { + if (dc_attr->hdc) DeleteDC( dc_attr->hdc ); + return 0; + } + + ret = dc_attr->hdc; + + if (/*!(dc_attr = get_dc_ptr( ret )) ||*/ !(emf = HeapAlloc( GetProcessHeap(), 0, sizeof(*emf) ))) + { + DeleteDC( ret ); + return 0; + } + + emf->dc_attr = dc_attr; + dc_attr->emf = emf; + + 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 (!(emf->emh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size))) + { + DeleteDC( ret ); + return 0; + } + emf->dc_attr = dc_attr; + + emf->handles = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + HANDLE_LIST_INC * sizeof(emf->handles[0]) ); + emf->handles_size = HANDLE_LIST_INC; + emf->cur_handles = 1; + emf->file = 0; + emf->dc_brush = 0; + emf->dc_pen = 0; + emf->path = FALSE; + + emf->emh->iType = EMR_HEADER; + emf->emh->nSize = size; + + dc_attr->emf_bounds.left = dc_attr->emf_bounds.top = 0; + dc_attr->emf_bounds.right = dc_attr->emf_bounds.bottom = -1; + + if (rect) + { + emf->emh->rclFrame.left = rect->left; + emf->emh->rclFrame.top = rect->top; + emf->emh->rclFrame.right = rect->right; + emf->emh->rclFrame.bottom = rect->bottom; + } + else + { + /* Set this to {0,0 - -1,-1} and update it at the end */ + emf->emh->rclFrame.left = emf->emh->rclFrame.top = 0; + emf->emh->rclFrame.right = emf->emh->rclFrame.bottom = -1; + } + + emf->emh->dSignature = ENHMETA_SIGNATURE; + emf->emh->nVersion = 0x10000; + emf->emh->nBytes = emf->emh->nSize; + emf->emh->nRecords = 1; + emf->emh->nHandles = 1; + + emf->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */ + emf->emh->nDescription = length / 2; + + emf->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0; + + emf->emh->nPalEntries = 0; /* I guess this should start at 0 */ + + /* Size in pixels */ + emf->emh->szlDevice.cx = GetDeviceCaps( ret, HORZRES ); + emf->emh->szlDevice.cy = GetDeviceCaps( ret, VERTRES ); + + /* Size in millimeters */ + emf->emh->szlMillimeters.cx = GetDeviceCaps( ret, HORZSIZE ); + emf->emh->szlMillimeters.cy = GetDeviceCaps( ret, VERTSIZE ); + + /* Size in micrometers */ + emf->emh->szlMicrometers.cx = emf->emh->szlMillimeters.cx * 1000; + emf->emh->szlMicrometers.cy = emf->emh->szlMillimeters.cy * 1000; + + memcpy( (char *)emf->emh + sizeof(ENHMETAHEADER), description, length ); + + if (filename) /* disk based metafile */ + { + if ((file = CreateFileW( filename, GENERIC_WRITE | GENERIC_READ, 0, + NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) + { + DeleteDC( ret ); + return 0; + } + emf->file = file; + } + + TRACE( "returning %p\n", ret ); + return ret; +} + +/****************************************************************** + * CloseEnhMetaFile (GDI32.@) + */ +HENHMETAFILE WINAPI CloseEnhMetaFile( HDC hdc ) +{ + HENHMETAFILE hmf; + struct emf *emf; + WINEDC *dc_attr; + EMREOF emr; + HANDLE mapping = 0; + + if (!(dc_attr = get_dc_ptr( hdc )) || !dc_attr->emf) return 0; + emf = dc_attr->emf; + + if (dc_attr->save_level) + RestoreDC( hdc, 1 ); + + if (emf->dc_brush) DeleteObject( emf->dc_brush ); + if (emf->dc_pen) DeleteObject( emf->dc_pen ); + + emr.emr.iType = EMR_EOF; + emr.emr.nSize = sizeof(emr); + emr.nPalEntries = 0; + emr.offPalEntries = FIELD_OFFSET(EMREOF, nSizeLast); + emr.nSizeLast = emr.emr.nSize; + emfdc_record( emf, &emr.emr ); + + emf->emh->rclBounds = dc_attr->emf_bounds; + + /* Update rclFrame if not initialized in CreateEnhMetaFile */ + if (emf->emh->rclFrame.left > emf->emh->rclFrame.right) + { + emf->emh->rclFrame.left = emf->emh->rclBounds.left * + emf->emh->szlMillimeters.cx * 100 / emf->emh->szlDevice.cx; + emf->emh->rclFrame.top = emf->emh->rclBounds.top * + emf->emh->szlMillimeters.cy * 100 / emf->emh->szlDevice.cy; + emf->emh->rclFrame.right = emf->emh->rclBounds.right * + emf->emh->szlMillimeters.cx * 100 / emf->emh->szlDevice.cx; + emf->emh->rclFrame.bottom = emf->emh->rclBounds.bottom * + emf->emh->szlMillimeters.cy * 100 / emf->emh->szlDevice.cy; + } + + if (emf->file) /* disk based metafile */ + { + DWORD bytes_written; + + if (!WriteFile( emf->file, emf->emh, emf->emh->nBytes, &bytes_written, NULL )) + { + CloseHandle( emf->file ); + return 0; + } + HeapFree( GetProcessHeap(), 0, emf->emh ); + mapping = CreateFileMappingA( emf->file, NULL, PAGE_READONLY, 0, 0, NULL ); + TRACE( "mapping = %p\n", mapping ); + emf->emh = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 ); + TRACE( "view = %p\n", emf->emh ); + CloseHandle( mapping ); + CloseHandle( emf->file ); + } + + hmf = EMF_Create_HENHMETAFILE( emf->emh, emf->emh->nBytes, emf->file != 0 ); + emf->emh = NULL; /* So it won't be deleted */ + DeleteDC( hdc ); + return hmf; +} diff --git a/win32ss/gdi/gdi32/wine/emfdrv.c b/win32ss/gdi/gdi32/wine/emfdrv.c new file mode 100644 index 00000000000..26a13c67215 --- /dev/null +++ b/win32ss/gdi/gdi32/wine/emfdrv.c @@ -0,0 +1,430 @@ +/* + * Enhanced MetaFile driver + * + * Copyright 1999 Huw D M Davies + * Copyright 2021 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +//#include "ntgdi_private.h" +#include "wine/config.h" + +#include +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winnls.h" +#include "winerror.h" +#include "gdi_private.h" +#ifdef __REACTOS__ +#include "wine/winternl.h" +#else +#include "winternl.h" +#endif +#include "wine/wingdi16.h" +#include "wine/debug.h" + +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.570796326794896619 + +static void emfdrv_update_bounds( WINEDC *dc, RECTL *rect ) +{ + RECTL *bounds = &dc->emf_bounds; + RECTL vport_rect = *rect; + + //lp_to_dp( dc, (POINT *)&vport_rect, 2 ); + LPtoDP(dc->hdc, (POINT *)&vport_rect, 2 ); + + /* The coordinate systems may be mirrored + (LPtoDP handles points, not rectangles) */ + if (vport_rect.left > vport_rect.right) + { + LONG temp = vport_rect.right; + vport_rect.right = vport_rect.left; + vport_rect.left = temp; + } + if (vport_rect.top > vport_rect.bottom) + { + LONG temp = vport_rect.bottom; + vport_rect.bottom = vport_rect.top; + vport_rect.top = temp; + } + + if (bounds->left > bounds->right) + { + /* first bounding rectangle */ + *bounds = vport_rect; + } + else + { + bounds->left = min( bounds->left, vport_rect.left ); + bounds->top = min( bounds->top, vport_rect.top ); + bounds->right = max( bounds->right, vport_rect.right ); + bounds->bottom = max( bounds->bottom, vport_rect.bottom ); + } +} + +BOOL EMFDRV_LineTo( WINEDC *dc, INT x, INT y ) +{ + RECTL bounds; + POINT pt; + + //pt = dc->attr->cur_pos; + GetCurrentPositionEx(dc->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_update_bounds( dc, &bounds ); + return TRUE; +} + +BOOL EMFDRV_RoundRect( WINEDC *dc, INT left, INT top, INT right, + INT bottom, INT ell_width, INT ell_height ) +{ + RECTL bounds; + + if (left == right || top == bottom) return FALSE; + + bounds.left = min( left, right ); + bounds.top = min( top, bottom ); + bounds.right = max( left, right ); + bounds.bottom = max( top, bottom ); + if (GetGraphicsMode(dc->hdc) == GM_COMPATIBLE)//dc->attr->graphics_mode == GM_COMPATIBLE) + { + bounds.right--; + bounds.bottom--; + } + + emfdrv_update_bounds( dc, &bounds ); + return TRUE; +} + +BOOL EMFDRV_ArcChordPie( WINEDC *dc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend, DWORD type ) +{ + INT temp, x_centre, y_centre, i; + double angle_start, angle_end; + double xinter_start, yinter_start, xinter_end, yinter_end; + EMRARC emr; + RECTL bounds; + + 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(dc->hdc) == GM_COMPATIBLE)//dc->attr->graphics_mode == GM_COMPATIBLE) + { + right--; + bottom--; + } + + emr.emr.iType = type; + 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.y = yend; + + /* Now calculate the BBox */ + x_centre = (left + right + 1) / 2; + y_centre = (top + bottom + 1) / 2; + + xstart -= x_centre; + ystart -= y_centre; + xend -= x_centre; + yend -= y_centre; + + /* invert y co-ords to get angle anti-clockwise from x-axis */ + angle_start = atan2( -(double)ystart, (double)xstart ); + angle_end = atan2( -(double)yend, (double)xend ); + + /* These are the intercepts of the start/end lines with the arc */ + xinter_start = (right - left + 1)/2 * cos(angle_start) + x_centre; + yinter_start = -(bottom - top + 1)/2 * sin(angle_start) + y_centre; + xinter_end = (right - left + 1)/2 * cos(angle_end) + x_centre; + yinter_end = -(bottom - top + 1)/2 * sin(angle_end) + y_centre; + + if (angle_start < 0) angle_start += 2 * M_PI; + if (angle_end < 0) angle_end += 2 * M_PI; + if (angle_end < angle_start) angle_end += 2 * M_PI; + + bounds.left = min( xinter_start, xinter_end ); + bounds.top = min( yinter_start, yinter_end ); + bounds.right = max( xinter_start, xinter_end ); + bounds.bottom = max( yinter_start, yinter_end ); + + for (i = 0; i <= 8; i++) + { + if(i * M_PI / 2 < angle_start) /* loop until we're past start */ + continue; + if(i * M_PI / 2 > angle_end) /* 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 (type == EMR_PIE) + { + if (bounds.left > x_centre) bounds.left = x_centre; + else if (bounds.right < x_centre) bounds.right = x_centre; + if (bounds.top > y_centre) bounds.top = y_centre; + else if (bounds.bottom < y_centre) bounds.bottom = y_centre; + } + else if (type == EMR_ARCTO) + { + POINT pt; + //pt = dc->attr->cur_pos; + GetCurrentPositionEx(dc->hdc, &pt); + bounds.left = min( bounds.left, pt.x ); + bounds.top = min( bounds.top, pt.y ); + bounds.right = max( bounds.right, pt.x ); + bounds.bottom = max( bounds.bottom, pt.y ); + } + emfdrv_update_bounds( dc, &bounds ); + return TRUE; +} + +BOOL EMFDRV_Arc( WINEDC *dc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dc, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_ARC ); +} + +BOOL EMFDRV_ArcTo( WINEDC *dc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dc, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_ARCTO ); +} + +BOOL EMFDRV_Pie( WINEDC *dc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dc, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_PIE ); +} + +BOOL EMFDRV_Chord( WINEDC *dc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dc, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_CHORD ); +} + +BOOL EMFDRV_Ellipse( WINEDC *dc, INT left, INT top, INT right, INT bottom ) +{ + RECTL bounds; + + if (left == right || top == bottom) return FALSE; + + bounds.left = min( left, right ); + bounds.top = min( top, bottom ); + bounds.right = max( left, right ); + bounds.bottom = max( top, bottom ); + if (GetGraphicsMode(dc->hdc) == GM_COMPATIBLE)//dc->attr->graphics_mode == GM_COMPATIBLE) + { + bounds.right--; + bounds.bottom--; + } + + emfdrv_update_bounds( dc, &bounds ); + return TRUE; +} + +BOOL EMFDRV_Rectangle( WINEDC *dc, INT left, INT top, INT right, INT bottom ) +{ + RECTL bounds; + + if (left == right || top == bottom) return FALSE; + + bounds.left = min( left, right ); + bounds.top = min( top, bottom ); + bounds.right = max( left, right ); + bounds.bottom = max( top, bottom ); + if (GetGraphicsMode(dc->hdc) == GM_COMPATIBLE)//dc->attr->graphics_mode == GM_COMPATIBLE) + { + bounds.right--; + bounds.bottom--; + } + + emfdrv_update_bounds( dc, &bounds ); + return TRUE; +} + +COLORREF EMFDRV_SetPixel( WINEDC *dc, INT x, INT y, COLORREF color ) +{ + RECTL bounds; + + bounds.left = bounds.right = x; + bounds.top = bounds.bottom = y; + emfdrv_update_bounds( dc, &bounds ); + return CLR_INVALID; +} + +BOOL EMFDRV_PolylineTo( WINEDC *dc, const POINT *pt, INT count ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_PolyBezier( WINEDC *dc, const POINT *pts, DWORD count ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_PolyBezierTo( WINEDC *dc, const POINT *pts, DWORD count ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_PolyPolyline( WINEDC *dc, const POINT *pt, + const DWORD *counts, UINT polys ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_PolyPolygon( WINEDC *dc, const POINT *pt, + const INT *counts, UINT polys ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_PolyDraw( WINEDC *dc, const POINT *pts, + const BYTE *types, DWORD count ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_FillRgn( WINEDC *dc, HRGN hrgn, HBRUSH hbrush ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_FrameRgn( WINEDC *dc, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_InvertRgn( WINEDC *dc, HRGN hrgn ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_ExtTextOut( WINEDC *dc, INT x, INT y, UINT flags, const RECT *lprect, + LPCWSTR str, UINT count, const INT *lpDx ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_GradientFill( WINEDC *dc, TRIVERTEX *vert_array, ULONG nvert, + void *grad_array, ULONG ngrad, ULONG mode ) +{ + /* FIXME: update bounding rect */ + return TRUE; +} + +BOOL EMFDRV_FillPath( WINEDC *dc ) +{ + /* FIXME: update bound rect */ + return TRUE; +} + +BOOL EMFDRV_StrokeAndFillPath( WINEDC *dc ) +{ + /* FIXME: update bound rect */ + return TRUE; +} + +BOOL EMFDRV_StrokePath( WINEDC *dc ) +{ + /* FIXME: update bound rect */ + return TRUE; +} + +BOOL EMFDRV_AlphaBlend( WINEDC *dc_dst, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC dc_src, INT x_src, INT y_src, INT width_src, INT height_src, + BLENDFUNCTION func ) +{ + /* FIXME: update bound rect */ + return TRUE; +} + +BOOL EMFDRV_PatBlt( WINEDC *dc, INT left, INT top, INT width, INT height, DWORD rop ) +{ + /* FIXME: update bound rect */ + return TRUE; +} + +INT EMFDRV_StretchDIBits( WINEDC *dc, INT x_dst, INT y_dst, INT width_dst, + INT height_dst, INT x_src, INT y_src, INT width_src, + INT height_src, const void *bits, BITMAPINFO *info, + UINT wUsage, DWORD dwRop ) +{ + /* FIXME: Update bound rect */ + return height_src; +} + +INT EMFDRV_SetDIBitsToDevice( WINEDC *dc, INT x_dst, INT y_dst, DWORD width, + DWORD height, INT x_src, INT y_src, UINT startscan, + UINT lines, const void *bits, BITMAPINFO *info, + UINT usage ) +{ + /* FIXME: Update bound rect */ + return lines; +} + +HBITMAP EMFDRV_SelectBitmap( WINEDC *dc, HBITMAP hbitmap ) +{ + return 0; +} + diff --git a/win32ss/gdi/gdi32/wine/enhmetafile.c b/win32ss/gdi/gdi32/wine/enhmetafile.c index 07faf2a24d6..f8c0762590f 100644 --- a/win32ss/gdi/gdi32/wine/enhmetafile.c +++ b/win32ss/gdi/gdi32/wine/enhmetafile.c @@ -48,6 +48,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +static CRITICAL_SECTION enhmetafile_cs; +static CRITICAL_SECTION_DEBUG critsect_debug = +{ + 0, 0, &enhmetafile_cs, + { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": enhmetafile_cs") } +}; +static CRITICAL_SECTION enhmetafile_cs = { &critsect_debug, -1, 0, 0, 0, 0 }; + typedef struct { ENHMETAHEADER *emh; @@ -246,7 +256,7 @@ static inline BOOL is_dib_monochrome( const BITMAPINFO* info ) /**************************************************************************** * EMF_Create_HENHMETAFILE */ -HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) +HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, DWORD filesize, BOOL on_disk ) { HENHMETAFILE hmf; ENHMETAFILEOBJ *metaObj; @@ -263,6 +273,11 @@ HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) emh->iType, emh->dSignature); return 0; } + if (filesize < emh->nBytes) + { + WARN("File truncated (got %u bytes, header says %u)\n", emh->nBytes, filesize); + return 0; + } if (!(metaObj = HeapAlloc( GetProcessHeap(), 0, sizeof(*metaObj) ))) return 0; @@ -279,15 +294,22 @@ HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) */ static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf ) { - ENHMETAFILEOBJ *metaObj = free_gdi_handle( hmf ); + ENHMETAFILEOBJ *metaObj; + BOOL Ret = FALSE; - if(!metaObj) return FALSE; - - if(metaObj->on_disk) - UnmapViewOfFile( metaObj->emh ); - else - HeapFree( GetProcessHeap(), 0, metaObj->emh ); - return HeapFree( GetProcessHeap(), 0, metaObj ); + EnterCriticalSection( &enhmetafile_cs ); + metaObj = free_gdi_handle( hmf ); + if(metaObj) + { + if(metaObj->on_disk) + UnmapViewOfFile( metaObj->emh ); + else + HeapFree( GetProcessHeap(), 0, metaObj->emh ); + HeapFree( GetProcessHeap(), 0, metaObj ); + Ret = TRUE; + } + LeaveCriticalSection( &enhmetafile_cs ); + return Ret; } /****************************************************************** @@ -298,13 +320,17 @@ static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf ) static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf ) { ENHMETAHEADER *ret = NULL; - ENHMETAFILEOBJ *metaObj = GDI_GetObjPtr( hmf, OBJ_ENHMETAFILE ); + ENHMETAFILEOBJ *metaObj; + + EnterCriticalSection( &enhmetafile_cs ); + metaObj = GDI_GetObjPtr( hmf, OBJ_ENHMETAFILE ); TRACE("hmf %p -> enhmetaObj %p\n", hmf, metaObj); if (metaObj) { ret = metaObj->emh; GDI_ReleaseObj( hmf ); } + LeaveCriticalSection( &enhmetafile_cs ); return ret; } @@ -317,6 +343,9 @@ static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile ) ENHMETAHEADER *emh; HANDLE hMapping; HENHMETAFILE hemf; + DWORD filesize; + + filesize = GetFileSize( hFile, NULL ); hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); @@ -324,7 +353,7 @@ static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile ) if (!emh) return 0; - hemf = EMF_Create_HENHMETAFILE( emh, TRUE ); + hemf = EMF_Create_HENHMETAFILE( emh, filesize, TRUE ); if (!hemf) UnmapViewOfFile( emh ); return hemf; @@ -467,7 +496,7 @@ HENHMETAFILE WINAPI SetEnhMetaFileBits(UINT bufsize, const BYTE *buf) ENHMETAHEADER *emh = HeapAlloc( GetProcessHeap(), 0, bufsize ); HENHMETAFILE hmf; memmove(emh, buf, bufsize); - hmf = EMF_Create_HENHMETAFILE( emh, FALSE ); + hmf = EMF_Create_HENHMETAFILE( emh, bufsize, FALSE ); if (!hmf) HeapFree( GetProcessHeap(), 0, emh ); return hmf; @@ -1127,6 +1156,31 @@ BOOL WINAPI PlayEnhMetaFileRecord( break; } + case EMR_POLYDRAW16: + { + const EMRPOLYDRAW16 *pPolyDraw16 = (const EMRPOLYDRAW16 *)mr; + const POINTS *ptl = pPolyDraw16->apts; + POINT *pts = HeapAlloc(GetProcessHeap(), 0, pPolyDraw16->cpts * sizeof(POINT)); + DWORD i; + + /* NB abTypes array doesn't start at pPolyDraw16->abTypes. It's actually + pPolyDraw16->apts + pPolyDraw16->cpts. */ + const BYTE *types = (BYTE*)(pPolyDraw16->apts + pPolyDraw16->cpts); + + if (!pts) + break; + + for (i = 0; i < pPolyDraw16->cpts; ++i) + { + pts[i].x = ptl[i].x; + pts[i].y = ptl[i].y; + } + + PolyDraw(hdc, pts, types, pPolyDraw16->cpts); + HeapFree(GetProcessHeap(), 0, pts); + break; + } + case EMR_STRETCHDIBITS: { const EMRSTRETCHDIBITS *pStretchDIBits = (const EMRSTRETCHDIBITS *)mr; @@ -2231,15 +2285,33 @@ BOOL WINAPI PlayEnhMetaFileRecord( break; } - case EMR_POLYDRAW16: + case EMR_DRAWESCAPE: + { + PEMRESCAPE pemr = (PEMRESCAPE)mr; + DrawEscape( hdc, pemr->iEsc, pemr->cjIn, (LPCSTR)pemr->Data ); + break; + } + + case EMR_EXTESCAPE: + { + PEMRESCAPE pemr = (PEMRESCAPE)mr; + ExtEscape( hdc, pemr->iEsc, pemr->cjIn, (LPCSTR)pemr->Data, 0, NULL ); + break; + } + + case EMR_NAMEDESCAPE: + { + PEMRNAMEDESCAPE pemr = (PEMRNAMEDESCAPE)mr; + INT rounded_size = (pemr->cjIn+3) & ~3; + NamedEscape( hdc, (PWCHAR)&pemr->Data[rounded_size], pemr->iEsc, pemr->cjIn, (LPSTR)pemr->Data, 0, NULL ); + break; + } + case EMR_GLSRECORD: case EMR_GLSBOUNDEDRECORD: - case EMR_DRAWESCAPE: - case EMR_EXTESCAPE: case EMR_STARTDOC: case EMR_SMALLTEXTOUT: case EMR_FORCEUFIMAPPING: - case EMR_NAMEDESCAPE: case EMR_COLORCORRECTPALETTE: case EMR_SETICMPROFILEA: case EMR_SETICMPROFILEW: @@ -2262,7 +2334,6 @@ BOOL WINAPI PlayEnhMetaFileRecord( return TRUE; } - /***************************************************************************** * * EnumEnhMetaFile (GDI32.@) @@ -2358,13 +2429,14 @@ BOOL WINAPI EnumEnhMetaFile( info->state.next = NULL; info->save_level = 0; info->saved_state = NULL; + info->init_transform = info->state.world_transform; ht = (HANDLETABLE*) &info[1]; ht->objectHandle[0] = hmf; for(i = 1; i < emh->nHandles; i++) ht->objectHandle[i] = NULL; - if(hdc) + if(hdc && !is_meta_dc( hdc )) { savedMode = SetGraphicsMode(hdc, GM_ADVANCED); GetWorldTransform(hdc, &savedXform); @@ -2394,17 +2466,7 @@ BOOL WINAPI EnumEnhMetaFile( old_polyfill = SetPolyFillMode(hdc, ALTERNATE); old_stretchblt = SetStretchBltMode(hdc, BLACKONWHITE); - if ( IS_WIN9X() ) - { - /* Win95 leaves the vp/win ext/org info alone */ - info->init_transform.eM11 = 1.0; - info->init_transform.eM12 = 0.0; - info->init_transform.eM21 = 0.0; - info->init_transform.eM22 = 1.0; - info->init_transform.eDx = 0.0; - info->init_transform.eDy = 0.0; - } - else + if (!IS_WIN9X() ) { /* WinNT combines the vp/win ext/org info into a transform */ double xscale, yscale; @@ -2463,6 +2525,14 @@ BOOL WINAPI EnumEnhMetaFile( { emr = (ENHMETARECORD *)((char *)emh + offset); + if (offset + 8 > emh->nBytes || + offset > offset + emr->nSize || + offset + emr->nSize > emh->nBytes) + { + WARN("record truncated\n"); + break; + } + /* In Win9x mode we update the xform if the record will produce output */ if (hdc && IS_WIN9X() && emr_produces_output(emr->iType)) EMF_Update_MF_Xform(hdc, info); @@ -2472,7 +2542,7 @@ BOOL WINAPI EnumEnhMetaFile( offset += emr->nSize; } - if (hdc) + if (hdc && !is_meta_dc( hdc )) { SetStretchBltMode(hdc, old_stretchblt); SetPolyFillMode(hdc, old_polyfill); @@ -2536,8 +2606,7 @@ BOOL WINAPI PlayEnhMetaFile( const RECT *lpRect /* [in] rectangle to place metafile inside */ ) { - return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL, - lpRect); + return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL, lpRect); } /***************************************************************************** @@ -2568,7 +2637,7 @@ HENHMETAFILE WINAPI CopyEnhMetaFileA( if (!file) { emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes ); memcpy( emrDst, emrSrc, emrSrc->nBytes ); - hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE ); + hmfDst = EMF_Create_HENHMETAFILE( emrDst, emrSrc->nBytes, FALSE ); if (!hmfDst) HeapFree( GetProcessHeap(), 0, emrDst ); } else { @@ -2610,7 +2679,7 @@ HENHMETAFILE WINAPI CopyEnhMetaFileW( if (!file) { emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes ); memcpy( emrDst, emrSrc, emrSrc->nBytes ); - hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE ); + hmfDst = EMF_Create_HENHMETAFILE( emrDst, emrSrc->nBytes, FALSE ); if (!hmfDst) HeapFree( GetProcessHeap(), 0, emrDst ); } else { diff --git a/win32ss/gdi/gdi32/wine/gdi_private.h b/win32ss/gdi/gdi32/wine/gdi_private.h index f3b79c462b7..de49fae2a47 100644 --- a/win32ss/gdi/gdi32/wine/gdi_private.h +++ b/win32ss/gdi/gdi32/wine/gdi_private.h @@ -26,7 +26,33 @@ #include "windef.h" #include "winbase.h" #include "wingdi.h" -#include + +#define GDILoObjType_LO_DC_TYPE 0x10000 +#define GDILoObjType_LO_FONT_TYPE 0xa0000 +#define GDILoObjType_LO_BRUSH_TYPE 0x100000 +#define GDILoObjType_LO_ALTDC_TYPE 0x210000 +#define GDILoObjType_LO_PEN_TYPE 0x300000 +#define GDILoObjType_LO_EXTPEN_TYPE 0x500000 +#define GDILoObjType_LO_METAFILE16_TYPE 0x260000 +#define GDILoObjType_LO_METAFILE_TYPE 0x460000 +#define GDILoObjType_LO_METADC16_TYPE 0x660000 + +#define GDI_HANDLE_TYPE_MASK 0x007f0000 +#define GDI_HANDLE_GET_TYPE(h) \ + (((ULONG_PTR)(h)) & GDI_HANDLE_TYPE_MASK) + +HRGN APIENTRY NtGdiPathToRegion(_In_ HDC hdc); +HDC APIENTRY NtGdiCreateMetafileDC(_In_ HDC hdc); +#define GdiWorldSpaceToDeviceSpace 0x204 +BOOL APIENTRY NtGdiGetTransform(_In_ HDC hdc,_In_ DWORD iXform, _Out_ LPXFORM pxf); +/* Get/SetBounds/Rect support. */ +#define DCB_WINDOWMGR 0x8000 /* Queries the Windows bounding rectangle instead of the application's */ +BOOL WINAPI GetBoundsRectAlt(HDC hdc,LPRECT prc,UINT flags); +BOOL WINAPI SetBoundsRectAlt(HDC hdc,LPRECT prc,UINT flags); + +HGDIOBJ WINAPI GdiCreateClientObj(_In_ PVOID pvObject,_In_ UINT eObjType); +PVOID WINAPI GdiGetClientObjLink(_In_ HGDIOBJ hobj); +PVOID WINAPI GdiDeleteClientObj(_In_ HGDIOBJ hobj); /* Metafile defines */ #define META_EOF 0x0000 @@ -43,6 +69,15 @@ typedef struct { INT nBreakCount; } EMRSETTEXTJUSTIFICATION, *PEMRSETTEXTJUSTIFICATION; +typedef struct tagEMRESCAPE { + EMR emr; + INT iEsc; + INT cjIn; + BYTE Data[1]; +} EMRESCAPE, *PEMRESCAPE, EMRNAMEDESCAPE, *PEMRNAMEDESCAPE; + +INT WINAPI NamedEscape(HDC,PWCHAR,INT,INT,LPSTR,INT,LPSTR); + struct gdi_obj_funcs { HGDIOBJ (*pSelectObject)( HGDIOBJ handle, HDC hdc ); @@ -56,15 +91,14 @@ struct gdi_obj_funcs #define LDC_LDC 0x00000001 #define LDC_EMFLDC 0x00000002 +typedef struct emf *PEMF; + typedef struct tagWINEDC { HDC hdc; ULONG Flags; INT iType; - union { - PVOID pvEmfDC; /* Pointer to ENHMETAFILE structure */ - PHYSDEV physDev; /* current top of the physdev stack */ - }; + PEMF emf; /* Pointer to ENHMETAFILE structure */ LPWSTR pwszPort; ABORTPROC pAbortProc; DWORD CallBackTick; @@ -72,21 +106,27 @@ typedef struct tagWINEDC PDEVMODEW pdm; PVOID pUMPDev; PVOID pUMdhpdev; + PVOID UFIHashTable[3]; + ULONG ufi[2]; + PVOID pvEMFSpoolData; + ULONG cjSize; + LIST_ENTRY leRecords; ULONG DevCaps[36]; HBRUSH hBrush; HPEN hPen; //// - struct gdi_physdev NullPhysDev; - LONG refcount; /* thread refcount */ - INT saveLevel; - HFONT hFont; - HPALETTE hPalette; + INT save_level; + RECTL emf_bounds; } WINEDC, DC; -WINEDC* get_physdev_dc( PHYSDEV dev ); +static inline BOOL is_meta_dc( HDC hdc ) +{ + return GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE; +} + /* brush.c */ -extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void **bits, UINT *usage ) DECLSPEC_HIDDEN; +extern BOOL get_brush_bitmap_info( HBRUSH handle, BITMAPINFO *info, void *bits, UINT *usage ) DECLSPEC_HIDDEN; /* dc.c */ extern DC *alloc_dc_ptr( WORD magic ) DECLSPEC_HIDDEN; @@ -98,7 +138,7 @@ extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; extern int bitmap_info_size( const BITMAPINFO * info, WORD coloruse ) DECLSPEC_HIDDEN; /* enhmetafile.c */ -extern HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) DECLSPEC_HIDDEN; +extern HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, DWORD filesize, BOOL on_disk ) DECLSPEC_HIDDEN; /* gdiobj.c */ extern HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN; @@ -117,13 +157,11 @@ extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOO #include typedef struct { - DWORD magic; /* WMFC */ - WORD unk04; /* 1 */ - WORD unk06; /* 0 */ - WORD unk08; /* 0 */ - WORD unk0a; /* 1 */ + DWORD magic; /* WMFC */ + DWORD comment_type; /* Always 0x00000001 */ + DWORD version; /* Always 0x00010000 */ WORD checksum; - DWORD unk0e; /* 0 */ + DWORD flags; /* Always 0 */ DWORD num_chunks; DWORD chunk_size; DWORD remaining_size; @@ -137,29 +175,10 @@ typedef struct extern HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg) DECLSPEC_HIDDEN; extern UINT WINAPI GDIRealizePalette( HDC hdc ) DECLSPEC_HIDDEN; +DWORD WINAPI GetDCDWord(_In_ HDC hdc,_In_ UINT u,_In_ DWORD dwError); + #define EMR_SETLINKEDUFI 119 -#define GET_DC_PHYSDEV(dc,func) \ - get_physdev_entry_point( (dc)->physDev, FIELD_OFFSET(struct gdi_dc_funcs,func)) - -static inline PHYSDEV pop_dc_driver( DC *dc, const struct gdi_dc_funcs *funcs ) -{ - PHYSDEV dev, *pdev = &dc->physDev; - while (*pdev && (*pdev)->funcs != funcs) pdev = &(*pdev)->next; - if (!*pdev) return NULL; - dev = *pdev; - *pdev = dev->next; - return dev; -} - -static inline PHYSDEV find_dc_driver( DC *dc, const struct gdi_dc_funcs *funcs ) -{ - PHYSDEV dev; - - for (dev = dc->physDev; dev; dev = dev->next) if (dev->funcs == funcs) return dev; - return NULL; -} - /* Undocumented value for DIB's iUsage: Indicates a mono DIB w/o pal entries */ #define DIB_PAL_MONO 2 @@ -196,8 +215,6 @@ BOOL APIENTRY NtGdiGetTransform( _In_ HDC hdc, _In_ DWORD iXform, _Out_ LPXFORM HGDIOBJ WINAPI GdiFixUpHandle(HGDIOBJ hGdiObj); #define get_full_gdi_handle GdiFixUpHandle -extern void push_dc_driver_ros(PHYSDEV *dev, PHYSDEV physdev, const struct gdi_dc_funcs *funcs); -#define push_dc_driver push_dc_driver_ros #if 0 BOOL WINAPI SetWorldTransformForMetafile(HDC hdc, const XFORM *pxform); #define SetWorldTransform SetWorldTransformForMetafile @@ -211,5 +228,36 @@ BOOL WINAPI SetWorldTransformForMetafile(HDC hdc, const XFORM *pxform); #undef ASSERT #define ASSERT(x) if (!(x)) DbgRaiseAssertionFailure() +BOOL EMFDRV_LineTo( WINEDC *dc, INT x, INT y ); +BOOL EMFDRV_RoundRect( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT ell_width, INT ell_height ); +BOOL EMFDRV_ArcChordPie( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend, DWORD type ); +BOOL EMFDRV_Arc( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ); +BOOL EMFDRV_ArcTo( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ); +BOOL EMFDRV_Pie( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ); +BOOL EMFDRV_Chord( WINEDC *dc, INT left, INT top, INT right, INT bottom, INT xstart, INT ystart, INT xend, INT yend ); +BOOL EMFDRV_Ellipse( WINEDC *dc, INT left, INT top, INT right, INT bottom ); +BOOL EMFDRV_Rectangle( WINEDC *dc, INT left, INT top, INT right, INT bottom ); +COLORREF EMFDRV_SetPixel( WINEDC *dc, INT x, INT y, COLORREF color ); +BOOL EMFDRV_PolylineTo( WINEDC *dc, const POINT *pt, INT count ); +BOOL EMFDRV_PolyBezier( WINEDC *dc, const POINT *pts, DWORD count ); +BOOL EMFDRV_PolyBezierTo( WINEDC *dc, const POINT *pts, DWORD count ); +BOOL EMFDRV_PolyPolyline( WINEDC *dc, const POINT *pt, const DWORD *counts, UINT polys ); +BOOL EMFDRV_PolyPolygon( WINEDC *dc, const POINT *pt, const INT *counts, UINT polys ); +BOOL EMFDRV_PolyDraw( WINEDC *dc, const POINT *pts, const BYTE *types, DWORD count ); +BOOL EMFDRV_FillRgn( WINEDC *dc, HRGN hrgn, HBRUSH hbrush ); +BOOL EMFDRV_FrameRgn( WINEDC *dc, HRGN hrgn, HBRUSH hbrush, INT width, INT height ); +BOOL EMFDRV_InvertRgn( WINEDC *dc, HRGN hrgn ); +BOOL EMFDRV_ExtTextOut( WINEDC *dc, INT x, INT y, UINT flags, const RECT *lprect,LPCWSTR str, UINT count, const INT *lpDx ); +BOOL EMFDRV_GradientFill( WINEDC *dc, TRIVERTEX *vert_array, ULONG nvert, void *grad_array, ULONG ngrad, ULONG mode ); +BOOL EMFDRV_FillPath( WINEDC *dc ); +BOOL EMFDRV_StrokeAndFillPath( WINEDC *dc ); +BOOL EMFDRV_StrokePath( WINEDC *dc ); +BOOL EMFDRV_AlphaBlend( WINEDC *dc_dst, INT x_dst, INT y_dst, INT width_dst, INT height_dst,HDC dc_src, INT x_src, INT y_src, INT width_src, INT height_src, BLENDFUNCTION func ); +BOOL EMFDRV_PatBlt( WINEDC *dc, INT left, INT top, INT width, INT height, DWORD rop ); +INT EMFDRV_StretchDIBits( WINEDC *dc, INT x_dst, INT y_dst, INT width_dst,INT height_dst, INT x_src, INT y_src, INT width_src, INT height_src, const void *bits, BITMAPINFO *info, UINT wUsage, DWORD dwRop ); +INT EMFDRV_SetDIBitsToDevice( WINEDC *dc, INT x_dst, INT y_dst, DWORD width, DWORD height, INT x_src, INT y_src, UINT startscan, UINT lines, const void *bits, BITMAPINFO *info, UINT usage ); +HBITMAP EMFDRV_SelectBitmap( WINEDC *dc, HBITMAP hbitmap ); + + #endif /* __WINE_GDI_PRIVATE_H */ diff --git a/win32ss/gdi/gdi32/wine/metadc.c b/win32ss/gdi/gdi32/wine/metadc.c new file mode 100644 index 00000000000..c5bff94416e --- /dev/null +++ b/win32ss/gdi/gdi32/wine/metadc.c @@ -0,0 +1,1445 @@ +/* + * Metafile DC functions + * + * Copyright 1999 Huw D M Davies + * Copyright 1993, 1994, 1996 Alexandre Julliard + * Copyright 2021 Jacek Caban for CodeWeavers + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wine/config.h" + +#include +#include +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winnls.h" +#include "winerror.h" +#include "gdi_private.h" +#ifdef __REACTOS__ +#include "wine/winternl.h" +#else +#include "winternl.h" +#endif +#include "wine/wingdi16.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +struct metadc +{ + HDC hdc; + METAHEADER *mh; /* Pointer to metafile header */ + UINT handles_size, cur_handles; + HGDIOBJ *handles; + HANDLE hFile; /* Handle for disk based MetaFile */ + HPEN pen; + HBRUSH brush; + HFONT font; +}; + +#define HANDLE_LIST_INC 20 + + +struct metadc *get_metadc_ptr( HDC hdc ) +{ + struct metadc *metafile = GdiGetClientObjLink(hdc);//get_gdi_client_ptr( hdc, NTGDI_OBJ_METADC ); + if (!metafile) SetLastError( ERROR_INVALID_HANDLE ); + return metafile; +} + +static BOOL metadc_write_record( struct metadc *metadc, METARECORD *mr, unsigned int rlen ) +{ + DWORD len, size; + METAHEADER *mh; + + len = metadc->mh->mtSize * sizeof(WORD) + rlen; + size = HeapSize( GetProcessHeap(), 0, metadc->mh ); + if (len > size) + { + size += size / sizeof(WORD) + rlen; + mh = HeapReAlloc( GetProcessHeap(), 0, metadc->mh, size ); + if (!mh) return FALSE; + metadc->mh = mh; + } + memcpy( (WORD *)metadc->mh + metadc->mh->mtSize, mr, rlen ); + + metadc->mh->mtSize += rlen / sizeof(WORD); + metadc->mh->mtMaxRecord = max( metadc->mh->mtMaxRecord, rlen / sizeof(WORD) ); + return TRUE; +} + +static BOOL metadc_record( HDC hdc, METARECORD *mr, DWORD rlen ) +{ + struct metadc *metadc; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + return metadc_write_record( metadc, mr, rlen ); +} + +static BOOL metadc_param0( HDC hdc, short func ) +{ + METARECORD mr; + + mr.rdSize = FIELD_OFFSET(METARECORD, rdParm[0]) / sizeof(WORD); + mr.rdFunction = func; + return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) ); +} + +static BOOL metadc_param1( HDC hdc, short func, short param ) +{ + METARECORD mr; + + mr.rdSize = sizeof(mr) / sizeof(WORD); + mr.rdFunction = func; + mr.rdParm[0] = param; + return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) ); +} + +static BOOL metadc_param2( HDC hdc, short func, short param1, short param2 ) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[2])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = func; + mr->rdParm[0] = param2; + mr->rdParm[1] = param1; + return metadc_record( hdc, mr, sizeof(buffer) ); +} + +static BOOL metadc_param4( HDC hdc, short func, short param1, short param2, + short param3, short param4 ) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[4])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = func; + mr->rdParm[0] = param4; + mr->rdParm[1] = param3; + mr->rdParm[2] = param2; + mr->rdParm[3] = param1; + return metadc_record( hdc, mr, sizeof(buffer) ); +} + +static BOOL metadc_param5( HDC hdc, short func, short param1, short param2, + short param3, short param4, short param5 ) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[5])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = func; + mr->rdParm[0] = param5; + mr->rdParm[1] = param4; + mr->rdParm[2] = param3; + mr->rdParm[3] = param2; + mr->rdParm[4] = param1; + return metadc_record( hdc, mr, sizeof(buffer) ); +} + +static BOOL metadc_param6( HDC hdc, short func, short param1, short param2, + short param3, short param4, short param5, + short param6 ) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[6])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = func; + mr->rdParm[0] = param6; + mr->rdParm[1] = param5; + mr->rdParm[2] = param4; + mr->rdParm[3] = param3; + mr->rdParm[4] = param2; + mr->rdParm[5] = param1; + return metadc_record( hdc, mr, sizeof(buffer) ); +} + +static BOOL metadc_param8( HDC hdc, short func, short param1, short param2, + short param3, short param4, short param5, + short param6, short param7, short param8) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[8])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = func; + mr->rdParm[0] = param8; + mr->rdParm[1] = param7; + mr->rdParm[2] = param6; + mr->rdParm[3] = param5; + mr->rdParm[4] = param4; + mr->rdParm[5] = param3; + mr->rdParm[6] = param2; + mr->rdParm[7] = param1; + return metadc_record( hdc, mr, sizeof(buffer) ); +} + +BOOL METADC_SaveDC( HDC hdc ) +{ + return metadc_param0( hdc, META_SAVEDC ); +} + +BOOL METADC_RestoreDC( HDC hdc, INT level ) +{ + return metadc_param1( hdc, META_RESTOREDC, level ); +} + +BOOL METADC_SetTextAlign( HDC hdc, UINT align ) +{ + return metadc_param2( hdc, META_SETTEXTALIGN, HIWORD(align), LOWORD(align) ); +} + +BOOL METADC_SetBkMode( HDC hdc, INT mode ) +{ + return metadc_param1( hdc, META_SETBKMODE, (WORD)mode ); +} + +BOOL METADC_SetBkColor( HDC hdc, COLORREF color ) +{ + return metadc_param2( hdc, META_SETBKCOLOR, HIWORD(color), LOWORD(color) ); +} + +BOOL METADC_SetTextColor( HDC hdc, COLORREF color ) +{ + return metadc_param2( hdc, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color) ); +} + +BOOL METADC_SetROP2( HDC hdc, INT rop ) +{ + return metadc_param1( hdc, META_SETROP2, (WORD)rop ); +} + +BOOL METADC_SetRelAbs( HDC hdc, INT mode ) +{ + return metadc_param1( hdc, META_SETRELABS, (WORD)mode ); +} + +BOOL METADC_SetPolyFillMode( HDC hdc, INT mode ) +{ + return metadc_param1( hdc, META_SETPOLYFILLMODE, mode ); +} + +BOOL METADC_SetStretchBltMode( HDC hdc, INT mode ) +{ + return metadc_param1( hdc, META_SETSTRETCHBLTMODE, mode ); +} + +BOOL METADC_IntersectClipRect( HDC hdc, INT left, INT top, INT right, INT bottom ) +{ + return metadc_param4( hdc, META_INTERSECTCLIPRECT, left, top, right, bottom ); +} + +BOOL METADC_ExcludeClipRect( HDC hdc, INT left, INT top, INT right, INT bottom ) +{ + return metadc_param4( hdc, META_EXCLUDECLIPRECT, left, top, right, bottom ); +} + +BOOL METADC_OffsetClipRgn( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_OFFSETCLIPRGN, x, y ); +} + +BOOL METADC_SetLayout( HDC hdc, DWORD layout ) +{ + return metadc_param2( hdc, META_SETLAYOUT, HIWORD(layout), LOWORD(layout) ); +} + +BOOL METADC_SetMapMode( HDC hdc, INT mode ) +{ + return metadc_param1( hdc, META_SETMAPMODE, mode ); +} + +BOOL METADC_SetViewportExtEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_SETVIEWPORTEXT, x, y ); +} + +BOOL METADC_SetViewportOrgEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_SETVIEWPORTORG, x, y ); +} + +BOOL METADC_SetWindowExtEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_SETWINDOWEXT, x, y ); +} + +BOOL METADC_SetWindowOrgEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_SETWINDOWORG, x, y ); +} + +BOOL METADC_OffsetViewportOrgEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_OFFSETVIEWPORTORG, x, y ); +} + +BOOL METADC_OffsetWindowOrgEx( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_OFFSETWINDOWORG, x, y ); +} + +BOOL METADC_ScaleViewportExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom ) +{ + return metadc_param4( hdc, META_SCALEVIEWPORTEXT, x_num, x_denom, y_num, y_denom ); +} + +BOOL METADC_ScaleWindowExtEx( HDC hdc, INT x_num, INT x_denom, INT y_num, INT y_denom ) +{ + return metadc_param4( hdc, META_SCALEWINDOWEXT, x_num, x_denom, y_num, y_denom ); +} + +BOOL METADC_SetTextJustification( HDC hdc, INT extra, INT breaks ) +{ + return metadc_param2( hdc, META_SETTEXTJUSTIFICATION, extra, breaks ); +} + +BOOL METADC_SetTextCharacterExtra( HDC hdc, INT extra ) +{ + return metadc_param1( hdc, META_SETTEXTCHAREXTRA, extra ); +} + +BOOL METADC_SetMapperFlags( HDC hdc, DWORD flags ) +{ + return metadc_param2( hdc, META_SETMAPPERFLAGS, HIWORD(flags), LOWORD(flags) ); +} + +BOOL METADC_MoveTo( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_MOVETO, x, y ); +} + +BOOL METADC_LineTo( HDC hdc, INT x, INT y ) +{ + return metadc_param2( hdc, META_LINETO, x, y ); +} + +BOOL METADC_Arc( HDC hdc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return metadc_param8( hdc, META_ARC, left, top, right, bottom, + xstart, ystart, xend, yend ); +} + +BOOL METADC_Pie( HDC hdc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return metadc_param8( hdc, META_PIE, left, top, right, bottom, + xstart, ystart, xend, yend ); +} + +BOOL METADC_Chord( HDC hdc, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return metadc_param8( hdc, META_CHORD, left, top, right, bottom, + xstart, ystart, xend, yend ); +} + +BOOL METADC_Ellipse( HDC hdc, INT left, INT top, INT right, INT bottom ) +{ + return metadc_param4( hdc, META_ELLIPSE, left, top, right, bottom ); +} + +BOOL METADC_Rectangle( HDC hdc, INT left, INT top, INT right, INT bottom ) +{ + return metadc_param4( hdc, META_RECTANGLE, left, top, right, bottom ); +} + +BOOL METADC_RoundRect( HDC hdc, INT left, INT top, INT right, + INT bottom, INT ell_width, INT ell_height ) +{ + return metadc_param6( hdc, META_ROUNDRECT, left, top, right, bottom, + ell_width, ell_height ); +} + +BOOL METADC_SetPixel( HDC hdc, INT x, INT y, COLORREF color ) +{ + return metadc_param4( hdc, META_SETPIXEL, x, y, HIWORD(color), LOWORD(color) ); +} + +static BOOL metadc_poly( HDC hdc, short func, POINTS *pt, short count ) +{ + BOOL ret; + DWORD len; + METARECORD *mr; + + len = sizeof(METARECORD) + count * 4; + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) + return FALSE; + + mr->rdSize = len / 2; + mr->rdFunction = func; + *(mr->rdParm) = count; + memcpy(mr->rdParm + 1, pt, count * 4); + ret = metadc_record( hdc, mr, mr->rdSize * 2); + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + +BOOL METADC_Polyline( HDC hdc, const POINT *pt, INT count ) +{ + int i; + POINTS *pts; + BOOL ret; + + pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count ); + if(!pts) return FALSE; + for (i=count;i--;) + { + pts[i].x = pt[i].x; + pts[i].y = pt[i].y; + } + ret = metadc_poly( hdc, META_POLYLINE, pts, count ); + + HeapFree( GetProcessHeap(), 0, pts ); + return ret; +} + +BOOL METADC_Polygon( HDC hdc, const POINT *pt, INT count ) +{ + int i; + POINTS *pts; + BOOL ret; + + pts = HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * count ); + if(!pts) return FALSE; + for (i = count; i--;) + { + pts[i].x = pt[i].x; + pts[i].y = pt[i].y; + } + ret = metadc_poly( hdc, META_POLYGON, pts, count ); + + HeapFree( GetProcessHeap(), 0, pts ); + return ret; +} + +BOOL METADC_PolyPolygon( HDC hdc, const POINT *pt, const INT *counts, UINT polygons ) +{ + BOOL ret; + DWORD len; + METARECORD *mr; + unsigned int i,j; + POINTS *pts; + INT16 totalpoint16 = 0; + INT16 * pointcounts; + + for (i = 0; i < polygons; i++) + totalpoint16 += counts[i]; + + /* allocate space for all points */ + pts=HeapAlloc( GetProcessHeap(), 0, sizeof(POINTS) * totalpoint16 ); + pointcounts = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * totalpoint16 ); + + /* copy point counts */ + for (i = 0; i < polygons; i++) + pointcounts[i] = counts[i]; + + /* convert all points */ + for (j = totalpoint16; j--;) + { + pts[j].x = pt[j].x; + pts[j].y = pt[j].y; + } + + len = sizeof(METARECORD) + sizeof(WORD) + polygons * sizeof(INT16) + + totalpoint16 * sizeof(*pts); + + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) + { + HeapFree( GetProcessHeap(), 0, pts ); + HeapFree( GetProcessHeap(), 0, pointcounts ); + return FALSE; + } + + mr->rdSize = len / sizeof(WORD); + mr->rdFunction = META_POLYPOLYGON; + *mr->rdParm = polygons; + memcpy( mr->rdParm + 1, pointcounts, polygons * sizeof(INT16) ); + memcpy( mr->rdParm + 1+polygons, pts , totalpoint16 * sizeof(*pts) ); + ret = metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) ); + + HeapFree( GetProcessHeap(), 0, pts ); + HeapFree( GetProcessHeap(), 0, pointcounts ); + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + +BOOL METADC_ExtFloodFill( HDC hdc, INT x, INT y, COLORREF color, UINT fill_type ) +{ + return metadc_param5( hdc, META_EXTFLOODFILL, x, y, HIWORD(color), LOWORD(color), fill_type ); +} + +static UINT metadc_add_handle( struct metadc *metadc, HGDIOBJ obj ) +{ + UINT16 index; + + for (index = 0; index < metadc->handles_size; index++) + if (metadc->handles[index] == 0) break; + if(index == metadc->handles_size) + { + metadc->handles_size += HANDLE_LIST_INC; + metadc->handles = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + metadc->handles, + metadc->handles_size * sizeof(metadc->handles[0]) ); + } + metadc->handles[index] = get_full_gdi_handle( obj ); + + metadc->cur_handles++; + if (metadc->cur_handles > metadc->mh->mtNoObjects) + metadc->mh->mtNoObjects++; + + return index ; /* index 0 is not reserved for metafiles */ +} + +static BOOL metadc_remove_handle( struct metadc *metadc, UINT index ) +{ + BOOL ret = FALSE; + + if (index < metadc->handles_size && metadc->handles[index]) + { + metadc->handles[index] = 0; + metadc->cur_handles--; + ret = TRUE; + } + return ret; +} + +static INT16 metadc_create_brush( struct metadc *metadc, HBRUSH brush ) +{ + DWORD size; + METARECORD *mr; + LOGBRUSH logbrush; + BOOL r; + + if (!GetObjectA( brush, sizeof(logbrush), &logbrush )) return -1; + + switch (logbrush.lbStyle) + { + case BS_SOLID: + case BS_NULL: + case BS_HATCHED: + { + LOGBRUSH16 lb16; + + lb16.lbStyle = logbrush.lbStyle; + lb16.lbColor = logbrush.lbColor; + lb16.lbHatch = logbrush.lbHatch; + size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - sizeof(WORD); + mr = HeapAlloc( GetProcessHeap(), 0, size ); + mr->rdSize = size / sizeof(WORD); + mr->rdFunction = META_CREATEBRUSHINDIRECT; + memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16) ); + break; + } + case BS_PATTERN: + case BS_DIBPATTERN: + { + char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; + DWORD info_size; + UINT usage; + + if (!get_brush_bitmap_info( brush, src_info, NULL, &usage )) goto done; + + info_size = get_dib_info_size( src_info, usage ); + size = FIELD_OFFSET( METARECORD, rdParm[2] ) + + info_size + src_info->bmiHeader.biSizeImage; + + if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) goto done; + mr->rdFunction = META_DIBCREATEPATTERNBRUSH; + mr->rdSize = size / sizeof(WORD); + mr->rdParm[0] = logbrush.lbStyle; + mr->rdParm[1] = usage; + dst_info = (BITMAPINFO *)(mr->rdParm + 2); + get_brush_bitmap_info( brush, dst_info, (char *)dst_info + info_size, NULL ); + if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount) + dst_info->bmiHeader.biClrUsed = 0; + break; + } + + default: + FIXME( "Unknown brush style %x\n", logbrush.lbStyle ); + return 0; + } + + r = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) ); + HeapFree(GetProcessHeap(), 0, mr); + if (!r) return -1; +done: + return metadc_add_handle( metadc, brush ); +} + +static INT16 metadc_create_region( struct metadc *metadc, HRGN hrgn ) +{ + DWORD len; + METARECORD *mr; + RGNDATA *rgndata; + RECT *cur_rect, *end_rect; + WORD bands = 0, max_bounds = 0; + WORD *param, *start_band; + BOOL ret; + + if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1; + if (!(rgndata = HeapAlloc( GetProcessHeap(), 0, len ))) + { + WARN( "Can't alloc rgndata buffer\n" ); + return -1; + } + GetRegionData( hrgn, len, rgndata ); + + /* Overestimate of length: + * Assume every rect is a separate band -> 6 WORDs per rect, + * see MF_Play_MetaCreateRegion for format details. + */ + len = sizeof(METARECORD) + 20 + rgndata->rdh.nCount * 12; + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) + { + WARN( "Can't alloc METARECORD buffer\n" ); + HeapFree( GetProcessHeap(), 0, rgndata ); + return -1; + } + + param = mr->rdParm + 11; + start_band = NULL; + + end_rect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount; + for (cur_rect = (RECT *)rgndata->Buffer; cur_rect < end_rect; cur_rect++) + { + if (start_band && cur_rect->top == start_band[1]) + { + *param++ = cur_rect->left; + *param++ = cur_rect->right; + } + else + { + if (start_band) + { + *start_band = param - start_band - 3; + *param++ = *start_band; + if (*start_band > max_bounds) + max_bounds = *start_band; + bands++; + } + start_band = param++; + *param++ = cur_rect->top; + *param++ = cur_rect->bottom; + *param++ = cur_rect->left; + *param++ = cur_rect->right; + } + } + + if (start_band) + { + *start_band = param - start_band - 3; + *param++ = *start_band; + if (*start_band > max_bounds) + max_bounds = *start_band; + bands++; + } + + mr->rdParm[0] = 0; + mr->rdParm[1] = 6; + mr->rdParm[2] = 0x2f6; + mr->rdParm[3] = 0; + mr->rdParm[4] = (param - &mr->rdFunction) * sizeof(WORD); + mr->rdParm[5] = bands; + mr->rdParm[6] = max_bounds; + mr->rdParm[7] = rgndata->rdh.rcBound.left; + mr->rdParm[8] = rgndata->rdh.rcBound.top; + mr->rdParm[9] = rgndata->rdh.rcBound.right; + mr->rdParm[10] = rgndata->rdh.rcBound.bottom; + mr->rdFunction = META_CREATEREGION; + mr->rdSize = param - (WORD *)mr; + ret = metadc_write_record( metadc, mr, mr->rdSize * 2 ); + HeapFree( GetProcessHeap(), 0, mr ); + HeapFree( GetProcessHeap(), 0, rgndata ); + if (!ret) + { + WARN("MFDRV_WriteRecord failed\n"); + return -1; + } + return metadc_add_handle( metadc, hrgn ); +} + +BOOL METADC_PaintRgn( HDC hdc, HRGN hrgn ) +{ + struct metadc *metadc; + INT16 index; + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + index = metadc_create_region( metadc, hrgn ); + if(index == -1) return FALSE; + return metadc_param1( hdc, META_PAINTREGION, index ); +} + +BOOL METADC_InvertRgn( HDC hdc, HRGN hrgn ) +{ + struct metadc *metadc; + INT16 index; + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + index = metadc_create_region( metadc, hrgn ); + if (index == -1) return FALSE; + return metadc_param1( hdc, META_INVERTREGION, index ); +} + +BOOL METADC_FillRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush ) +{ + struct metadc *metadc; + INT16 rgn, brush; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + + rgn = metadc_create_region( metadc, hrgn ); + if (rgn == -1) return FALSE; + brush = metadc_create_brush( metadc, hbrush ); + if (!brush) return FALSE; + return metadc_param2( hdc, META_FILLREGION, rgn, brush ); +} + +BOOL METADC_FrameRgn( HDC hdc, HRGN hrgn, HBRUSH hbrush, INT x, INT y ) +{ + struct metadc *metadc; + INT16 rgn, brush; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + rgn = metadc_create_region( metadc, hrgn ); + if (rgn == -1) return FALSE; + brush = metadc_create_brush( metadc, hbrush ); + if (!brush) return FALSE; + return metadc_param4( hdc, META_FRAMEREGION, rgn, brush, x, y ); +} + +BOOL METADC_PatBlt( HDC hdc, INT left, INT top, INT width, INT height, DWORD rop ) +{ + return metadc_param6( hdc, META_PATBLT, left, top, width, height, + HIWORD(rop), LOWORD(rop) ); +} + +static BOOL metadc_stretchblt( HDC hdc, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop, WORD type ) +{ + BITMAPINFO src_info = {{ sizeof( src_info.bmiHeader ) }}; + UINT bmi_size, size, bpp; + int i = 0, bitmap_offset; + BITMAPINFO *bmi; + METARECORD *mr; + HBITMAP bitmap; + BOOL ret; + + if (!(bitmap = GetCurrentObject( hdc_src, OBJ_BITMAP ))) return FALSE; + if (!GetDIBits( hdc_src, bitmap, 0, INT_MAX, NULL, &src_info, DIB_RGB_COLORS )) return FALSE; + + bpp = src_info.bmiHeader.biBitCount; + if (bpp <= 8) + bmi_size = sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD); + else if (bpp == 16 || bpp == 32) + bmi_size = sizeof(BITMAPINFOHEADER) + 3 * sizeof(RGBQUAD); + else + bmi_size = sizeof(BITMAPINFOHEADER); + + bitmap_offset = type == META_DIBBITBLT ? 8 : 10; + size = FIELD_OFFSET( METARECORD, rdParm[bitmap_offset] ) + bmi_size + + src_info.bmiHeader.biSizeImage; + if (!(mr = HeapAlloc( GetProcessHeap(), 0, size ))) return FALSE; + mr->rdFunction = type; + bmi = (BITMAPINFO *)&mr->rdParm[bitmap_offset]; + bmi->bmiHeader = src_info.bmiHeader; + TRACE( "size = %u rop=%x\n", size, rop ); + + ret = GetDIBits( hdc_src, bitmap, 0, src_info.bmiHeader.biHeight, (BYTE *)bmi + bmi_size, + bmi, DIB_RGB_COLORS ); + if (ret) + { + mr->rdSize = size / sizeof(WORD); + mr->rdParm[i++] = LOWORD(rop); + mr->rdParm[i++] = HIWORD(rop); + if (bitmap_offset > 8) + { + mr->rdParm[i++] = height_src; + mr->rdParm[i++] = width_src; + } + mr->rdParm[i++] = y_src; + mr->rdParm[i++] = x_src; + mr->rdParm[i++] = height_dst; + mr->rdParm[i++] = width_dst; + mr->rdParm[i++] = y_dst; + mr->rdParm[i++] = x_dst; + ret = metadc_record( hdc, mr, size ); + } + + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + +BOOL METADC_BitBlt( HDC hdc, INT x_dst, INT y_dst, INT width, INT height, + HDC hdc_src, INT x_src, INT y_src, DWORD rop ) +{ + return metadc_stretchblt( hdc, x_dst, y_dst, width, height, + hdc_src, x_src, y_src, width, height, rop, META_DIBBITBLT ); +} + +BOOL METADC_StretchBlt( HDC hdc_dst, INT x_dst, INT y_dst, INT width_dst, INT height_dst, + HDC hdc_src, INT x_src, INT y_src, INT width_src, INT height_src, + DWORD rop ) +{ + return metadc_stretchblt( hdc_dst, x_dst, y_dst, width_dst, height_dst, + hdc_src, x_src, y_src, width_src, height_src, rop, META_DIBSTRETCHBLT ); +} + +INT METADC_StretchDIBits( HDC hdc, INT x_dst, INT y_dst, INT width_dst, + INT height_dst, INT x_src, INT y_src, INT width_src, + INT height_src, const void *bits, + const BITMAPINFO *info, UINT usage, DWORD rop ) +{ + DWORD infosize = get_dib_info_size( info, usage ); + DWORD len = sizeof(METARECORD) + 10 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage; + METARECORD *mr; + + if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) return 0; + + mr->rdSize = len / sizeof(WORD); + mr->rdFunction = META_STRETCHDIB; + mr->rdParm[0] = LOWORD(rop); + mr->rdParm[1] = HIWORD(rop); + mr->rdParm[2] = usage; + mr->rdParm[3] = height_src; + mr->rdParm[4] = width_src; + mr->rdParm[5] = y_src; + mr->rdParm[6] = x_src; + mr->rdParm[7] = height_dst; + mr->rdParm[8] = width_dst; + mr->rdParm[9] = y_dst; + mr->rdParm[10] = x_dst; + memcpy( mr->rdParm + 11, info, infosize ); + memcpy( mr->rdParm + 11 + infosize / 2, bits, info->bmiHeader.biSizeImage ); + metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) ); + HeapFree( GetProcessHeap(), 0, mr ); + return height_src; +} + +INT METADC_SetDIBitsToDevice( HDC hdc, INT x_dst, INT y_dst, DWORD width, DWORD height, + INT x_src, INT y_src, UINT startscan, UINT lines, + const void *bits, const BITMAPINFO *info, UINT coloruse ) + +{ + DWORD infosize = get_dib_info_size(info, coloruse); + DWORD len = sizeof(METARECORD) + 8 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage; + METARECORD *mr; + + if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) return 0; + + mr->rdSize = len / sizeof(WORD); + mr->rdFunction = META_SETDIBTODEV; + mr->rdParm[0] = coloruse; + mr->rdParm[1] = lines; + mr->rdParm[2] = startscan; + mr->rdParm[3] = y_src; + mr->rdParm[4] = x_src; + mr->rdParm[5] = height; + mr->rdParm[6] = width; + mr->rdParm[7] = y_dst; + mr->rdParm[8] = x_dst; + memcpy( mr->rdParm + 9, info, infosize ); + memcpy( mr->rdParm + 9 + infosize / sizeof(WORD), bits, info->bmiHeader.biSizeImage ); + metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) ); + HeapFree( GetProcessHeap(), 0, mr ); + return lines; +} + +static BOOL metadc_text( HDC hdc, short x, short y, UINT16 flags, const RECT16 *rect, + const char *str, short count, const INT16 *dx ) +{ + BOOL ret; + DWORD len; + METARECORD *mr; + BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE); + + len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short) + + sizeof(UINT16); + if (isrect) len += sizeof(RECT16); + if (dx) len += count * sizeof(INT16); + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) return FALSE; + + mr->rdSize = len / sizeof(WORD); + mr->rdFunction = META_EXTTEXTOUT; + mr->rdParm[0] = y; + mr->rdParm[1] = x; + mr->rdParm[2] = count; + mr->rdParm[3] = flags; + if (isrect) memcpy( mr->rdParm + 4, rect, sizeof(RECT16) ); + memcpy( mr->rdParm + (isrect ? 8 : 4), str, count ); + if (dx) + memcpy( mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1), dx, count * sizeof(INT16) ); + ret = metadc_record( hdc, mr, mr->rdSize * sizeof(WORD) ); + HeapFree( GetProcessHeap(), 0, mr ); + return ret; +} + +BOOL METADC_ExtTextOut( HDC hdc, INT x, INT y, UINT flags, const RECT *lprect, + const WCHAR *str, UINT count, const INT *dx ) +{ + RECT16 rect16; + LPINT16 lpdx16 = NULL; + BOOL ret; + unsigned int i, j; + char *ascii; + DWORD len; + CHARSETINFO csi; + int charset = GetTextCharset( hdc ); + UINT cp = CP_ACP; + + if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET )) + cp = csi.ciACP; + else + { + switch(charset) + { + case OEM_CHARSET: + cp = GetOEMCP(); + break; + case DEFAULT_CHARSET: + cp = GetACP(); + break; + + case VISCII_CHARSET: + case TCVN_CHARSET: + case KOI8_CHARSET: + case ISO3_CHARSET: + case ISO4_CHARSET: + case ISO10_CHARSET: + case CELTIC_CHARSET: + /* FIXME: These have no place here, but because x11drv + enumerates fonts with these (made up) charsets some apps + might use them and then the FIXME below would become + annoying. Now we could pick the intended codepage for + each of these, but since it's broken anyway we'll just + use CP_ACP and hope it'll go away... + */ + cp = CP_ACP; + break; + + default: + FIXME("Can't find codepage for charset %d\n", charset); + break; + } + } + + + TRACE( "cp = %d\n", cp ); + len = WideCharToMultiByte( cp, 0, str, count, NULL, 0, NULL, NULL ); + ascii = HeapAlloc( GetProcessHeap(), 0, len ); + WideCharToMultiByte( cp, 0, str, count, ascii, len, NULL, NULL ); + TRACE( "mapped %s -> %s\n", debugstr_wn(str, count), debugstr_an(ascii, len) ); + + + if (lprect) + { + rect16.left = lprect->left; + rect16.top = lprect->top; + rect16.right = lprect->right; + rect16.bottom = lprect->bottom; + } + + if (dx) + { + lpdx16 = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16) * len ); + for (i = j = 0; i < len; ) + if (IsDBCSLeadByteEx( cp, ascii[i] )) + { + lpdx16[i++] = dx[j++]; + lpdx16[i++] = 0; + } + else + lpdx16[i++] = dx[j++]; + } + + ret = metadc_text( hdc, x, y, flags, lprect ? &rect16 : NULL, ascii, len, lpdx16 ); + HeapFree( GetProcessHeap(), 0, ascii ); + HeapFree( GetProcessHeap(), 0, lpdx16 ); + return ret; +} + +BOOL METADC_ExtSelectClipRgn( HDC hdc, HRGN hrgn, INT mode ) +{ + struct metadc *metadc; + INT16 rgn; + INT ret; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + if (mode != RGN_COPY) return ERROR; + if (!hrgn) return NULLREGION; + rgn = metadc_create_region( metadc, hrgn ); + if(rgn == -1) return ERROR; + ret = metadc_param1( hdc, META_SELECTOBJECT, rgn ) ? NULLREGION : ERROR; + metadc_param1( hdc, META_DELETEOBJECT, rgn ); + metadc_remove_handle( metadc, rgn ); + return ret; +} + +static INT16 metadc_find_object( struct metadc *metadc, HGDIOBJ obj ) +{ + INT16 index; + + for (index = 0; index < metadc->handles_size; index++) + if (metadc->handles[index] == obj) return index; + + return -1; +} + +void METADC_DeleteObject( HDC hdc, HGDIOBJ obj ) +{ + struct metadc *metadc = get_metadc_ptr( hdc ); + METARECORD mr; + INT16 index; + + if ((index = metadc_find_object( metadc, obj )) < 0) return; + if (obj == metadc->pen || obj == metadc->brush || obj == metadc->font) + { + WARN( "deleting selected object %p\n", obj ); + return; + } + + mr.rdSize = sizeof(mr) / sizeof(WORD); + mr.rdFunction = META_DELETEOBJECT; + mr.rdParm[0] = index; + + metadc_write_record( metadc, &mr, mr.rdSize * sizeof(WORD) ); + + metadc->handles[index] = 0; + metadc->cur_handles--; +} + +static BOOL metadc_select_object( HDC hdc, INT16 index) +{ + METARECORD mr; + + mr.rdSize = sizeof mr / 2; + mr.rdFunction = META_SELECTOBJECT; + mr.rdParm[0] = index; + return metadc_record( hdc, &mr, mr.rdSize * sizeof(WORD) ); +} + +static HBRUSH METADC_SelectBrush( HDC hdc, HBRUSH hbrush ) +{ + struct metadc *metadc = get_metadc_ptr( hdc ); + INT16 index; + HBRUSH ret; + + index = metadc_find_object( metadc, hbrush ); + if( index < 0 ) + { + index = metadc_create_brush( metadc, hbrush ); + if( index < 0 ) + return 0; + GDI_hdc_using_object( hbrush, hdc );//, METADC_DeleteObject ); + } + if (!metadc_select_object( hdc, index )) return 0; + ret = metadc->brush; + metadc->brush = hbrush; + return ret; +} + +static UINT16 metadc_create_font( struct metadc *metadc, HFONT font, LOGFONTW *logfont ) +{ + char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT16)]; + METARECORD *mr = (METARECORD *)&buffer; + LOGFONT16 *font16; + INT written; + + mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT16) - 2) / 2; + mr->rdFunction = META_CREATEFONTINDIRECT; + font16 = (LOGFONT16 *)&mr->rdParm; + + font16->lfHeight = logfont->lfHeight; + font16->lfWidth = logfont->lfWidth; + font16->lfEscapement = logfont->lfEscapement; + font16->lfOrientation = logfont->lfOrientation; + font16->lfWeight = logfont->lfWeight; + font16->lfItalic = logfont->lfItalic; + font16->lfUnderline = logfont->lfUnderline; + font16->lfStrikeOut = logfont->lfStrikeOut; + font16->lfCharSet = logfont->lfCharSet; + font16->lfOutPrecision = logfont->lfOutPrecision; + font16->lfClipPrecision = logfont->lfClipPrecision; + font16->lfQuality = logfont->lfQuality; + font16->lfPitchAndFamily = logfont->lfPitchAndFamily; + written = WideCharToMultiByte( CP_ACP, 0, logfont->lfFaceName, -1, font16->lfFaceName, + LF_FACESIZE - 1, NULL, NULL ); + /* Zero pad the facename buffer, so that we don't write uninitialized data to disk */ + memset( font16->lfFaceName + written, 0, LF_FACESIZE - written ); + + if (!metadc_write_record( metadc, mr, mr->rdSize * 2 )) + return 0; + return metadc_add_handle( metadc, font ); +} + +static HFONT METADC_SelectFont( HDC hdc, HFONT hfont ) +{ + struct metadc *metadc = get_metadc_ptr( hdc ); + LOGFONTW font; + INT16 index; + HFONT ret; + + index = metadc_find_object( metadc, hfont ); + if (index < 0) + { + if (!GetObjectW( hfont, sizeof(font), &font )) + return 0; + index = metadc_create_font( metadc, hfont, &font ); + if( index < 0 ) + return 0; + GDI_hdc_using_object( hfont, hdc );//, METADC_DeleteObject ); + } + if (!metadc_select_object( hdc, index )) return 0; + ret = metadc->font; + metadc->font = hfont; + return ret; +} + +static UINT16 metadc_create_pen( struct metadc *metadc, HPEN pen, LOGPEN16 *logpen ) +{ + char buffer[FIELD_OFFSET(METARECORD, rdParm[sizeof(*logpen) / sizeof(WORD)])]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = sizeof(buffer) / sizeof(WORD); + mr->rdFunction = META_CREATEPENINDIRECT; + memcpy( mr->rdParm, logpen, sizeof(*logpen) ); + if (!metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) )) return 0; + return metadc_add_handle( metadc, pen ); +} + +static HPEN METADC_SelectPen( HDC hdc, HPEN hpen ) +{ + struct metadc *metadc = get_metadc_ptr( hdc ); + LOGPEN16 logpen; + INT16 index; + HPEN ret; + + index = metadc_find_object( metadc, hpen ); + if (index < 0) + { + /* must be an extended pen */ + INT size = GetObjectW( hpen, 0, NULL ); + + if (!size) return 0; + + if (size == sizeof(LOGPEN)) + { + LOGPEN pen; + + GetObjectW( hpen, sizeof(pen), &pen ); + logpen.lopnStyle = pen.lopnStyle; + logpen.lopnWidth.x = pen.lopnWidth.x; + logpen.lopnWidth.y = pen.lopnWidth.y; + logpen.lopnColor = pen.lopnColor; + } + else /* must be an extended pen */ + { + EXTLOGPEN *elp = HeapAlloc( GetProcessHeap(), 0, size ); + + GetObjectW( hpen, size, elp ); + /* FIXME: add support for user style pens */ + logpen.lopnStyle = elp->elpPenStyle; + logpen.lopnWidth.x = elp->elpWidth; + logpen.lopnWidth.y = 0; + logpen.lopnColor = elp->elpColor; + + HeapFree( GetProcessHeap(), 0, elp ); + } + + index = metadc_create_pen( metadc, hpen, &logpen ); + if( index < 0 ) + return 0; + GDI_hdc_using_object( hpen, hdc );//, METADC_DeleteObject ); + } + + if (!metadc_select_object( hdc, index )) return 0; + ret = metadc->pen; + metadc->pen = hpen; + return ret; +} + +static BOOL metadc_create_palette( struct metadc *metadc, HPALETTE palette, + LOGPALETTE *log_palette, int sizeofPalette ) +{ + int index; + BOOL ret; + METARECORD *mr; + + mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) ); + if (!mr) return FALSE; + mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD); + mr->rdFunction = META_CREATEPALETTE; + memcpy(&(mr->rdParm), log_palette, sizeofPalette); + if (!metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) )) + { + HeapFree(GetProcessHeap(), 0, mr); + return FALSE; + } + + mr->rdSize = sizeof(METARECORD) / sizeof(WORD); + mr->rdFunction = META_SELECTPALETTE; + + if ((index = metadc_add_handle( metadc, palette )) == -1) ret = FALSE; + else + { + mr->rdParm[0] = index; + ret = metadc_write_record( metadc, mr, mr->rdSize * sizeof(WORD) ); + } + HeapFree( GetProcessHeap(), 0, mr ); + return ret; +} + +BOOL METADC_SelectPalette( HDC hdc, HPALETTE palette ) +{ + struct metadc *metadc; + PLOGPALETTE log_palette; + WORD count = 0; + BOOL ret; + int size; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + GetObjectA( palette, sizeof(WORD), &count ); + if (!count) return 0; + + size = sizeof(LOGPALETTE) + (count - 1) * sizeof(PALETTEENTRY); + log_palette = HeapAlloc( GetProcessHeap(), 0, size ); + if (!log_palette) return 0; + + log_palette->palVersion = 0x300; + log_palette->palNumEntries = count; + + GetPaletteEntries( palette, 0, count, log_palette->palPalEntry ); + + ret = metadc_create_palette( metadc, palette, log_palette, size ); + + HeapFree( GetProcessHeap(), 0, log_palette ); + return ret; +} + +BOOL METADC_RealizePalette( HDC hdc ) +{ + return metadc_param0( hdc, META_REALIZEPALETTE ); +} + +HGDIOBJ METADC_SelectObject( HDC hdc, HGDIOBJ obj ) +{ + switch (GDI_HANDLE_GET_TYPE( obj )) + { + case GDILoObjType_LO_BRUSH_TYPE: + return METADC_SelectBrush( hdc, obj ); + case GDILoObjType_LO_FONT_TYPE: + return METADC_SelectFont( hdc, obj ); + case GDILoObjType_LO_PEN_TYPE: + case GDILoObjType_LO_EXTPEN_TYPE: + return METADC_SelectPen( hdc, obj ); + default: + SetLastError( ERROR_INVALID_FUNCTION ); + return 0; + } +} + +BOOL METADC_ExtEscape( HDC hdc, INT escape, INT input_size, LPCSTR input, INT output_size, LPVOID output ) +{ + METARECORD *mr; + DWORD len; + BOOL ret; + + if (output_size) return FALSE; /* escapes that require output cannot work in metafiles */ + + len = sizeof(*mr) + sizeof(WORD) + ((input_size + 1) & ~1); + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len ))) return FALSE; + mr->rdSize = len / sizeof(WORD); + mr->rdFunction = META_ESCAPE; + mr->rdParm[0] = escape; + mr->rdParm[1] = input_size; + memcpy( &mr->rdParm[2], input, input_size ); + ret = metadc_record( hdc, mr, len ); + HeapFree(GetProcessHeap(), 0, mr); + return ret; +} + +INT METADC_GetDeviceCaps( HDC hdc, INT cap ) +{ + if (!get_metadc_ptr( hdc )) return 0; + + switch(cap) + { + case TECHNOLOGY: + return DT_METAFILE; + case TEXTCAPS: + return 0; + default: + TRACE(" unsupported capability %d, will return 0\n", cap ); + } + return 0; +} + +static void metadc_free( struct metadc *metadc ) +{ + DWORD index; + + CloseHandle( metadc->hFile ); + HeapFree( GetProcessHeap(), 0, metadc->mh ); + for(index = 0; index < metadc->handles_size; index++) + if(metadc->handles[index]) + GDI_hdc_not_using_object( metadc->handles[index], metadc->hdc ); + HeapFree( GetProcessHeap(), 0, metadc->handles ); + HeapFree( GetProcessHeap(), 0, metadc ); +} + +BOOL METADC_DeleteDC( HDC hdc ) +{ + struct metadc *metadc; + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + if (!GdiDeleteClientObj( hdc )) return FALSE; + metadc_free( metadc ); + return TRUE; +} + +/********************************************************************** + * CreateMetaFileW (GDI32.@) + * + * Create a new DC and associate it with a metafile. Pass a filename + * to create a disk-based metafile, NULL to create a memory metafile. + */ +HDC WINAPI CreateMetaFileW( const WCHAR *filename ) +{ + struct metadc *metadc; + HANDLE hdc; + + TRACE( "%s\n", debugstr_w(filename) ); + + metadc = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc) ); + if (!metadc) + { + return NULL; + } + if (!(metadc->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*metadc->mh) ))) + { + HeapFree( GetProcessHeap(), 0, metadc ); + return NULL; + } + + if (!(hdc = GdiCreateClientObj( metadc, GDILoObjType_LO_METADC16_TYPE ))) + { + HeapFree( GetProcessHeap(), 0, metadc ); + return NULL; + } + + metadc->hdc = hdc; + + metadc->handles = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + HANDLE_LIST_INC * sizeof(metadc->handles[0]) ); + metadc->handles_size = HANDLE_LIST_INC; + metadc->cur_handles = 0; + + metadc->hFile = 0; + + metadc->mh->mtHeaderSize = sizeof(METAHEADER) / sizeof(WORD); + metadc->mh->mtVersion = 0x0300; + metadc->mh->mtSize = metadc->mh->mtHeaderSize; + metadc->mh->mtNoObjects = 0; + metadc->mh->mtMaxRecord = 0; + metadc->mh->mtNoParameters = 0; + metadc->mh->mtType = METAFILE_MEMORY; + + metadc->pen = GetStockObject( BLACK_PEN ); + metadc->brush = GetStockObject( WHITE_BRUSH ); + metadc->font = GetStockObject( DEVICE_DEFAULT_FONT ); + + SetVirtualResolution( hdc, 0, 0, 0, 0); + + if (filename) /* disk based metafile */ + { + HANDLE file = CreateFileW( filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0 ); + if (file == INVALID_HANDLE_VALUE) + { + HeapFree( GetProcessHeap(), 0, metadc ); + GdiDeleteClientObj( hdc ); + return 0; + } + metadc->hFile = file; + } + + TRACE( "returning %p\n", hdc ); + return hdc; +} + +/********************************************************************** + * CreateMetaFileA (GDI32.@) + */ +HDC WINAPI CreateMetaFileA( const char *filename ) +{ + LPWSTR filenameW; + DWORD len; + HDC hdc; + + if (!filename) return CreateMetaFileW( NULL ); + + len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 ); + filenameW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len ); + + hdc = CreateMetaFileW( filenameW ); + + HeapFree( GetProcessHeap(), 0, filenameW ); + return hdc; +} + +/****************************************************************** + * CloseMetaFile (GDI32.@) + * + * Stop recording graphics operations in metafile associated with + * hdc and retrieve metafile. + */ +HMETAFILE WINAPI CloseMetaFile( HDC hdc ) +{ + struct metadc *metadc; + DWORD bytes_written; + HMETAFILE hmf; + + TRACE( "(%p)\n", hdc ); + + if (!(metadc = get_metadc_ptr( hdc ))) return FALSE; + + /* Construct the end of metafile record - this is documented + * in SDK Knowledgebase Q99334. + */ + if (!metadc_param0( hdc, META_EOF )) return FALSE; + if (!GdiDeleteClientObj( hdc )) return FALSE; + + if (metadc->hFile && !WriteFile( metadc->hFile, metadc->mh, metadc->mh->mtSize * sizeof(WORD), + &bytes_written, NULL )) + { + metadc_free( metadc ); + return FALSE; + } + + /* Now allocate a global handle for the metafile */ + hmf = MF_Create_HMETAFILE( metadc->mh ); + if (hmf) metadc->mh = NULL; /* So it won't be deleted */ + metadc_free( metadc ); + return hmf; +} diff --git a/win32ss/gdi/gdi32/wine/metafile.c b/win32ss/gdi/gdi32/wine/metafile.c index dbd552102a6..70d64f916cf 100644 --- a/win32ss/gdi/gdi32/wine/metafile.c +++ b/win32ss/gdi/gdi32/wine/metafile.c @@ -1143,12 +1143,10 @@ static BOOL add_mf_comment(HDC hdc, HENHMETAFILE emf) if(!chunk) goto end; chunk->magic = WMFC_MAGIC; - chunk->unk04 = 1; - chunk->unk06 = 0; - chunk->unk08 = 0; - chunk->unk0a = 1; + chunk->comment_type = 0x1; + chunk->version = 0x00010000; chunk->checksum = 0; /* We fixup the first chunk's checksum before returning from GetWinMetaFileBits */ - chunk->unk0e = 0; + chunk->flags = 0; chunk->num_chunks = (size + max_chunk_size - 1) / max_chunk_size; chunk->chunk_size = max_chunk_size; chunk->remaining_size = size; diff --git a/win32ss/gdi/gdi32/wine/rosglue.c b/win32ss/gdi/gdi32/wine/rosglue.c index b537b90e419..80d6b73fbb5 100644 --- a/win32ss/gdi/gdi32/wine/rosglue.c +++ b/win32ss/gdi/gdi32/wine/rosglue.c @@ -6,195 +6,6 @@ #define NDEBUG #include -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( @@ -304,11 +115,8 @@ alloc_dc_ptr(WORD magic) } 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) { @@ -326,54 +134,15 @@ alloc_dc_ptr(WORD magic) /* 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) { @@ -393,25 +162,6 @@ get_dc_ptr(HDC 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, @@ -473,11 +223,12 @@ BOOL get_brush_bitmap_info( HBRUSH hbr, PBITMAPINFO pbmi, - PVOID *ppvBits, + PVOID pvBits, PUINT puUsage) { HBITMAP hbmp; HDC hdc; + PVOID Bits; /* Call win32k to get the bitmap handle and color usage */ hbmp = NtGdiGetObjectBitmapHandle(hbr, puUsage); @@ -496,17 +247,22 @@ get_brush_bitmap_info( 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)) + if (pvBits) { - HeapFree(GetProcessHeap(), 0, *ppvBits); - *ppvBits = NULL; - return FALSE; + /* Now allocate a buffer for the bits */ + Bits = HeapAlloc(GetProcessHeap(), 0, pbmi->bmiHeader.biSizeImage); + if (Bits == NULL) + return FALSE; + + /* Retrieve the bitmap bits */ + if (!GetDIBits(hdc, hbmp, 0, pbmi->bmiHeader.biHeight, Bits, pbmi, *puUsage)) + { + HeapFree(GetProcessHeap(), 0, Bits); + return FALSE; + } + + CopyMemory( pvBits, Bits, pbmi->bmiHeader.biSizeImage ); + } /* GetDIBits doesn't set biClrUsed, but wine code needs it, so we set it */ @@ -514,7 +270,6 @@ get_brush_bitmap_info( { pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount; } - return TRUE; } @@ -541,34 +296,6 @@ DeleteColorSpace( { 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 ( @@ -580,657 +307,52 @@ _assert ( } /******************************************************************************/ - -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) +WINAPI +METADC_SetD( + _In_ HDC hdc, + _In_ DWORD dwIn, + _In_ USHORT usMF16Id +) { - 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) + switch(usMF16Id) { - /* 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 */ + case META_SETMAPMODE: + return METADC_SetMapMode(hdc, dwIn); + case META_SETRELABS: + return METADC_SetRelAbs(hdc, dwIn); + default: 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, +EMFDC_SetD( + _In_ PLDC pldc, _In_ DWORD dwIn, - _In_ ULONG ulMFId, - _In_ USHORT usMF16Id, - _In_ DWORD dwError) + _In_ ULONG ulMFId) { - PHYSDEV physdev; - - /* Ignore these, we let wine code handle this */ - UNREFERENCED_PARAMETER(ulMFId); - UNREFERENCED_PARAMETER(usMF16Id); - - physdev = GetPhysDev(hdc); - if (physdev == NULL) + switch(ulMFId) { - SetLastError(ERROR_INVALID_HANDLE); - *pdwResult = dwError; - return TRUE; + case EMR_SETMAPMODE: + return EMFDC_SetMapMode( pldc, dwIn); + case EMR_SETARCDIRECTION: + return EMFDC_SetArcDirection( pldc, dwIn); + default: + return FALSE; } - - /* 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)); } +extern void METADC_DeleteObject( HDC hdc, HGDIOBJ obj ); +extern void emfdc_delete_object( HDC hdc, HGDIOBJ obj ); + VOID WINAPI -METADC_DeleteObject(HGDIOBJ hobj) +METADC_RosGlueDeleteObject(HGDIOBJ hobj) { GDILOOBJTYPE eObjectType; HDC hdc; - PHYSDEV physdev; /* Check for one of the types we actually handle here */ eObjectType = GDI_HANDLE_GET_TYPE(hobj); @@ -1248,64 +370,58 @@ METADC_DeleteObject(HGDIOBJ hobj) hdc = GdiRemoveClientObjLink(hobj); if (hdc == NULL) { + DPRINT1("the link was not found\n"); /* 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; - } + if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE ) METADC_DeleteObject( hdc, hobj ); - physdev->funcs->pDeleteObject(physdev, hobj); + if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE ) + { + LDC* pWineDc = GdiGetLDC(hdc); + if ( pWineDc ) + { + emfdc_delete_object( hdc, hobj ); + } + } } BOOL WINAPI -METADC_DeleteDC( +METADC_RosGlueDeleteDC( _In_ HDC hdc) { - /* Only ALTDCs are supported */ - if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) + LDC* pWineDc = NULL; + + if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE ) { - DPRINT1("Trying to delete METADC %p\n", hdc); - return FALSE; + return METADC_DeleteDC(hdc); } - // FIXME call the driver? + + if ( GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE ) + { + pWineDc = GdiGetLDC(hdc); + + if ( pWineDc ) + { + // Handle Printer LDC + if (pWineDc->iType != LDC_EMFLDC) + { + //return IntDeleteDC(hdc); + } + + EMFDC_DeleteDC( pWineDc ); + + /* Get rid of the LDC */ + ASSERT(GdiGetLDC(pWineDc->hDC) == pWineDc); + GdiSetLDC(pWineDc->hDC, NULL); + + /* Free the Wine DC */ + HeapFree(GetProcessHeap(), 0, pWineDc); + } + } + 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; -} diff --git a/win32ss/include/ntgdihdl.h b/win32ss/include/ntgdihdl.h index 36dc54ce8e7..c81f01341cf 100644 --- a/win32ss/include/ntgdihdl.h +++ b/win32ss/include/ntgdihdl.h @@ -294,11 +294,16 @@ typedef struct _LDC PDEVMODEW pdm; PVOID pUMPDev; /* Ptr to User Mode Printer Device structure */ PUMDHPDEV pUMdhpdev; /* Ptr to Combined UMPD and DHPDEV structure */ + PVOID UFIHashTable[3]; + UNIVERSAL_FONT_ID ufi; + PVOID pvEMFSpoolData; + ULONG cjSize; + LIST_ENTRY leRecords; DEVCAPS DevCaps; HBRUSH BrushColor; HPEN PenColor; // wine data - DWORD dwData[7]; + DWORD dwData[5]; } LDC, *PLDC; typedef struct _DC_ATTR diff --git a/win32ss/include/ntuser.h b/win32ss/include/ntuser.h index 482ea232926..7afe6906fba 100644 --- a/win32ss/include/ntuser.h +++ b/win32ss/include/ntuser.h @@ -575,7 +575,7 @@ typedef struct _SBINFOEX SCROLLINFO ScrollInfo; } SBINFOEX, *PSBINFOEX; -/* State Flags !Not Implemented! */ +/* State Flags !Not ALL Implemented! */ #define WNDS_HASMENU 0X00000001 #define WNDS_HASVERTICALSCROOLLBAR 0X00000002 #define WNDS_HASHORIZONTALSCROLLBAR 0X00000004 @@ -611,7 +611,7 @@ typedef struct _SBINFOEX #define WNDSACTIVEFRAME 0x00000006 -/* State2 Flags !Not Implemented! */ +/* State2 Flags !Not ALL Implemented! */ #define WNDS2_WMPAINTSENT 0X00000001 #define WNDS2_ENDPAINTINVALIDATE 0X00000002 #define WNDS2_STARTPAINT 0X00000004