diff --git a/reactos/win32ss/gdi/gdi32/CMakeLists.txt b/reactos/win32ss/gdi/gdi32/CMakeLists.txt index f2ee2412b58..796b50d658c 100644 --- a/reactos/win32ss/gdi/gdi32/CMakeLists.txt +++ b/reactos/win32ss/gdi/gdi32/CMakeLists.txt @@ -1,4 +1,8 @@ +add_subdirectory(wine) + +add_definitions(-DLANGPACK) + include_directories( include ${REACTOS_SOURCE_DIR}/win32ss/include) @@ -46,8 +50,19 @@ add_library(gdi32 SHARED gdi32.rc ${CMAKE_CURRENT_BINARY_DIR}/gdi32.def) -set_module_type(gdi32 win32dll ENTRYPOINT DllMain 12 UNICODE) -target_link_libraries(gdi32 win32ksys dxguid msvcrtex ${PSEH_LIB}) +set_module_type(gdi32 + win32dll + ENTRYPOINT DllMain 12 + UNICODE) + +target_link_libraries(gdi32 + winegdi + wine + win32ksys + dxguid + msvcrtex + ${PSEH_LIB}) + add_importlibs(gdi32 user32 advapi32 kernel32 ntdll) add_pch(gdi32 include/precomp.h SOURCE) add_cd_file(TARGET gdi32 DESTINATION reactos/system32 FOR all) diff --git a/reactos/win32ss/gdi/gdi32/include/gdi32p.h b/reactos/win32ss/gdi/gdi32/include/gdi32p.h index 7c855d61a5b..ad868ac3e79 100644 --- a/reactos/win32ss/gdi/gdi32/include/gdi32p.h +++ b/reactos/win32ss/gdi/gdi32/include/gdi32p.h @@ -444,6 +444,24 @@ _lrintf(float f) #endif } +HBRUSH +WINAPI +GdiSelectBrush( + _In_ HDC hdc, + _In_ HBRUSH hbr); + +HPEN +WINAPI +GdiSelectPen( + _In_ HDC hdc, + _In_ HPEN hpen); + +HFONT +WINAPI +GdiSelectFont( + _In_ HDC hdc, + _In_ HFONT hfont); + HGDIOBJ WINAPI GdiCreateClientObj( @@ -473,5 +491,182 @@ GdiRemoveClientObjLink( extern ULONG gcClientObj; +VOID +WINAPI +METADC_DeleteObject(HGDIOBJ hobj); + +BOOL +WINAPI +METADC_DeleteDC( + _In_ HDC hdc); + +INT +WINAPI +METADC16_Escape( + _In_ HDC hdc, + _In_ INT nEscape, + _In_ INT cbInput, + _In_ LPCSTR lpvInData, + _Out_ LPVOID lpvOutData); + +BOOL +WINAPI +METADC_ExtTextOutW( + HDC hdc, + INT x, + INT y, + UINT fuOptions, + const RECT *lprc, + LPCWSTR lpString, + 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__)) \ + { \ + return (_RetType)dwResult; \ + } \ + } + + +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_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, ...) \ + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_DC_TYPE) \ + { \ + _RetType result; \ + if (METADC_##_Func(&result, hdc, __VA_ARGS__)) \ + { \ + return result; \ + } \ + } + +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); /* EOF */ diff --git a/reactos/win32ss/gdi/gdi32/include/wine/gdi_driver.h b/reactos/win32ss/gdi/gdi32/include/wine/gdi_driver.h new file mode 100644 index 00000000000..f8bfe8cbc62 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/include/wine/gdi_driver.h @@ -0,0 +1,282 @@ +/* + * Definitions for Wine GDI drivers + * + * Copyright 2011 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_WINE_GDI_DRIVER_H +#define __WINE_WINE_GDI_DRIVER_H + +//#include "wine/list.h" + +struct gdi_dc_funcs; +struct opengl_funcs; + +typedef struct gdi_physdev +{ + const struct gdi_dc_funcs *funcs; + struct gdi_physdev *next; + HDC hdc; +} *PHYSDEV; + +struct bitblt_coords +{ + int log_x; /* original position and size, in logical coords */ + int log_y; + int log_width; + int log_height; + int x; /* mapped position and size, in device coords */ + int y; + int width; + int height; + RECT visrect; /* rectangle clipped to the visible part, in device coords */ + DWORD layout; /* DC layout */ +}; + +struct gdi_image_bits +{ + void *ptr; /* pointer to the bits */ + BOOL is_copy; /* whether this is a copy of the bits that can be modified */ + void (*free)(struct gdi_image_bits *); /* callback for freeing the bits */ + void *param; /* extra parameter for callback private use */ +}; + +struct brush_pattern +{ + BITMAPINFO *info; /* DIB info */ + struct gdi_image_bits bits; /* DIB bits */ + UINT usage; /* color usage for DIB info */ +}; + +struct gdi_dc_funcs +{ + INT (*pAbortDoc)(PHYSDEV); + BOOL (*pAbortPath)(PHYSDEV); + BOOL (*pAlphaBlend)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,BLENDFUNCTION); + BOOL (*pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT); + BOOL (*pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT); + BOOL (*pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT); + BOOL (*pBeginPath)(PHYSDEV); + DWORD (*pBlendImage)(PHYSDEV,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,BLENDFUNCTION); + BOOL (*pChord)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT); + BOOL (*pCloseFigure)(PHYSDEV); + BOOL (*pCreateCompatibleDC)(PHYSDEV,PHYSDEV*); + BOOL (*pCreateDC)(PHYSDEV*,LPCWSTR,LPCWSTR,LPCWSTR,const DEVMODEW*); + BOOL (*pDeleteDC)(PHYSDEV); + BOOL (*pDeleteObject)(PHYSDEV,HGDIOBJ); + DWORD (*pDeviceCapabilities)(LPSTR,LPCSTR,LPCSTR,WORD,LPSTR,LPDEVMODEA); + BOOL (*pEllipse)(PHYSDEV,INT,INT,INT,INT); + INT (*pEndDoc)(PHYSDEV); + INT (*pEndPage)(PHYSDEV); + BOOL (*pEndPath)(PHYSDEV); + BOOL (*pEnumFonts)(PHYSDEV,LPLOGFONTW,FONTENUMPROCW,LPARAM); + INT (*pEnumICMProfiles)(PHYSDEV,ICMENUMPROCW,LPARAM); + INT (*pExcludeClipRect)(PHYSDEV,INT,INT,INT,INT); + INT (*pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD); + INT (*pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID); + BOOL (*pExtFloodFill)(PHYSDEV,INT,INT,COLORREF,UINT); + INT (*pExtSelectClipRgn)(PHYSDEV,HRGN,INT); + BOOL (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*); + BOOL (*pFillPath)(PHYSDEV); + BOOL (*pFillRgn)(PHYSDEV,HRGN,HBRUSH); + BOOL (*pFlattenPath)(PHYSDEV); + BOOL (*pFontIsLinked)(PHYSDEV); + BOOL (*pFrameRgn)(PHYSDEV,HRGN,HBRUSH,INT,INT); + BOOL (*pGdiComment)(PHYSDEV,UINT,const BYTE*); + BOOL (*pGdiRealizationInfo)(PHYSDEV,void*); + UINT (*pGetBoundsRect)(PHYSDEV,RECT*,UINT); + BOOL (*pGetCharABCWidths)(PHYSDEV,UINT,UINT,LPABC); + BOOL (*pGetCharABCWidthsI)(PHYSDEV,UINT,UINT,WORD*,LPABC); + BOOL (*pGetCharWidth)(PHYSDEV,UINT,UINT,LPINT); + INT (*pGetDeviceCaps)(PHYSDEV,INT); + BOOL (*pGetDeviceGammaRamp)(PHYSDEV,LPVOID); + DWORD (*pGetFontData)(PHYSDEV,DWORD,DWORD,LPVOID,DWORD); + DWORD (*pGetFontUnicodeRanges)(PHYSDEV,LPGLYPHSET); + DWORD (*pGetGlyphIndices)(PHYSDEV,LPCWSTR,INT,LPWORD,DWORD); + DWORD (*pGetGlyphOutline)(PHYSDEV,UINT,UINT,LPGLYPHMETRICS,DWORD,LPVOID,const MAT2*); + BOOL (*pGetICMProfile)(PHYSDEV,LPDWORD,LPWSTR); + DWORD (*pGetImage)(PHYSDEV,BITMAPINFO*,struct gdi_image_bits*,struct bitblt_coords*); + DWORD (*pGetKerningPairs)(PHYSDEV,DWORD,LPKERNINGPAIR); + COLORREF (*pGetNearestColor)(PHYSDEV,COLORREF); + UINT (*pGetOutlineTextMetrics)(PHYSDEV,UINT,LPOUTLINETEXTMETRICW); + COLORREF (*pGetPixel)(PHYSDEV,INT,INT); + UINT (*pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY); + UINT (*pGetTextCharsetInfo)(PHYSDEV,LPFONTSIGNATURE,DWORD); + BOOL (*pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,LPINT); + BOOL (*pGetTextExtentExPointI)(PHYSDEV,const WORD*,INT,LPINT); + INT (*pGetTextFace)(PHYSDEV,INT,LPWSTR); + BOOL (*pGetTextMetrics)(PHYSDEV,TEXTMETRICW*); + BOOL (*pGradientFill)(PHYSDEV,TRIVERTEX*,ULONG,void*,ULONG,ULONG); + INT (*pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT); + BOOL (*pInvertRgn)(PHYSDEV,HRGN); + BOOL (*pLineTo)(PHYSDEV,INT,INT); + BOOL (*pModifyWorldTransform)(PHYSDEV,const XFORM*,DWORD); + BOOL (*pMoveTo)(PHYSDEV,INT,INT); + INT (*pOffsetClipRgn)(PHYSDEV,INT,INT); + BOOL (*pOffsetViewportOrgEx)(PHYSDEV,INT,INT,POINT*); + BOOL (*pOffsetWindowOrgEx)(PHYSDEV,INT,INT,POINT*); + BOOL (*pPaintRgn)(PHYSDEV,HRGN); + BOOL (*pPatBlt)(PHYSDEV,struct bitblt_coords*,DWORD); + BOOL (*pPie)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT); + BOOL (*pPolyBezier)(PHYSDEV,const POINT*,DWORD); + BOOL (*pPolyBezierTo)(PHYSDEV,const POINT*,DWORD); + BOOL (*pPolyDraw)(PHYSDEV,const POINT*,const BYTE *,DWORD); + BOOL (*pPolyPolygon)(PHYSDEV,const POINT*,const INT*,UINT); + BOOL (*pPolyPolyline)(PHYSDEV,const POINT*,const DWORD*,DWORD); + BOOL (*pPolygon)(PHYSDEV,const POINT*,INT); + BOOL (*pPolyline)(PHYSDEV,const POINT*,INT); + BOOL (*pPolylineTo)(PHYSDEV,const POINT*,INT); + DWORD (*pPutImage)(PHYSDEV,HRGN,BITMAPINFO*,const struct gdi_image_bits*,struct bitblt_coords*,struct bitblt_coords*,DWORD); + UINT (*pRealizeDefaultPalette)(PHYSDEV); + UINT (*pRealizePalette)(PHYSDEV,HPALETTE,BOOL); + BOOL (*pRectangle)(PHYSDEV,INT,INT,INT,INT); + HDC (*pResetDC)(PHYSDEV,const DEVMODEW*); + BOOL (*pRestoreDC)(PHYSDEV,INT); + BOOL (*pRoundRect)(PHYSDEV,INT,INT,INT,INT,INT,INT); + INT (*pSaveDC)(PHYSDEV); + BOOL (*pScaleViewportExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*); + BOOL (*pScaleWindowExtEx)(PHYSDEV,INT,INT,INT,INT,SIZE*); + HBITMAP (*pSelectBitmap)(PHYSDEV,HBITMAP); + HBRUSH (*pSelectBrush)(PHYSDEV,HBRUSH,const struct brush_pattern*); + BOOL (*pSelectClipPath)(PHYSDEV,INT); + HFONT (*pSelectFont)(PHYSDEV,HFONT,UINT*); + HPALETTE (*pSelectPalette)(PHYSDEV,HPALETTE,BOOL); + HPEN (*pSelectPen)(PHYSDEV,HPEN,const struct brush_pattern*); + INT (*pSetArcDirection)(PHYSDEV,INT); + COLORREF (*pSetBkColor)(PHYSDEV,COLORREF); + INT (*pSetBkMode)(PHYSDEV,INT); + UINT (*pSetBoundsRect)(PHYSDEV,RECT*,UINT); + COLORREF (*pSetDCBrushColor)(PHYSDEV, COLORREF); + COLORREF (*pSetDCPenColor)(PHYSDEV, COLORREF); + INT (*pSetDIBitsToDevice)(PHYSDEV,INT,INT,DWORD,DWORD,INT,INT,UINT,UINT,LPCVOID,BITMAPINFO*,UINT); + VOID (*pSetDeviceClipping)(PHYSDEV,HRGN); + BOOL (*pSetDeviceGammaRamp)(PHYSDEV,LPVOID); + DWORD (*pSetLayout)(PHYSDEV,DWORD); + INT (*pSetMapMode)(PHYSDEV,INT); + DWORD (*pSetMapperFlags)(PHYSDEV,DWORD); + COLORREF (*pSetPixel)(PHYSDEV,INT,INT,COLORREF); + INT (*pSetPolyFillMode)(PHYSDEV,INT); + INT (*pSetROP2)(PHYSDEV,INT); + INT (*pSetRelAbs)(PHYSDEV,INT); + INT (*pSetStretchBltMode)(PHYSDEV,INT); + UINT (*pSetTextAlign)(PHYSDEV,UINT); + INT (*pSetTextCharacterExtra)(PHYSDEV,INT); + COLORREF (*pSetTextColor)(PHYSDEV,COLORREF); + BOOL (*pSetTextJustification)(PHYSDEV,INT,INT); + BOOL (*pSetViewportExtEx)(PHYSDEV,INT,INT,SIZE*); + BOOL (*pSetViewportOrgEx)(PHYSDEV,INT,INT,POINT*); + BOOL (*pSetWindowExtEx)(PHYSDEV,INT,INT,SIZE*); + BOOL (*pSetWindowOrgEx)(PHYSDEV,INT,INT,POINT*); + BOOL (*pSetWorldTransform)(PHYSDEV,const XFORM*); + INT (*pStartDoc)(PHYSDEV,const DOCINFOW*); + INT (*pStartPage)(PHYSDEV); + BOOL (*pStretchBlt)(PHYSDEV,struct bitblt_coords*,PHYSDEV,struct bitblt_coords*,DWORD); + INT (*pStretchDIBits)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT,const void*,BITMAPINFO*,UINT,DWORD); + BOOL (*pStrokeAndFillPath)(PHYSDEV); + BOOL (*pStrokePath)(PHYSDEV); + BOOL (*pUnrealizePalette)(HPALETTE); + BOOL (*pWidenPath)(PHYSDEV); + struct opengl_funcs * (*wine_get_wgl_driver)(PHYSDEV,UINT); + + /* priority order for the driver on the stack */ + UINT priority; +}; + +/* increment this when you change the DC function table */ +#define WINE_GDI_DRIVER_VERSION 46 + +#define GDI_PRIORITY_NULL_DRV 0 /* null driver */ +#define GDI_PRIORITY_FONT_DRV 100 /* any font driver */ +#define GDI_PRIORITY_GRAPHICS_DRV 200 /* any graphics driver */ +#define GDI_PRIORITY_DIB_DRV 300 /* the DIB driver */ +#define GDI_PRIORITY_PATH_DRV 400 /* the path driver */ + +static inline PHYSDEV get_physdev_entry_point( PHYSDEV dev, size_t offset ) +{ + while (!((void **)dev->funcs)[offset / sizeof(void *)]) dev = dev->next; + return dev; +} + +#define GET_NEXT_PHYSDEV(dev,func) \ + get_physdev_entry_point( (dev)->next, FIELD_OFFSET(struct gdi_dc_funcs,func)) + +static inline void push_dc_driver( 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 = (*dev)->hdc; + *dev = physdev; +} + +/* support for window surfaces */ + +struct window_surface; + +struct window_surface_funcs +{ + void (*lock)( struct window_surface *surface ); + void (*unlock)( struct window_surface *surface ); + void* (*get_info)( struct window_surface *surface, BITMAPINFO *info ); + RECT* (*get_bounds)( struct window_surface *surface ); + void (*set_region)( struct window_surface *surface, HRGN region ); + void (*flush)( struct window_surface *surface ); + void (*destroy)( struct window_surface *surface ); +}; + +struct window_surface +{ + const struct window_surface_funcs *funcs; /* driver-specific implementations */ +// struct list entry; /* entry in global list managed by user32 */ + LONG ref; /* reference count */ + RECT rect; /* constant, no locking needed */ + /* driver-specific fields here */ +}; + +static inline ULONG window_surface_add_ref( struct window_surface *surface ) +{ + return InterlockedIncrement( &surface->ref ); +} + +static inline ULONG window_surface_release( struct window_surface *surface ) +{ + ULONG ret = InterlockedDecrement( &surface->ref ); + if (!ret) surface->funcs->destroy( surface ); + return ret; +} + +/* the DC hook support is only exported on Win16, the 32-bit version is a Wine extension */ + +#define DCHC_INVALIDVISRGN 0x0001 +#define DCHC_DELETEDC 0x0002 +#define DCHF_INVALIDATEVISRGN 0x0001 +#define DCHF_VALIDATEVISRGN 0x0002 +#define DCHF_RESETDC 0x0004 /* Wine extension */ + +typedef BOOL (CALLBACK *DCHOOKPROC)(HDC,WORD,DWORD_PTR,LPARAM); + +WINGDIAPI DWORD_PTR WINAPI GetDCHook(HDC,DCHOOKPROC*); +WINGDIAPI BOOL WINAPI SetDCHook(HDC,DCHOOKPROC,DWORD_PTR); +WINGDIAPI WORD WINAPI SetHookFlags(HDC,WORD); + +extern void CDECL __wine_make_gdi_object_system( HGDIOBJ handle, BOOL set ); +extern void CDECL __wine_set_visible_region( HDC hdc, HRGN hrgn, const RECT *vis_rect, + const RECT *device_rect, struct window_surface *surface ); +extern void CDECL __wine_set_display_driver( HMODULE module ); +extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version ); + +#endif /* __WINE_WINE_GDI_DRIVER_H */ diff --git a/reactos/win32ss/gdi/gdi32/misc/misc.c b/reactos/win32ss/gdi/gdi32/misc/misc.c index b433260edff..f53651041a1 100644 --- a/reactos/win32ss/gdi/gdi32/misc/misc.c +++ b/reactos/win32ss/gdi/gdi32/misc/misc.c @@ -66,10 +66,7 @@ Escape( if (ulObjType == GDILoObjType_LO_METADC16_TYPE) { - /* FIXME we do not support metafile */ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return SP_ERROR; + return METADC16_Escape(hdc, nEscape, cbInput, lpvInData, lpvOutData); } switch (nEscape) diff --git a/reactos/win32ss/gdi/gdi32/objects/arc.c b/reactos/win32ss/gdi/gdi32/objects/arc.c index 2e962754d21..37dd5145d0f 100644 --- a/reactos/win32ss/gdi/gdi32/objects/arc.c +++ b/reactos/win32ss/gdi/gdi32/objects/arc.c @@ -13,31 +13,19 @@ Arc( _In_ INT xEndArc, _In_ INT yEndArc) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) -// Call Wine (rewrite of) MFDRV_MetaParam8 - return MFDRV_MetaParam8( hDC, META_ARC, a1, a2, a3, a4, a5, a6, a7, a8) - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { -// Call Wine (rewrite of) EMFDRV_ArcChordPie - BOOL Ret = EMFDRV_ArcChordPie( hDC, a1, a2, a3, a4, a5, a6, a7, a8, EMR_ARC); - return Ret; - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, + Arc, + FALSE, + hdc, + xLeft, + yTop, + xRight, + yBottom, + xStartArc, + yStartArc, + xEndArc, + yEndArc); + return NtGdiArcInternal(GdiTypeArc, hdc, xLeft, @@ -64,29 +52,16 @@ AngleArc( _In_ FLOAT eStartAngle, _In_ FLOAT eSweepAngle) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return FALSE; //No meta support for AngleArc - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - BOOL Ret = EMFDRV_AngleArc( hDC, X, Y, Radius, StartAngle, SweepAngle); - return Ret; - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, + AngleArc, + FALSE, + hdc, + x, + y, + dwRadius, + RCAST(DWORD, eStartAngle), + RCAST(DWORD, eSweepAngle)); + return NtGdiAngleArc(hdc, x, y, @@ -108,29 +83,19 @@ ArcTo( _In_ INT xRadial2, _In_ INT yRadial2) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return FALSE; //No meta support for ArcTo - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - BOOL Ret = EMFDRV_ArcChordPie( hDC, a1, a2, a3, a4, a5, a6, a7, a8, EMR_ARCTO); - return Ret; - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, + ArcTo, + FALSE, + hdc, + xLeft, + yTop, + xRight, + yBottom, + xRadial1, + yRadial1, + xRadial2, + yRadial2); + return NtGdiArcInternal(GdiTypeArcTo, hdc, xLeft, @@ -156,29 +121,19 @@ Chord( _In_ INT xRadial2, _In_ INT yRadial2) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam8( hDC, META_CHORD, a1, a2, a3, a4, a5, a6, a7, a8) - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - BOOL Ret = EMFDRV_ArcChordPie( hDC, a1, a2, a3, a4, a5, a6, a7, a8, EMR_CHORD); - return Ret; - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, + Chord, + FALSE, + hdc, + xLeft, + yTop, + xRight, + yBottom, + xRadial1, + yRadial1, + xRadial2, + yRadial2); + return NtGdiArcInternal(GdiTypeChord, hdc, xLeft, @@ -208,29 +163,19 @@ Pie( _In_ INT xRadial2, _In_ INT yRadial2) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam8( hDC, META_PIE, a1, a2, a3, a4, a5, a6, a7, a8) - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - BOOL Ret = EMFDRV_ArcChordPie( hDC, a1, a2, a3, a4, a5, a6, a7, a8, EMR_PIE); - return Ret; - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, + Pie, + FALSE, + hdc, + xLeft, + yTop, + xRight, + yBottom, + xRadial1, + yRadial1, + xRadial2, + yRadial2); + return NtGdiArcInternal(GdiTypePie, hdc, xLeft, diff --git a/reactos/win32ss/gdi/gdi32/objects/bitmap.c b/reactos/win32ss/gdi/gdi32/objects/bitmap.c index e764fa36ff1..d5b81dc69cd 100644 --- a/reactos/win32ss/gdi/gdi32/objects/bitmap.c +++ b/reactos/win32ss/gdi/gdi32/objects/bitmap.c @@ -631,50 +631,21 @@ SetDIBitsToDevice( if (!pConvertedInfo) return 0; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetDIBitsToDevice( hdc, - XDest, - YDest, - Width, - Height, - XSrc, - YSrc, - StartScan, - ScanLines, - Bits, - lpbmi, - ColorUse); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetDIBitsToDevice(hdc, - XDest, - YDest, - Width, - Height, - XSrc, - YSrc, - StartScan, - ScanLines, - Bits, - lpbmi, - ColorUse); - } - return 0; - } - } -#endif + HANDLE_METADC(INT, + SetDIBitsToDevice, + 0, + hdc, + XDest, + YDest, + Width, + Height, + XSrc, + YSrc, + StartScan, + ScanLines, + Bits, + lpbmi, + ColorUse); if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) || (pConvertedInfo->bmiHeader.biCompression == BI_RLE4)) diff --git a/reactos/win32ss/gdi/gdi32/objects/coord.c b/reactos/win32ss/gdi/gdi32/objects/coord.c index 4fc29a1c468..b186b78aeaa 100644 --- a/reactos/win32ss/gdi/gdi32/objects/coord.c +++ b/reactos/win32ss/gdi/gdi32/objects/coord.c @@ -139,6 +139,12 @@ SetMapMode( { PDC_ATTR pdcattr; + /* 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 ); + } + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -147,27 +153,13 @@ SetMapMode( return 0; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetMapMode(hdc, iMode); - else - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - } -#endif - /* Force change if Isotropic is set for recompute. */ if ((iMode != pdcattr->iMapMode) || (iMode == MM_ISOTROPIC)) { pdcattr->ulDirty_ &= ~SLOW_WIDTHS; - return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0); + return GetAndSetDCDWord(hdc, GdiGetSetMapMode, iMode, 0, 0, 0 ); } - /* Simply return the old mode, which equals the new mode */ return pdcattr->iMapMode; } @@ -324,30 +316,10 @@ ModifyWorldTransform( { PDC_ATTR pdcattr; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - if (dwMode == MWT_MAX+1) - if (!EMFDRV_SetWorldTransform(hdc, pxform) ) return FALSE; - return EMFDRV_ModifyWorldTransform(hdc, pxform, dwMode); // Ported from wine. - } - return FALSE; - } - } -#endif + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + return FALSE; + + HANDLE_METADC(BOOL, ModifyWorldTransform, FALSE, hdc, pxform, dwMode); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -488,26 +460,8 @@ SetViewportExtEx( _Out_opt_ LPSIZE lpSize) { PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetViewportExtEx(); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetViewportExtEx(); - } - } - } -#endif + + HANDLE_METADC(BOOL, SetViewportExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -569,28 +523,10 @@ SetWindowOrgEx( _In_ int Y, _Out_opt_ LPPOINT lpPoint) { -#if 0 PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetWindowOrgEx(); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetWindowOrgEx(); - } - } - } -#endif + + HANDLE_METADC(BOOL, SetWindowOrgEx, FALSE, hdc, X, Y, lpPoint); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -598,7 +534,7 @@ SetWindowOrgEx( /* Do not set LastError here! */ return FALSE; } - +#if 0 if (lpPoint) { lpPoint->x = pdcattr->ptlWindowOrg.x; @@ -624,7 +560,7 @@ SetWindowOrgEx( pdcattr->flXform |= (PAGE_XLATE_CHANGED|DEVICE_TO_WORLD_INVALID); return TRUE; #endif - return NtGdiSetWindowOrgEx(hdc,X,Y,lpPoint); + return NtGdiSetWindowOrgEx(hdc, X, Y, lpPoint); } /* @@ -639,28 +575,8 @@ SetWindowExtEx( _Out_opt_ LPSIZE lpSize) { PDC_ATTR pdcattr; - ULONG ulType; - /* Check what type of DC that is */ - ulType = GDI_HANDLE_GET_TYPE(hdc); - switch (ulType) - { - case GDILoObjType_LO_ALTDC_TYPE: - case GDILoObjType_LO_DC_TYPE: - /* Handle this in the path below */ - break; -#if 0// FIXME: we don't support this - case GDILoObjType_LO_METADC16_TYPE: - return MFDRV_SetWindowExtEx(hdc, nXExtent, nYExtent, lpSize); - - case GDILoObjType_LO_METAFILE_TYPE: - return EMFDRV_SetWindowExtEx(hdc, nXExtent, nYExtent, lpSize); -#endif - default: - /* Other types are not allowed */ - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } + HANDLE_METADC(BOOL, SetWindowExtEx, FALSE, hdc, nXExtent, nYExtent, lpSize); /* Get the DC attr */ pdcattr = GdiGetDcAttr(hdc); @@ -729,28 +645,9 @@ SetViewportOrgEx( _In_ int Y, _Out_opt_ LPPOINT lpPoint) { -#if 0 PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetViewportOrgEx(); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetViewportOrgEx(); - } - } - } -#endif + + HANDLE_METADC(BOOL, SetViewportOrgEx, FALSE, hdc, X, Y, lpPoint); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -760,6 +657,7 @@ SetViewportOrgEx( return FALSE; } +#if 0 if (lpPoint) { lpPoint->x = pdcattr->ptlViewportOrg.x; @@ -788,26 +686,8 @@ ScaleViewportExtEx( _In_ INT yDenom, _Out_ LPSIZE lpSize) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(a0) == GDI_OBJECT_TYPE_METADC) - return MFDRV_; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_; - } - } - } -#endif + HANDLE_METADC(BOOL, ScaleViewportExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize); + if (!GdiGetDcAttr(hdc)) { SetLastError(ERROR_INVALID_PARAMETER); @@ -830,26 +710,7 @@ ScaleWindowExtEx( _In_ INT yDenom, _Out_ LPSIZE lpSize) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_; - } - } - } -#endif + HANDLE_METADC(BOOL, ScaleWindowExtEx, FALSE, hdc, xNum, xDenom, yNum, yDenom, lpSize); if (!GdiGetDcAttr(hdc)) { @@ -899,26 +760,8 @@ SetLayout( _In_ HDC hdc, _In_ DWORD dwLayout) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetLayout( hdc, dwLayout); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetLayout( hdc, dwLayout); - } - } - } -#endif + HANDLE_METADC(DWORD, SetLayout, GDI_ERROR, hdc, dwLayout); + if (!GdiGetDcAttr(hdc)) { SetLastError(ERROR_INVALID_PARAMETER); @@ -950,7 +793,7 @@ SetLayoutWidth( return GDI_ERROR; } - return NtGdiSetLayout( hdc, wox, dwLayout); + return NtGdiSetLayout(hdc, wox, dwLayout); } /* @@ -997,28 +840,11 @@ OffsetViewportOrgEx( _In_ int nYOffset, _Out_opt_ LPPOINT lpPoint) { + //PDC_ATTR pdcattr; + + HANDLE_METADC(BOOL, OffsetViewportOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint); #if 0 - PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_OffsetViewportOrgEx(hdc, nXOffset, nYOffset, lpPoint); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_OffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint); - } - } - } -#endif + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (!pdcattr) @@ -1066,28 +892,11 @@ OffsetWindowOrgEx( _In_ int nYOffset, _Out_opt_ LPPOINT lpPoint) { + //PDC_ATTR pdcattr; + + HANDLE_METADC(BOOL, OffsetWindowOrgEx, FALSE, hdc, nXOffset, nYOffset, lpPoint); + #if 0 - PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_OffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_OffsetWindowOrgEx(hdc, nXOffset, nYOffset, lpPoint); - } - } - } -#endif /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (!pdcattr) diff --git a/reactos/win32ss/gdi/gdi32/objects/dc.c b/reactos/win32ss/gdi/gdi32/objects/dc.c index 4262cbaca3a..f506eff1d6f 100644 --- a/reactos/win32ss/gdi/gdi32/objects/dc.c +++ b/reactos/win32ss/gdi/gdi32/objects/dc.c @@ -289,19 +289,7 @@ DeleteDC(HDC hdc) if (hType != GDILoObjType_LO_DC_TYPE) { - - if ( !pLDC || hType == GDILoObjType_LO_METADC16_TYPE) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->Flags & LDC_INIT_DOCUMENT) AbortDoc(hdc); - if (pLDC->hPrinter) - { - DocumentEventEx(NULL, pLDC->hPrinter, hdc, DOCUMENTEVENT_DELETEDC, 0, NULL, 0, NULL); - hPrinter = pLDC->hPrinter; - pLDC->hPrinter = NULL; - } + return METADC_DeleteDC(hdc); } bResult = NtGdiDeleteObjectApp(hdc); @@ -326,7 +314,7 @@ INT WINAPI SaveDC(IN HDC hdc) { - /* FIXME Sharememory */ + HANDLE_METADC0P(INT, SaveDC, 0, hdc); return NtGdiSaveDC(hdc); } @@ -339,7 +327,7 @@ WINAPI RestoreDC(IN HDC hdc, IN INT iLevel) { - /* FIXME Sharememory */ + HANDLE_METADC(BOOL, RestoreDC, FALSE, hdc, iLevel); return NtGdiRestoreDC(hdc, iLevel); } @@ -389,8 +377,8 @@ GetArcDirection( INT WINAPI SetArcDirection( - _In_ HDC hdc, - _In_ INT nDirection) + _In_ HDC hdc, + _In_ INT nDirection) { return GetAndSetDCDWord(hdc, GdiGetSetArcDirection, nDirection, 0, 0, 0); } @@ -576,48 +564,21 @@ GetDeviceCaps( _In_ int nIndex) { PDC_ATTR pdcattr; - PLDC pLDC; PDEVCAPS pDevCaps = GdiDevCaps; // Primary display device capabilities. DPRINT("Device CAPS1\n"); - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - { - if (nIndex == TECHNOLOGY) return DT_METAFILE; - return 0; - } - else - { - 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); - pLDC->Flags |= LDC_DEVCAPS; - } - pDevCaps = &pLDC->DevCaps; - } - } - else - { - /* Get the DC attribute */ - pdcattr = GdiGetDcAttr(hdc); - if (pdcattr == NULL) - { - SetLastError(ERROR_INVALID_PARAMETER); - return 0; - } + HANDLE_METADC(INT, GetDeviceCaps, 0, hdc, nIndex); - if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY) ) - return NtGdiGetDeviceCaps(hdc, nIndex); + /* Get the DC attribute */ + pdcattr = GdiGetDcAttr(hdc); + if (pdcattr == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return 0; } - DPRINT("Device CAPS2\n"); + + if (!(pdcattr->ulDirty_ & DC_PRIMARY_DISPLAY)) + return NtGdiGetDeviceCaps(hdc, nIndex); switch (nIndex) { @@ -781,35 +742,14 @@ GetAndSetDCDWord( _In_ DWORD dwError) { DWORD dwResult; - BOOL Ret = TRUE; - /* Handle something other than a normal dc object. */ - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return 0; //call MFDRV - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - if (pLDC->iType == LDC_EMFLDC) - { - Ret = TRUE; //call EMFDRV - if (Ret) - return u; - return 0; - } - } - } + /* This is a special API, handle it appropriately */ + HANDLE_METADC2(DWORD, GetAndSetDCDWord, hdc, u, dwIn, ulMFId, usMF16Id, dwError); + /* Call win32k to do the real work */ if (!NtGdiGetAndSetDCDword(hdc, u, dwIn, &dwResult)) { - SetLastError(ERROR_INVALID_HANDLE); - return 0; + return dwError; } return dwResult; @@ -888,7 +828,7 @@ WINAPI GetClipBox(HDC hdc, LPRECT lprc) { - return NtGdiGetAppClipBox(hdc, lprc); + return NtGdiGetAppClipBox(hdc, lprc); } @@ -954,6 +894,9 @@ SetDCBrushColor( return CLR_INVALID; } + /* We handle only enhanced meta DCs here */ + HANDLE_METADC(COLORREF, SetDCBrushColor, CLR_INVALID, hdc, crColor); + /* Get old color and store the new */ crOldColor = pdcattr->ulBrushClr; pdcattr->ulBrushClr = crColor; @@ -987,6 +930,9 @@ SetDCPenColor( return CLR_INVALID; } + /* We handle only enhanced meta DCs here */ + HANDLE_METADC(COLORREF, SetDCPenColor, CLR_INVALID, hdc, crColor); + /* Get old color and store the new */ crOldColor = pdcattr->ulPenClr; pdcattr->ulPenClr = (ULONG)crColor; @@ -1034,6 +980,8 @@ SetBkColor( PDC_ATTR pdcattr; COLORREF crOldColor; + HANDLE_METADC(COLORREF, SetBkColor, CLR_INVALID, hdc, crColor); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -1042,27 +990,6 @@ SetBkColor( return CLR_INVALID; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetBkColor(hdc, crColor ); - else - { - PLDC pLDC = pdcattr->pvLDC; - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetBkColor(hdc, crColor ); - } - } - } -#endif - /* Get old color and store the new */ crOldColor = pdcattr->ulBackgroundClr; pdcattr->ulBackgroundClr = crColor; @@ -1110,6 +1037,8 @@ SetBkMode( PDC_ATTR pdcattr; INT iOldMode; + HANDLE_METADC(INT, SetBkMode, 0, hdc, iBkMode); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -1118,27 +1047,6 @@ SetBkMode( return 0; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetBkMode( hdc, iBkMode ) - else - { - PLDC pLDC = pdcattr->pvLDC; - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetBkMode(hdc, iBkMode) - } - } - } -#endif - iOldMode = pdcattr->lBkMode; pdcattr->jBkMode = iBkMode; // Processed pdcattr->lBkMode = iBkMode; // Raw @@ -1180,28 +1088,7 @@ SetROP2( PDC_ATTR pdcattr; INT rop2Old; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetROP2( hdc, rop2); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetROP2(( hdc, rop2); - } - return FALSE; - } - } -#endif + HANDLE_METADC(INT, SetROP2, 0, hdc, rop2); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -1261,26 +1148,7 @@ SetPolyFillMode( INT iOldPolyFillMode; PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetPolyFillMode( hdc, iPolyFillMode ) - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetPolyFillMode( hdc, iPolyFillMode ) - } - } - } -#endif + HANDLE_METADC(INT, SetPolyFillMode, 0, hdc, iPolyFillMode); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -1423,26 +1291,8 @@ SelectPalette( HPALETTE hpal, BOOL bForceBackground) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SelectPalette(hdc, hpal, bForceBackground); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return NULL; - } - if (pLDC->iType == LDC_EMFLDC) - { - if return EMFDRV_SelectPalette(hdc, hpal, bForceBackground); - } - } - } -#endif + HANDLE_METADC(HPALETTE, SelectPalette, NULL, hdc, hpal, bForceBackground); + return NtUserSelectPalette(hdc, hpal, bForceBackground); } @@ -1478,26 +1328,9 @@ SetStretchBltMode( { INT iOldMode; PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetStretchBltMode( hdc, iStretchMode); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetStretchBltMode( hdc, iStretchMode); - } - } - } -#endif + + HANDLE_METADC(INT, SetStretchBltMode, 0, hdc, iStretchMode); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -1558,6 +1391,8 @@ GdiSelectBrush( PDC_ATTR pdcattr; HBRUSH hbrOld; + HANDLE_METADC(HBRUSH, SelectBrush, NULL, hdc, hbr); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -1586,6 +1421,8 @@ GdiSelectPen( PDC_ATTR pdcattr; HPEN hpenOld; + HANDLE_METADC(HPEN, SelectPen, NULL, hdc, hpen); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -1614,6 +1451,8 @@ GdiSelectFont( PDC_ATTR pdcattr; HFONT hfontOld; + HANDLE_METADC(HFONT, SelectFont, NULL, hdc, hfont); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) diff --git a/reactos/win32ss/gdi/gdi32/objects/enhmfile.c b/reactos/win32ss/gdi/gdi32/objects/enhmfile.c index e44a61ce82c..bf8a94a947d 100644 --- a/reactos/win32ss/gdi/gdi32/objects/enhmfile.c +++ b/reactos/win32ss/gdi/gdi32/objects/enhmfile.c @@ -3,690 +3,6 @@ #define NDEBUG #include - - -/* - * @unimplemented - */ -HENHMETAFILE -WINAPI -CloseEnhMetaFile( - HDC hdc) -{ - UNIMPLEMENTED; - return 0; -} - - -#if 0 // Remove once new EnhMetaFile support is implemented. -HDC -WINAPI -CreateEnhMetaFileW( - HDC hDC, /* [in] optional reference DC */ - LPCWSTR filename, /* [in] optional filename for disk metafiles */ - const RECT* rect, /* [in] optional bounding rectangle */ - LPCWSTR description /* [in] optional description */ -) -{ - HDC mDC; - PDC_ATTR Dc_Attr; - PLDC pLDC; - HANDLE hFile; - PENHMETAFILE EmfDC; - DWORD size = 0, length = 0; - - mDC = NtGdiCreateMetafileDC( hDC ); // Basically changes the handle from 1xxxx to 46xxxx. - // If hDC == NULL, works just like createdc in win32k. - - if ( !GdiGetHandleUserData((HGDIOBJ) mDC, GDI_OBJECT_TYPE_DC, (PVOID) &Dc_Attr)) - { - SetLastError (ERROR_INVALID_PARAMETER); - return NULL; // need to delete the handle? - } - - pLDC = LocalAlloc(LMEM_ZEROINIT, sizeof(LDC)); - - Dc_Attr->pvLDC = pLDC; - pLDC->hDC = mDC; - pLDC->iType = LDC_EMFDC - - - if (description) - { - /* App name\0Title\0\0 */ - length = lstrlenW(description); - length += lstrlenW(description + length + 1); - length += 3; - length *= 2; - } - - size = sizeof(ENHMETAFILE) + (length + 3) / 4 * 4; - - //Allocate ENHMETAFILE structure - EmfDC = LocalAlloc(LMEM_ZEROINIT, sizeof(ENHMETAFILE)); - pLDC->pvEmfDC = EmfDC; - - EmfDC->handles_size = HANDLE_LIST_INC; - EmfDC->cur_handles = 1; - - EmfDC->horzres = GetDeviceCaps(mDC, HORZRES); - EmfDC->vertres = GetDeviceCaps(mDC, VERTRES); - EmfDC->logpixelsx = GetDeviceCaps(mDC, LOGPIXELSX); - EmfDC->logpixelsy = GetDeviceCaps(mDC, LOGPIXELSY); - EmfDC->horzsize = GetDeviceCaps(mDC, HORZSIZE); - EmfDC->vertsize = GetDeviceCaps(mDC, VERTSIZE); - EmfDC->bitspixel = GetDeviceCaps(mDC, BITSPIXEL); - EmfDC->textcaps = GetDeviceCaps(mDC, TEXTCAPS); - EmfDC->rastercaps = GetDeviceCaps(mDC, RASTERCAPS); - EmfDC->technology = GetDeviceCaps(mDC, TECHNOLOGY); - EmfDC->planes = GetDeviceCaps(mDC, PLANES); - - EmfDC->emf = LocalAlloc(LMEM_ZEROINIT, size); - - EmfDC->emf->iType = EMR_HEADER; - EmfDC->emf->nSize = size; - - EmfDC->emf->rclBounds.left = EmfDC->emf->rclBounds.top = 0; - EmfDC->emf->rclBounds.right = EmfDC->emf->rclBounds.bottom = -1; - - if(rect) - { - EmfDC->emf->rclFrame.left = rect->left; - EmfDC->emf->rclFrame.top = rect->top; - EmfDC->emf->rclFrame.right = rect->right; - EmfDC->emf->rclFrame.bottom = rect->bottom; - } - else - { - /* Set this to {0,0 - -1,-1} and update it at the end */ - EmfDC->emf->rclFrame.left = EmfDC->emf->rclFrame.top = 0; - EmfDC->emf->rclFrame.right = EmfDC->emf->rclFrame.bottom = -1; - } - - EmfDC->emf->dSignature = ENHMETA_SIGNATURE; - EmfDC->emf->nVersion = 0x10000; - EmfDC->emf->nBytes = pLDC->pvEmfDC->nSize; - EmfDC->emf->nRecords = 1; - EmfDC->emf->nHandles = 1; - - EmfDC->emf->sReserved = 0; /* According to docs, this is reserved and must be 0 */ - EmfDC->emf->nDescription = length / 2; - - EmfDC->emf->offDescription = length ? sizeof(ENHMETAHEADER) : 0; - - EmfDC->emf->nPalEntries = 0; /* I guess this should start at 0 */ - - /* Size in pixels */ - EmfDC->emf->szlDevice.cx = EmfDC->horzres; - EmfDC->emf->szlDevice.cy = EmfDC->vertres; - - /* Size in millimeters */ - EmfDC->emf->szlMillimeters.cx = EmfDC->horzsize; - EmfDC->emf->szlMillimeters.cy = EmfDC->vertsize; - - /* Size in micrometers */ - EmfDC->emf->szlMicrometers.cx = EmfDC->horzsize * 1000; - EmfDC->emf->szlMicrometers.cy = EmfDC->vertsize * 1000; - - RtlCopyMemory((char *)EmfDC->emf + sizeof(ENHMETAHEADER), description, length); - - if (filename) /* disk based metafile */ - { - if ((hFile = CreateFileW(filename, GENERIC_WRITE | GENERIC_READ, 0, - NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) - { - EMFDRV_DeleteDC( EmfDC ); - return NULL; - } - if (!WriteFile( hFile, (LPSTR)EmfDC->emf, size, NULL, NULL )) - { - EMFDRV_DeleteDC( EmfDC ); - return NULL; - } - EmfDC.hFile = hFile; - EmfDC.iType = METAFILE_DISK; - } - else - EmfDC.iType = METAFILE_MEMORY; - - return mDC; -} -#endif - - -/* - * @unimplemented - */ -HENHMETAFILE -WINAPI -CopyEnhMetaFileA( - HENHMETAFILE hemfSrc, - LPCSTR lpszFile) -{ - NTSTATUS Status; - LPWSTR lpszFileW; - HENHMETAFILE rc = 0; - - Status = HEAP_strdupA2W ( &lpszFileW, lpszFile ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - else - { - rc = NULL; - - HEAP_free ( lpszFileW ); - } - return rc; -} - - -/* - * @unimplemented - */ -HDC -WINAPI -CreateEnhMetaFileA( - HDC hdcRef, - LPCSTR lpFileName, - CONST RECT *lpRect, - LPCSTR lpDescription) -{ - NTSTATUS Status; - LPWSTR lpFileNameW, lpDescriptionW; - HDC rc = 0; - - lpFileNameW = NULL; - if (lpFileName != NULL) - { - Status = HEAP_strdupA2W ( &lpFileNameW, lpFileName ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - - return rc; - } - - lpDescriptionW = NULL; - if (lpDescription != NULL) - { - Status = HEAP_strdupA2W ( &lpDescriptionW, lpDescription ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - - return rc; - } - - rc = NULL; - - if (lpDescriptionW != NULL) - HEAP_free ( lpDescriptionW ); - - if (lpFileNameW != NULL) - HEAP_free ( lpFileNameW ); - - return rc; -} - -#if 0 -/* Previous implementation in win32k */ -HDC -WINAPI -NtGdiCreateEnhMetaFile(HDC hDCRef, - LPCWSTR File, - CONST LPRECT Rect, - LPCWSTR Description) -{ - PDC Dc; - HDC ret = NULL; - DWORD length = 0; - HDC tempHDC; - DWORD MemSize; - DWORD dwDesiredAccess; - - tempHDC = hDCRef; - if (hDCRef == NULL) - { - /* FIXME ?? - * Shall we create hdc NtGdiHdcCompatible hdc ?? - */ - UNICODE_STRING DriverName; - RtlInitUnicodeString(&DriverName, L"DISPLAY"); - //IntGdiCreateDC(&DriverName, NULL, NULL, NULL, FALSE); - tempHDC = NtGdiOpenDCW( &DriverName, - NULL, - NULL, - 0, // DCW 0 and ICW 1. - NULL, - (PVOID) NULL, - (PVOID) NULL ); - } - - GDIOBJ_SetOwnership(GdiHandleTable, tempHDC, PsGetCurrentProcess()); - DC_SetOwnership(tempHDC, PsGetCurrentProcess()); - - Dc = DC_LockDc(tempHDC); - if (Dc == NULL) - { - if (hDCRef == NULL) - { - NtGdiDeleteObjectApp(tempHDC); - } - SetLastWin32Error(ERROR_INVALID_HANDLE); - return NULL; - } - - if(Description) - { - length = wcslen(Description); - length += wcslen(Description + length + 1); - length += 3; - length *= 2; - } - - MemSize = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4; - - if (!(Dc->emh = EngAllocMem(FL_ZERO_MEMORY, MemSize, 0))) - { - DC_UnlockDc(Dc); - if (hDCRef == NULL) - { - NtGdiDeleteObjectApp(tempHDC); - } - SetLastWin32Error(ERROR_INVALID_HANDLE); - return NULL; - } - - Dc->emh->iType = EMR_HEADER; - Dc->emh->nSize = MemSize; - - Dc->emh->rclBounds.left = Dc->emh->rclBounds.top = 0; - Dc->emh->rclBounds.right = Dc->emh->rclBounds.bottom = -1; - - if(Rect) - { - Dc->emh->rclFrame.left = Rect->left; - Dc->emh->rclFrame.top = Rect->top; - Dc->emh->rclFrame.right = Rect->right; - Dc->emh->rclFrame.bottom = Rect->bottom; - } - else - { - /* Set this to {0,0 - -1,-1} and update it at the end */ - Dc->emh->rclFrame.left = Dc->emh->rclFrame.top = 0; - Dc->emh->rclFrame.right = Dc->emh->rclFrame.bottom = -1; - } - - Dc->emh->dSignature = ENHMETA_SIGNATURE; - Dc->emh->nVersion = 0x10000; - Dc->emh->nBytes = Dc->emh->nSize; - Dc->emh->nRecords = 1; - Dc->emh->nHandles = 1; - - Dc->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */ - Dc->emh->nDescription = length / 2; - - Dc->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0; - - Dc->emh->nPalEntries = 0; /* I guess this should start at 0 */ - - /* Size in pixels */ - Dc->emh->szlDevice.cx = NtGdiGetDeviceCaps(tempHDC, HORZRES); - Dc->emh->szlDevice.cy = NtGdiGetDeviceCaps(tempHDC, VERTRES); - - /* Size in millimeters */ - Dc->emh->szlMillimeters.cx = NtGdiGetDeviceCaps(tempHDC, HORZSIZE); - Dc->emh->szlMillimeters.cy = NtGdiGetDeviceCaps(tempHDC, VERTSIZE); - - /* Size in micrometers */ - Dc->emh->szlMicrometers.cx = Dc->emh->szlMillimeters.cx * 1000; - Dc->emh->szlMicrometers.cy = Dc->emh->szlMillimeters.cy * 1000; - - if(Description) - { - memcpy((char *)Dc->emh + sizeof(ENHMETAHEADER), Description, length); - } - - ret = tempHDC; - if (File) - { - OBJECT_ATTRIBUTES ObjectAttributes; - IO_STATUS_BLOCK IoStatusBlock; - IO_STATUS_BLOCK Iosb; - UNICODE_STRING NtPathU; - NTSTATUS Status; - ULONG FileAttributes = (FILE_ATTRIBUTE_VALID_FLAGS & ~FILE_ATTRIBUTE_DIRECTORY); - - DPRINT1("Trying Create EnhMetaFile\n"); - - /* disk based metafile */ - dwDesiredAccess = GENERIC_WRITE | GENERIC_READ | SYNCHRONIZE | FILE_READ_ATTRIBUTES; - - if (!RtlDosPathNameToNtPathName_U (File, &NtPathU, NULL, NULL)) - { - DC_UnlockDc(Dc); - if (hDCRef == NULL) - { - NtGdiDeleteObjectApp(tempHDC); - } - DPRINT1("Can not Create EnhMetaFile\n"); - SetLastWin32Error(ERROR_PATH_NOT_FOUND); - return NULL; - } - - InitializeObjectAttributes(&ObjectAttributes, &NtPathU, 0, NULL, NULL); - - Status = NtCreateFile (&Dc->hFile, dwDesiredAccess, &ObjectAttributes, &IoStatusBlock, - NULL, FileAttributes, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE, - NULL, 0); - - RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU.Buffer); - - if (!NT_SUCCESS(Status)) - { - Dc->hFile = NULL; - DC_UnlockDc(Dc); - if (hDCRef == NULL) - { - NtGdiDeleteObjectApp(tempHDC); - } - DPRINT1("Create EnhMetaFile fail\n"); - SetLastWin32Error(ERROR_INVALID_HANDLE); - return NULL; - } - - SetLastWin32Error(IoStatusBlock.Information == FILE_OVERWRITTEN ? ERROR_ALREADY_EXISTS : 0); - - Status = NtWriteFile(Dc->hFile, NULL, NULL, NULL, &Iosb, (PVOID)&Dc->emh, Dc->emh->nSize, NULL, NULL); - if (Status == STATUS_PENDING) - { - Status = NtWaitForSingleObject(Dc->hFile,FALSE,NULL); - if (NT_SUCCESS(Status)) - { - Status = Iosb.Status; - } - } - - if (NT_SUCCESS(Status)) - { - ret = tempHDC; - DC_UnlockDc(Dc); - } - else - { - Dc->hFile = NULL; - DPRINT1("Write to EnhMetaFile fail\n"); - SetLastWin32Error(ERROR_CAN_NOT_COMPLETE); - ret = NULL; - DC_UnlockDc(Dc); - if (hDCRef == NULL) - { - NtGdiDeleteObjectApp(tempHDC); - } - } - } - else - { - DC_UnlockDc(Dc); - } - - return ret; -} -#endif - - - -/* - * @unimplemented - */ -HENHMETAFILE -WINAPI -GetEnhMetaFileA( - LPCSTR lpszMetaFile) -{ - NTSTATUS Status; - LPWSTR lpszMetaFileW; - HENHMETAFILE rc = 0; - - Status = HEAP_strdupA2W ( &lpszMetaFileW, lpszMetaFile ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - else - { - rc = NULL; - - HEAP_free ( lpszMetaFileW ); - } - - return rc; -} - - -/* - * @unimplemented - */ -UINT -WINAPI -GetEnhMetaFileDescriptionA( - HENHMETAFILE hemf, - UINT cchBuffer, - LPSTR lpszDescription) -{ - NTSTATUS Status; - LPWSTR lpszDescriptionW; - - if ( lpszDescription && cchBuffer ) - { - lpszDescriptionW = (LPWSTR)HEAP_alloc ( cchBuffer*sizeof(WCHAR) ); - if ( !lpszDescriptionW ) - { - SetLastError (RtlNtStatusToDosError(STATUS_NO_MEMORY)); - return 0; - } - } - else - lpszDescriptionW = NULL; - - if ( lpszDescription && cchBuffer ) - { - Status = RtlUnicodeToMultiByteN ( lpszDescription, - cchBuffer, - NULL, - lpszDescriptionW, - cchBuffer ); - HEAP_free ( lpszDescriptionW ); - if ( !NT_SUCCESS(Status) ) - { - SetLastError (RtlNtStatusToDosError(Status)); - return 0; - } - } - - return 0; -} - - - -/* Unimplemented functions */ - -HENHMETAFILE -WINAPI -CopyEnhMetaFileW( - HENHMETAFILE hemfSrc, - LPCWSTR lpszFile) -{ - UNIMPLEMENTED; - return 0; -} - - -HENHMETAFILE -WINAPI -GetEnhMetaFileW( - LPCWSTR lpszMetaFile) -{ - UNIMPLEMENTED; - return 0; -} - - -UINT -WINAPI -GetEnhMetaFileDescriptionW( - HENHMETAFILE hemf, - UINT cchBuffer, - LPWSTR lpszDescription) -{ - UNIMPLEMENTED; - return 0; -} - - -HDC -WINAPI -CreateEnhMetaFileW( - HDC hdcRef, - LPCWSTR lpFileName, - LPCRECT lpRect, - LPCWSTR lpDescription) -{ - UNIMPLEMENTED; - return 0; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteEnhMetaFile( - HENHMETAFILE a0 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumEnhMetaFile( - HDC hdc, - HENHMETAFILE hmf, - ENHMFENUMPROC callback, - LPVOID data, - CONST RECT *lpRect -) -{ - if(!lpRect && hdc) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -UINT -WINAPI -GetEnhMetaFileBits( - HENHMETAFILE a0, - UINT a1, - LPBYTE a2 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -HENHMETAFILE -WINAPI -SetEnhMetaFileBits( - UINT a0, - CONST BYTE *a1 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -UINT -WINAPI -GetEnhMetaFileHeader( - HENHMETAFILE a0, - UINT a1, - LPENHMETAHEADER a2 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -UINT -WINAPI -GetEnhMetaFilePaletteEntries( - HENHMETAFILE a0, - UINT a1, - LPPALETTEENTRY a2 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -PlayEnhMetaFile( - HDC a0, - HENHMETAFILE a1, - CONST RECT *a2 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -PlayEnhMetaFileRecord( - HDC a0, - LPHANDLETABLE a1, - CONST ENHMETARECORD *a2, - UINT a3 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - /* * @unimplemented */ @@ -746,33 +62,21 @@ GdiCreateLocalEnhMetaFile(HENHMETAFILE hmo) } /* - * @unimplemented + * @implemented */ BOOL WINAPI GdiComment( - HDC hDC, - UINT bytes, - CONST BYTE *buffer -) + _In_ HDC hdc, + _In_ UINT cbSize, + _In_ const BYTE *lpData) { -#if 0 - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_EMF) - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - // Wine port - return EMFDRV_GdiComment( hDC, bytes, buffer ); - } - } -#endif - return FALSE; + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) + return TRUE; + + HANDLE_METADC(BOOL, GdiComment, FALSE, hdc, cbSize, lpData); + + return TRUE; } /* diff --git a/reactos/win32ss/gdi/gdi32/objects/gdiobj.c b/reactos/win32ss/gdi/gdi32/objects/gdiobj.c index 18984bf20d0..55f04908245 100644 --- a/reactos/win32ss/gdi/gdi32/objects/gdiobj.c +++ b/reactos/win32ss/gdi/gdi32/objects/gdiobj.c @@ -327,6 +327,12 @@ DeleteObject(HGDIOBJ hObject) return TRUE; } + /* If we have any METAFILE objects, we need to check them */ + if (gcClientObj > 0) + { + METADC_DeleteObject(hObject); + } + /* Switch by object type */ switch (GDI_HANDLE_GET_TYPE(hObject)) { diff --git a/reactos/win32ss/gdi/gdi32/objects/metafile.c b/reactos/win32ss/gdi/gdi32/objects/metafile.c index c75bca8f491..c6f57bcdc21 100644 --- a/reactos/win32ss/gdi/gdi32/objects/metafile.c +++ b/reactos/win32ss/gdi/gdi32/objects/metafile.c @@ -1,321 +1,8 @@ #include #include -/* DEFINES *******************************************************************/ - - -/* PRIVATE DATA **************************************************************/ - -PMF_ENTRY hMF_List = NULL; -DWORD hMFCount = 0; - -/* INTERNAL FUNCTIONS ********************************************************/ - -BOOL -MF_CreateMFDC ( HGDIOBJ hMDC, - PMETAFILEDC pmfDC ) -{ - PMF_ENTRY pMFME; - - pMFME = LocalAlloc(LMEM_ZEROINIT, sizeof(MF_ENTRY)); - if (!pMFME) - { - return FALSE; - } - - if (hMF_List == NULL) - { - hMF_List = pMFME; - InitializeListHead(&hMF_List->List); - } - else - InsertTailList(&hMF_List->List, &pMFME->List); - - pMFME->hmDC = hMDC; - pMFME->pmfDC = pmfDC; - - hMFCount++; - return TRUE; -} - - -PMETAFILEDC -MF_GetMFDC ( HGDIOBJ hMDC ) -{ - PMF_ENTRY pMFME = hMF_List; - - do - { - if ( pMFME->hmDC == hMDC ) return pMFME->pmfDC; - pMFME = (PMF_ENTRY) pMFME->List.Flink; - } - while ( pMFME != hMF_List ); - - return NULL; -} - - -BOOL -MF_DeleteMFDC ( HGDIOBJ hMDC ) -{ - PMF_ENTRY pMFME = hMF_List; - - do - { - if ( pMFME->hmDC == hMDC) - { - RemoveEntryList(&pMFME->List); - LocalFree ( pMFME ); - hMFCount--; - if (!hMFCount) hMF_List = NULL; - return TRUE; - } - pMFME = (PMF_ENTRY) pMFME->List.Flink; - } - while ( pMFME != hMF_List ); - - return FALSE; -} - /* FUNCTIONS *****************************************************************/ -/* - * @unimplemented - */ -HMETAFILE -WINAPI -CloseMetaFile( - HDC a0 -) -{ - return 0; -} - - -/* - * @implemented - */ -HMETAFILE -WINAPI -CopyMetaFileW( - HMETAFILE hmfSrc, - LPCWSTR lpszFile -) -{ - return NULL; -} - - -/* - * @implemented - */ -HMETAFILE -WINAPI -CopyMetaFileA( - HMETAFILE hmfSrc, - LPCSTR lpszFile -) -{ - NTSTATUS Status; - PWSTR lpszFileW; - HMETAFILE rc = 0; - - Status = HEAP_strdupA2W ( &lpszFileW, lpszFile ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - else - { - rc = CopyMetaFileW( hmfSrc, lpszFileW ); - HEAP_free ( lpszFileW ); - } - - return rc; -} - - -/* - * @implemented - */ -HDC -WINAPI -CreateMetaFileW( - LPCWSTR lpszFile -) -{ - HANDLE hFile; - HDC hmDC; - PMETAFILEDC pmfDC = LocalAlloc(LMEM_ZEROINIT, sizeof(METAFILEDC)); - if (!pmfDC) return NULL; - - pmfDC->mh.mtHeaderSize = sizeof(METAHEADER) / sizeof(WORD); - pmfDC->mh.mtVersion = 0x0300; - pmfDC->mh.mtSize = pmfDC->mh.mtHeaderSize; - - pmfDC->hPen = GetStockObject(BLACK_PEN); - pmfDC->hBrush = GetStockObject(WHITE_BRUSH); - pmfDC->hFont = GetStockObject(DEVICE_DEFAULT_FONT); - pmfDC->hBitmap = GetStockObject(DEFAULT_BITMAP); - pmfDC->hPalette = GetStockObject(DEFAULT_PALETTE); - - if (lpszFile) /* disk based metafile */ - { - pmfDC->mh.mtType = METAFILE_DISK; - - if(!GetFullPathName( lpszFile, - MAX_PATH, - (LPTSTR) &pmfDC->Filename, - (LPTSTR*) &lpszFile)) - { - LocalFree(pmfDC); - return NULL; - } - - if ((hFile = CreateFileW(pmfDC->Filename, GENERIC_WRITE, 0, NULL, - CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) - { - LocalFree(pmfDC); - return NULL; - } - - if (!WriteFile( hFile, &pmfDC->mh, sizeof(pmfDC->mh), &pmfDC->dwWritten, NULL )) - { - LocalFree(pmfDC); - return NULL; - } - pmfDC->hFile = hFile; - } - else /* memory based metafile */ - pmfDC->mh.mtType = METAFILE_MEMORY; - - hmDC = NtGdiCreateClientObj ( GDI_OBJECT_TYPE_METADC ); - - MF_CreateMFDC ( hmDC, pmfDC ); - - return hmDC; -} - - -/* - * @implemented - */ -HDC -WINAPI -CreateMetaFileA( - LPCSTR lpszFile -) -{ - NTSTATUS Status; - PWSTR lpszFileW; - HDC rc = 0; - - Status = HEAP_strdupA2W ( &lpszFileW, lpszFile ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - else - { - rc = CreateMetaFileW( lpszFileW ); - HEAP_free ( lpszFileW ); - } - return rc; -} - - -/* - * @unimplemented - */ -BOOL -WINAPI -DeleteMetaFile( - HMETAFILE a0 -) -{ - return FALSE; -} - - -/* - * @implemented - */ -HMETAFILE -WINAPI -GetMetaFileW( - LPCWSTR lpszMetaFile -) -{ - return NULL; -} - - -/* - * @implemented - */ -HMETAFILE -WINAPI -GetMetaFileA( - LPCSTR lpszMetaFile -) -{ - NTSTATUS Status; - LPWSTR lpszMetaFileW; - HMETAFILE rc = 0; - - Status = HEAP_strdupA2W ( &lpszMetaFileW, lpszMetaFile ); - if (!NT_SUCCESS (Status)) - SetLastError (RtlNtStatusToDosError(Status)); - else - { - rc = GetMetaFileW( lpszMetaFileW ); - HEAP_free ( lpszMetaFileW ); - } - - return rc; -} - - -/* - * @unimplemented - */ -UINT -WINAPI -GetMetaFileBitsEx( - HMETAFILE a0, - UINT a1, - LPVOID a2 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -HMETAFILE -WINAPI -SetMetaFileBitsEx( - UINT size, - CONST BYTE *lpData -) -{ - const METAHEADER *mh_in = (const METAHEADER *)lpData; - - if (size & 1) return 0; - - if (!size || mh_in->mtType != METAFILE_MEMORY || mh_in->mtVersion != 0x300 || - mh_in->mtHeaderSize != sizeof(METAHEADER) / 2) - { - DPRINT1("SetMetaFileBitsEx failed: %lu,%lu,0x&lx,%lu\n", - size, mh_in->mtType, mh_in->mtVersion, mh_in->mtHeaderSize); - SetLastError(ERROR_INVALID_DATA); - return 0; - } - - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - /* * @implemented */ @@ -323,95 +10,17 @@ BOOL WINAPI GdiIsPlayMetafileDC(HDC hDC) { +#if 0 PLDC pLDC = GdiGetLDC(hDC); if ( pLDC ) { if ( pLDC->Flags & LDC_PLAY_MFDC ) return TRUE; } return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -PlayMetaFile( - HDC a0, - HMETAFILE a1 -) -{ +#else UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -PlayMetaFileRecord( - HDC a0, - LPHANDLETABLE a1, - LPMETARECORD a2, - UINT a3 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -BOOL -WINAPI -EnumMetaFile( - HDC a0, - HMETAFILE a1, - MFENUMPROC a2, - LPARAM a3 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return FALSE; -} - -/* - * @unimplemented - */ -UINT -WINAPI -GetWinMetaFileBits( - HENHMETAFILE a0, - UINT a1, - LPBYTE a2, - INT a3, - HDC a4 -) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; -} - -/* - * @unimplemented - */ -HENHMETAFILE -WINAPI -SetWinMetaFileBits( - UINT a0, - CONST BYTE *a1, - HDC a2, - CONST METAFILEPICT *a3) -{ - UNIMPLEMENTED; - SetLastError(ERROR_CALL_NOT_IMPLEMENTED); - return 0; +#endif } /* @@ -419,23 +28,31 @@ SetWinMetaFileBits( */ BOOL WINAPI -GdiIsMetaFileDC(HDC hDC) +GdiIsMetaFileDC(HDC hdc) { - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) + ULONG ulObjType; + + ulObjType = GDI_HANDLE_GET_TYPE(hdc); + if (ulObjType == GDILoObjType_LO_METADC16_TYPE) { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return TRUE; - else - { - PLDC pLDC = GdiGetLDC(hDC); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if ( pLDC->iType == LDC_EMFLDC) return TRUE; - } + return TRUE; } + + 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 FALSE; } @@ -446,7 +63,7 @@ BOOL WINAPI GdiIsMetaPrintDC(HDC hDC) { - +#if 0 if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) { if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) @@ -463,6 +80,10 @@ GdiIsMetaPrintDC(HDC hDC) } } return FALSE; +#else + UNIMPLEMENTED; + return FALSE; +#endif } /* diff --git a/reactos/win32ss/gdi/gdi32/objects/painting.c b/reactos/win32ss/gdi/gdi32/objects/painting.c index a191de053dd..931241f1c4b 100644 --- a/reactos/win32ss/gdi/gdi32/objects/painting.c +++ b/reactos/win32ss/gdi/gdi32/objects/painting.c @@ -11,28 +11,8 @@ LineTo( _In_ INT x, _In_ INT y ) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam2(hdc, META_LINETO, x, y); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if (!pLDC) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return MFDRV_LineTo(hdc, x, y ) - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, LineTo, FALSE, hdc, x, y); + return NtGdiLineTo(hdc, x, y); } @@ -46,26 +26,9 @@ MoveToEx( _Out_opt_ LPPOINT ppt) { PDC_ATTR pdcattr; -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam2(hdc, META_MOVETO, x, y); - else - { - PLDC pLDC = pdcattr->pvLDC; - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - if (!EMFDRV_MoveTo(hdc, x, y)) return FALSE; - } - } - } -#endif + + HANDLE_METADC(BOOL, MoveTo, FALSE, hdc, x, y, ppt); + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -110,28 +73,8 @@ Ellipse( _In_ INT right, _In_ INT bottom) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam4(hdc, META_ELLIPSE, left, top, right, bottom ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_Ellipse(hdc, left, top, right, bottom ); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, Ellipse, FALSE, hdc, left, top, right, bottom); + return NtGdiEllipse(hdc, left, top, right, bottom); } @@ -148,28 +91,8 @@ Rectangle( _In_ INT right, _In_ INT bottom) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam4(hdc, META_RECTANGLE, left, top, right, bottom); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_Rectangle(hdc, left, top, right, bottom); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, Rectangle, FALSE, hdc, left, top, right, bottom); + return NtGdiRectangle(hdc, left, top, right, bottom); } @@ -188,30 +111,8 @@ RoundRect( _In_ INT width, _In_ INT height) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam6(hdc, META_ROUNDRECT, left, top, right, bottom, - width, height ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_RoundRect(hdc, left, top, right, bottom, - width, height ); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, RoundRect, FALSE, hdc, left, top, right, bottom, width, height); + return NtGdiRoundRect(hdc, left, top, right, bottom, width, height); } @@ -243,29 +144,8 @@ SetPixel( _In_ INT y, _In_ COLORREF crColor) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_MetaParam4(hdc, META_SETPIXEL, x, y, HIWORD(crColor), - LOWORD(crColor)); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return 0; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_SetPixel(hdc, x, y, crColor); - } - return 0; - } - } -#endif + HANDLE_METADC(COLORREF, SetPixel, CLR_INVALID, hdc, x, y, crColor); + return NtGdiSetPixel(hdc, x, y, crColor); } @@ -298,28 +178,9 @@ FillRgn( if ((hrgn == NULL) || (hbr == NULL)) return FALSE; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_FillRgn(hdc, hrgn, hbr); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_FillRgn((hdc, hrgn, hbr); - } - return FALSE; - } - } -#endif + + HANDLE_METADC(BOOL, FillRgn, FALSE, hdc, hrgn, hbr); + return NtGdiFillRgn(hdc, hrgn, hbr); } @@ -339,28 +200,9 @@ FrameRgn( if ((hrgn == NULL) || (hbr == NULL)) return FALSE; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_FrameRgn(hdc, hrgn, hbr, nWidth, nHeight ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_FrameRgn(hdc, hrgn, hbr, nWidth, nHeight ); - } - return FALSE; - } - } -#endif + + HANDLE_METADC(BOOL, FrameRgn, FALSE, hdc, hrgn, hbr, nWidth, nHeight); + return NtGdiFrameRgn(hdc, hrgn, hbr, nWidth, nHeight); } @@ -377,28 +219,9 @@ InvertRgn( if (hrgn == NULL) return FALSE; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_InvertRgn(hdc, HRGN hrgn ); // Use this instead of MFDRV_MetaParam. - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_PaintInvertRgn(hdc, hrgn, EMR_INVERTRGN ); - } - return FALSE; - } - } -#endif + + HANDLE_METADC(BOOL, InvertRgn, FALSE, hdc, hrgn); + return NtGdiInvertRgn(hdc, hrgn); } @@ -412,32 +235,7 @@ PaintRgn( _In_ HDC hdc, _In_ HRGN hrgn) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_PaintRgn(hdc, HRGN hrgn ); // Use this instead of MFDRV_MetaParam. - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_PaintInvertRgn(hdc, hrgn, EMR_PAINTRGN ); - } - return FALSE; - } - } -#endif -// Could just use pdcattr->hbrush? No. - HBRUSH hbr = GetCurrentObject(hdc, OBJ_BRUSH); - - return NtGdiFillRgn(hdc, hrgn, hbr); + return FillRgn(hdc, hrgn, GetCurrentObject(hdc, OBJ_BRUSH)); } @@ -451,32 +249,8 @@ PolyBezier( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - /* - * Since MetaFiles don't record Beziers and they don't even record - * approximations to them using lines. - */ - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return FALSE; // Not supported yet. - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, PolyBezier, FALSE, hdc, apt, cpt); + return NtGdiPolyPolyDraw(hdc ,(PPOINT)apt, &cpt, 1, GdiPolyBezier); } @@ -491,28 +265,8 @@ PolyBezierTo( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return FALSE; // Not supported yet. - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, PolyBezierTo, FALSE, hdc, apt, cpt); + return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyBezierTo); } @@ -528,28 +282,8 @@ PolyDraw( _In_reads_(cpt) const BYTE *aj, _In_ INT cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return FALSE; // Not supported yet. - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, PolyDraw, FALSE, hdc, apt, aj, cpt); + return NtGdiPolyDraw(hdc, (PPOINT)apt, (PBYTE)aj, cpt); } @@ -564,28 +298,8 @@ Polygon( _In_reads_(cpt) const POINT *apt, _In_ INT cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_Polygon(hdc, apt, cpt ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_Polygon(hdc, apt, cpt ); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, Polygon, FALSE, hdc, apt, cpt); + return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, (PULONG)&cpt, 1, GdiPolyPolygon); } @@ -600,28 +314,8 @@ Polyline( _In_reads_(cpt) const POINT *apt, _In_ INT cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_Polyline(hdc, apt, cpt); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_Polyline(hdc, apt, cpt); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, Polyline, FALSE, hdc, apt, cpt); + return NtGdiPolyPolyDraw(hdc, (PPOINT)apt, (PULONG)&cpt, 1, GdiPolyPolyLine); } @@ -636,28 +330,8 @@ PolylineTo( _In_reads_(cpt) const POINT *apt, _In_ DWORD cpt) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return FALSE; // Not supported yet. - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, PolylineTo, FALSE, hdc, apt, cpt); + return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, &cpt, 1, GdiPolyLineTo); } @@ -673,28 +347,8 @@ PolyPolygon( _In_reads_(csz) const INT *asz, _In_ INT csz) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_PolyPolygon(hdc, apt, asz, csz); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_PolyPolygon(hdc, apt, asz, csz ); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, PolyPolygon, FALSE, hdc, apt, asz, csz); + return NtGdiPolyPolyDraw(hdc, (PPOINT)apt, (PULONG)asz, csz, GdiPolyPolygon); } @@ -710,28 +364,11 @@ PolyPolyline( _In_reads_(csz) CONST DWORD *asz, _In_ DWORD csz) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return FALSE; - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_PolyPolyline(hdc, apt, asz, csz); - } - return FALSE; - } - } -#endif + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + return FALSE; + + HANDLE_METADC(BOOL, PolyPolyline, FALSE, hdc, apt, asz, csz); + return NtGdiPolyPolyDraw(hdc , (PPOINT)apt, (PULONG)asz, csz, GdiPolyPolyLine); } @@ -748,28 +385,8 @@ ExtFloodFill( _In_ COLORREF crFill, _In_ UINT fuFillType) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_ExtFloodFill(hdc, xStart, yStart, crFill, fuFillType ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - return EMFDRV_ExtFloodFill(hdc, xStart, yStart, crFill, fuFillType ); - } - return FALSE; - } - } -#endif + HANDLE_METADC(BOOL, ExtFloodFill, FALSE, hdc, xStart, yStart, crFill, fuFillType); + return NtGdiExtFloodFill(hdc, xStart, yStart, crFill, fuFillType); } @@ -810,6 +427,22 @@ BitBlt( return PatBlt(hdcDest, xDest, yDest, cx, cy, dwRop); } + /* For meta DCs we use StretchBlt */ + HANDLE_METADC(BOOL, + StretchBlt, + FALSE, + hdcDest, + xDest, + yDest, + cx, + cx, + hdcSrc, + xSrc, + ySrc, + cx, + cx, + dwRop); + return NtGdiBitBlt(hdcDest, xDest, yDest, cx, cy, hdcSrc, xSrc, ySrc, dwRop, 0, 0); } @@ -823,6 +456,8 @@ PatBlt( _In_ INT nHeight, _In_ DWORD dwRop) { + HANDLE_METADC(BOOL, PatBlt, FALSE, hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop); + /* FIXME some part need be done in user mode */ return NtGdiPatBlt( hdc, nXLeft, nYLeft, nWidth, nHeight, dwRop); } @@ -836,6 +471,46 @@ PolyPatBlt( _In_ DWORD nCount, _In_ DWORD dwMode) { + UINT i; + BOOL bResult; + HBRUSH hbrOld; + + /* Handle meta DCs */ + if ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) || + (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE)) + { + if (!GdiIsHandleValid(hdc)) + { + return FALSE; + } + + /* Save the current DC brush */ + hbrOld = SelectObject(hdc, GetStockObject(DC_BRUSH)); + + /* Assume success */ + bResult = TRUE; + + /* Loop all rect */ + for (i = 0; i < nCount; i++) + { + /* Select the brush for this rect */ + SelectObject(hdc, pPoly[i].hBrush); + + /* Do the PatBlt operation for this rect */ + bResult &= PatBlt(hdc, + pPoly[i].nXLeft, + pPoly[i].nYLeft, + pPoly[i].nWidth, + pPoly[i].nHeight, + dwRop); + } + + /* Restore the old brush */ + SelectObject(hdc, hbrOld); + + return bResult; + } + /* FIXME some part need be done in user mode */ return NtGdiPolyPatBlt(hdc, dwRop, pPoly, nCount, dwMode); } @@ -858,6 +533,21 @@ StretchBlt( _In_ INT cySrc, _In_ DWORD dwRop) { + HANDLE_METADC(BOOL, + StretchBlt, + FALSE, + hdcDest, + xDest, + yDest, + cxDest, + cyDest, + hdcSrc, + xSrc, + ySrc, + cxSrc, + cySrc, + dwRop); + return NtGdiStretchBlt(hdcDest, xDest, yDest, @@ -892,6 +582,22 @@ MaskBlt( _In_ INT yMask, _In_ DWORD dwRop) { + HANDLE_METADC(BOOL, + MaskBlt, + FALSE, + hdcDest, + xDest, + yDest, + cx, + cy, + hdcSrc, + xSrc, + ySrc, + hbmMask, + xMask, + yMask, + dwRop); + return NtGdiMaskBlt(hdcDest, xDest, yDest, @@ -925,6 +631,20 @@ PlgBlt( _In_ INT xMask, _In_ INT yMask) { + HANDLE_METADC(BOOL, + PlgBlt, + FALSE, + hdcDest, + ppt, + hdcSrc, + xSrc, + ySrc, + cx, + cy, + hbmMask, + xMask, + yMask); + return NtGdiPlgBlt(hdcDest, (LPPOINT)ppt, hdcSrc, @@ -957,6 +677,21 @@ GdiAlphaBlend( if (GDI_HANDLE_GET_TYPE(hdcSrc) == GDI_OBJECT_TYPE_METADC) return FALSE; + HANDLE_METADC(BOOL, + AlphaBlend, + FALSE, + hdcDst, + xDst, + yDst, + cxDst, + cyDst, + hdcSrc, + xSrc, + ySrc, + cxSrc, + cySrc, + blendfn); + return NtGdiAlphaBlend(hdcDst, xDst, yDst, @@ -990,6 +725,21 @@ GdiTransparentBlt( _In_ INT cySrc, _In_ UINT crTransparent) { + HANDLE_METADC(BOOL, + TransparentBlt, + FALSE, + hdcDst, + xDst, + yDst, + cxDst, + cyDst, + hdcSrc, + xSrc, + ySrc, + cxSrc, + cySrc, + crTransparent); + /* FIXME some part need be done in user mode */ return NtGdiTransparentBlt(hdcDst, xDst, yDst, cxDst, cyDst, hdcSrc, xSrc, ySrc, cxSrc, cySrc, crTransparent); } @@ -1007,6 +757,8 @@ GdiGradientFill( _In_ ULONG nCount, _In_ ULONG ulMode) { + HANDLE_METADC(BOOL, GradientFill, FALSE, hdc, pVertex, nVertex, pMesh, nCount, ulMode); + /* FIXME some part need be done in user mode */ return NtGdiGradientFill(hdc, pVertex, nVertex, pMesh, nCount, ulMode); } diff --git a/reactos/win32ss/gdi/gdi32/objects/palette.c b/reactos/win32ss/gdi/gdi32/objects/palette.c index 81202ef8d5e..a9bd24ab1b7 100644 --- a/reactos/win32ss/gdi/gdi32/objects/palette.c +++ b/reactos/win32ss/gdi/gdi32/objects/palette.c @@ -135,25 +135,11 @@ GetDIBColorTable(HDC hDC, */ UINT WINAPI -RealizePalette(HDC hDC) /* [in] Handle of device context */ +RealizePalette( + _In_ HDC hdc) /* [in] Handle of device context */ { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_(hDC); - else - { - HPALETTE Pal = GetCurrentObject(hDC, OBJ_PAL); - PLDC pLDC = GdiGetLDC((HDC) Pal); - if ( !pLDC ) return FALSE; - if (pLDC->iType == LDC_EMFLDC) return EMFDRV_(Pal); - return FALSE; - } - } -#endif - return UserRealizePalette(hDC); + HANDLE_METADC0P(UINT, RealizePalette, GDI_ERROR, hdc); + return UserRealizePalette(hdc); } /* diff --git a/reactos/win32ss/gdi/gdi32/objects/path.c b/reactos/win32ss/gdi/gdi32/objects/path.c index 50ed87fc93f..01ba886c3ae 100644 --- a/reactos/win32ss/gdi/gdi32/objects/path.c +++ b/reactos/win32ss/gdi/gdi32/objects/path.c @@ -16,10 +16,10 @@ BOOL WINAPI AbortPath( - HDC hdc -) + HDC hdc) { - return NtGdiAbortPath( hdc ); + HANDLE_METADC0P(BOOL, AbortPath, FALSE, hdc); + return NtGdiAbortPath(hdc); } @@ -29,10 +29,10 @@ AbortPath( BOOL WINAPI BeginPath( - HDC hdc -) + HDC hdc) { - return NtGdiBeginPath( hdc ); + HANDLE_METADC0P(BOOL, BeginPath, FALSE, hdc); + return NtGdiBeginPath(hdc); } /* @@ -41,10 +41,10 @@ BeginPath( BOOL WINAPI CloseFigure( - HDC hdc -) + HDC hdc) { - return NtGdiCloseFigure ( hdc ); + HANDLE_METADC0P(BOOL, CloseFigure, FALSE, hdc); + return NtGdiCloseFigure(hdc); } @@ -54,9 +54,9 @@ CloseFigure( BOOL WINAPI EndPath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, EndPath, FALSE, hdc); return NtGdiEndPath( hdc ); } @@ -67,9 +67,9 @@ EndPath( BOOL WINAPI FillPath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, FillPath, FALSE, hdc); return NtGdiFillPath( hdc ); } @@ -80,9 +80,9 @@ FillPath( BOOL WINAPI FlattenPath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, FlattenPath, FALSE, hdc); return NtGdiFlattenPath ( hdc ); } @@ -118,10 +118,10 @@ GetPath(HDC hdc, HRGN WINAPI PathToRegion( - HDC hdc -) + HDC hdc) { - return NtGdiPathToRegion ( hdc ); + HANDLE_METADC0P(HRGN, PathToRegion, NULL, hdc); + return NtGdiPathToRegion(hdc); } /* @@ -151,9 +151,9 @@ SetMiterLimit( BOOL WINAPI StrokeAndFillPath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, StrokeAndFillPath, FALSE, hdc); return NtGdiStrokeAndFillPath ( hdc ); } @@ -164,9 +164,9 @@ StrokeAndFillPath( BOOL WINAPI StrokePath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, StrokePath, FALSE, hdc); return NtGdiStrokePath ( hdc ); } @@ -177,9 +177,9 @@ StrokePath( BOOL WINAPI WidenPath( - HDC hdc -) + HDC hdc) { + HANDLE_METADC0P(BOOL, WidenPath, FALSE, hdc); return NtGdiWidenPath ( hdc ); } @@ -190,8 +190,8 @@ BOOL WINAPI SelectClipPath( HDC hdc, - int Mode -) + int iMode) { - return NtGdiSelectClipPath ( hdc, Mode ); + HANDLE_METADC(BOOL, SelectClipPath, FALSE, hdc, iMode); + return NtGdiSelectClipPath(hdc, iMode); } diff --git a/reactos/win32ss/gdi/gdi32/objects/region.c b/reactos/win32ss/gdi/gdi32/objects/region.c index 0b066000075..dd5c1287b0f 100644 --- a/reactos/win32ss/gdi/gdi32/objects/region.c +++ b/reactos/win32ss/gdi/gdi32/objects/region.c @@ -104,12 +104,13 @@ SortRects(PRECT pRect, INT nCount) */ BOOL FASTCALL -DeleteRegion( HRGN hRgn ) +DeleteRegion( + _In_ HRGN hrgn) { #if 0 PRGN_ATTR Rgn_Attr; - if ((GdiGetHandleUserData((HGDIOBJ) hRgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) && + if ((GdiGetHandleUserData(hrgn, GDI_OBJECT_TYPE_REGION, (PVOID) &Rgn_Attr)) && ( Rgn_Attr != NULL )) { PGDIBSOBJECT pgO; @@ -117,29 +118,32 @@ DeleteRegion( HRGN hRgn ) pgO = GdiAllocBatchCommand(NULL, GdiBCDelRgn); if (pgO) { - pgO->hgdiobj = (HGDIOBJ)hRgn; + pgO->hgdiobj = hrgn; return TRUE; } } #endif - return NtGdiDeleteObjectApp((HGDIOBJ) hRgn); + return NtGdiDeleteObjectApp(hrgn); } INT FASTCALL -MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn) +MirrorRgnByWidth( + _In_ HRGN hrgn, + _In_ INT Width, + _In_ HRGN *phrgn) { INT cRgnDSize, Ret = 0; PRGNDATA pRgnData; - cRgnDSize = NtGdiGetRegionData(hRgn, 0, NULL); + cRgnDSize = NtGdiGetRegionData(hrgn, 0, NULL); if (cRgnDSize) { pRgnData = LocalAlloc(LMEM_FIXED, cRgnDSize * sizeof(LONG)); if (pRgnData) { - if ( GetRegionData(hRgn, cRgnDSize, pRgnData) ) + if ( GetRegionData(hrgn, cRgnDSize, pRgnData) ) { HRGN hRgnex; UINT i; @@ -160,10 +164,10 @@ MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn) hRgnex = ExtCreateRegion(NULL, cRgnDSize , pRgnData); if (hRgnex) { - if (phRgn) phRgn = (HRGN *)hRgnex; + if (phrgn) phrgn = (HRGN *)hRgnex; else { - CombineRgn(hRgn, hRgnex, 0, RGN_COPY); + CombineRgn(hrgn, hRgnex, 0, RGN_COPY); DeleteObject(hRgnex); } Ret = 1; @@ -177,12 +181,16 @@ MirrorRgnByWidth(HRGN hRgn, INT Width, HRGN *phRgn) INT WINAPI -MirrorRgnDC(HDC hdc, HRGN hRgn, HRGN *phRgn) +MirrorRgnDC( + _In_ HDC hdc, + _In_ HRGN hrgn, + _In_ HRGN *phrn) { if (!GdiIsHandleValid((HGDIOBJ) hdc) || - (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) return 0; + (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)) + return 0; - return MirrorRgnByWidth(hRgn, NtGdiGetDeviceWidth(hdc), phRgn); + return MirrorRgnByWidth(hrgn, NtGdiGetDeviceWidth(hdc), phrn); } /* FUNCTIONS *****************************************************************/ @@ -677,28 +685,15 @@ CreateRectRgnIndirect( */ INT WINAPI -ExcludeClipRect(IN HDC hdc, IN INT xLeft, IN INT yTop, IN INT xRight, IN INT yBottom) +ExcludeClipRect( + _In_ HDC hdc, + _In_ INT xLeft, + _In_ INT yTop, + _In_ INT xRight, + _In_ INT yBottom) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( pLDC ) - { - if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExcludeClipRect( hdc, xLeft, yTop, xRight, yBottom)) - return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ERROR; - } - } -#endif + HANDLE_METADC(INT, ExcludeClipRect, ERROR, hdc, xLeft, yTop, xRight, yBottom); + return NtGdiExcludeClipRect(hdc, xLeft, yTop, xRight, yBottom); } @@ -731,31 +726,16 @@ ExtCreateRegion( */ INT WINAPI -ExtSelectClipRgn( IN HDC hdc, IN HRGN hrgn, IN INT iMode) +ExtSelectClipRgn( + _In_ HDC hdc, + _In_ HRGN hrgn, + _In_ INT iMode) { INT Ret; HRGN NewRgn = NULL; -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_ExtSelectClipRgn( hdc, ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( pLDC ) - { - if (pLDC->iType != LDC_EMFLDC || EMFDRV_ExtSelectClipRgn( hdc, )) - return NtGdiExtSelectClipRgn(hdc, ); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ERROR; - } - } -#endif + HANDLE_METADC(INT, ExtSelectClipRgn, 0, hdc, hrgn, iMode); + #if 0 if ( hrgn ) { @@ -934,33 +914,15 @@ GetRgnBox(HRGN hrgn, */ INT WINAPI -IntersectClipRect(HDC hdc, - int nLeftRect, - int nTopRect, - int nRightRect, - int nBottomRect) +IntersectClipRect( + _In_ HDC hdc, + _In_ INT nLeft, + _In_ INT nTop, + _In_ INT nRight, + _In_ INT nBottom) { -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( pLDC ) - { - if (pLDC->iType != LDC_EMFLDC || EMFDRV_IntersectClipRect( hdc, nLeftRect, nTopRect, nRightRect, nBottomRect)) - return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); - } - else - SetLastError(ERROR_INVALID_HANDLE); - return ERROR; - } - } -#endif - return NtGdiIntersectClipRect(hdc, nLeftRect, nTopRect, nRightRect, nBottomRect); + HANDLE_METADC(INT, IntersectClipRect, ERROR, hdc, nLeft, nTop, nRight, nBottom); + return NtGdiIntersectClipRect(hdc, nLeft, nTop, nRight, nBottom); } /* @@ -980,36 +942,13 @@ MirrorRgn(HWND hwnd, HRGN hrgn) */ INT WINAPI -OffsetClipRgn(HDC hdc, - int nXOffset, - int nYOffset) +OffsetClipRgn( + HDC hdc, + INT nXOffset, + INT nYOffset) { - if (hdc == NULL) - { - SetLastError(ERROR_INVALID_HANDLE); - return ERROR; - } -#if 0 -// Handle something other than a normal dc object. - if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) - return MFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset ); - else - { - PLDC pLDC = GdiGetLDC(hdc); - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return ERROR; - } - if (pLDC->iType == LDC_EMFLDC && !EMFDRV_OffsetClipRgn( hdc, nXOffset, nYOffset )) - return ERROR; - return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset); - } - } -#endif - return NtGdiOffsetClipRgn( hdc, nXOffset, nYOffset); + HANDLE_METADC(INT, OffsetClipRgn, ERROR, hdc, nXOffset, nYOffset); + return NtGdiOffsetClipRgn(hdc, nXOffset, nYOffset); } /* @@ -1145,11 +1084,11 @@ RectInRegion(HRGN hrgn, /* * @implemented */ -int WINAPI +int +WINAPI SelectClipRgn( - HDC hdc, - HRGN hrgn -) + _In_ HDC hdc, + _In_ HRGN hrgn) { return ExtSelectClipRgn(hdc, hrgn, RGN_COPY); } @@ -1215,7 +1154,7 @@ SetRectRgn( */ int WINAPI -SetMetaRgn( HDC hDC ) +SetMetaRgn(HDC hDC) { if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_DC) return NtGdiSetMetaRgn(hDC); diff --git a/reactos/win32ss/gdi/gdi32/objects/text.c b/reactos/win32ss/gdi/gdi32/objects/text.c index effd022c93f..4eca1924edd 100644 --- a/reactos/win32ss/gdi/gdi32/objects/text.c +++ b/reactos/win32ss/gdi/gdi32/objects/text.c @@ -48,14 +48,7 @@ TextOutW( _In_reads_(cchString) LPCWSTR lpString, _In_ INT cchString) { - return NtGdiExtTextOutW(hdc, - nXStart, - nYStart, - 0, NULL, - (LPWSTR)lpString, - cchString, - NULL, - 0); + return ExtTextOutW(hdc, nXStart, nYStart, 0, NULL, (LPWSTR)lpString, cchString, NULL); } @@ -473,6 +466,18 @@ ExtTextOutW( _In_ UINT cwc, _In_reads_opt_(cwc) const INT *lpDx) { + HANDLE_METADC(BOOL, + ExtTextOut, + FALSE, + hdc, + x, + y, + fuOptions, + lprc, + lpString, + cwc, + lpDx); + return NtGdiExtTextOutW(hdc, x, y, @@ -633,12 +638,10 @@ SetTextCharacterExtra( return 0x80000000; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC) + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) { - return MFDRV_SetTextCharacterExtra( hdc, nCharExtra ); // Wine port. + HANDLE_METADC(INT, SetTextCharacterExtra, 0x80000000, hdc, nCharExtra); } -#endif /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -718,7 +721,9 @@ SetTextAlign( _In_ UINT fMode) { PDC_ATTR pdcattr; - INT fOldMode; + UINT fOldMode; + + HANDLE_METADC(BOOL, SetTextAlign, GDI_ERROR, hdc, fMode); /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); @@ -728,26 +733,6 @@ SetTextAlign( return GDI_ERROR; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetTextAlign( hdc, fMode ) - else - { - PLDC pLDC = pdcattr->pvLDC; - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - if return EMFDRV_SetTextAlign( hdc, fMode ) - } - } - } -#endif fOldMode = pdcattr->lTextAlign; pdcattr->lTextAlign = fMode; // Raw @@ -771,37 +756,17 @@ SetTextColor( _In_ COLORREF crColor) { PDC_ATTR pdcattr; - COLORREF crOldColor = CLR_INVALID; + COLORREF crOldColor; + + HANDLE_METADC(COLORREF, SetTextColor, CLR_INVALID, hdc, crColor); - /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) { SetLastError(ERROR_INVALID_PARAMETER); - return GDI_ERROR; + return CLR_INVALID; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetTextColor( hDC, crColor ); - else - { - PLDC pLDC = pdcattr->pvLDC; - if ( !pLDC ) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - if (pLDC->iType == LDC_EMFLDC) - { - if return EMFDRV_SetTextColor( hDC, crColor ); - } - } - } -#endif - crOldColor = (COLORREF) pdcattr->ulForegroundClr; pdcattr->ulForegroundClr = (ULONG)crColor; @@ -826,6 +791,11 @@ SetTextJustification( { PDC_ATTR pdcattr; + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + { + HANDLE_METADC(BOOL, SetTextJustification, FALSE, hdc, nBreakExtra, nBreakCount); + } + /* Get the DC attribute */ pdcattr = GdiGetDcAttr(hdc); if (pdcattr == NULL) @@ -834,17 +804,6 @@ SetTextJustification( return GDI_ERROR; } -#if 0 - if (GDI_HANDLE_GET_TYPE(hDC) != GDI_OBJECT_TYPE_DC) - { - if (GDI_HANDLE_GET_TYPE(hDC) == GDI_OBJECT_TYPE_METADC) - return MFDRV_SetTextJustification( hdc, nBreakExtra, nBreakCount ) - else - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } -#endif if (NtCurrentTeb()->GdiTebBatch.HDC == hdc) { diff --git a/reactos/win32ss/gdi/gdi32/wine/CMakeLists.txt b/reactos/win32ss/gdi/gdi32/wine/CMakeLists.txt new file mode 100644 index 00000000000..040e6a4607a --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/CMakeLists.txt @@ -0,0 +1,25 @@ + +include_directories( + ${REACTOS_SOURCE_DIR}/include/reactos/wine + ${REACTOS_SOURCE_DIR}/win32ss/include + ../include + .) + +list(APPEND SOURCE + enhmetafile.c + metafile.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/reactos/win32ss/gdi/gdi32/wine/enhmetafile.c b/reactos/win32ss/gdi/gdi32/wine/enhmetafile.c new file mode 100644 index 00000000000..c7bcec0a271 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmetafile.c @@ -0,0 +1,2820 @@ +/* + * Enhanced metafile functions + * Copyright 1998 Douglas Ridgway + * 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * + * NOTES: + * + * The enhanced format consists of the following elements: + * + * A header + * A table of handles to GDI objects + * An array of metafile records + * A private palette + * + * + * The standard format consists of a header and an array of metafile records. + * + */ + +#include "config.h" +#include "wine/port.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/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +typedef struct +{ + ENHMETAHEADER *emh; + BOOL on_disk; /* true if metafile is on disk */ +} ENHMETAFILEOBJ; + +static const struct emr_name { + DWORD type; + const char *name; +} emr_names[] = { +#define X(p) {p, #p} +X(EMR_HEADER), +X(EMR_POLYBEZIER), +X(EMR_POLYGON), +X(EMR_POLYLINE), +X(EMR_POLYBEZIERTO), +X(EMR_POLYLINETO), +X(EMR_POLYPOLYLINE), +X(EMR_POLYPOLYGON), +X(EMR_SETWINDOWEXTEX), +X(EMR_SETWINDOWORGEX), +X(EMR_SETVIEWPORTEXTEX), +X(EMR_SETVIEWPORTORGEX), +X(EMR_SETBRUSHORGEX), +X(EMR_EOF), +X(EMR_SETPIXELV), +X(EMR_SETMAPPERFLAGS), +X(EMR_SETMAPMODE), +X(EMR_SETBKMODE), +X(EMR_SETPOLYFILLMODE), +X(EMR_SETROP2), +X(EMR_SETSTRETCHBLTMODE), +X(EMR_SETTEXTALIGN), +X(EMR_SETCOLORADJUSTMENT), +X(EMR_SETTEXTCOLOR), +X(EMR_SETBKCOLOR), +X(EMR_OFFSETCLIPRGN), +X(EMR_MOVETOEX), +X(EMR_SETMETARGN), +X(EMR_EXCLUDECLIPRECT), +X(EMR_INTERSECTCLIPRECT), +X(EMR_SCALEVIEWPORTEXTEX), +X(EMR_SCALEWINDOWEXTEX), +X(EMR_SAVEDC), +X(EMR_RESTOREDC), +X(EMR_SETWORLDTRANSFORM), +X(EMR_MODIFYWORLDTRANSFORM), +X(EMR_SELECTOBJECT), +X(EMR_CREATEPEN), +X(EMR_CREATEBRUSHINDIRECT), +X(EMR_DELETEOBJECT), +X(EMR_ANGLEARC), +X(EMR_ELLIPSE), +X(EMR_RECTANGLE), +X(EMR_ROUNDRECT), +X(EMR_ARC), +X(EMR_CHORD), +X(EMR_PIE), +X(EMR_SELECTPALETTE), +X(EMR_CREATEPALETTE), +X(EMR_SETPALETTEENTRIES), +X(EMR_RESIZEPALETTE), +X(EMR_REALIZEPALETTE), +X(EMR_EXTFLOODFILL), +X(EMR_LINETO), +X(EMR_ARCTO), +X(EMR_POLYDRAW), +X(EMR_SETARCDIRECTION), +X(EMR_SETMITERLIMIT), +X(EMR_BEGINPATH), +X(EMR_ENDPATH), +X(EMR_CLOSEFIGURE), +X(EMR_FILLPATH), +X(EMR_STROKEANDFILLPATH), +X(EMR_STROKEPATH), +X(EMR_FLATTENPATH), +X(EMR_WIDENPATH), +X(EMR_SELECTCLIPPATH), +X(EMR_ABORTPATH), +X(EMR_GDICOMMENT), +X(EMR_FILLRGN), +X(EMR_FRAMERGN), +X(EMR_INVERTRGN), +X(EMR_PAINTRGN), +X(EMR_EXTSELECTCLIPRGN), +X(EMR_BITBLT), +X(EMR_STRETCHBLT), +X(EMR_MASKBLT), +X(EMR_PLGBLT), +X(EMR_SETDIBITSTODEVICE), +X(EMR_STRETCHDIBITS), +X(EMR_EXTCREATEFONTINDIRECTW), +X(EMR_EXTTEXTOUTA), +X(EMR_EXTTEXTOUTW), +X(EMR_POLYBEZIER16), +X(EMR_POLYGON16), +X(EMR_POLYLINE16), +X(EMR_POLYBEZIERTO16), +X(EMR_POLYLINETO16), +X(EMR_POLYPOLYLINE16), +X(EMR_POLYPOLYGON16), +X(EMR_POLYDRAW16), +X(EMR_CREATEMONOBRUSH), +X(EMR_CREATEDIBPATTERNBRUSHPT), +X(EMR_EXTCREATEPEN), +X(EMR_POLYTEXTOUTA), +X(EMR_POLYTEXTOUTW), +X(EMR_SETICMMODE), +X(EMR_CREATECOLORSPACE), +X(EMR_SETCOLORSPACE), +X(EMR_DELETECOLORSPACE), +X(EMR_GLSRECORD), +X(EMR_GLSBOUNDEDRECORD), +X(EMR_PIXELFORMAT), +X(EMR_DRAWESCAPE), +X(EMR_EXTESCAPE), +X(EMR_STARTDOC), +X(EMR_SMALLTEXTOUT), +X(EMR_FORCEUFIMAPPING), +X(EMR_NAMEDESCAPE), +X(EMR_COLORCORRECTPALETTE), +X(EMR_SETICMPROFILEA), +X(EMR_SETICMPROFILEW), +X(EMR_ALPHABLEND), +X(EMR_SETLAYOUT), +X(EMR_TRANSPARENTBLT), +X(EMR_RESERVED_117), +X(EMR_GRADIENTFILL), +X(EMR_SETLINKEDUFI), +X(EMR_SETTEXTJUSTIFICATION), +X(EMR_COLORMATCHTOTARGETW), +X(EMR_CREATECOLORSPACEW) +#undef X +}; + +/**************************************************************************** + * get_emr_name + */ +static const char *get_emr_name(DWORD type) +{ + unsigned int i; + for(i = 0; i < sizeof(emr_names) / sizeof(emr_names[0]); i++) + if(type == emr_names[i].type) return emr_names[i].name; + TRACE("Unknown record type %d\n", type); + return NULL; +} + +/*********************************************************************** + * is_dib_monochrome + * + * Returns whether a DIB can be converted to a monochrome DDB. + * + * A DIB can be converted if its color table contains only black and + * white. Black must be the first color in the color table. + * + * Note : If the first color in the color table is white followed by + * black, we can't convert it to a monochrome DDB with + * SetDIBits, because black and white would be inverted. + */ +static inline BOOL is_dib_monochrome( const BITMAPINFO* info ) +{ + if (info->bmiHeader.biBitCount != 1) return FALSE; + + if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) + { + const RGBTRIPLE *rgb = ((const BITMAPCOREINFO *) info)->bmciColors; + + /* Check if the first color is black */ + if ((rgb->rgbtRed == 0) && (rgb->rgbtGreen == 0) && (rgb->rgbtBlue == 0)) + { + rgb++; + /* Check if the second color is white */ + return ((rgb->rgbtRed == 0xff) && (rgb->rgbtGreen == 0xff) + && (rgb->rgbtBlue == 0xff)); + } + else return FALSE; + } + else /* assume BITMAPINFOHEADER */ + { + const RGBQUAD *rgb = info->bmiColors; + + /* Check if the first color is black */ + if ((rgb->rgbRed == 0) && (rgb->rgbGreen == 0) && + (rgb->rgbBlue == 0) && (rgb->rgbReserved == 0)) + { + rgb++; + + /* Check if the second color is white */ + return ((rgb->rgbRed == 0xff) && (rgb->rgbGreen == 0xff) + && (rgb->rgbBlue == 0xff) && (rgb->rgbReserved == 0)); + } + else return FALSE; + } +} + +/**************************************************************************** + * EMF_Create_HENHMETAFILE + */ +HENHMETAFILE EMF_Create_HENHMETAFILE(ENHMETAHEADER *emh, BOOL on_disk ) +{ + HENHMETAFILE hmf; + ENHMETAFILEOBJ *metaObj; + + if (emh->iType != EMR_HEADER) + { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + if (emh->dSignature != ENHMETA_SIGNATURE || + (emh->nBytes & 3)) /* refuse to load unaligned EMF as Windows does */ + { + WARN("Invalid emf header type 0x%08x sig 0x%08x.\n", + emh->iType, emh->dSignature); + return 0; + } + + if (!(metaObj = HeapAlloc( GetProcessHeap(), 0, sizeof(*metaObj) ))) return 0; + + metaObj->emh = emh; + metaObj->on_disk = on_disk; + + if (!(hmf = alloc_gdi_handle( metaObj, OBJ_ENHMETAFILE, NULL ))) + HeapFree( GetProcessHeap(), 0, metaObj ); + return hmf; +} + +/**************************************************************************** + * EMF_Delete_HENHMETAFILE + */ +static BOOL EMF_Delete_HENHMETAFILE( HENHMETAFILE hmf ) +{ + ENHMETAFILEOBJ *metaObj = free_gdi_handle( hmf ); + + if(!metaObj) return FALSE; + + if(metaObj->on_disk) + UnmapViewOfFile( metaObj->emh ); + else + HeapFree( GetProcessHeap(), 0, metaObj->emh ); + return HeapFree( GetProcessHeap(), 0, metaObj ); +} + +/****************************************************************** + * EMF_GetEnhMetaHeader + * + * Returns ptr to ENHMETAHEADER associated with HENHMETAFILE + */ +static ENHMETAHEADER *EMF_GetEnhMetaHeader( HENHMETAFILE hmf ) +{ + ENHMETAHEADER *ret = NULL; + ENHMETAFILEOBJ *metaObj = GDI_GetObjPtr( hmf, OBJ_ENHMETAFILE ); + TRACE("hmf %p -> enhmetaObj %p\n", hmf, metaObj); + if (metaObj) + { + ret = metaObj->emh; + GDI_ReleaseObj( hmf ); + } + return ret; +} + +/***************************************************************************** + * EMF_GetEnhMetaFile + * + */ +static HENHMETAFILE EMF_GetEnhMetaFile( HANDLE hFile ) +{ + ENHMETAHEADER *emh; + HANDLE hMapping; + HENHMETAFILE hemf; + + hMapping = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); + emh = MapViewOfFile( hMapping, FILE_MAP_READ, 0, 0, 0 ); + CloseHandle( hMapping ); + + if (!emh) return 0; + + hemf = EMF_Create_HENHMETAFILE( emh, TRUE ); + if (!hemf) + UnmapViewOfFile( emh ); + return hemf; +} + + +/***************************************************************************** + * GetEnhMetaFileA (GDI32.@) + * + * + */ +HENHMETAFILE WINAPI GetEnhMetaFileA( + LPCSTR lpszMetaFile /* [in] filename of enhanced metafile */ + ) +{ + HENHMETAFILE hmf; + HANDLE hFile; + + hFile = CreateFileA(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0, + OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) { + WARN("could not open %s\n", lpszMetaFile); + return 0; + } + hmf = EMF_GetEnhMetaFile( hFile ); + CloseHandle( hFile ); + return hmf; +} + +/***************************************************************************** + * GetEnhMetaFileW (GDI32.@) + */ +HENHMETAFILE WINAPI GetEnhMetaFileW( + LPCWSTR lpszMetaFile) /* [in] filename of enhanced metafile */ +{ + HENHMETAFILE hmf; + HANDLE hFile; + + hFile = CreateFileW(lpszMetaFile, GENERIC_READ, FILE_SHARE_READ, 0, + OPEN_EXISTING, 0, 0); + if (hFile == INVALID_HANDLE_VALUE) { + WARN("could not open %s\n", debugstr_w(lpszMetaFile)); + return 0; + } + hmf = EMF_GetEnhMetaFile( hFile ); + CloseHandle( hFile ); + return hmf; +} + +/***************************************************************************** + * GetEnhMetaFileHeader (GDI32.@) + * + * Retrieves the record containing the header for the specified + * enhanced-format metafile. + * + * RETURNS + * If buf is NULL, returns the size of buffer required. + * Otherwise, copy up to bufsize bytes of enhanced metafile header into + * buf. + */ +UINT WINAPI GetEnhMetaFileHeader( + HENHMETAFILE hmf, /* [in] enhanced metafile */ + UINT bufsize, /* [in] size of buffer */ + LPENHMETAHEADER buf /* [out] buffer */ + ) +{ + LPENHMETAHEADER emh; + UINT size; + + emh = EMF_GetEnhMetaHeader(hmf); + if(!emh) return FALSE; + size = emh->nSize; + if (!buf) return size; + size = min(size, bufsize); + memmove(buf, emh, size); + return size; +} + + +/***************************************************************************** + * GetEnhMetaFileDescriptionA (GDI32.@) + * + * See GetEnhMetaFileDescriptionW. + */ +UINT WINAPI GetEnhMetaFileDescriptionA( + HENHMETAFILE hmf, /* [in] enhanced metafile */ + UINT size, /* [in] size of buf */ + LPSTR buf /* [out] buffer to receive description */ + ) +{ + LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf); + DWORD len; + WCHAR *descrW; + + if(!emh) return FALSE; + if(emh->nDescription == 0 || emh->offDescription == 0) return 0; + descrW = (WCHAR *) ((char *) emh + emh->offDescription); + len = WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, NULL, 0, NULL, NULL ); + + if (!buf || !size ) return len; + + len = min( size, len ); + WideCharToMultiByte( CP_ACP, 0, descrW, emh->nDescription, buf, len, NULL, NULL ); + return len; +} + +/***************************************************************************** + * GetEnhMetaFileDescriptionW (GDI32.@) + * + * Copies the description string of an enhanced metafile into a buffer + * _buf_. + * + * RETURNS + * If _buf_ is NULL, returns size of _buf_ required. Otherwise, returns + * number of characters copied. + */ +UINT WINAPI GetEnhMetaFileDescriptionW( + HENHMETAFILE hmf, /* [in] enhanced metafile */ + UINT size, /* [in] size of buf */ + LPWSTR buf /* [out] buffer to receive description */ + ) +{ + LPENHMETAHEADER emh = EMF_GetEnhMetaHeader(hmf); + + if(!emh) return FALSE; + if(emh->nDescription == 0 || emh->offDescription == 0) return 0; + if (!buf || !size ) return emh->nDescription; + + memmove(buf, (char *) emh + emh->offDescription, min(size,emh->nDescription)*sizeof(WCHAR)); + return min(size, emh->nDescription); +} + +/**************************************************************************** + * SetEnhMetaFileBits (GDI32.@) + * + * Creates an enhanced metafile by copying _bufsize_ bytes from _buf_. + */ +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 ); + if (!hmf) + HeapFree( GetProcessHeap(), 0, emh ); + return hmf; +} + +/***************************************************************************** + * GetEnhMetaFileBits (GDI32.@) + * + */ +UINT WINAPI GetEnhMetaFileBits( + HENHMETAFILE hmf, + UINT bufsize, + LPBYTE buf +) +{ + LPENHMETAHEADER emh = EMF_GetEnhMetaHeader( hmf ); + UINT size; + + if(!emh) return 0; + + size = emh->nBytes; + if( buf == NULL ) return size; + + size = min( size, bufsize ); + memmove(buf, emh, size); + return size; +} + +typedef struct EMF_dc_state +{ + INT mode; + XFORM world_transform; + INT wndOrgX; + INT wndOrgY; + INT wndExtX; + INT wndExtY; + INT vportOrgX; + INT vportOrgY; + INT vportExtX; + INT vportExtY; + struct EMF_dc_state *next; +} EMF_dc_state; + +typedef struct enum_emh_data +{ + XFORM init_transform; + EMF_dc_state state; + INT save_level; + EMF_dc_state *saved_state; +} enum_emh_data; + +#define ENUM_GET_PRIVATE_DATA(ht) \ + ((enum_emh_data*)(((unsigned char*)(ht))-sizeof (enum_emh_data))) + +#define WIDTH(rect) ( (rect).right - (rect).left ) +#define HEIGHT(rect) ( (rect).bottom - (rect).top ) + +#define IS_WIN9X() (GetVersion()&0x80000000) + +static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info) +{ + XFORM mapping_mode_trans, final_trans; + double scaleX, scaleY; + + scaleX = (double)info->state.vportExtX / (double)info->state.wndExtX; + scaleY = (double)info->state.vportExtY / (double)info->state.wndExtY; + mapping_mode_trans.eM11 = scaleX; + mapping_mode_trans.eM12 = 0.0; + mapping_mode_trans.eM21 = 0.0; + mapping_mode_trans.eM22 = scaleY; + mapping_mode_trans.eDx = (double)info->state.vportOrgX - scaleX * (double)info->state.wndOrgX; + mapping_mode_trans.eDy = (double)info->state.vportOrgY - scaleY * (double)info->state.wndOrgY; + + CombineTransform(&final_trans, &info->state.world_transform, &mapping_mode_trans); + CombineTransform(&final_trans, &final_trans, &info->init_transform); + + if (!SetWorldTransform(hdc, &final_trans)) + { + __debugbreak(); + SetWorldTransform(hdc, &final_trans); + ERR("World transform failed!\n"); + } +} + +static void EMF_RestoreDC( enum_emh_data *info, INT level ) +{ + if (abs(level) > info->save_level || level == 0) return; + + if (level < 0) level = info->save_level + level + 1; + + while (info->save_level >= level) + { + EMF_dc_state *state = info->saved_state; + info->saved_state = state->next; + state->next = NULL; + if (--info->save_level < level) + info->state = *state; + HeapFree( GetProcessHeap(), 0, state ); + } +} + +static void EMF_SaveDC( enum_emh_data *info ) +{ + EMF_dc_state *state = HeapAlloc( GetProcessHeap(), 0, sizeof(*state)); + if (state) + { + *state = info->state; + state->next = info->saved_state; + info->saved_state = state; + info->save_level++; + TRACE("save_level %d\n", info->save_level); + } +} + +static void EMF_SetMapMode(HDC hdc, enum_emh_data *info) +{ + INT horzSize = GetDeviceCaps( hdc, HORZSIZE ); + INT vertSize = GetDeviceCaps( hdc, VERTSIZE ); + INT horzRes = GetDeviceCaps( hdc, HORZRES ); + INT vertRes = GetDeviceCaps( hdc, VERTRES ); + + TRACE("%d\n", info->state.mode); + + switch(info->state.mode) + { + case MM_TEXT: + info->state.wndExtX = 1; + info->state.wndExtY = 1; + info->state.vportExtX = 1; + info->state.vportExtY = 1; + break; + case MM_LOMETRIC: + case MM_ISOTROPIC: + info->state.wndExtX = horzSize * 10; + info->state.wndExtY = vertSize * 10; + info->state.vportExtX = horzRes; + info->state.vportExtY = -vertRes; + break; + case MM_HIMETRIC: + info->state.wndExtX = horzSize * 100; + info->state.wndExtY = vertSize * 100; + info->state.vportExtX = horzRes; + info->state.vportExtY = -vertRes; + break; + case MM_LOENGLISH: + info->state.wndExtX = MulDiv(1000, horzSize, 254); + info->state.wndExtY = MulDiv(1000, vertSize, 254); + info->state.vportExtX = horzRes; + info->state.vportExtY = -vertRes; + break; + case MM_HIENGLISH: + info->state.wndExtX = MulDiv(10000, horzSize, 254); + info->state.wndExtY = MulDiv(10000, vertSize, 254); + info->state.vportExtX = horzRes; + info->state.vportExtY = -vertRes; + break; + case MM_TWIPS: + info->state.wndExtX = MulDiv(14400, horzSize, 254); + info->state.wndExtY = MulDiv(14400, vertSize, 254); + info->state.vportExtX = horzRes; + info->state.vportExtY = -vertRes; + break; + case MM_ANISOTROPIC: + break; + default: + return; + } +} + +/*********************************************************************** + * EMF_FixIsotropic + * + * Fix viewport extensions for isotropic mode. + */ + +static void EMF_FixIsotropic(HDC hdc, enum_emh_data *info) +{ + double xdim = fabs((double)info->state.vportExtX * GetDeviceCaps( hdc, HORZSIZE ) / + (GetDeviceCaps( hdc, HORZRES ) * info->state.wndExtX)); + double ydim = fabs((double)info->state.vportExtY * GetDeviceCaps( hdc, VERTSIZE ) / + (GetDeviceCaps( hdc, VERTRES ) * info->state.wndExtY)); + + if (xdim > ydim) + { + INT mincx = (info->state.vportExtX >= 0) ? 1 : -1; + info->state.vportExtX = floor(info->state.vportExtX * ydim / xdim + 0.5); + if (!info->state.vportExtX) info->state.vportExtX = mincx; + } + else + { + INT mincy = (info->state.vportExtY >= 0) ? 1 : -1; + info->state.vportExtY = floor(info->state.vportExtY * xdim / ydim + 0.5); + if (!info->state.vportExtY) info->state.vportExtY = mincy; + } +} + +/***************************************************************************** + * emr_produces_output + * + * Returns TRUE if the record type writes something to the dc. Used by + * PlayEnhMetaFileRecord to determine whether it needs to update the + * dc's xform when in win9x mode. + * + * FIXME: need to test which records should be here. + */ +static BOOL emr_produces_output(int type) +{ + switch(type) { + case EMR_POLYBEZIER: + case EMR_POLYGON: + case EMR_POLYLINE: + case EMR_POLYBEZIERTO: + case EMR_POLYLINETO: + case EMR_POLYPOLYLINE: + case EMR_POLYPOLYGON: + case EMR_SETPIXELV: + case EMR_MOVETOEX: + case EMR_EXCLUDECLIPRECT: + case EMR_INTERSECTCLIPRECT: + case EMR_SELECTOBJECT: + case EMR_ANGLEARC: + case EMR_ELLIPSE: + case EMR_RECTANGLE: + case EMR_ROUNDRECT: + case EMR_ARC: + case EMR_CHORD: + case EMR_PIE: + case EMR_EXTFLOODFILL: + case EMR_LINETO: + case EMR_ARCTO: + case EMR_POLYDRAW: + case EMR_GDICOMMENT: + case EMR_FILLRGN: + case EMR_FRAMERGN: + case EMR_INVERTRGN: + case EMR_PAINTRGN: + case EMR_BITBLT: + case EMR_STRETCHBLT: + case EMR_MASKBLT: + case EMR_PLGBLT: + case EMR_SETDIBITSTODEVICE: + case EMR_STRETCHDIBITS: + case EMR_EXTTEXTOUTA: + case EMR_EXTTEXTOUTW: + case EMR_POLYBEZIER16: + case EMR_POLYGON16: + case EMR_POLYLINE16: + case EMR_POLYBEZIERTO16: + case EMR_POLYLINETO16: + case EMR_POLYPOLYLINE16: + case EMR_POLYPOLYGON16: + case EMR_POLYDRAW16: + case EMR_POLYTEXTOUTA: + case EMR_POLYTEXTOUTW: + case EMR_SMALLTEXTOUT: + case EMR_ALPHABLEND: + case EMR_TRANSPARENTBLT: + return TRUE; + default: + return FALSE; + } +} + + +/***************************************************************************** + * PlayEnhMetaFileRecord (GDI32.@) + * + * Render a single enhanced metafile record in the device context hdc. + * + * RETURNS + * TRUE (non zero) on success, FALSE on error. + * BUGS + * Many unimplemented records. + * No error handling on record play failures (ie checking return codes) + * + * NOTES + * WinNT actually updates the current world transform in this function + * whereas Win9x does not. + */ +BOOL WINAPI PlayEnhMetaFileRecord( + HDC hdc, /* [in] device context in which to render EMF record */ + LPHANDLETABLE handletable, /* [in] array of handles to be used in rendering record */ + const ENHMETARECORD *mr, /* [in] EMF record to render */ + UINT handles /* [in] size of handle array */ + ) +{ + int type; + RECT tmprc; + enum_emh_data *info = ENUM_GET_PRIVATE_DATA(handletable); + + TRACE("hdc = %p, handletable = %p, record = %p, numHandles = %d\n", + hdc, handletable, mr, handles); + if (!mr) return FALSE; + + type = mr->iType; + + TRACE("record %s\n", get_emr_name(type)); + switch(type) + { + case EMR_HEADER: + break; + case EMR_EOF: + break; + case EMR_GDICOMMENT: + { + const EMRGDICOMMENT *lpGdiComment = (const EMRGDICOMMENT *)mr; + /* In an enhanced metafile, there can be both public and private GDI comments */ + GdiComment( hdc, lpGdiComment->cbData, lpGdiComment->Data ); + break; + } + case EMR_SETMAPMODE: + { + const EMRSETMAPMODE *pSetMapMode = (const EMRSETMAPMODE *)mr; + + if (info->state.mode == pSetMapMode->iMode && + (info->state.mode == MM_ISOTROPIC || info->state.mode == MM_ANISOTROPIC)) + break; + info->state.mode = pSetMapMode->iMode; + EMF_SetMapMode(hdc, info); + break; + } + case EMR_SETBKMODE: + { + const EMRSETBKMODE *pSetBkMode = (const EMRSETBKMODE *)mr; + SetBkMode(hdc, pSetBkMode->iMode); + break; + } + case EMR_SETBKCOLOR: + { + const EMRSETBKCOLOR *pSetBkColor = (const EMRSETBKCOLOR *)mr; + SetBkColor(hdc, pSetBkColor->crColor); + break; + } + case EMR_SETPOLYFILLMODE: + { + const EMRSETPOLYFILLMODE *pSetPolyFillMode = (const EMRSETPOLYFILLMODE *)mr; + SetPolyFillMode(hdc, pSetPolyFillMode->iMode); + break; + } + case EMR_SETROP2: + { + const EMRSETROP2 *pSetROP2 = (const EMRSETROP2 *)mr; + SetROP2(hdc, pSetROP2->iMode); + break; + } + case EMR_SETSTRETCHBLTMODE: + { + const EMRSETSTRETCHBLTMODE *pSetStretchBltMode = (const EMRSETSTRETCHBLTMODE *)mr; + SetStretchBltMode(hdc, pSetStretchBltMode->iMode); + break; + } + case EMR_SETTEXTALIGN: + { + const EMRSETTEXTALIGN *pSetTextAlign = (const EMRSETTEXTALIGN *)mr; + SetTextAlign(hdc, pSetTextAlign->iMode); + break; + } + case EMR_SETTEXTCOLOR: + { + const EMRSETTEXTCOLOR *pSetTextColor = (const EMRSETTEXTCOLOR *)mr; + SetTextColor(hdc, pSetTextColor->crColor); + break; + } + case EMR_SAVEDC: + { + if (SaveDC( hdc )) + EMF_SaveDC( info ); + break; + } + case EMR_RESTOREDC: + { + const EMRRESTOREDC *pRestoreDC = (const EMRRESTOREDC *)mr; + TRACE("EMR_RESTORE: %d\n", pRestoreDC->iRelative); + if (RestoreDC( hdc, pRestoreDC->iRelative )) + EMF_RestoreDC( info, pRestoreDC->iRelative ); + break; + } + case EMR_INTERSECTCLIPRECT: + { + const EMRINTERSECTCLIPRECT *pClipRect = (const EMRINTERSECTCLIPRECT *)mr; + TRACE("EMR_INTERSECTCLIPRECT: rect %d,%d - %d, %d\n", + pClipRect->rclClip.left, pClipRect->rclClip.top, + pClipRect->rclClip.right, pClipRect->rclClip.bottom); + IntersectClipRect(hdc, pClipRect->rclClip.left, pClipRect->rclClip.top, + pClipRect->rclClip.right, pClipRect->rclClip.bottom); + break; + } + case EMR_SELECTOBJECT: + { + const EMRSELECTOBJECT *pSelectObject = (const EMRSELECTOBJECT *)mr; + if( pSelectObject->ihObject & 0x80000000 ) { + /* High order bit is set - it's a stock object + * Strip the high bit to get the index. + * See MSDN article Q142319 + */ + SelectObject( hdc, GetStockObject( pSelectObject->ihObject & + 0x7fffffff ) ); + } else { + /* High order bit wasn't set - not a stock object + */ + SelectObject( hdc, + (handletable->objectHandle)[pSelectObject->ihObject] ); + } + break; + } + case EMR_DELETEOBJECT: + { + const EMRDELETEOBJECT *pDeleteObject = (const EMRDELETEOBJECT *)mr; + DeleteObject( (handletable->objectHandle)[pDeleteObject->ihObject]); + (handletable->objectHandle)[pDeleteObject->ihObject] = 0; + break; + } + case EMR_SETWINDOWORGEX: + { + const EMRSETWINDOWORGEX *pSetWindowOrgEx = (const EMRSETWINDOWORGEX *)mr; + + info->state.wndOrgX = pSetWindowOrgEx->ptlOrigin.x; + info->state.wndOrgY = pSetWindowOrgEx->ptlOrigin.y; + + TRACE("SetWindowOrgEx: %d,%d\n", info->state.wndOrgX, info->state.wndOrgY); + break; + } + case EMR_SETWINDOWEXTEX: + { + const EMRSETWINDOWEXTEX *pSetWindowExtEx = (const EMRSETWINDOWEXTEX *)mr; + + if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC) + break; + info->state.wndExtX = pSetWindowExtEx->szlExtent.cx; + info->state.wndExtY = pSetWindowExtEx->szlExtent.cy; + if (info->state.mode == MM_ISOTROPIC) + EMF_FixIsotropic(hdc, info); + + TRACE("SetWindowExtEx: %d,%d\n",info->state.wndExtX, info->state.wndExtY); + break; + } + case EMR_SETVIEWPORTORGEX: + { + const EMRSETVIEWPORTORGEX *pSetViewportOrgEx = (const EMRSETVIEWPORTORGEX *)mr; + + info->state.vportOrgX = pSetViewportOrgEx->ptlOrigin.x; + info->state.vportOrgY = pSetViewportOrgEx->ptlOrigin.y; + TRACE("SetViewportOrgEx: %d,%d\n", info->state.vportOrgX, info->state.vportOrgY); + break; + } + case EMR_SETVIEWPORTEXTEX: + { + const EMRSETVIEWPORTEXTEX *pSetViewportExtEx = (const EMRSETVIEWPORTEXTEX *)mr; + + if (info->state.mode != MM_ISOTROPIC && info->state.mode != MM_ANISOTROPIC) + break; + info->state.vportExtX = pSetViewportExtEx->szlExtent.cx; + info->state.vportExtY = pSetViewportExtEx->szlExtent.cy; + if (info->state.mode == MM_ISOTROPIC) + EMF_FixIsotropic(hdc, info); + TRACE("SetViewportExtEx: %d,%d\n", info->state.vportExtX, info->state.vportExtY); + break; + } + case EMR_CREATEPEN: + { + const EMRCREATEPEN *pCreatePen = (const EMRCREATEPEN *)mr; + (handletable->objectHandle)[pCreatePen->ihPen] = + CreatePenIndirect(&pCreatePen->lopn); + break; + } + case EMR_EXTCREATEPEN: + { + const EMREXTCREATEPEN *pPen = (const EMREXTCREATEPEN *)mr; + LOGBRUSH lb; + lb.lbStyle = pPen->elp.elpBrushStyle; + lb.lbColor = pPen->elp.elpColor; + lb.lbHatch = pPen->elp.elpHatch; + + if(pPen->offBmi || pPen->offBits) + FIXME("EMR_EXTCREATEPEN: Need to copy brush bitmap\n"); + + (handletable->objectHandle)[pPen->ihPen] = + ExtCreatePen(pPen->elp.elpPenStyle, pPen->elp.elpWidth, &lb, + pPen->elp.elpNumEntries, pPen->elp.elpNumEntries ? pPen->elp.elpStyleEntry : NULL); + break; + } + case EMR_CREATEBRUSHINDIRECT: + { + const EMRCREATEBRUSHINDIRECT *pBrush = (const EMRCREATEBRUSHINDIRECT *)mr; + LOGBRUSH brush; + brush.lbStyle = pBrush->lb.lbStyle; + brush.lbColor = pBrush->lb.lbColor; + brush.lbHatch = pBrush->lb.lbHatch; + (handletable->objectHandle)[pBrush->ihBrush] = CreateBrushIndirect(&brush); + break; + } + case EMR_EXTCREATEFONTINDIRECTW: + { + const EMREXTCREATEFONTINDIRECTW *pFont = (const EMREXTCREATEFONTINDIRECTW *)mr; + (handletable->objectHandle)[pFont->ihFont] = + CreateFontIndirectW(&pFont->elfw.elfLogFont); + break; + } + case EMR_MOVETOEX: + { + const EMRMOVETOEX *pMoveToEx = (const EMRMOVETOEX *)mr; + MoveToEx(hdc, pMoveToEx->ptl.x, pMoveToEx->ptl.y, NULL); + break; + } + case EMR_LINETO: + { + const EMRLINETO *pLineTo = (const EMRLINETO *)mr; + LineTo(hdc, pLineTo->ptl.x, pLineTo->ptl.y); + break; + } + case EMR_RECTANGLE: + { + const EMRRECTANGLE *pRect = (const EMRRECTANGLE *)mr; + Rectangle(hdc, pRect->rclBox.left, pRect->rclBox.top, + pRect->rclBox.right, pRect->rclBox.bottom); + break; + } + case EMR_ELLIPSE: + { + const EMRELLIPSE *pEllipse = (const EMRELLIPSE *)mr; + Ellipse(hdc, pEllipse->rclBox.left, pEllipse->rclBox.top, + pEllipse->rclBox.right, pEllipse->rclBox.bottom); + break; + } + case EMR_POLYGON16: + { + const EMRPOLYGON16 *pPoly = (const EMRPOLYGON16 *)mr; + /* Shouldn't use Polygon16 since pPoly->cpts is DWORD */ + POINT *pts = HeapAlloc( GetProcessHeap(), 0, + pPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPoly->cpts; i++) + { + pts[i].x = pPoly->apts[i].x; + pts[i].y = pPoly->apts[i].y; + } + Polygon(hdc, pts, pPoly->cpts); + HeapFree( GetProcessHeap(), 0, pts ); + break; + } + case EMR_POLYLINE16: + { + const EMRPOLYLINE16 *pPoly = (const EMRPOLYLINE16 *)mr; + /* Shouldn't use Polyline16 since pPoly->cpts is DWORD */ + POINT *pts = HeapAlloc( GetProcessHeap(), 0, + pPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPoly->cpts; i++) + { + pts[i].x = pPoly->apts[i].x; + pts[i].y = pPoly->apts[i].y; + } + Polyline(hdc, pts, pPoly->cpts); + HeapFree( GetProcessHeap(), 0, pts ); + break; + } + case EMR_POLYLINETO16: + { + const EMRPOLYLINETO16 *pPoly = (const EMRPOLYLINETO16 *)mr; + /* Shouldn't use PolylineTo16 since pPoly->cpts is DWORD */ + POINT *pts = HeapAlloc( GetProcessHeap(), 0, + pPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPoly->cpts; i++) + { + pts[i].x = pPoly->apts[i].x; + pts[i].y = pPoly->apts[i].y; + } + PolylineTo(hdc, pts, pPoly->cpts); + HeapFree( GetProcessHeap(), 0, pts ); + break; + } + case EMR_POLYBEZIER16: + { + const EMRPOLYBEZIER16 *pPoly = (const EMRPOLYBEZIER16 *)mr; + /* Shouldn't use PolyBezier16 since pPoly->cpts is DWORD */ + POINT *pts = HeapAlloc( GetProcessHeap(), 0, + pPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPoly->cpts; i++) + { + pts[i].x = pPoly->apts[i].x; + pts[i].y = pPoly->apts[i].y; + } + PolyBezier(hdc, pts, pPoly->cpts); + HeapFree( GetProcessHeap(), 0, pts ); + break; + } + case EMR_POLYBEZIERTO16: + { + const EMRPOLYBEZIERTO16 *pPoly = (const EMRPOLYBEZIERTO16 *)mr; + /* Shouldn't use PolyBezierTo16 since pPoly->cpts is DWORD */ + POINT *pts = HeapAlloc( GetProcessHeap(), 0, + pPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPoly->cpts; i++) + { + pts[i].x = pPoly->apts[i].x; + pts[i].y = pPoly->apts[i].y; + } + PolyBezierTo(hdc, pts, pPoly->cpts); + HeapFree( GetProcessHeap(), 0, pts ); + break; + } + case EMR_POLYPOLYGON16: + { + const EMRPOLYPOLYGON16 *pPolyPoly = (const EMRPOLYPOLYGON16 *)mr; + /* NB POINTS array doesn't start at pPolyPoly->apts it's actually + pPolyPoly->aPolyCounts + pPolyPoly->nPolys */ + + const POINTS *pts = (const POINTS *)(pPolyPoly->aPolyCounts + pPolyPoly->nPolys); + POINT *pt = HeapAlloc( GetProcessHeap(), 0, pPolyPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPolyPoly->cpts; i++) + { + pt[i].x = pts[i].x; + pt[i].y = pts[i].y; + } + PolyPolygon(hdc, pt, (const INT*)pPolyPoly->aPolyCounts, pPolyPoly->nPolys); + HeapFree( GetProcessHeap(), 0, pt ); + break; + } + case EMR_POLYPOLYLINE16: + { + const EMRPOLYPOLYLINE16 *pPolyPoly = (const EMRPOLYPOLYLINE16 *)mr; + /* NB POINTS array doesn't start at pPolyPoly->apts it's actually + pPolyPoly->aPolyCounts + pPolyPoly->nPolys */ + + const POINTS *pts = (const POINTS *)(pPolyPoly->aPolyCounts + pPolyPoly->nPolys); + POINT *pt = HeapAlloc( GetProcessHeap(), 0, pPolyPoly->cpts * sizeof(POINT) ); + DWORD i; + for(i = 0; i < pPolyPoly->cpts; i++) + { + pt[i].x = pts[i].x; + pt[i].y = pts[i].y; + } + PolyPolyline(hdc, pt, pPolyPoly->aPolyCounts, pPolyPoly->nPolys); + HeapFree( GetProcessHeap(), 0, pt ); + break; + } + + case EMR_STRETCHDIBITS: + { + const EMRSTRETCHDIBITS *pStretchDIBits = (const EMRSTRETCHDIBITS *)mr; + + StretchDIBits(hdc, + pStretchDIBits->xDest, + pStretchDIBits->yDest, + pStretchDIBits->cxDest, + pStretchDIBits->cyDest, + pStretchDIBits->xSrc, + pStretchDIBits->ySrc, + pStretchDIBits->cxSrc, + pStretchDIBits->cySrc, + (const BYTE *)mr + pStretchDIBits->offBitsSrc, + (const BITMAPINFO *)((const BYTE *)mr + pStretchDIBits->offBmiSrc), + pStretchDIBits->iUsageSrc, + pStretchDIBits->dwRop); + break; + } + + case EMR_EXTTEXTOUTA: + { + const EMREXTTEXTOUTA *pExtTextOutA = (const EMREXTTEXTOUTA *)mr; + RECT rc; + const INT *dx = NULL; + int old_mode; + + rc.left = pExtTextOutA->emrtext.rcl.left; + rc.top = pExtTextOutA->emrtext.rcl.top; + rc.right = pExtTextOutA->emrtext.rcl.right; + rc.bottom = pExtTextOutA->emrtext.rcl.bottom; + TRACE("EMR_EXTTEXTOUTA: x,y = %d, %d. rect = %d, %d - %d, %d. flags %08x\n", + pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y, + rc.left, rc.top, rc.right, rc.bottom, pExtTextOutA->emrtext.fOptions); + + old_mode = SetGraphicsMode(hdc, pExtTextOutA->iGraphicsMode); + /* Reselect the font back into the dc so that the transformation + gets updated. */ + SelectObject(hdc, GetCurrentObject(hdc, OBJ_FONT)); + + /* Linux version of pstoedit produces EMFs with offDx set to 0. + * These files can be enumerated and played under Win98 just + * fine, but at least Win2k chokes on them. + */ + if (pExtTextOutA->emrtext.offDx) + dx = (const INT *)((const BYTE *)mr + pExtTextOutA->emrtext.offDx); + + ExtTextOutA(hdc, pExtTextOutA->emrtext.ptlReference.x, pExtTextOutA->emrtext.ptlReference.y, + pExtTextOutA->emrtext.fOptions, &rc, + (LPCSTR)((const BYTE *)mr + pExtTextOutA->emrtext.offString), pExtTextOutA->emrtext.nChars, + dx); + + SetGraphicsMode(hdc, old_mode); + break; + } + + case EMR_EXTTEXTOUTW: + { + const EMREXTTEXTOUTW *pExtTextOutW = (const EMREXTTEXTOUTW *)mr; + RECT rc; + const INT *dx = NULL; + int old_mode; + + rc.left = pExtTextOutW->emrtext.rcl.left; + rc.top = pExtTextOutW->emrtext.rcl.top; + rc.right = pExtTextOutW->emrtext.rcl.right; + rc.bottom = pExtTextOutW->emrtext.rcl.bottom; + TRACE("EMR_EXTTEXTOUTW: x,y = %d, %d. rect = %d, %d - %d, %d. flags %08x\n", + pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y, + rc.left, rc.top, rc.right, rc.bottom, pExtTextOutW->emrtext.fOptions); + + old_mode = SetGraphicsMode(hdc, pExtTextOutW->iGraphicsMode); + /* Reselect the font back into the dc so that the transformation + gets updated. */ + SelectObject(hdc, GetCurrentObject(hdc, OBJ_FONT)); + + /* Linux version of pstoedit produces EMFs with offDx set to 0. + * These files can be enumerated and played under Win98 just + * fine, but at least Win2k chokes on them. + */ + if (pExtTextOutW->emrtext.offDx) + dx = (const INT *)((const BYTE *)mr + pExtTextOutW->emrtext.offDx); + + ExtTextOutW(hdc, pExtTextOutW->emrtext.ptlReference.x, pExtTextOutW->emrtext.ptlReference.y, + pExtTextOutW->emrtext.fOptions, &rc, + (LPCWSTR)((const BYTE *)mr + pExtTextOutW->emrtext.offString), pExtTextOutW->emrtext.nChars, + dx); + + SetGraphicsMode(hdc, old_mode); + break; + } + + case EMR_CREATEPALETTE: + { + const EMRCREATEPALETTE *lpCreatePal = (const EMRCREATEPALETTE *)mr; + + (handletable->objectHandle)[ lpCreatePal->ihPal ] = + CreatePalette( &lpCreatePal->lgpl ); + + break; + } + + case EMR_SELECTPALETTE: + { + const EMRSELECTPALETTE *lpSelectPal = (const EMRSELECTPALETTE *)mr; + + if( lpSelectPal->ihPal & 0x80000000 ) { + SelectPalette( hdc, GetStockObject(lpSelectPal->ihPal & 0x7fffffff), TRUE); + } else { + SelectPalette( hdc, (handletable->objectHandle)[lpSelectPal->ihPal], TRUE); + } + break; + } + + case EMR_REALIZEPALETTE: + { + RealizePalette( hdc ); + break; + } + + case EMR_EXTSELECTCLIPRGN: + { + const EMREXTSELECTCLIPRGN *lpRgn = (const EMREXTSELECTCLIPRGN *)mr; + const RGNDATA *pRgnData = (const RGNDATA *)lpRgn->RgnData; + DWORD dwSize = sizeof(RGNDATAHEADER) + pRgnData->rdh.nCount * sizeof(RECT); + HRGN hRgn = 0; + + if (mr->nSize >= sizeof(*lpRgn) + sizeof(RGNDATAHEADER)) + hRgn = ExtCreateRegion( &info->init_transform, dwSize, pRgnData ); + + ExtSelectClipRgn(hdc, hRgn, (INT)(lpRgn->iMode)); + /* ExtSelectClipRgn created a copy of the region */ + DeleteObject(hRgn); + break; + } + + case EMR_SETMETARGN: + { + SetMetaRgn( hdc ); + break; + } + + case EMR_SETWORLDTRANSFORM: + { + const EMRSETWORLDTRANSFORM *lpXfrm = (const EMRSETWORLDTRANSFORM *)mr; + info->state.world_transform = lpXfrm->xform; + break; + } + + case EMR_POLYBEZIER: + { + const EMRPOLYBEZIER *lpPolyBez = (const EMRPOLYBEZIER *)mr; + PolyBezier(hdc, (const POINT*)lpPolyBez->aptl, (UINT)lpPolyBez->cptl); + break; + } + + case EMR_POLYGON: + { + const EMRPOLYGON *lpPoly = (const EMRPOLYGON *)mr; + Polygon( hdc, (const POINT*)lpPoly->aptl, (UINT)lpPoly->cptl ); + break; + } + + case EMR_POLYLINE: + { + const EMRPOLYLINE *lpPolyLine = (const EMRPOLYLINE *)mr; + Polyline(hdc, (const POINT*)lpPolyLine->aptl, (UINT)lpPolyLine->cptl); + break; + } + + case EMR_POLYBEZIERTO: + { + const EMRPOLYBEZIERTO *lpPolyBezierTo = (const EMRPOLYBEZIERTO *)mr; + PolyBezierTo( hdc, (const POINT*)lpPolyBezierTo->aptl, + (UINT)lpPolyBezierTo->cptl ); + break; + } + + case EMR_POLYLINETO: + { + const EMRPOLYLINETO *lpPolyLineTo = (const EMRPOLYLINETO *)mr; + PolylineTo( hdc, (const POINT*)lpPolyLineTo->aptl, + (UINT)lpPolyLineTo->cptl ); + break; + } + + case EMR_POLYPOLYLINE: + { + const EMRPOLYPOLYLINE *pPolyPolyline = (const EMRPOLYPOLYLINE *)mr; + /* NB Points at pPolyPolyline->aPolyCounts + pPolyPolyline->nPolys */ + + PolyPolyline(hdc, (const POINT*)(pPolyPolyline->aPolyCounts + + pPolyPolyline->nPolys), + pPolyPolyline->aPolyCounts, + pPolyPolyline->nPolys ); + + break; + } + + case EMR_POLYPOLYGON: + { + const EMRPOLYPOLYGON *pPolyPolygon = (const EMRPOLYPOLYGON *)mr; + + /* NB Points at pPolyPolygon->aPolyCounts + pPolyPolygon->nPolys */ + + PolyPolygon(hdc, (const POINT*)(pPolyPolygon->aPolyCounts + + pPolyPolygon->nPolys), + (const INT*)pPolyPolygon->aPolyCounts, pPolyPolygon->nPolys ); + break; + } + + case EMR_SETBRUSHORGEX: + { + const EMRSETBRUSHORGEX *lpSetBrushOrgEx = (const EMRSETBRUSHORGEX *)mr; + + SetBrushOrgEx( hdc, + (INT)lpSetBrushOrgEx->ptlOrigin.x, + (INT)lpSetBrushOrgEx->ptlOrigin.y, + NULL ); + + break; + } + + case EMR_SETPIXELV: + { + const EMRSETPIXELV *lpSetPixelV = (const EMRSETPIXELV *)mr; + + SetPixelV( hdc, + (INT)lpSetPixelV->ptlPixel.x, + (INT)lpSetPixelV->ptlPixel.y, + lpSetPixelV->crColor ); + + break; + } + + case EMR_SETMAPPERFLAGS: + { + const EMRSETMAPPERFLAGS *lpSetMapperFlags = (const EMRSETMAPPERFLAGS *)mr; + + SetMapperFlags( hdc, lpSetMapperFlags->dwFlags ); + + break; + } + + case EMR_SETCOLORADJUSTMENT: + { + const EMRSETCOLORADJUSTMENT *lpSetColorAdjust = (const EMRSETCOLORADJUSTMENT *)mr; + + SetColorAdjustment( hdc, &lpSetColorAdjust->ColorAdjustment ); + + break; + } + + case EMR_OFFSETCLIPRGN: + { + const EMROFFSETCLIPRGN *lpOffsetClipRgn = (const EMROFFSETCLIPRGN *)mr; + + OffsetClipRgn( hdc, + (INT)lpOffsetClipRgn->ptlOffset.x, + (INT)lpOffsetClipRgn->ptlOffset.y ); + FIXME("OffsetClipRgn\n"); + + break; + } + + case EMR_EXCLUDECLIPRECT: + { + const EMREXCLUDECLIPRECT *lpExcludeClipRect = (const EMREXCLUDECLIPRECT *)mr; + + ExcludeClipRect( hdc, + lpExcludeClipRect->rclClip.left, + lpExcludeClipRect->rclClip.top, + lpExcludeClipRect->rclClip.right, + lpExcludeClipRect->rclClip.bottom ); + FIXME("ExcludeClipRect\n"); + + break; + } + + case EMR_SCALEVIEWPORTEXTEX: + { + const EMRSCALEVIEWPORTEXTEX *lpScaleViewportExtEx = (const EMRSCALEVIEWPORTEXTEX *)mr; + + if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC)) + break; + if (!lpScaleViewportExtEx->xNum || !lpScaleViewportExtEx->xDenom || + !lpScaleViewportExtEx->yNum || !lpScaleViewportExtEx->yDenom) + break; + info->state.vportExtX = MulDiv(info->state.vportExtX, lpScaleViewportExtEx->xNum, + lpScaleViewportExtEx->xDenom); + info->state.vportExtY = MulDiv(info->state.vportExtY, lpScaleViewportExtEx->yNum, + lpScaleViewportExtEx->yDenom); + if (info->state.vportExtX == 0) info->state.vportExtX = 1; + if (info->state.vportExtY == 0) info->state.vportExtY = 1; + if (info->state.mode == MM_ISOTROPIC) + EMF_FixIsotropic(hdc, info); + + TRACE("EMRSCALEVIEWPORTEXTEX %d/%d %d/%d\n", + lpScaleViewportExtEx->xNum,lpScaleViewportExtEx->xDenom, + lpScaleViewportExtEx->yNum,lpScaleViewportExtEx->yDenom); + + break; + } + + case EMR_SCALEWINDOWEXTEX: + { + const EMRSCALEWINDOWEXTEX *lpScaleWindowExtEx = (const EMRSCALEWINDOWEXTEX *)mr; + + if ((info->state.mode != MM_ISOTROPIC) && (info->state.mode != MM_ANISOTROPIC)) + break; + if (!lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->xDenom || + !lpScaleWindowExtEx->xNum || !lpScaleWindowExtEx->yDenom) + break; + info->state.wndExtX = MulDiv(info->state.wndExtX, lpScaleWindowExtEx->xNum, + lpScaleWindowExtEx->xDenom); + info->state.wndExtY = MulDiv(info->state.wndExtY, lpScaleWindowExtEx->yNum, + lpScaleWindowExtEx->yDenom); + if (info->state.wndExtX == 0) info->state.wndExtX = 1; + if (info->state.wndExtY == 0) info->state.wndExtY = 1; + if (info->state.mode == MM_ISOTROPIC) + EMF_FixIsotropic(hdc, info); + + TRACE("EMRSCALEWINDOWEXTEX %d/%d %d/%d\n", + lpScaleWindowExtEx->xNum,lpScaleWindowExtEx->xDenom, + lpScaleWindowExtEx->yNum,lpScaleWindowExtEx->yDenom); + + break; + } + + case EMR_MODIFYWORLDTRANSFORM: + { + const EMRMODIFYWORLDTRANSFORM *lpModifyWorldTrans = (const EMRMODIFYWORLDTRANSFORM *)mr; + + switch(lpModifyWorldTrans->iMode) { + case MWT_IDENTITY: + info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1; + info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0; + info->state.world_transform.eDx = info->state.world_transform.eDy = 0; + break; + case MWT_LEFTMULTIPLY: + CombineTransform(&info->state.world_transform, &lpModifyWorldTrans->xform, + &info->state.world_transform); + break; + case MWT_RIGHTMULTIPLY: + CombineTransform(&info->state.world_transform, &info->state.world_transform, + &lpModifyWorldTrans->xform); + break; + default: + FIXME("Unknown imode %d\n", lpModifyWorldTrans->iMode); + break; + } + break; + } + + case EMR_ANGLEARC: + { + const EMRANGLEARC *lpAngleArc = (const EMRANGLEARC *)mr; + + AngleArc( hdc, + (INT)lpAngleArc->ptlCenter.x, (INT)lpAngleArc->ptlCenter.y, + lpAngleArc->nRadius, lpAngleArc->eStartAngle, + lpAngleArc->eSweepAngle ); + + break; + } + + case EMR_ROUNDRECT: + { + const EMRROUNDRECT *lpRoundRect = (const EMRROUNDRECT *)mr; + + RoundRect( hdc, + lpRoundRect->rclBox.left, + lpRoundRect->rclBox.top, + lpRoundRect->rclBox.right, + lpRoundRect->rclBox.bottom, + lpRoundRect->szlCorner.cx, + lpRoundRect->szlCorner.cy ); + + break; + } + + case EMR_ARC: + { + const EMRARC *lpArc = (const EMRARC *)mr; + + Arc( hdc, + (INT)lpArc->rclBox.left, + (INT)lpArc->rclBox.top, + (INT)lpArc->rclBox.right, + (INT)lpArc->rclBox.bottom, + (INT)lpArc->ptlStart.x, + (INT)lpArc->ptlStart.y, + (INT)lpArc->ptlEnd.x, + (INT)lpArc->ptlEnd.y ); + + break; + } + + case EMR_CHORD: + { + const EMRCHORD *lpChord = (const EMRCHORD *)mr; + + Chord( hdc, + (INT)lpChord->rclBox.left, + (INT)lpChord->rclBox.top, + (INT)lpChord->rclBox.right, + (INT)lpChord->rclBox.bottom, + (INT)lpChord->ptlStart.x, + (INT)lpChord->ptlStart.y, + (INT)lpChord->ptlEnd.x, + (INT)lpChord->ptlEnd.y ); + + break; + } + + case EMR_PIE: + { + const EMRPIE *lpPie = (const EMRPIE *)mr; + + Pie( hdc, + (INT)lpPie->rclBox.left, + (INT)lpPie->rclBox.top, + (INT)lpPie->rclBox.right, + (INT)lpPie->rclBox.bottom, + (INT)lpPie->ptlStart.x, + (INT)lpPie->ptlStart.y, + (INT)lpPie->ptlEnd.x, + (INT)lpPie->ptlEnd.y ); + + break; + } + + case EMR_ARCTO: + { + const EMRARC *lpArcTo = (const EMRARC *)mr; + + ArcTo( hdc, + (INT)lpArcTo->rclBox.left, + (INT)lpArcTo->rclBox.top, + (INT)lpArcTo->rclBox.right, + (INT)lpArcTo->rclBox.bottom, + (INT)lpArcTo->ptlStart.x, + (INT)lpArcTo->ptlStart.y, + (INT)lpArcTo->ptlEnd.x, + (INT)lpArcTo->ptlEnd.y ); + + break; + } + + case EMR_EXTFLOODFILL: + { + const EMREXTFLOODFILL *lpExtFloodFill = (const EMREXTFLOODFILL *)mr; + + ExtFloodFill( hdc, + (INT)lpExtFloodFill->ptlStart.x, + (INT)lpExtFloodFill->ptlStart.y, + lpExtFloodFill->crColor, + (UINT)lpExtFloodFill->iMode ); + + break; + } + + case EMR_POLYDRAW: + { + const EMRPOLYDRAW *lpPolyDraw = (const EMRPOLYDRAW *)mr; + PolyDraw( hdc, + (const POINT*)lpPolyDraw->aptl, + lpPolyDraw->abTypes, + (INT)lpPolyDraw->cptl ); + + break; + } + + case EMR_SETARCDIRECTION: + { + const EMRSETARCDIRECTION *lpSetArcDirection = (const EMRSETARCDIRECTION *)mr; + SetArcDirection( hdc, (INT)lpSetArcDirection->iArcDirection ); + break; + } + + case EMR_SETMITERLIMIT: + { + const EMRSETMITERLIMIT *lpSetMiterLimit = (const EMRSETMITERLIMIT *)mr; + SetMiterLimit( hdc, lpSetMiterLimit->eMiterLimit, NULL ); + break; + } + + case EMR_BEGINPATH: + { + BeginPath( hdc ); + break; + } + + case EMR_ENDPATH: + { + EndPath( hdc ); + break; + } + + case EMR_CLOSEFIGURE: + { + CloseFigure( hdc ); + break; + } + + case EMR_FILLPATH: + { + /*const EMRFILLPATH lpFillPath = (const EMRFILLPATH *)mr;*/ + FillPath( hdc ); + break; + } + + case EMR_STROKEANDFILLPATH: + { + /*const EMRSTROKEANDFILLPATH lpStrokeAndFillPath = (const EMRSTROKEANDFILLPATH *)mr;*/ + StrokeAndFillPath( hdc ); + break; + } + + case EMR_STROKEPATH: + { + /*const EMRSTROKEPATH lpStrokePath = (const EMRSTROKEPATH *)mr;*/ + StrokePath( hdc ); + break; + } + + case EMR_FLATTENPATH: + { + FlattenPath( hdc ); + break; + } + + case EMR_WIDENPATH: + { + WidenPath( hdc ); + break; + } + + case EMR_SELECTCLIPPATH: + { + const EMRSELECTCLIPPATH *lpSelectClipPath = (const EMRSELECTCLIPPATH *)mr; + SelectClipPath( hdc, (INT)lpSelectClipPath->iMode ); + break; + } + + case EMR_ABORTPATH: + { + AbortPath( hdc ); + break; + } + + case EMR_CREATECOLORSPACE: + { + PEMRCREATECOLORSPACE lpCreateColorSpace = (PEMRCREATECOLORSPACE)mr; + (handletable->objectHandle)[lpCreateColorSpace->ihCS] = + CreateColorSpaceA( &lpCreateColorSpace->lcs ); + break; + } + + case EMR_SETCOLORSPACE: + { + const EMRSETCOLORSPACE *lpSetColorSpace = (const EMRSETCOLORSPACE *)mr; + SetColorSpace( hdc, + (handletable->objectHandle)[lpSetColorSpace->ihCS] ); + break; + } + + case EMR_DELETECOLORSPACE: + { + const EMRDELETECOLORSPACE *lpDeleteColorSpace = (const EMRDELETECOLORSPACE *)mr; + DeleteColorSpace( (handletable->objectHandle)[lpDeleteColorSpace->ihCS] ); + break; + } + + case EMR_SETICMMODE: + { + const EMRSETICMMODE *lpSetICMMode = (const EMRSETICMMODE *)mr; + SetICMMode( hdc, (INT)lpSetICMMode->iMode ); + break; + } + + case EMR_PIXELFORMAT: + { + INT iPixelFormat; + const EMRPIXELFORMAT *lpPixelFormat = (const EMRPIXELFORMAT *)mr; + + iPixelFormat = ChoosePixelFormat( hdc, &lpPixelFormat->pfd ); + SetPixelFormat( hdc, iPixelFormat, &lpPixelFormat->pfd ); + + break; + } + + case EMR_SETPALETTEENTRIES: + { + const EMRSETPALETTEENTRIES *lpSetPaletteEntries = (const EMRSETPALETTEENTRIES *)mr; + + SetPaletteEntries( (handletable->objectHandle)[lpSetPaletteEntries->ihPal], + (UINT)lpSetPaletteEntries->iStart, + (UINT)lpSetPaletteEntries->cEntries, + lpSetPaletteEntries->aPalEntries ); + + break; + } + + case EMR_RESIZEPALETTE: + { + const EMRRESIZEPALETTE *lpResizePalette = (const EMRRESIZEPALETTE *)mr; + + ResizePalette( (handletable->objectHandle)[lpResizePalette->ihPal], + (UINT)lpResizePalette->cEntries ); + + break; + } + + case EMR_CREATEDIBPATTERNBRUSHPT: + { + const EMRCREATEDIBPATTERNBRUSHPT *lpCreate = (const EMRCREATEDIBPATTERNBRUSHPT *)mr; + LPVOID lpPackedStruct; + + /* Check that offsets and data are contained within the record + * (including checking for wrap-arounds). + */ + if ( lpCreate->offBmi + lpCreate->cbBmi > mr->nSize + || lpCreate->offBits + lpCreate->cbBits > mr->nSize + || lpCreate->offBmi + lpCreate->cbBmi < lpCreate->offBmi + || lpCreate->offBits + lpCreate->cbBits < lpCreate->offBits ) + { + ERR("Invalid EMR_CREATEDIBPATTERNBRUSHPT record\n"); + break; + } + + /* This is a BITMAPINFO struct followed directly by bitmap bits */ + lpPackedStruct = HeapAlloc( GetProcessHeap(), 0, + lpCreate->cbBmi + lpCreate->cbBits ); + if(!lpPackedStruct) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + break; + } + + /* Now pack this structure */ + memcpy( lpPackedStruct, + ((const BYTE *)lpCreate) + lpCreate->offBmi, + lpCreate->cbBmi ); + memcpy( ((BYTE*)lpPackedStruct) + lpCreate->cbBmi, + ((const BYTE *)lpCreate) + lpCreate->offBits, + lpCreate->cbBits ); + + (handletable->objectHandle)[lpCreate->ihBrush] = + CreateDIBPatternBrushPt( lpPackedStruct, + (UINT)lpCreate->iUsage ); + + HeapFree(GetProcessHeap(), 0, lpPackedStruct); + break; + } + + case EMR_CREATEMONOBRUSH: + { + const EMRCREATEMONOBRUSH *pCreateMonoBrush = (const EMRCREATEMONOBRUSH *)mr; + const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pCreateMonoBrush->offBmi); + HBITMAP hBmp; + + /* Need to check if the bitmap is monochrome, and if the + two colors are really black and white */ + if (pCreateMonoBrush->iUsage == DIB_PAL_MONO) + { + BITMAP bm; + + /* Undocumented iUsage indicates a mono bitmap with no palette table, + * aligned to 32 rather than 16 bits. + */ + bm.bmType = 0; + bm.bmWidth = pbi->bmiHeader.biWidth; + bm.bmHeight = abs(pbi->bmiHeader.biHeight); + bm.bmWidthBytes = 4 * ((pbi->bmiHeader.biWidth + 31) / 32); + bm.bmPlanes = pbi->bmiHeader.biPlanes; + bm.bmBitsPixel = pbi->bmiHeader.biBitCount; + bm.bmBits = (BYTE *)mr + pCreateMonoBrush->offBits; + hBmp = CreateBitmapIndirect(&bm); + } + else if (is_dib_monochrome(pbi)) + { + /* Top-down DIBs have a negative height */ + LONG height = pbi->bmiHeader.biHeight; + + hBmp = CreateBitmap(pbi->bmiHeader.biWidth, abs(height), 1, 1, NULL); + SetDIBits(hdc, hBmp, 0, pbi->bmiHeader.biHeight, + (const BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage); + } + else + { + hBmp = CreateDIBitmap(hdc, (const BITMAPINFOHEADER *)pbi, CBM_INIT, + (const BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage); + } + + (handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp); + + /* CreatePatternBrush created a copy of the bitmap */ + DeleteObject(hBmp); + break; + } + + case EMR_BITBLT: + { + const EMRBITBLT *pBitBlt = (const EMRBITBLT *)mr; + + if(pBitBlt->offBmiSrc == 0) { /* Record is a PatBlt */ + PatBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest, + pBitBlt->dwRop); + } else { /* BitBlt */ + HDC hdcSrc = CreateCompatibleDC(hdc); + HBRUSH hBrush, hBrushOld; + HBITMAP hBmp = 0, hBmpOld = 0; + const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pBitBlt->offBmiSrc); + + SetWorldTransform(hdcSrc, &pBitBlt->xformSrc); + + hBrush = CreateSolidBrush(pBitBlt->crBkColorSrc); + hBrushOld = SelectObject(hdcSrc, hBrush); + PatBlt(hdcSrc, pBitBlt->rclBounds.left, pBitBlt->rclBounds.top, + pBitBlt->rclBounds.right - pBitBlt->rclBounds.left, + pBitBlt->rclBounds.bottom - pBitBlt->rclBounds.top, PATCOPY); + SelectObject(hdcSrc, hBrushOld); + DeleteObject(hBrush); + + hBmp = CreateDIBitmap(hdc, (const BITMAPINFOHEADER *)pbi, CBM_INIT, + (const BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc); + hBmpOld = SelectObject(hdcSrc, hBmp); + + BitBlt(hdc, pBitBlt->xDest, pBitBlt->yDest, pBitBlt->cxDest, pBitBlt->cyDest, + hdcSrc, pBitBlt->xSrc, pBitBlt->ySrc, pBitBlt->dwRop); + + SelectObject(hdcSrc, hBmpOld); + DeleteObject(hBmp); + DeleteDC(hdcSrc); + } + break; + } + + case EMR_STRETCHBLT: + { + const EMRSTRETCHBLT *pStretchBlt = (const EMRSTRETCHBLT *)mr; + + TRACE("EMR_STRETCHBLT: %d, %d %dx%d -> %d, %d %dx%d. rop %08x offBitsSrc %d\n", + pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc, + pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest, + pStretchBlt->dwRop, pStretchBlt->offBitsSrc); + + if(pStretchBlt->offBmiSrc == 0) { /* Record is a PatBlt */ + PatBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest, + pStretchBlt->dwRop); + } else { /* StretchBlt */ + HDC hdcSrc = CreateCompatibleDC(hdc); + HBRUSH hBrush, hBrushOld; + HBITMAP hBmp = 0, hBmpOld = 0; + const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pStretchBlt->offBmiSrc); + + SetWorldTransform(hdcSrc, &pStretchBlt->xformSrc); + + hBrush = CreateSolidBrush(pStretchBlt->crBkColorSrc); + hBrushOld = SelectObject(hdcSrc, hBrush); + PatBlt(hdcSrc, pStretchBlt->rclBounds.left, pStretchBlt->rclBounds.top, + pStretchBlt->rclBounds.right - pStretchBlt->rclBounds.left, + pStretchBlt->rclBounds.bottom - pStretchBlt->rclBounds.top, PATCOPY); + SelectObject(hdcSrc, hBrushOld); + DeleteObject(hBrush); + + hBmp = CreateDIBitmap(hdc, (const BITMAPINFOHEADER *)pbi, CBM_INIT, + (const BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc); + hBmpOld = SelectObject(hdcSrc, hBmp); + + StretchBlt(hdc, pStretchBlt->xDest, pStretchBlt->yDest, pStretchBlt->cxDest, pStretchBlt->cyDest, + hdcSrc, pStretchBlt->xSrc, pStretchBlt->ySrc, pStretchBlt->cxSrc, pStretchBlt->cySrc, + pStretchBlt->dwRop); + + SelectObject(hdcSrc, hBmpOld); + DeleteObject(hBmp); + DeleteDC(hdcSrc); + } + break; + } + + case EMR_ALPHABLEND: + { + const EMRALPHABLEND *pAlphaBlend = (const EMRALPHABLEND *)mr; + + TRACE("EMR_ALPHABLEND: %d, %d %dx%d -> %d, %d %dx%d. blendfn %08x offBitsSrc %d\n", + pAlphaBlend->xSrc, pAlphaBlend->ySrc, pAlphaBlend->cxSrc, pAlphaBlend->cySrc, + pAlphaBlend->xDest, pAlphaBlend->yDest, pAlphaBlend->cxDest, pAlphaBlend->cyDest, + pAlphaBlend->dwRop, pAlphaBlend->offBitsSrc); + + if(pAlphaBlend->offBmiSrc == 0) { + FIXME("EMR_ALPHABLEND: offBmiSrc == 0\n"); + } else { + HDC hdcSrc = CreateCompatibleDC(hdc); + HBITMAP hBmp = 0, hBmpOld = 0; + const BITMAPINFO *pbi = (const BITMAPINFO *)((const BYTE *)mr + pAlphaBlend->offBmiSrc); + void *bits; + + SetWorldTransform(hdcSrc, &pAlphaBlend->xformSrc); + + hBmp = CreateDIBSection(hdc, pbi, pAlphaBlend->iUsageSrc, &bits, NULL, 0); + memcpy(bits, (const BYTE *)mr + pAlphaBlend->offBitsSrc, pAlphaBlend->cbBitsSrc); + hBmpOld = SelectObject(hdcSrc, hBmp); + + GdiAlphaBlend(hdc, pAlphaBlend->xDest, pAlphaBlend->yDest, pAlphaBlend->cxDest, pAlphaBlend->cyDest, + hdcSrc, pAlphaBlend->xSrc, pAlphaBlend->ySrc, pAlphaBlend->cxSrc, pAlphaBlend->cySrc, + *(BLENDFUNCTION *)&pAlphaBlend->dwRop); + + SelectObject(hdcSrc, hBmpOld); + DeleteObject(hBmp); + DeleteDC(hdcSrc); + } + break; + } + + case EMR_MASKBLT: + { + const EMRMASKBLT *pMaskBlt = (const EMRMASKBLT *)mr; + HDC hdcSrc = CreateCompatibleDC(hdc); + HBRUSH hBrush, hBrushOld; + HBITMAP hBmp, hBmpOld, hBmpMask; + const BITMAPINFO *pbi; + + SetWorldTransform(hdcSrc, &pMaskBlt->xformSrc); + + hBrush = CreateSolidBrush(pMaskBlt->crBkColorSrc); + hBrushOld = SelectObject(hdcSrc, hBrush); + PatBlt(hdcSrc, pMaskBlt->rclBounds.left, pMaskBlt->rclBounds.top, + pMaskBlt->rclBounds.right - pMaskBlt->rclBounds.left, + pMaskBlt->rclBounds.bottom - pMaskBlt->rclBounds.top, PATCOPY); + SelectObject(hdcSrc, hBrushOld); + DeleteObject(hBrush); + + pbi = (const BITMAPINFO *)((const BYTE *)mr + pMaskBlt->offBmiMask); + hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight, + 1, 1, NULL); + SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight, + (const BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask); + + pbi = (const BITMAPINFO *)((const BYTE *)mr + pMaskBlt->offBmiSrc); + hBmp = CreateDIBitmap(hdc, (const BITMAPINFOHEADER *)pbi, CBM_INIT, + (const BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc); + hBmpOld = SelectObject(hdcSrc, hBmp); + MaskBlt(hdc, + pMaskBlt->xDest, + pMaskBlt->yDest, + pMaskBlt->cxDest, + pMaskBlt->cyDest, + hdcSrc, + pMaskBlt->xSrc, + pMaskBlt->ySrc, + hBmpMask, + pMaskBlt->xMask, + pMaskBlt->yMask, + pMaskBlt->dwRop); + SelectObject(hdcSrc, hBmpOld); + DeleteObject(hBmp); + DeleteObject(hBmpMask); + DeleteDC(hdcSrc); + break; + } + + case EMR_PLGBLT: + { + const EMRPLGBLT *pPlgBlt = (const EMRPLGBLT *)mr; + HDC hdcSrc = CreateCompatibleDC(hdc); + HBRUSH hBrush, hBrushOld; + HBITMAP hBmp, hBmpOld, hBmpMask; + const BITMAPINFO *pbi; + POINT pts[3]; + + SetWorldTransform(hdcSrc, &pPlgBlt->xformSrc); + + pts[0].x = pPlgBlt->aptlDest[0].x; pts[0].y = pPlgBlt->aptlDest[0].y; + pts[1].x = pPlgBlt->aptlDest[1].x; pts[1].y = pPlgBlt->aptlDest[1].y; + pts[2].x = pPlgBlt->aptlDest[2].x; pts[2].y = pPlgBlt->aptlDest[2].y; + + hBrush = CreateSolidBrush(pPlgBlt->crBkColorSrc); + hBrushOld = SelectObject(hdcSrc, hBrush); + PatBlt(hdcSrc, pPlgBlt->rclBounds.left, pPlgBlt->rclBounds.top, + pPlgBlt->rclBounds.right - pPlgBlt->rclBounds.left, + pPlgBlt->rclBounds.bottom - pPlgBlt->rclBounds.top, PATCOPY); + SelectObject(hdcSrc, hBrushOld); + DeleteObject(hBrush); + + pbi = (const BITMAPINFO *)((const BYTE *)mr + pPlgBlt->offBmiMask); + hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight, + 1, 1, NULL); + SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight, + (const BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask); + + pbi = (const BITMAPINFO *)((const BYTE *)mr + pPlgBlt->offBmiSrc); + hBmp = CreateDIBitmap(hdc, (const BITMAPINFOHEADER *)pbi, CBM_INIT, + (const BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc); + hBmpOld = SelectObject(hdcSrc, hBmp); + PlgBlt(hdc, + pts, + hdcSrc, + pPlgBlt->xSrc, + pPlgBlt->ySrc, + pPlgBlt->cxSrc, + pPlgBlt->cySrc, + hBmpMask, + pPlgBlt->xMask, + pPlgBlt->yMask); + SelectObject(hdcSrc, hBmpOld); + DeleteObject(hBmp); + DeleteObject(hBmpMask); + DeleteDC(hdcSrc); + break; + } + + case EMR_SETDIBITSTODEVICE: + { + const EMRSETDIBITSTODEVICE *pSetDIBitsToDevice = (const EMRSETDIBITSTODEVICE *)mr; + + SetDIBitsToDevice(hdc, + pSetDIBitsToDevice->xDest, + pSetDIBitsToDevice->yDest, + pSetDIBitsToDevice->cxSrc, + pSetDIBitsToDevice->cySrc, + pSetDIBitsToDevice->xSrc, + pSetDIBitsToDevice->ySrc, + pSetDIBitsToDevice->iStartScan, + pSetDIBitsToDevice->cScans, + (const BYTE *)mr + pSetDIBitsToDevice->offBitsSrc, + (const BITMAPINFO *)((const BYTE *)mr + pSetDIBitsToDevice->offBmiSrc), + pSetDIBitsToDevice->iUsageSrc); + break; + } + + case EMR_POLYTEXTOUTA: + { + const EMRPOLYTEXTOUTA *pPolyTextOutA = (const EMRPOLYTEXTOUTA *)mr; + POLYTEXTA *polytextA = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutA->cStrings * sizeof(POLYTEXTA)); + LONG i; + XFORM xform, xformOld; + int gModeOld; + + gModeOld = SetGraphicsMode(hdc, pPolyTextOutA->iGraphicsMode); + GetWorldTransform(hdc, &xformOld); + + xform.eM11 = pPolyTextOutA->exScale; + xform.eM12 = 0.0; + xform.eM21 = 0.0; + xform.eM22 = pPolyTextOutA->eyScale; + xform.eDx = 0.0; + xform.eDy = 0.0; + SetWorldTransform(hdc, &xform); + + /* Set up POLYTEXTA structures */ + for(i = 0; i < pPolyTextOutA->cStrings; i++) + { + polytextA[i].x = pPolyTextOutA->aemrtext[i].ptlReference.x; + polytextA[i].y = pPolyTextOutA->aemrtext[i].ptlReference.y; + polytextA[i].n = pPolyTextOutA->aemrtext[i].nChars; + polytextA[i].lpstr = (LPCSTR)((const BYTE *)mr + pPolyTextOutA->aemrtext[i].offString); + polytextA[i].uiFlags = pPolyTextOutA->aemrtext[i].fOptions; + polytextA[i].rcl.left = pPolyTextOutA->aemrtext[i].rcl.left; + polytextA[i].rcl.right = pPolyTextOutA->aemrtext[i].rcl.right; + polytextA[i].rcl.top = pPolyTextOutA->aemrtext[i].rcl.top; + polytextA[i].rcl.bottom = pPolyTextOutA->aemrtext[i].rcl.bottom; + polytextA[i].pdx = (int *)((BYTE *)mr + pPolyTextOutA->aemrtext[i].offDx); + } + PolyTextOutA(hdc, polytextA, pPolyTextOutA->cStrings); + HeapFree(GetProcessHeap(), 0, polytextA); + + SetWorldTransform(hdc, &xformOld); + SetGraphicsMode(hdc, gModeOld); + break; + } + + case EMR_POLYTEXTOUTW: + { + const EMRPOLYTEXTOUTW *pPolyTextOutW = (const EMRPOLYTEXTOUTW *)mr; + POLYTEXTW *polytextW = HeapAlloc(GetProcessHeap(), 0, pPolyTextOutW->cStrings * sizeof(POLYTEXTW)); + LONG i; + XFORM xform, xformOld; + int gModeOld; + + gModeOld = SetGraphicsMode(hdc, pPolyTextOutW->iGraphicsMode); + GetWorldTransform(hdc, &xformOld); + + xform.eM11 = pPolyTextOutW->exScale; + xform.eM12 = 0.0; + xform.eM21 = 0.0; + xform.eM22 = pPolyTextOutW->eyScale; + xform.eDx = 0.0; + xform.eDy = 0.0; + SetWorldTransform(hdc, &xform); + + /* Set up POLYTEXTW structures */ + for(i = 0; i < pPolyTextOutW->cStrings; i++) + { + polytextW[i].x = pPolyTextOutW->aemrtext[i].ptlReference.x; + polytextW[i].y = pPolyTextOutW->aemrtext[i].ptlReference.y; + polytextW[i].n = pPolyTextOutW->aemrtext[i].nChars; + polytextW[i].lpstr = (LPCWSTR)((const BYTE *)mr + pPolyTextOutW->aemrtext[i].offString); + polytextW[i].uiFlags = pPolyTextOutW->aemrtext[i].fOptions; + polytextW[i].rcl.left = pPolyTextOutW->aemrtext[i].rcl.left; + polytextW[i].rcl.right = pPolyTextOutW->aemrtext[i].rcl.right; + polytextW[i].rcl.top = pPolyTextOutW->aemrtext[i].rcl.top; + polytextW[i].rcl.bottom = pPolyTextOutW->aemrtext[i].rcl.bottom; + polytextW[i].pdx = (int *)((BYTE *)mr + pPolyTextOutW->aemrtext[i].offDx); + } + PolyTextOutW(hdc, polytextW, pPolyTextOutW->cStrings); + HeapFree(GetProcessHeap(), 0, polytextW); + + SetWorldTransform(hdc, &xformOld); + SetGraphicsMode(hdc, gModeOld); + break; + } + + case EMR_FILLRGN: + { + const EMRFILLRGN *pFillRgn = (const EMRFILLRGN *)mr; + HRGN hRgn = ExtCreateRegion(NULL, pFillRgn->cbRgnData, (const RGNDATA *)pFillRgn->RgnData); + FillRgn(hdc, + hRgn, + (handletable->objectHandle)[pFillRgn->ihBrush]); + DeleteObject(hRgn); + break; + } + + case EMR_FRAMERGN: + { + const EMRFRAMERGN *pFrameRgn = (const EMRFRAMERGN *)mr; + HRGN hRgn = ExtCreateRegion(NULL, pFrameRgn->cbRgnData, (const RGNDATA *)pFrameRgn->RgnData); + FrameRgn(hdc, + hRgn, + (handletable->objectHandle)[pFrameRgn->ihBrush], + pFrameRgn->szlStroke.cx, + pFrameRgn->szlStroke.cy); + DeleteObject(hRgn); + break; + } + + case EMR_INVERTRGN: + { + const EMRINVERTRGN *pInvertRgn = (const EMRINVERTRGN *)mr; + HRGN hRgn = ExtCreateRegion(NULL, pInvertRgn->cbRgnData, (const RGNDATA *)pInvertRgn->RgnData); + InvertRgn(hdc, hRgn); + DeleteObject(hRgn); + break; + } + + case EMR_PAINTRGN: + { + const EMRPAINTRGN *pPaintRgn = (const EMRPAINTRGN *)mr; + HRGN hRgn = ExtCreateRegion(NULL, pPaintRgn->cbRgnData, (const RGNDATA *)pPaintRgn->RgnData); + PaintRgn(hdc, hRgn); + DeleteObject(hRgn); + break; + } + + case EMR_SETTEXTJUSTIFICATION: + { + const EMRSETTEXTJUSTIFICATION *pSetTextJust = (const EMRSETTEXTJUSTIFICATION *)mr; + SetTextJustification(hdc, pSetTextJust->nBreakExtra, pSetTextJust->nBreakCount); + break; + } + + case EMR_SETLAYOUT: + { + const EMRSETLAYOUT *pSetLayout = (const EMRSETLAYOUT *)mr; + SetLayout(hdc, pSetLayout->iMode); + break; + } + + case EMR_POLYDRAW16: + 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: + case EMR_TRANSPARENTBLT: + case EMR_GRADIENTFILL: + case EMR_SETLINKEDUFI: + case EMR_COLORMATCHTOTARGETW: + case EMR_CREATECOLORSPACEW: + + default: + /* From docs: If PlayEnhMetaFileRecord doesn't recognize a + record then ignore and return TRUE. */ + FIXME("type %d is unimplemented\n", type); + break; + } + tmprc.left = tmprc.top = 0; + tmprc.right = tmprc.bottom = 1000; + LPtoDP(hdc, (POINT*)&tmprc, 2); + TRACE("L:0,0 - 1000,1000 -> D:%d,%d - %d,%d\n", tmprc.left, + tmprc.top, tmprc.right, tmprc.bottom); + + return TRUE; +} + + +/***************************************************************************** + * + * EnumEnhMetaFile (GDI32.@) + * + * Walk an enhanced metafile, calling a user-specified function _EnhMetaFunc_ + * for each + * record. Returns when either every record has been used or + * when _EnhMetaFunc_ returns FALSE. + * + * + * RETURNS + * TRUE if every record is used, FALSE if any invocation of _EnhMetaFunc_ + * returns FALSE. + * + * BUGS + * Ignores rect. + * + * NOTES + * This function behaves differently in Win9x and WinNT. + * + * In WinNT, the DC's world transform is updated as the EMF changes + * the Window/Viewport Extent and Origin or its world transform. + * The actual Window/Viewport Extent and Origin are left untouched. + * + * In Win9x, the DC is left untouched, and PlayEnhMetaFileRecord + * updates the scaling itself but only just before a record that + * writes anything to the DC. + * + * I'm not sure where the data (enum_emh_data) is stored in either + * version. For this implementation, it is stored before the handle + * table, but it could be stored in the DC, in the EMF handle or in + * TLS. + * MJM 5 Oct 2002 + */ +BOOL WINAPI EnumEnhMetaFile( + HDC hdc, /* [in] device context to pass to _EnhMetaFunc_ */ + HENHMETAFILE hmf, /* [in] EMF to walk */ + ENHMFENUMPROC callback, /* [in] callback function */ + LPVOID data, /* [in] optional data for callback function */ + const RECT *lpRect /* [in] bounding rectangle for rendered metafile */ + ) +{ + BOOL ret; + ENHMETAHEADER *emh; + ENHMETARECORD *emr; + DWORD offset; + UINT i; + HANDLETABLE *ht; + INT savedMode = 0; + XFORM savedXform; + HPEN hPen = NULL; + HBRUSH hBrush = NULL; + HFONT hFont = NULL; + HRGN hRgn = NULL; + enum_emh_data *info; + SIZE vp_size, win_size; + POINT vp_org, win_org; + INT mapMode = MM_TEXT, old_align = 0, old_rop2 = 0, old_arcdir = 0, old_polyfill = 0, old_stretchblt = 0; + COLORREF old_text_color = 0, old_bk_color = 0; + + if(!lpRect && hdc) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + emh = EMF_GetEnhMetaHeader(hmf); + if(!emh) { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + + info = HeapAlloc( GetProcessHeap(), 0, + sizeof (enum_emh_data) + sizeof(HANDLETABLE) * emh->nHandles ); + if(!info) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + info->state.wndOrgX = 0; + info->state.wndOrgY = 0; + info->state.wndExtX = 1; + info->state.wndExtY = 1; + info->state.vportOrgX = 0; + info->state.vportOrgY = 0; + info->state.vportExtX = 1; + info->state.vportExtY = 1; + info->state.world_transform.eM11 = info->state.world_transform.eM22 = 1; + info->state.world_transform.eM12 = info->state.world_transform.eM21 = 0; + info->state.world_transform.eDx = info->state.world_transform.eDy = 0; + + info->state.next = NULL; + info->save_level = 0; + info->saved_state = NULL; + + ht = (HANDLETABLE*) &info[1]; + ht->objectHandle[0] = hmf; + for(i = 1; i < emh->nHandles; i++) + ht->objectHandle[i] = NULL; + + if(hdc) + { + savedMode = SetGraphicsMode(hdc, GM_ADVANCED); + GetWorldTransform(hdc, &savedXform); + GetViewportExtEx(hdc, &vp_size); + GetWindowExtEx(hdc, &win_size); + GetViewportOrgEx(hdc, &vp_org); + GetWindowOrgEx(hdc, &win_org); + mapMode = GetMapMode(hdc); + + /* save DC */ + hPen = GetCurrentObject(hdc, OBJ_PEN); + hBrush = GetCurrentObject(hdc, OBJ_BRUSH); + hFont = GetCurrentObject(hdc, OBJ_FONT); + + hRgn = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(hdc, hRgn)) + { + DeleteObject(hRgn); + hRgn = 0; + } + + old_text_color = SetTextColor(hdc, RGB(0,0,0)); + old_bk_color = SetBkColor(hdc, RGB(0xff, 0xff, 0xff)); + old_align = SetTextAlign(hdc, 0); + old_rop2 = SetROP2(hdc, R2_COPYPEN); + old_arcdir = SetArcDirection(hdc, AD_COUNTERCLOCKWISE); + old_polyfill = SetPolyFillMode(hdc, ALTERNATE); + old_stretchblt = SetStretchBltMode(hdc, BLACKONWHITE); + } + + info->state.mode = MM_TEXT; + + 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 + { + /* WinNT combines the vp/win ext/org info into a transform */ + double xscale, yscale; + xscale = (double)vp_size.cx / (double)win_size.cx; + yscale = (double)vp_size.cy / (double)win_size.cy; + info->init_transform.eM11 = xscale; + info->init_transform.eM12 = 0.0; + info->init_transform.eM21 = 0.0; + info->init_transform.eM22 = yscale; + info->init_transform.eDx = (double)vp_org.x - xscale * (double)win_org.x; + info->init_transform.eDy = (double)vp_org.y - yscale * (double)win_org.y; + + CombineTransform(&info->init_transform, &savedXform, &info->init_transform); + } + + if ( lpRect && WIDTH(emh->rclFrame) && HEIGHT(emh->rclFrame) ) + { + double xSrcPixSize, ySrcPixSize, xscale, yscale; + XFORM xform; + + TRACE("rect: %d,%d - %d,%d. rclFrame: %d,%d - %d,%d\n", + lpRect->left, lpRect->top, lpRect->right, lpRect->bottom, + emh->rclFrame.left, emh->rclFrame.top, emh->rclFrame.right, + emh->rclFrame.bottom); + + xSrcPixSize = (double) emh->szlMillimeters.cx / emh->szlDevice.cx; + ySrcPixSize = (double) emh->szlMillimeters.cy / emh->szlDevice.cy; + xscale = (double) WIDTH(*lpRect) * 100.0 / + WIDTH(emh->rclFrame) * xSrcPixSize; + yscale = (double) HEIGHT(*lpRect) * 100.0 / + HEIGHT(emh->rclFrame) * ySrcPixSize; + TRACE("xscale = %f, yscale = %f\n", xscale, yscale); + + xform.eM11 = xscale; + xform.eM12 = 0; + xform.eM21 = 0; + xform.eM22 = yscale; + xform.eDx = (double) lpRect->left - (double) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left; + xform.eDy = (double) lpRect->top - (double) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top; + + CombineTransform(&info->init_transform, &xform, &info->init_transform); + } + + /* WinNT resets the current vp/win org/ext */ + if ( !IS_WIN9X() && hdc ) + { + SetMapMode(hdc, MM_TEXT); + SetWindowOrgEx(hdc, 0, 0, NULL); + SetViewportOrgEx(hdc, 0, 0, NULL); + EMF_Update_MF_Xform(hdc, info); + } + + ret = TRUE; + offset = 0; + while(ret && offset < emh->nBytes) + { + emr = (ENHMETARECORD *)((char *)emh + offset); + + /* 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); + + TRACE("Calling EnumFunc with record %s, size %d\n", get_emr_name(emr->iType), emr->nSize); + ret = (*callback)(hdc, ht, emr, emh->nHandles, (LPARAM)data); + offset += emr->nSize; + + /* WinNT - update the transform (win9x updates when the next graphics + output record is played). */ + if (hdc && !IS_WIN9X()) + EMF_Update_MF_Xform(hdc, info); + } + + if (hdc) + { + SetStretchBltMode(hdc, old_stretchblt); + SetPolyFillMode(hdc, old_polyfill); + SetArcDirection(hdc, old_arcdir); + SetROP2(hdc, old_rop2); + SetTextAlign(hdc, old_align); + SetBkColor(hdc, old_bk_color); + SetTextColor(hdc, old_text_color); + + /* restore DC */ + SelectObject(hdc, hBrush); + SelectObject(hdc, hPen); + SelectObject(hdc, hFont); + ExtSelectClipRgn(hdc, hRgn, RGN_COPY); + DeleteObject(hRgn); + + SetWorldTransform(hdc, &savedXform); + if (savedMode) + SetGraphicsMode(hdc, savedMode); + SetMapMode(hdc, mapMode); + SetWindowOrgEx(hdc, win_org.x, win_org.y, NULL); + SetWindowExtEx(hdc, win_size.cx, win_size.cy, NULL); + SetViewportOrgEx(hdc, vp_org.x, vp_org.y, NULL); + SetViewportExtEx(hdc, vp_size.cx, vp_size.cy, NULL); + } + + for(i = 1; i < emh->nHandles; i++) /* Don't delete element 0 (hmf) */ + if( (ht->objectHandle)[i] ) + DeleteObject( (ht->objectHandle)[i] ); + + while (info->saved_state) + { + EMF_dc_state *state = info->saved_state; + info->saved_state = info->saved_state->next; + HeapFree( GetProcessHeap(), 0, state ); + } + HeapFree( GetProcessHeap(), 0, info ); + return ret; +} + +static INT CALLBACK EMF_PlayEnhMetaFileCallback(HDC hdc, HANDLETABLE *ht, + const ENHMETARECORD *emr, + INT handles, LPARAM data) +{ + return PlayEnhMetaFileRecord(hdc, ht, emr, handles); +} + +/************************************************************************** + * PlayEnhMetaFile (GDI32.@) + * + * Renders an enhanced metafile into a specified rectangle *lpRect + * in device context hdc. + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI PlayEnhMetaFile( + HDC hdc, /* [in] DC to render into */ + HENHMETAFILE hmf, /* [in] metafile to render */ + const RECT *lpRect /* [in] rectangle to place metafile inside */ + ) +{ + return EnumEnhMetaFile(hdc, hmf, EMF_PlayEnhMetaFileCallback, NULL, + lpRect); +} + +/***************************************************************************** + * DeleteEnhMetaFile (GDI32.@) + * + * Deletes an enhanced metafile and frees the associated storage. + */ +BOOL WINAPI DeleteEnhMetaFile(HENHMETAFILE hmf) +{ + return EMF_Delete_HENHMETAFILE( hmf ); +} + +/***************************************************************************** + * CopyEnhMetaFileA (GDI32.@) + * + * Duplicate an enhanced metafile. + * + * + */ +HENHMETAFILE WINAPI CopyEnhMetaFileA( + HENHMETAFILE hmfSrc, + LPCSTR file) +{ + ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst; + HENHMETAFILE hmfDst; + + if(!emrSrc) return FALSE; + if (!file) { + emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes ); + memcpy( emrDst, emrSrc, emrSrc->nBytes ); + hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE ); + if (!hmfDst) + HeapFree( GetProcessHeap(), 0, emrDst ); + } else { + HANDLE hFile; + DWORD w; + hFile = CreateFileA( file, GENERIC_WRITE | GENERIC_READ, 0, + NULL, CREATE_ALWAYS, 0, 0); + WriteFile( hFile, emrSrc, emrSrc->nBytes, &w, NULL); + CloseHandle( hFile ); + /* Reopen file for reading only, so that apps can share + read access to the file while hmf is still valid */ + hFile = CreateFileA( file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0); + if(hFile == INVALID_HANDLE_VALUE) { + ERR("Can't reopen emf for reading\n"); + return 0; + } + hmfDst = EMF_GetEnhMetaFile( hFile ); + CloseHandle( hFile ); + } + return hmfDst; +} + +/***************************************************************************** + * CopyEnhMetaFileW (GDI32.@) + * + * See CopyEnhMetaFileA. + * + * + */ +HENHMETAFILE WINAPI CopyEnhMetaFileW( + HENHMETAFILE hmfSrc, + LPCWSTR file) +{ + ENHMETAHEADER *emrSrc = EMF_GetEnhMetaHeader( hmfSrc ), *emrDst; + HENHMETAFILE hmfDst; + + if(!emrSrc) return FALSE; + if (!file) { + emrDst = HeapAlloc( GetProcessHeap(), 0, emrSrc->nBytes ); + memcpy( emrDst, emrSrc, emrSrc->nBytes ); + hmfDst = EMF_Create_HENHMETAFILE( emrDst, FALSE ); + if (!hmfDst) + HeapFree( GetProcessHeap(), 0, emrDst ); + } else { + HANDLE hFile; + DWORD w; + hFile = CreateFileW( file, GENERIC_WRITE | GENERIC_READ, 0, + NULL, CREATE_ALWAYS, 0, 0); + WriteFile( hFile, emrSrc, emrSrc->nBytes, &w, NULL); + CloseHandle( hFile ); + /* Reopen file for reading only, so that apps can share + read access to the file while hmf is still valid */ + hFile = CreateFileW( file, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0); + if(hFile == INVALID_HANDLE_VALUE) { + ERR("Can't reopen emf for reading\n"); + return 0; + } + hmfDst = EMF_GetEnhMetaFile( hFile ); + CloseHandle( hFile ); + } + return hmfDst; +} + + +/* Struct to be used to be passed in the LPVOID parameter for cbEnhPaletteCopy */ +typedef struct tagEMF_PaletteCopy +{ + UINT cEntries; + LPPALETTEENTRY lpPe; +} EMF_PaletteCopy; + +/*************************************************************** + * Find the EMR_EOF record and then use it to find the + * palette entries for this enhanced metafile. + * The lpData is actually a pointer to an EMF_PaletteCopy struct + * which contains the max number of elements to copy and where + * to copy them to. + * + * NOTE: To be used by GetEnhMetaFilePaletteEntries only! + */ +static INT CALLBACK cbEnhPaletteCopy( HDC a, + HANDLETABLE *b, + const ENHMETARECORD *lpEMR, + INT c, + LPARAM lpData ) +{ + + if ( lpEMR->iType == EMR_EOF ) + { + const EMREOF *lpEof = (const EMREOF *)lpEMR; + EMF_PaletteCopy* info = (EMF_PaletteCopy*)lpData; + DWORD dwNumPalToCopy = min( lpEof->nPalEntries, info->cEntries ); + + TRACE( "copying 0x%08x palettes\n", dwNumPalToCopy ); + + memcpy( info->lpPe, (LPCSTR)lpEof + lpEof->offPalEntries, + sizeof( *(info->lpPe) ) * dwNumPalToCopy ); + + /* Update the passed data as a return code */ + info->lpPe = NULL; /* Palettes were copied! */ + info->cEntries = dwNumPalToCopy; + + return FALSE; /* That's all we need */ + } + + return TRUE; +} + +/***************************************************************************** + * GetEnhMetaFilePaletteEntries (GDI32.@) + * + * Copy the palette and report size + * + * BUGS: Error codes (SetLastError) are not set on failures + */ +UINT WINAPI GetEnhMetaFilePaletteEntries( HENHMETAFILE hEmf, + UINT cEntries, + LPPALETTEENTRY lpPe ) +{ + ENHMETAHEADER* enhHeader = EMF_GetEnhMetaHeader( hEmf ); + EMF_PaletteCopy infoForCallBack; + + TRACE( "(%p,%d,%p)\n", hEmf, cEntries, lpPe ); + + if (!enhHeader) return 0; + + /* First check if there are any palettes associated with + this metafile. */ + if ( enhHeader->nPalEntries == 0 ) return 0; + + /* Is the user requesting the number of palettes? */ + if ( lpPe == NULL ) return enhHeader->nPalEntries; + + /* Copy cEntries worth of PALETTEENTRY structs into the buffer */ + infoForCallBack.cEntries = cEntries; + infoForCallBack.lpPe = lpPe; + + if ( !EnumEnhMetaFile( 0, hEmf, cbEnhPaletteCopy, + &infoForCallBack, 0 ) ) + return GDI_ERROR; + + /* Verify that the callback executed correctly */ + if ( infoForCallBack.lpPe != NULL ) + { + /* Callback proc had error! */ + ERR( "cbEnhPaletteCopy didn't execute correctly\n" ); + return GDI_ERROR; + } + + return infoForCallBack.cEntries; +} + +typedef struct gdi_mf_comment +{ + DWORD ident; + DWORD iComment; + DWORD nVersion; + DWORD nChecksum; + DWORD fFlags; + DWORD cbWinMetaFile; +} gdi_mf_comment; + +/****************************************************************** + * SetWinMetaFileBits (GDI32.@) + * + * Translate from old style to new style. + * + */ +HENHMETAFILE WINAPI SetWinMetaFileBits(UINT cbBuffer, const BYTE *lpbBuffer, HDC hdcRef, + const METAFILEPICT *lpmfp) +{ + static const WCHAR szDisplayW[] = { 'D','I','S','P','L','A','Y','\0' }; + HMETAFILE hmf = NULL; + HENHMETAFILE ret = NULL; + HDC hdc = NULL, hdcdisp = NULL; + RECT rc, *prcFrame = NULL; + LONG mm, xExt, yExt; + INT horzsize, vertsize, horzres, vertres; + + TRACE("(%d, %p, %p, %p)\n", cbBuffer, lpbBuffer, hdcRef, lpmfp); + + hmf = SetMetaFileBitsEx(cbBuffer, lpbBuffer); + if(!hmf) + { + WARN("SetMetaFileBitsEx failed\n"); + return NULL; + } + + if(!hdcRef) + hdcRef = hdcdisp = CreateDCW(szDisplayW, NULL, NULL, NULL); + + if (lpmfp) + { + TRACE("mm = %d %dx%d\n", lpmfp->mm, lpmfp->xExt, lpmfp->yExt); + + mm = lpmfp->mm; + xExt = lpmfp->xExt; + yExt = lpmfp->yExt; + } + else + { + TRACE("lpmfp == NULL\n"); + + /* Use the whole device surface */ + mm = MM_ANISOTROPIC; + xExt = 0; + yExt = 0; + } + + if (mm == MM_ISOTROPIC || mm == MM_ANISOTROPIC) + { + if (xExt < 0 || yExt < 0) + { + /* Use the whole device surface */ + xExt = 0; + yExt = 0; + } + + /* Use the x and y extents as the frame box */ + if (xExt && yExt) + { + rc.left = rc.top = 0; + rc.right = xExt; + rc.bottom = yExt; + prcFrame = &rc; + } + } + + if(!(hdc = CreateEnhMetaFileW(hdcRef, NULL, prcFrame, NULL))) + { + ERR("CreateEnhMetaFile failed\n"); + goto end; + } + + /* + * Write the original METAFILE into the enhanced metafile. + * It is encapsulated in a GDICOMMENT_WINDOWS_METAFILE record. + */ + if (mm != MM_TEXT) + { + gdi_mf_comment *mfcomment; + UINT mfcomment_size; + + mfcomment_size = sizeof (gdi_mf_comment) + cbBuffer; + mfcomment = HeapAlloc(GetProcessHeap(), 0, mfcomment_size); + if (mfcomment) + { + mfcomment->ident = GDICOMMENT_IDENTIFIER; + mfcomment->iComment = GDICOMMENT_WINDOWS_METAFILE; + mfcomment->nVersion = 0x00000300; + mfcomment->nChecksum = 0; /* FIXME */ + mfcomment->fFlags = 0; + mfcomment->cbWinMetaFile = cbBuffer; + memcpy(&mfcomment[1], lpbBuffer, cbBuffer); + GdiComment(hdc, mfcomment_size, (BYTE*) mfcomment); + HeapFree(GetProcessHeap(), 0, mfcomment); + } + SetMapMode(hdc, mm); + } + + + horzsize = GetDeviceCaps(hdcRef, HORZSIZE); + vertsize = GetDeviceCaps(hdcRef, VERTSIZE); + horzres = GetDeviceCaps(hdcRef, HORZRES); + vertres = GetDeviceCaps(hdcRef, VERTRES); + + if (!xExt || !yExt) + { + /* Use the whole device surface */ + xExt = horzres; + yExt = vertres; + } + else + { + xExt = MulDiv(xExt, horzres, 100 * horzsize); + yExt = MulDiv(yExt, vertres, 100 * vertsize); + } + + /* set the initial viewport:window ratio as 1:1 */ + SetViewportExtEx(hdc, xExt, yExt, NULL); + SetWindowExtEx(hdc, xExt, yExt, NULL); + + PlayMetaFile(hdc, hmf); + + ret = CloseEnhMetaFile(hdc); +end: + if (hdcdisp) DeleteDC(hdcdisp); + DeleteMetaFile(hmf); + return ret; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/bitblt.c b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/bitblt.c new file mode 100644 index 00000000000..db0274d8efa --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/bitblt.c @@ -0,0 +1,267 @@ +/* + * Enhanced MetaFile driver BitBlt functions + * + * Copyright 2002 Huw D M Davies 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 +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "enhmetafiledrv.h" +#include "wine/debug.h" + +BOOL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) +{ + EMRBITBLT emr; + BOOL ret; + + emr.emr.iType = EMR_BITBLT; + emr.emr.nSize = sizeof(emr); + emr.rclBounds.left = dst->log_x; + emr.rclBounds.top = dst->log_y; + emr.rclBounds.right = dst->log_x + dst->log_width - 1; + emr.rclBounds.bottom = dst->log_y + dst->log_height - 1; + emr.xDest = dst->log_x; + emr.yDest = dst->log_y; + emr.cxDest = dst->log_width; + emr.cyDest = dst->log_height; + emr.dwRop = rop; + emr.xSrc = 0; + emr.ySrc = 0; + emr.xformSrc.eM11 = 1.0; + emr.xformSrc.eM12 = 0.0; + emr.xformSrc.eM21 = 0.0; + emr.xformSrc.eM22 = 1.0; + emr.xformSrc.eDx = 0.0; + emr.xformSrc.eDy = 0.0; + emr.crBkColorSrc = 0; + emr.iUsageSrc = 0; + emr.offBmiSrc = 0; + emr.cbBmiSrc = 0; + emr.offBitsSrc = 0; + emr.cbBitsSrc = 0; + + ret = EMFDRV_WriteRecord( dev, &emr.emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr.rclBounds ); + return ret; +} + +BOOL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, + PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) +{ + BOOL ret; + PEMRBITBLT pEMR; + UINT emrSize; + UINT bmiSize; + UINT bitsSize; + UINT size; + BITMAP BM; + WORD nBPP = 0; + LPBITMAPINFOHEADER lpBmiH; + HBITMAP hBitmap = NULL; + DWORD emrType; + + if (devSrc->funcs == devDst->funcs) return FALSE; /* can't use a metafile DC as source */ + + if (src->log_width == dst->log_width && src->log_height == dst->log_height) + { + emrType = EMR_BITBLT; + emrSize = sizeof(EMRBITBLT); + } + else + { + emrType = EMR_STRETCHBLT; + emrSize = sizeof(EMRSTRETCHBLT); + } + + hBitmap = GetCurrentObject(devSrc->hdc, OBJ_BITMAP); + + if(sizeof(BITMAP) != GetObjectW(hBitmap, sizeof(BITMAP), &BM)) + return FALSE; + + nBPP = BM.bmPlanes * BM.bmBitsPixel; + if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ + bitsSize = get_dib_stride( BM.bmWidth, nBPP ) * BM.bmHeight; + bmiSize = sizeof(BITMAPINFOHEADER) + + (nBPP <= 8 ? 1 << nBPP : 0) * sizeof(RGBQUAD); + + size = emrSize + bmiSize + bitsSize; + + pEMR = HeapAlloc(GetProcessHeap(), 0, size); + if (!pEMR) return FALSE; + + /* Initialize EMR */ + pEMR->emr.iType = emrType; + pEMR->emr.nSize = size; + pEMR->rclBounds.left = dst->log_x; + pEMR->rclBounds.top = dst->log_y; + pEMR->rclBounds.right = dst->log_x + dst->log_width - 1; + pEMR->rclBounds.bottom = dst->log_y + dst->log_height - 1; + pEMR->xDest = dst->log_x; + pEMR->yDest = dst->log_y; + pEMR->cxDest = dst->log_width; + pEMR->cyDest = dst->log_height; + pEMR->dwRop = rop; + pEMR->xSrc = src->log_x; + pEMR->ySrc = src->log_y; + GetWorldTransform(devSrc->hdc, &pEMR->xformSrc); + pEMR->crBkColorSrc = GetBkColor(devSrc->hdc); + pEMR->iUsageSrc = DIB_RGB_COLORS; + pEMR->offBmiSrc = emrSize; + pEMR->offBitsSrc = emrSize + bmiSize; + pEMR->cbBmiSrc = bmiSize; + pEMR->cbBitsSrc = bitsSize; + if (emrType == EMR_STRETCHBLT) + { + PEMRSTRETCHBLT pEMRStretch = (PEMRSTRETCHBLT)pEMR; + pEMRStretch->cxSrc = src->log_width; + pEMRStretch->cySrc = src->log_height; + } + + /* Initialize BITMAPINFO structure */ + lpBmiH = (LPBITMAPINFOHEADER)((BYTE*)pEMR + pEMR->offBmiSrc); + + lpBmiH->biSize = sizeof(BITMAPINFOHEADER); + lpBmiH->biWidth = BM.bmWidth; + lpBmiH->biHeight = BM.bmHeight; + lpBmiH->biPlanes = BM.bmPlanes; + lpBmiH->biBitCount = nBPP; + /* Assume the bitmap isn't compressed and set the BI_RGB flag. */ + lpBmiH->biCompression = BI_RGB; + lpBmiH->biSizeImage = bitsSize; + lpBmiH->biYPelsPerMeter = 0; + lpBmiH->biXPelsPerMeter = 0; + lpBmiH->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; + /* Set biClrImportant to 0, indicating that all of the + device colors are important. */ + lpBmiH->biClrImportant = 0; + + /* Initialize bitmap bits */ + if (GetDIBits(devSrc->hdc, hBitmap, 0, (UINT)lpBmiH->biHeight, + (BYTE*)pEMR + pEMR->offBitsSrc, + (LPBITMAPINFO)lpBmiH, DIB_RGB_COLORS)) + { + ret = EMFDRV_WriteRecord(devDst, (EMR*)pEMR); + if (ret) EMFDRV_UpdateBBox(devDst, &(pEMR->rclBounds)); + } + else + ret = FALSE; + + HeapFree( GetProcessHeap(), 0, pEMR); + return ret; +} + +INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, + INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits, + BITMAPINFO *info, UINT wUsage, DWORD dwRop ) +{ + EMRSTRETCHDIBITS *emr; + BOOL ret; + UINT bmi_size, emr_size; + + /* calculate the size of the colour table */ + bmi_size = get_dib_info_size(info, wUsage); + + emr_size = sizeof (EMRSTRETCHDIBITS) + bmi_size + info->bmiHeader.biSizeImage; + emr = HeapAlloc(GetProcessHeap(), 0, emr_size ); + if (!emr) return 0; + + /* write a bitmap info header (with colours) to the record */ + memcpy( &emr[1], info, bmi_size); + + /* write bitmap bits to the record */ + memcpy ( ( (BYTE *) (&emr[1]) ) + bmi_size, bits, 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 = xDst; + emr->yDest = yDst; + emr->cxDest = widthDst; + emr->cyDest = heightDst; + emr->dwRop = dwRop; + emr->xSrc = xSrc; /* FIXME: only save the piece of the bitmap needed */ + emr->ySrc = ySrc; + + emr->iUsageSrc = wUsage; + emr->offBmiSrc = sizeof (EMRSTRETCHDIBITS); + emr->cbBmiSrc = bmi_size; + emr->offBitsSrc = emr->offBmiSrc + bmi_size; + emr->cbBitsSrc = info->bmiHeader.biSizeImage; + + emr->cxSrc = widthSrc; + emr->cySrc = heightSrc; + + emr->rclBounds.left = xDst; + emr->rclBounds.top = yDst; + emr->rclBounds.right = xDst + widthDst; + emr->rclBounds.bottom = yDst + heightDst; + + /* save the record we just created */ + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + + HeapFree(GetProcessHeap(), 0, emr); + + return ret ? heightSrc : GDI_ERROR; +} + +INT EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD width, DWORD height, + INT xSrc, INT ySrc, UINT startscan, UINT lines, + LPCVOID bits, BITMAPINFO *info, UINT wUsage ) +{ + EMRSETDIBITSTODEVICE* pEMR; + DWORD bmiSize = get_dib_info_size(info, wUsage); + DWORD size = sizeof(EMRSETDIBITSTODEVICE) + bmiSize + info->bmiHeader.biSizeImage; + + pEMR = HeapAlloc(GetProcessHeap(), 0, size); + if (!pEMR) return 0; + + pEMR->emr.iType = EMR_SETDIBITSTODEVICE; + pEMR->emr.nSize = size; + pEMR->rclBounds.left = xDst; + pEMR->rclBounds.top = yDst; + pEMR->rclBounds.right = xDst + width - 1; + pEMR->rclBounds.bottom = yDst + height - 1; + pEMR->xDest = xDst; + pEMR->yDest = yDst; + pEMR->xSrc = xSrc; + pEMR->ySrc = ySrc; + pEMR->cxSrc = width; + pEMR->cySrc = height; + pEMR->offBmiSrc = sizeof(EMRSETDIBITSTODEVICE); + pEMR->cbBmiSrc = bmiSize; + pEMR->offBitsSrc = sizeof(EMRSETDIBITSTODEVICE) + bmiSize; + pEMR->cbBitsSrc = info->bmiHeader.biSizeImage; + pEMR->iUsageSrc = wUsage; + pEMR->iStartScan = startscan; + pEMR->cScans = lines; + memcpy((BYTE*)pEMR + pEMR->offBmiSrc, info, bmiSize); + memcpy((BYTE*)pEMR + pEMR->offBitsSrc, bits, info->bmiHeader.biSizeImage); + + if (EMFDRV_WriteRecord(dev, (EMR*)pEMR)) + EMFDRV_UpdateBBox(dev, &(pEMR->rclBounds)); + + HeapFree( GetProcessHeap(), 0, pEMR); + return lines; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/dc.c b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/dc.c new file mode 100644 index 00000000000..cbf3f5c2fd9 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/dc.c @@ -0,0 +1,531 @@ +/* + * Enhanced MetaFile driver dc value functions + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "enhmfdrv/enhmetafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +INT EMFDRV_SaveDC( PHYSDEV dev ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSaveDC ); + INT ret = next->funcs->pSaveDC( next ); + + if (ret) + { + EMRSAVEDC emr; + emr.emr.iType = EMR_SAVEDC; + emr.emr.nSize = sizeof(emr); + EMFDRV_WriteRecord( dev, &emr.emr ); + } + return ret; +} + +BOOL EMFDRV_RestoreDC( PHYSDEV dev, INT level ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pRestoreDC ); + EMFDRV_PDEVICE* physDev = (EMFDRV_PDEVICE*)dev; + DC *dc = get_dc_ptr( dev->hdc ); + EMRRESTOREDC emr; + BOOL ret; + + emr.emr.iType = EMR_RESTOREDC; + emr.emr.nSize = sizeof(emr); + + if (level < 0) + emr.iRelative = level; + else + emr.iRelative = level - dc->saveLevel - 1; + release_dc_ptr( dc ); + + physDev->restoring++; + ret = next->funcs->pRestoreDC( next, level ); + physDev->restoring--; + + if (ret) EMFDRV_WriteRecord( dev, &emr.emr ); + return ret; +} + +UINT EMFDRV_SetTextAlign( PHYSDEV dev, UINT align ) +{ + EMRSETTEXTALIGN emr; + emr.emr.iType = EMR_SETTEXTALIGN; + emr.emr.nSize = sizeof(emr); + emr.iMode = align; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? align : GDI_ERROR; +} + +BOOL EMFDRV_SetTextJustification(PHYSDEV dev, INT nBreakExtra, INT nBreakCount) +{ + EMRSETTEXTJUSTIFICATION emr; + emr.emr.iType = EMR_SETTEXTJUSTIFICATION; + emr.emr.nSize = sizeof(emr); + emr.nBreakExtra = nBreakExtra; + emr.nBreakCount = nBreakCount; + return EMFDRV_WriteRecord(dev, &emr.emr); +} + +INT EMFDRV_SetBkMode( PHYSDEV dev, INT mode ) +{ + EMRSETBKMODE emr; + emr.emr.iType = EMR_SETBKMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? mode : 0; +} + +COLORREF EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) +{ + EMRSETBKCOLOR emr; + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + + if (physDev->restoring) return color; /* don't output records during RestoreDC */ + + emr.emr.iType = EMR_SETBKCOLOR; + emr.emr.nSize = sizeof(emr); + emr.crColor = color; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID; +} + + +COLORREF EMFDRV_SetTextColor( PHYSDEV dev, COLORREF color ) +{ + EMRSETTEXTCOLOR emr; + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + + if (physDev->restoring) return color; /* don't output records during RestoreDC */ + + emr.emr.iType = EMR_SETTEXTCOLOR; + emr.emr.nSize = sizeof(emr); + emr.crColor = color; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID; +} + +INT EMFDRV_SetROP2( PHYSDEV dev, INT rop ) +{ + EMRSETROP2 emr; + emr.emr.iType = EMR_SETROP2; + emr.emr.nSize = sizeof(emr); + emr.iMode = rop; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? rop : 0; +} + +INT EMFDRV_SetPolyFillMode( PHYSDEV dev, INT mode ) +{ + EMRSETPOLYFILLMODE emr; + emr.emr.iType = EMR_SETPOLYFILLMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? mode : 0; +} + +INT EMFDRV_SetStretchBltMode( PHYSDEV dev, INT mode ) +{ + EMRSETSTRETCHBLTMODE emr; + emr.emr.iType = EMR_SETSTRETCHBLTMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? mode : 0; +} + +INT EMFDRV_SetArcDirection(PHYSDEV dev, INT arcDirection) +{ + EMRSETARCDIRECTION emr; + + emr.emr.iType = EMR_SETARCDIRECTION; + emr.emr.nSize = sizeof(emr); + emr.iArcDirection = arcDirection; + return EMFDRV_WriteRecord(dev, &emr.emr) ? arcDirection : 0; +} + +INT EMFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pExcludeClipRect ); + 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; + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return ERROR; + return next->funcs->pExcludeClipRect( next, left, top, right, bottom ); +} + +INT EMFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pIntersectClipRect ); + 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; + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return ERROR; + return next->funcs->pIntersectClipRect( next, left, top, right, bottom ); +} + +INT EMFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pOffsetClipRgn ); + EMROFFSETCLIPRGN emr; + + emr.emr.iType = EMR_OFFSETCLIPRGN; + emr.emr.nSize = sizeof(emr); + emr.ptlOffset.x = x; + emr.ptlOffset.y = y; + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return ERROR; + return next->funcs->pOffsetClipRgn( next, x, y ); +} + +INT EMFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pExtSelectClipRgn ); + EMREXTSELECTCLIPRGN *emr; + DWORD size, rgnsize; + BOOL ret; + + if (!hrgn) + { + if (mode != RGN_COPY) return ERROR; + rgnsize = 0; + } + else rgnsize = GetRegionData( hrgn, 0, NULL ); + + size = rgnsize + offsetof(EMREXTSELECTCLIPRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + if (rgnsize) GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); + + emr->emr.iType = EMR_EXTSELECTCLIPRGN; + emr->emr.nSize = size; + emr->cbRgnData = rgnsize; + emr->iMode = mode; + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret ? next->funcs->pExtSelectClipRgn( next, hrgn, mode ) : ERROR; +} + +INT EMFDRV_SetMapMode( PHYSDEV dev, INT mode ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetMapMode ); + EMRSETMAPMODE emr; + emr.emr.iType = EMR_SETMAPMODE; + emr.emr.nSize = sizeof(emr); + emr.iMode = mode; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return 0; + return next->funcs->pSetMapMode( next, mode ); +} + +BOOL EMFDRV_SetViewportExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetViewportExtEx ); + EMRSETVIEWPORTEXTEX emr; + + emr.emr.iType = EMR_SETVIEWPORTEXTEX; + emr.emr.nSize = sizeof(emr); + emr.szlExtent.cx = cx; + emr.szlExtent.cy = cy; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSetViewportExtEx( next, cx, cy, size ); +} + +BOOL EMFDRV_SetWindowExtEx( PHYSDEV dev, INT cx, INT cy, SIZE *size ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetWindowExtEx ); + EMRSETWINDOWEXTEX emr; + + emr.emr.iType = EMR_SETWINDOWEXTEX; + emr.emr.nSize = sizeof(emr); + emr.szlExtent.cx = cx; + emr.szlExtent.cy = cy; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSetWindowExtEx( next, cx, cy, size ); +} + +BOOL EMFDRV_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetViewportOrgEx ); + EMRSETVIEWPORTORGEX emr; + + emr.emr.iType = EMR_SETVIEWPORTORGEX; + emr.emr.nSize = sizeof(emr); + emr.ptlOrigin.x = x; + emr.ptlOrigin.y = y; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSetViewportOrgEx( next, x, y, pt ); +} + +BOOL EMFDRV_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetWindowOrgEx ); + EMRSETWINDOWORGEX emr; + + emr.emr.iType = EMR_SETWINDOWORGEX; + emr.emr.nSize = sizeof(emr); + emr.ptlOrigin.x = x; + emr.ptlOrigin.y = y; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSetWindowOrgEx( next, x, y, pt ); +} + +BOOL EMFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pScaleViewportExtEx ); + EMRSCALEVIEWPORTEXTEX emr; + + emr.emr.iType = EMR_SCALEVIEWPORTEXTEX; + emr.emr.nSize = sizeof(emr); + emr.xNum = xNum; + emr.xDenom = xDenom; + emr.yNum = yNum; + emr.yDenom = yDenom; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pScaleViewportExtEx( next, xNum, xDenom, yNum, yDenom, size ); +} + +BOOL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pScaleWindowExtEx ); + EMRSCALEWINDOWEXTEX emr; + + emr.emr.iType = EMR_SCALEWINDOWEXTEX; + emr.emr.nSize = sizeof(emr); + emr.xNum = xNum; + emr.xDenom = xDenom; + emr.yNum = yNum; + emr.yDenom = yDenom; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pScaleWindowExtEx( next, xNum, xDenom, yNum, yDenom, size ); +} + +DWORD EMFDRV_SetLayout( PHYSDEV dev, DWORD layout ) +{ + EMRSETLAYOUT emr; + + emr.emr.iType = EMR_SETLAYOUT; + emr.emr.nSize = sizeof(emr); + emr.iMode = layout; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? layout : GDI_ERROR; +} + +BOOL EMFDRV_SetWorldTransform( PHYSDEV dev, const XFORM *xform) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSetWorldTransform ); + EMRSETWORLDTRANSFORM emr; + + emr.emr.iType = EMR_SETWORLDTRANSFORM; + emr.emr.nSize = sizeof(emr); + emr.xform = *xform; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSetWorldTransform( next, xform ); +} + +BOOL EMFDRV_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pModifyWorldTransform ); + EMRMODIFYWORLDTRANSFORM emr; + + emr.emr.iType = EMR_MODIFYWORLDTRANSFORM; + emr.emr.nSize = sizeof(emr); + emr.xform = *xform; + emr.iMode = mode; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pModifyWorldTransform( next, xform, mode ); +} + +BOOL EMFDRV_OffsetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pOffsetViewportOrgEx ); + EMRSETVIEWPORTORGEX emr; + POINT prev; + + GetViewportOrgEx( dev->hdc, &prev ); + + emr.emr.iType = EMR_SETVIEWPORTORGEX; + emr.emr.nSize = sizeof(emr); + emr.ptlOrigin.x = prev.x + x; + emr.ptlOrigin.y = prev.y + y; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pOffsetViewportOrgEx( next, x, y, pt ); +} + +BOOL EMFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pOffsetWindowOrgEx ); + EMRSETWINDOWORGEX emr; + POINT prev; + + GetWindowOrgEx( dev->hdc, &prev ); + + emr.emr.iType = EMR_SETWINDOWORGEX; + emr.emr.nSize = sizeof(emr); + emr.ptlOrigin.x = prev.x + x; + emr.ptlOrigin.y = prev.y + y; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pOffsetWindowOrgEx( next, x, y, pt ); +} + +DWORD EMFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags ) +{ + EMRSETMAPPERFLAGS emr; + + emr.emr.iType = EMR_SETMAPPERFLAGS; + emr.emr.nSize = sizeof(emr); + emr.dwFlags = flags; + + return EMFDRV_WriteRecord( dev, &emr.emr ) ? flags : GDI_ERROR; +} + +BOOL EMFDRV_AbortPath( PHYSDEV dev ) +{ + EMRABORTPATH emr; + + emr.emr.iType = EMR_ABORTPATH; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_BeginPath( PHYSDEV dev ) +{ + EMRBEGINPATH emr; + + emr.emr.iType = EMR_BEGINPATH; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_CloseFigure( PHYSDEV dev ) +{ + EMRCLOSEFIGURE emr; + + emr.emr.iType = EMR_CLOSEFIGURE; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_EndPath( PHYSDEV dev ) +{ + EMRENDPATH emr; + + emr.emr.iType = EMR_ENDPATH; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_FillPath( PHYSDEV dev ) +{ + EMRFILLPATH emr; + + emr.emr.iType = EMR_FILLPATH; + emr.emr.nSize = sizeof(emr); + FIXME("Bounds\n"); + emr.rclBounds.left = 0; + emr.rclBounds.top = 0; + emr.rclBounds.right = 0; + emr.rclBounds.bottom = 0; + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_FlattenPath( PHYSDEV dev ) +{ + EMRFLATTENPATH emr; + + emr.emr.iType = EMR_FLATTENPATH; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectClipPath ); + EMRSELECTCLIPPATH emr; + + emr.emr.iType = EMR_SELECTCLIPPATH; + emr.emr.nSize = sizeof(emr); + emr.iMode = iMode; + + if (!EMFDRV_WriteRecord( dev, &emr.emr )) return FALSE; + return next->funcs->pSelectClipPath( next, iMode ); +} + +BOOL EMFDRV_StrokeAndFillPath( PHYSDEV dev ) +{ + EMRSTROKEANDFILLPATH emr; + + emr.emr.iType = EMR_STROKEANDFILLPATH; + emr.emr.nSize = sizeof(emr); + FIXME("Bounds\n"); + emr.rclBounds.left = 0; + emr.rclBounds.top = 0; + emr.rclBounds.right = 0; + emr.rclBounds.bottom = 0; + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_StrokePath( PHYSDEV dev ) +{ + EMRSTROKEPATH emr; + + emr.emr.iType = EMR_STROKEPATH; + emr.emr.nSize = sizeof(emr); + FIXME("Bounds\n"); + emr.rclBounds.left = 0; + emr.rclBounds.top = 0; + emr.rclBounds.right = 0; + emr.rclBounds.bottom = 0; + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +BOOL EMFDRV_WidenPath( PHYSDEV dev ) +{ + EMRWIDENPATH emr; + + emr.emr.iType = EMR_WIDENPATH; + emr.emr.nSize = sizeof(emr); + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +INT EMFDRV_GetDeviceCaps(PHYSDEV dev, INT cap) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev; + + return GetDeviceCaps( physDev->ref_dc, cap ); +} diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h new file mode 100644 index 00000000000..cbd73681ca0 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/enhmetafiledrv.h @@ -0,0 +1,144 @@ +/* + * Enhanced MetaFile driver definitions + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_ENHMETAFILEDRV_H +#define __WINE_ENHMETAFILEDRV_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "gdi_private.h" + +/* Enhanced Metafile driver physical DC */ + +typedef struct +{ + struct gdi_physdev dev; + ENHMETAHEADER *emh; /* Pointer to enhanced metafile header */ + UINT handles_size, cur_handles; + HGDIOBJ *handles; + HANDLE hFile; /* Handle for disk based MetaFile */ + HBRUSH dc_brush; + HPEN dc_pen; + HDC ref_dc; /* Reference device */ + HDC screen_dc; /* Screen DC if no reference device specified */ + INT restoring; /* RestoreDC counter */ +} EMFDRV_PDEVICE; + + +extern BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr ) DECLSPEC_HIDDEN; +extern void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect ) DECLSPEC_HIDDEN; +extern DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) DECLSPEC_HIDDEN; + +#define HANDLE_LIST_INC 20 + +/* Metafile driver functions */ +extern BOOL EMFDRV_AbortPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, + INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_BeginPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_BitBlt( PHYSDEV devDst, INT xDst, INT yDst, INT width, INT height, + PHYSDEV devSrc, INT xSrc, INT ySrc, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_CloseFigure( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_EndPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern INT EMFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) DECLSPEC_HIDDEN; +extern INT EMFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, + UINT count, const INT *lpDx ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_FlattenPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_GdiComment( PHYSDEV dev, UINT bytes, const BYTE *buffer ) DECLSPEC_HIDDEN; +extern INT EMFDRV_GetDeviceCaps( PHYSDEV dev, INT cap ) DECLSPEC_HIDDEN; +extern INT EMFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_ModifyWorldTransform( PHYSDEV dev, const XFORM *xform, DWORD mode ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_MoveTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern INT EMFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_OffsetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_PolyPolyline( PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polys) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Polyline( PHYSDEV dev, const POINT* pt,INT count) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT ell_width, INT ell_height ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, + INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, + INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN; +extern HBITMAP EMFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN; +extern HBRUSH EMFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) DECLSPEC_HIDDEN; +extern HFONT EMFDRV_SelectFont( PHYSDEV dev, HFONT handle, UINT *aa_flags ) DECLSPEC_HIDDEN; +extern HPEN EMFDRV_SelectPen( PHYSDEV dev, HPEN handle, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; +extern HPALETTE EMFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPal, BOOL force ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetArcDirection( PHYSDEV dev, INT arcDirection ) DECLSPEC_HIDDEN; +extern COLORREF EMFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetBkMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern COLORREF EMFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern COLORREF EMFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, DWORD cy, INT xSrc, + INT ySrc, UINT startscan, UINT lines, LPCVOID bits, + BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN; +extern DWORD EMFDRV_SetLayout( PHYSDEV dev, DWORD layout ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetMapMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern DWORD EMFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags ) DECLSPEC_HIDDEN; +extern COLORREF EMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetPolyFillMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetROP2( PHYSDEV dev, INT rop ) DECLSPEC_HIDDEN; +extern INT EMFDRV_SetStretchBltMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern UINT EMFDRV_SetTextAlign( PHYSDEV dev, UINT align ) DECLSPEC_HIDDEN; +extern COLORREF EMFDRV_SetTextColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetTextJustification( PHYSDEV dev, INT nBreakExtra, INT nBreakCount ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetViewportExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetWindowExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_SetWorldTransform( PHYSDEV dev, const XFORM *xform ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, + PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) DECLSPEC_HIDDEN; +extern INT EMFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst, + INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, + const void *bits, BITMAPINFO *info, UINT wUsage, DWORD dwRop ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL EMFDRV_WidenPath( PHYSDEV dev ) DECLSPEC_HIDDEN; + + +#endif /* __WINE_METAFILEDRV_H */ diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c new file mode 100644 index 00000000000..cf44e9c5e41 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/graphics.c @@ -0,0 +1,817 @@ +/* + * Enhanced MetaFile driver graphics functions + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include "wine/port.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "enhmfdrv/enhmetafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +/********************************************************************** + * EMFDRV_MoveTo + */ +BOOL EMFDRV_MoveTo(PHYSDEV dev, INT x, INT y) +{ + EMRMOVETOEX emr; + + emr.emr.iType = EMR_MOVETOEX; + emr.emr.nSize = sizeof(emr); + emr.ptl.x = x; + emr.ptl.y = y; + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +/*********************************************************************** + * EMFDRV_LineTo + */ +BOOL EMFDRV_LineTo( PHYSDEV dev, INT x, INT y ) +{ + POINT pt; + EMRLINETO emr; + RECTL bounds; + + emr.emr.iType = EMR_LINETO; + emr.emr.nSize = sizeof(emr); + emr.ptl.x = x; + emr.ptl.y = y; + + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + return FALSE; + + GetCurrentPositionEx( dev->hdc, &pt ); + + bounds.left = min(x, pt.x); + bounds.top = min(y, pt.y); + bounds.right = max(x, pt.x); + bounds.bottom = max(y, pt.y); + + EMFDRV_UpdateBBox( dev, &bounds ); + + return TRUE; +} + + +/*********************************************************************** + * EMFDRV_ArcChordPie + */ +static BOOL +EMFDRV_ArcChordPie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend, DWORD iType ) +{ + INT temp, xCentre, yCentre, i; + double angleStart, angleEnd; + double xinterStart, yinterStart, xinterEnd, yinterEnd; + EMRARC emr; + RECTL bounds; + + 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(dev->hdc) == GM_COMPATIBLE) { + right--; + bottom--; + } + + emr.emr.iType = iType; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = left; + emr.rclBox.top = top; + emr.rclBox.right = right; + emr.rclBox.bottom = bottom; + emr.ptlStart.x = xstart; + emr.ptlStart.y = ystart; + emr.ptlEnd.x = xend; + emr.ptlEnd.y = yend; + + + /* Now calculate the BBox */ + xCentre = (left + right + 1) / 2; + yCentre = (top + bottom + 1) / 2; + + xstart -= xCentre; + ystart -= yCentre; + xend -= xCentre; + yend -= yCentre; + + /* invert y co-ords to get angle anti-clockwise from x-axis */ + angleStart = atan2( -(double)ystart, (double)xstart); + angleEnd = atan2( -(double)yend, (double)xend); + + /* These are the intercepts of the start/end lines with the arc */ + + xinterStart = (right - left + 1)/2 * cos(angleStart) + xCentre; + yinterStart = -(bottom - top + 1)/2 * sin(angleStart) + yCentre; + xinterEnd = (right - left + 1)/2 * cos(angleEnd) + xCentre; + yinterEnd = -(bottom - top + 1)/2 * sin(angleEnd) + yCentre; + + if(angleStart < 0) angleStart += 2 * M_PI; + if(angleEnd < 0) angleEnd += 2 * M_PI; + if(angleEnd < angleStart) angleEnd += 2 * M_PI; + + bounds.left = min(xinterStart, xinterEnd); + bounds.top = min(yinterStart, yinterEnd); + bounds.right = max(xinterStart, xinterEnd); + bounds.bottom = max(yinterStart, yinterEnd); + + for(i = 0; i <= 8; i++) { + if(i * M_PI / 2 < angleStart) /* loop until we're past start */ + continue; + if(i * M_PI / 2 > angleEnd) /* if we're past end we're finished */ + break; + + /* the arc touches the rectangle at the start of quadrant i, so adjust + BBox to reflect this. */ + + switch(i % 4) { + case 0: + bounds.right = right; + break; + case 1: + bounds.top = top; + break; + case 2: + bounds.left = left; + break; + case 3: + bounds.bottom = bottom; + break; + } + } + + /* If we're drawing a pie then make sure we include the centre */ + if(iType == EMR_PIE) { + if(bounds.left > xCentre) bounds.left = xCentre; + else if(bounds.right < xCentre) bounds.right = xCentre; + if(bounds.top > yCentre) bounds.top = yCentre; + else if(bounds.bottom < yCentre) bounds.bottom = yCentre; + } + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + return FALSE; + EMFDRV_UpdateBBox( dev, &bounds ); + return TRUE; +} + + +/*********************************************************************** + * EMFDRV_Arc + */ +BOOL EMFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_ARC ); +} + +/*********************************************************************** + * EMFDRV_Pie + */ +BOOL EMFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_PIE ); +} + + +/*********************************************************************** + * EMFDRV_Chord + */ +BOOL EMFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return EMFDRV_ArcChordPie( dev, left, top, right, bottom, xstart, ystart, + xend, yend, EMR_CHORD ); +} + +/*********************************************************************** + * EMFDRV_Ellipse + */ +BOOL EMFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) +{ + EMRELLIPSE emr; + INT temp; + + TRACE("%d,%d - %d,%d\n", left, top, right, bottom); + + if(left == right || top == bottom) return FALSE; + + if(left > right) {temp = left; left = right; right = temp;} + if(top > bottom) {temp = top; top = bottom; bottom = temp;} + + if(GetGraphicsMode( dev->hdc ) == GM_COMPATIBLE) { + right--; + bottom--; + } + + emr.emr.iType = EMR_ELLIPSE; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = left; + emr.rclBox.top = top; + emr.rclBox.right = right; + emr.rclBox.bottom = bottom; + + EMFDRV_UpdateBBox( dev, &emr.rclBox ); + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +/*********************************************************************** + * EMFDRV_Rectangle + */ +BOOL EMFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom) +{ + EMRRECTANGLE emr; + INT temp; + + TRACE("%d,%d - %d,%d\n", left, top, right, bottom); + + if(left == right || top == bottom) return FALSE; + + if(left > right) {temp = left; left = right; right = temp;} + if(top > bottom) {temp = top; top = bottom; bottom = temp;} + + if(GetGraphicsMode( dev->hdc ) == GM_COMPATIBLE) { + right--; + bottom--; + } + + emr.emr.iType = EMR_RECTANGLE; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = left; + emr.rclBox.top = top; + emr.rclBox.right = right; + emr.rclBox.bottom = bottom; + + EMFDRV_UpdateBBox( dev, &emr.rclBox ); + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +/*********************************************************************** + * EMFDRV_RoundRect + */ +BOOL EMFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, + INT bottom, INT ell_width, INT ell_height ) +{ + EMRROUNDRECT emr; + INT temp; + + 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( dev->hdc ) == GM_COMPATIBLE) { + right--; + bottom--; + } + + emr.emr.iType = EMR_ROUNDRECT; + emr.emr.nSize = sizeof(emr); + emr.rclBox.left = left; + emr.rclBox.top = top; + emr.rclBox.right = right; + emr.rclBox.bottom = bottom; + emr.szlCorner.cx = ell_width; + emr.szlCorner.cy = ell_height; + + EMFDRV_UpdateBBox( dev, &emr.rclBox ); + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + +/*********************************************************************** + * EMFDRV_SetPixel + */ +COLORREF EMFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) +{ + EMRSETPIXELV emr; + + emr.emr.iType = EMR_SETPIXELV; + emr.emr.nSize = sizeof(emr); + emr.ptlPixel.x = x; + emr.ptlPixel.y = y; + emr.crColor = color; + + if (EMFDRV_WriteRecord( dev, &emr.emr )) { + RECTL bounds; + bounds.left = bounds.right = x; + bounds.top = bounds.bottom = y; + EMFDRV_UpdateBBox( dev, &bounds ); + return color; + } + return -1; +} + +/********************************************************************** + * EMFDRV_Polylinegon + * + * Helper for EMFDRV_Poly{line|gon} + */ +static BOOL +EMFDRV_Polylinegon( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ) +{ + EMRPOLYLINE *emr; + DWORD size; + INT i; + BOOL ret; + + size = sizeof(EMRPOLYLINE) + sizeof(POINTL) * (count - 1); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + emr->emr.iType = iType; + emr->emr.nSize = size; + + emr->rclBounds.left = emr->rclBounds.right = pt[0].x; + emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y; + + for(i = 1; i < count; i++) { + if(pt[i].x < emr->rclBounds.left) + emr->rclBounds.left = pt[i].x; + else if(pt[i].x > emr->rclBounds.right) + emr->rclBounds.right = pt[i].x; + if(pt[i].y < emr->rclBounds.top) + emr->rclBounds.top = pt[i].y; + else if(pt[i].y > emr->rclBounds.bottom) + emr->rclBounds.bottom = pt[i].y; + } + + emr->cptl = count; + memcpy(emr->aptl, pt, count * sizeof(POINTL)); + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + + +/********************************************************************** + * EMFDRV_Polylinegon16 + * + * Helper for EMFDRV_Poly{line|gon} + * + * This is not a legacy function! + * We are using SHORT integers to save space. + */ +static BOOL +EMFDRV_Polylinegon16( PHYSDEV dev, const POINT* pt, INT count, DWORD iType ) +{ + EMRPOLYLINE16 *emr; + DWORD size; + INT i; + BOOL ret; + + /* check whether all points fit in the SHORT int POINT structure */ + for(i = 0; i < count; i++) { + if( ((pt[i].x+0x8000) & ~0xffff ) || + ((pt[i].y+0x8000) & ~0xffff ) ) + return FALSE; + } + + size = sizeof(EMRPOLYLINE16) + sizeof(POINTS) * (count - 1); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + emr->emr.iType = iType; + emr->emr.nSize = size; + + emr->rclBounds.left = emr->rclBounds.right = pt[0].x; + emr->rclBounds.top = emr->rclBounds.bottom = pt[0].y; + + for(i = 1; i < count; i++) { + if(pt[i].x < emr->rclBounds.left) + emr->rclBounds.left = pt[i].x; + else if(pt[i].x > emr->rclBounds.right) + emr->rclBounds.right = pt[i].x; + if(pt[i].y < emr->rclBounds.top) + emr->rclBounds.top = pt[i].y; + else if(pt[i].y > emr->rclBounds.bottom) + emr->rclBounds.bottom = pt[i].y; + } + + emr->cpts = count; + for(i = 0; i < count; i++ ) { + emr->apts[i].x = pt[i].x; + emr->apts[i].y = pt[i].y; + } + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + + +/********************************************************************** + * EMFDRV_Polyline + */ +BOOL EMFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count ) +{ + if( EMFDRV_Polylinegon16( dev, pt, count, EMR_POLYLINE16 ) ) + return TRUE; + return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYLINE ); +} + +/********************************************************************** + * EMFDRV_Polygon + */ +BOOL EMFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count ) +{ + if(count < 2) return FALSE; + if( EMFDRV_Polylinegon16( dev, pt, count, EMR_POLYGON16 ) ) + return TRUE; + return EMFDRV_Polylinegon( dev, pt, count, EMR_POLYGON ); +} + +/********************************************************************** + * EMFDRV_PolyBezier + */ +BOOL EMFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count ) +{ + if(EMFDRV_Polylinegon16( dev, pts, count, EMR_POLYBEZIER16 )) + return TRUE; + return EMFDRV_Polylinegon( dev, pts, count, EMR_POLYBEZIER ); +} + +/********************************************************************** + * EMFDRV_PolyBezierTo + */ +BOOL EMFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count ) +{ + if(EMFDRV_Polylinegon16( dev, pts, count, EMR_POLYBEZIERTO16 )) + return TRUE; + return EMFDRV_Polylinegon( dev, pts, count, EMR_POLYBEZIERTO ); +} + + +/********************************************************************** + * EMFDRV_PolyPolylinegon + * + * Helper for EMFDRV_PolyPoly{line|gon} + */ +static BOOL +EMFDRV_PolyPolylinegon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys, + DWORD iType) +{ + EMRPOLYPOLYLINE *emr; + DWORD cptl = 0, poly, size; + INT point; + RECTL bounds; + const POINT *pts; + BOOL ret; + + bounds.left = bounds.right = pt[0].x; + bounds.top = bounds.bottom = pt[0].y; + + pts = pt; + for(poly = 0; poly < polys; poly++) { + cptl += counts[poly]; + for(point = 0; point < counts[poly]; point++) { + if(bounds.left > pts->x) bounds.left = pts->x; + else if(bounds.right < pts->x) bounds.right = pts->x; + if(bounds.top > pts->y) bounds.top = pts->y; + else if(bounds.bottom < pts->y) bounds.bottom = pts->y; + pts++; + } + } + + size = sizeof(EMRPOLYPOLYLINE) + (polys - 1) * sizeof(DWORD) + + (cptl - 1) * sizeof(POINTL); + + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + emr->emr.iType = iType; + emr->emr.nSize = size; + emr->rclBounds = bounds; + emr->nPolys = polys; + emr->cptl = cptl; + memcpy(emr->aPolyCounts, counts, polys * sizeof(DWORD)); + memcpy(emr->aPolyCounts + polys, pt, cptl * sizeof(POINTL)); + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +/********************************************************************** + * EMFDRV_PolyPolyline + */ +BOOL EMFDRV_PolyPolyline(PHYSDEV dev, const POINT* pt, const DWORD* counts, DWORD polys) +{ + return EMFDRV_PolyPolylinegon( dev, pt, (const INT *)counts, polys, + EMR_POLYPOLYLINE ); +} + +/********************************************************************** + * EMFDRV_PolyPolygon + */ +BOOL EMFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polys ) +{ + return EMFDRV_PolyPolylinegon( dev, pt, counts, polys, EMR_POLYPOLYGON ); +} + + +/********************************************************************** + * EMFDRV_ExtFloodFill + */ +BOOL EMFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) +{ + EMREXTFLOODFILL emr; + + emr.emr.iType = EMR_EXTFLOODFILL; + emr.emr.nSize = sizeof(emr); + emr.ptlStart.x = x; + emr.ptlStart.y = y; + emr.crColor = color; + emr.iMode = fillType; + + return EMFDRV_WriteRecord( dev, &emr.emr ); +} + + +/********************************************************************* + * EMFDRV_FillRgn + */ +BOOL EMFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush ) +{ + EMRFILLRGN *emr; + DWORD size, rgnsize, index; + BOOL ret; + + index = EMFDRV_CreateBrushIndirect( dev, hbrush ); + if(!index) return FALSE; + + rgnsize = GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRFILLRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); + + emr->emr.iType = EMR_FILLRGN; + emr->emr.nSize = size; + emr->rclBounds.left = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left; + emr->rclBounds.top = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top; + emr->rclBounds.right = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1; + emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1; + emr->cbRgnData = rgnsize; + emr->ihBrush = index; + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} +/********************************************************************* + * EMFDRV_FrameRgn + */ +BOOL EMFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT width, INT height ) +{ + EMRFRAMERGN *emr; + DWORD size, rgnsize, index; + BOOL ret; + + index = EMFDRV_CreateBrushIndirect( dev, hbrush ); + if(!index) return FALSE; + + rgnsize = GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRFRAMERGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); + + emr->emr.iType = EMR_FRAMERGN; + emr->emr.nSize = size; + emr->rclBounds.left = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left; + emr->rclBounds.top = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top; + emr->rclBounds.right = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1; + emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1; + emr->cbRgnData = rgnsize; + emr->ihBrush = index; + emr->szlStroke.cx = width; + emr->szlStroke.cy = height; + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +/********************************************************************* + * EMFDRV_PaintInvertRgn + * + * Helper for EMFDRV_{Paint|Invert}Rgn + */ +static BOOL EMFDRV_PaintInvertRgn( PHYSDEV dev, HRGN hrgn, DWORD iType ) +{ + EMRINVERTRGN *emr; + DWORD size, rgnsize; + BOOL ret; + + + rgnsize = GetRegionData( hrgn, 0, NULL ); + size = rgnsize + offsetof(EMRINVERTRGN,RgnData); + emr = HeapAlloc( GetProcessHeap(), 0, size ); + + GetRegionData( hrgn, rgnsize, (RGNDATA *)&emr->RgnData ); + + emr->emr.iType = iType; + emr->emr.nSize = size; + emr->rclBounds.left = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.left; + emr->rclBounds.top = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.top; + emr->rclBounds.right = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.right - 1; + emr->rclBounds.bottom = ((RGNDATA *)&emr->RgnData)->rdh.rcBound.bottom - 1; + emr->cbRgnData = rgnsize; + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + if(ret) + EMFDRV_UpdateBBox( dev, &emr->rclBounds ); + HeapFree( GetProcessHeap(), 0, emr ); + return ret; +} + +/********************************************************************** + * EMFDRV_PaintRgn + */ +BOOL EMFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) +{ + return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_PAINTRGN ); +} + +/********************************************************************** + * EMFDRV_InvertRgn + */ +BOOL EMFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) +{ + return EMFDRV_PaintInvertRgn( dev, hrgn, EMR_INVERTRGN ); +} + +/********************************************************************** + * EMFDRV_ExtTextOut + */ +BOOL EMFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, + LPCWSTR str, UINT count, const INT *lpDx ) +{ + EMREXTTEXTOUTW *pemr; + DWORD nSize; + BOOL ret; + int textHeight = 0; + int textWidth = 0; + const UINT textAlign = GetTextAlign( dev->hdc ); + const INT graphicsMode = GetGraphicsMode( dev->hdc ); + FLOAT exScale, eyScale; + + nSize = sizeof(*pemr) + ((count+1) & ~1) * sizeof(WCHAR) + count * sizeof(INT); + + TRACE("%s %s count %d nSize = %d\n", debugstr_wn(str, count), + wine_dbgstr_rect(lprect), count, nSize); + pemr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, nSize); + + if (graphicsMode == GM_COMPATIBLE) + { + const INT horzSize = GetDeviceCaps( dev->hdc, HORZSIZE ); + const INT horzRes = GetDeviceCaps( dev->hdc, HORZRES ); + const INT vertSize = GetDeviceCaps( dev->hdc, VERTSIZE ); + const INT vertRes = GetDeviceCaps( dev->hdc, VERTRES ); + SIZE wndext, vportext; + + GetViewportExtEx( dev->hdc, &vportext ); + GetWindowExtEx( dev->hdc, &wndext ); + exScale = 100.0 * ((FLOAT)horzSize / (FLOAT)horzRes) / + ((FLOAT)wndext.cx / (FLOAT)vportext.cx); + eyScale = 100.0 * ((FLOAT)vertSize / (FLOAT)vertRes) / + ((FLOAT)wndext.cy / (FLOAT)vportext.cy); + } + else + { + exScale = 0.0; + eyScale = 0.0; + } + + pemr->emr.iType = EMR_EXTTEXTOUTW; + pemr->emr.nSize = nSize; + pemr->iGraphicsMode = graphicsMode; + pemr->exScale = exScale; + pemr->eyScale = eyScale; + pemr->emrtext.ptlReference.x = x; + pemr->emrtext.ptlReference.y = y; + pemr->emrtext.nChars = count; + pemr->emrtext.offString = sizeof(*pemr); + memcpy((char*)pemr + pemr->emrtext.offString, str, count * sizeof(WCHAR)); + pemr->emrtext.fOptions = flags; + if(!lprect) { + pemr->emrtext.rcl.left = pemr->emrtext.rcl.top = 0; + pemr->emrtext.rcl.right = pemr->emrtext.rcl.bottom = -1; + } else { + pemr->emrtext.rcl.left = lprect->left; + pemr->emrtext.rcl.top = lprect->top; + pemr->emrtext.rcl.right = lprect->right; + pemr->emrtext.rcl.bottom = lprect->bottom; + } + + pemr->emrtext.offDx = pemr->emrtext.offString + ((count+1) & ~1) * sizeof(WCHAR); + if(lpDx) { + UINT i; + SIZE strSize; + memcpy((char*)pemr + pemr->emrtext.offDx, lpDx, count * sizeof(INT)); + for (i = 0; i < count; i++) { + textWidth += lpDx[i]; + } + if (GetTextExtentPoint32W( dev->hdc, str, count, &strSize )) + textHeight = strSize.cy; + } + else { + UINT i; + INT *dx = (INT *)((char*)pemr + pemr->emrtext.offDx); + SIZE charSize; + for (i = 0; i < count; i++) { + if (GetTextExtentPoint32W( dev->hdc, str + i, 1, &charSize )) { + dx[i] = charSize.cx; + textWidth += charSize.cx; + textHeight = max(textHeight, charSize.cy); + } + } + } + + if (!lprect) + { + pemr->rclBounds.left = pemr->rclBounds.top = 0; + pemr->rclBounds.right = pemr->rclBounds.bottom = -1; + goto no_bounds; + } + + switch (textAlign & (TA_LEFT | TA_RIGHT | TA_CENTER)) { + case TA_CENTER: { + pemr->rclBounds.left = x - (textWidth / 2) - 1; + pemr->rclBounds.right = x + (textWidth / 2) + 1; + break; + } + case TA_RIGHT: { + pemr->rclBounds.left = x - textWidth - 1; + pemr->rclBounds.right = x; + break; + } + default: { /* TA_LEFT */ + pemr->rclBounds.left = x; + pemr->rclBounds.right = x + textWidth + 1; + } + } + + switch (textAlign & (TA_TOP | TA_BOTTOM | TA_BASELINE)) { + case TA_BASELINE: { + TEXTMETRICW tm; + if (!GetTextMetricsW( dev->hdc, &tm )) + tm.tmDescent = 0; + /* Play safe here... it's better to have a bounding box */ + /* that is too big than too small. */ + pemr->rclBounds.top = y - textHeight - 1; + pemr->rclBounds.bottom = y + tm.tmDescent + 1; + break; + } + case TA_BOTTOM: { + pemr->rclBounds.top = y - textHeight - 1; + pemr->rclBounds.bottom = y; + break; + } + default: { /* TA_TOP */ + pemr->rclBounds.top = y; + pemr->rclBounds.bottom = y + textHeight + 1; + } + } + EMFDRV_UpdateBBox( dev, &pemr->rclBounds ); + +no_bounds: + ret = EMFDRV_WriteRecord( dev, &pemr->emr ); + HeapFree( GetProcessHeap(), 0, pemr ); + return ret; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/init.c b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/init.c new file mode 100644 index 00000000000..682f4120f80 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/init.c @@ -0,0 +1,510 @@ +/* + * Enhanced MetaFile driver initialisation functions + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winnls.h" +#include "gdi_private.h" +#include "enhmfdrv/enhmetafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + +static BOOL EMFDRV_DeleteDC( PHYSDEV dev ); + +static const struct gdi_dc_funcs EMFDRV_Funcs = +{ + NULL, /* pAbortDoc */ + EMFDRV_AbortPath, /* pAbortPath */ + NULL, /* pAlphaBlend */ + NULL, /* pAngleArc */ + EMFDRV_Arc, /* pArc */ + NULL, /* pArcTo */ + EMFDRV_BeginPath, /* pBeginPath */ + NULL, /* pBlendImage */ + EMFDRV_Chord, /* pChord */ + EMFDRV_CloseFigure, /* pCloseFigure */ + NULL, /* pCreateCompatibleDC */ + NULL, /* pCreateDC */ + EMFDRV_DeleteDC, /* pDeleteDC */ + EMFDRV_DeleteObject, /* pDeleteObject */ + NULL, /* pDeviceCapabilities */ + EMFDRV_Ellipse, /* pEllipse */ + NULL, /* pEndDoc */ + NULL, /* pEndPage */ + EMFDRV_EndPath, /* pEndPath */ + NULL, /* pEnumFonts */ + NULL, /* pEnumICMProfiles */ + EMFDRV_ExcludeClipRect, /* pExcludeClipRect */ + NULL, /* pExtDeviceMode */ + NULL, /* pExtEscape */ + EMFDRV_ExtFloodFill, /* pExtFloodFill */ + EMFDRV_ExtSelectClipRgn, /* pExtSelectClipRgn */ + EMFDRV_ExtTextOut, /* pExtTextOut */ + EMFDRV_FillPath, /* pFillPath */ + EMFDRV_FillRgn, /* pFillRgn */ + EMFDRV_FlattenPath, /* pFlattenPath */ + NULL, /* pFontIsLinked */ + EMFDRV_FrameRgn, /* pFrameRgn */ + EMFDRV_GdiComment, /* pGdiComment */ + NULL, /* pGdiRealizationInfo */ + NULL, /* pGetBoundsRect */ + NULL, /* pGetCharABCWidths */ + NULL, /* pGetCharABCWidthsI */ + NULL, /* pGetCharWidth */ + EMFDRV_GetDeviceCaps, /* pGetDeviceCaps */ + NULL, /* pGetDeviceGammaRamp */ + NULL, /* pGetFontData */ + NULL, /* pGetFontUnicodeRanges */ + NULL, /* pGetGlyphIndices */ + NULL, /* pGetGlyphOutline */ + NULL, /* pGetICMProfile */ + NULL, /* pGetImage */ + NULL, /* pGetKerningPairs */ + NULL, /* pGetNearestColor */ + NULL, /* pGetOutlineTextMetrics */ + NULL, /* pGetPixel */ + NULL, /* pGetSystemPaletteEntries */ + NULL, /* pGetTextCharsetInfo */ + NULL, /* pGetTextExtentExPoint */ + NULL, /* pGetTextExtentExPointI */ + NULL, /* pGetTextFace */ + NULL, /* pGetTextMetrics */ + NULL, /* pGradientFill */ + EMFDRV_IntersectClipRect, /* pIntersectClipRect */ + EMFDRV_InvertRgn, /* pInvertRgn */ + EMFDRV_LineTo, /* pLineTo */ + EMFDRV_ModifyWorldTransform, /* pModifyWorldTransform */ + EMFDRV_MoveTo, /* pMoveTo */ + EMFDRV_OffsetClipRgn, /* pOffsetClipRgn */ + EMFDRV_OffsetViewportOrgEx, /* pOffsetViewportOrgEx */ + EMFDRV_OffsetWindowOrgEx, /* pOffsetWindowOrgEx */ + EMFDRV_PaintRgn, /* pPaintRgn */ + EMFDRV_PatBlt, /* pPatBlt */ + EMFDRV_Pie, /* pPie */ + EMFDRV_PolyBezier, /* pPolyBezier */ + EMFDRV_PolyBezierTo, /* pPolyBezierTo */ + NULL, /* pPolyDraw */ + EMFDRV_PolyPolygon, /* pPolyPolygon */ + EMFDRV_PolyPolyline, /* pPolyPolyline */ + EMFDRV_Polygon, /* pPolygon */ + EMFDRV_Polyline, /* pPolyline */ + NULL, /* pPolylineTo */ + NULL, /* pPutImage */ + NULL, /* pRealizeDefaultPalette */ + NULL, /* pRealizePalette */ + EMFDRV_Rectangle, /* pRectangle */ + NULL, /* pResetDC */ + EMFDRV_RestoreDC, /* pRestoreDC */ + EMFDRV_RoundRect, /* pRoundRect */ + EMFDRV_SaveDC, /* pSaveDC */ + EMFDRV_ScaleViewportExtEx, /* pScaleViewportExtEx */ + EMFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */ + EMFDRV_SelectBitmap, /* pSelectBitmap */ + EMFDRV_SelectBrush, /* pSelectBrush */ + EMFDRV_SelectClipPath, /* pSelectClipPath */ + EMFDRV_SelectFont, /* pSelectFont */ + EMFDRV_SelectPalette, /* pSelectPalette */ + EMFDRV_SelectPen, /* pSelectPen */ + EMFDRV_SetArcDirection, /* pSetArcDirection */ + EMFDRV_SetBkColor, /* pSetBkColor */ + EMFDRV_SetBkMode, /* pSetBkMode */ + NULL, /* pSetBoundsRect */ + EMFDRV_SetDCBrushColor, /* pSetDCBrushColor*/ + EMFDRV_SetDCPenColor, /* pSetDCPenColor*/ + EMFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */ + NULL, /* pSetDeviceClipping */ + NULL, /* pSetDeviceGammaRamp */ + EMFDRV_SetLayout, /* pSetLayout */ + EMFDRV_SetMapMode, /* pSetMapMode */ + EMFDRV_SetMapperFlags, /* pSetMapperFlags */ + EMFDRV_SetPixel, /* pSetPixel */ + EMFDRV_SetPolyFillMode, /* pSetPolyFillMode */ + EMFDRV_SetROP2, /* pSetROP2 */ + NULL, /* pSetRelAbs */ + EMFDRV_SetStretchBltMode, /* pSetStretchBltMode */ + EMFDRV_SetTextAlign, /* pSetTextAlign */ + NULL, /* pSetTextCharacterExtra */ + EMFDRV_SetTextColor, /* pSetTextColor */ + EMFDRV_SetTextJustification, /* pSetTextJustification */ + EMFDRV_SetViewportExtEx, /* pSetViewportExtEx */ + EMFDRV_SetViewportOrgEx, /* pSetViewportOrgEx */ + EMFDRV_SetWindowExtEx, /* pSetWindowExtEx */ + EMFDRV_SetWindowOrgEx, /* pSetWindowOrgEx */ + EMFDRV_SetWorldTransform, /* pSetWorldTransform */ + NULL, /* pStartDoc */ + NULL, /* pStartPage */ + EMFDRV_StretchBlt, /* pStretchBlt */ + EMFDRV_StretchDIBits, /* pStretchDIBits */ + EMFDRV_StrokeAndFillPath, /* pStrokeAndFillPath */ + EMFDRV_StrokePath, /* pStrokePath */ + NULL, /* pUnrealizePalette */ + EMFDRV_WidenPath, /* pWidenPath */ + NULL, /* wine_get_wgl_driver */ + GDI_PRIORITY_GRAPHICS_DRV /* priority */ +}; + + +/********************************************************************** + * EMFDRV_DeleteDC + */ +static BOOL EMFDRV_DeleteDC( PHYSDEV dev ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + UINT index; + + if (physDev->emh) HeapFree( GetProcessHeap(), 0, physDev->emh ); + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index]) + GDI_hdc_not_using_object(physDev->handles[index], dev->hdc); + HeapFree( GetProcessHeap(), 0, physDev->handles ); + HeapFree( GetProcessHeap(), 0, physDev ); + return TRUE; +} + + +/****************************************************************** + * EMFDRV_WriteRecord + * + * Warning: this function can change the pointer to the metafile header. + */ +BOOL EMFDRV_WriteRecord( PHYSDEV dev, EMR *emr ) +{ + DWORD len; + DWORD bytes_written; + ENHMETAHEADER *emh; + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + + TRACE("record %d, size %d %s\n", + emr->iType, emr->nSize, physDev->hFile ? "(to disk)" : ""); + + assert( !(emr->nSize & 3) ); + + physDev->emh->nBytes += emr->nSize; + physDev->emh->nRecords++; + + if(physDev->hFile) { + if (!WriteFile(physDev->hFile, emr, emr->nSize, &bytes_written, NULL)) + return FALSE; + } else { + DWORD nEmfSize = HeapSize(GetProcessHeap(), 0, physDev->emh); + len = physDev->emh->nBytes; + if (len > nEmfSize) { + nEmfSize += (nEmfSize / 2) + emr->nSize; + emh = HeapReAlloc(GetProcessHeap(), 0, physDev->emh, nEmfSize); + if (!emh) return FALSE; + physDev->emh = emh; + } + memcpy((CHAR *)physDev->emh + physDev->emh->nBytes - emr->nSize, emr, + emr->nSize); + } + return TRUE; +} + + +/****************************************************************** + * EMFDRV_UpdateBBox + */ +void EMFDRV_UpdateBBox( PHYSDEV dev, RECTL *rect ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + RECTL *bounds = &physDev->emh->rclBounds; + RECTL vportRect = *rect; + + LPtoDP( dev->hdc, (LPPOINT)&vportRect, 2 ); + + /* The coordinate systems may be mirrored + (LPtoDP handles points, not rectangles) */ + if (vportRect.left > vportRect.right) + { + LONG temp = vportRect.right; + vportRect.right = vportRect.left; + vportRect.left = temp; + } + if (vportRect.top > vportRect.bottom) + { + LONG temp = vportRect.bottom; + vportRect.bottom = vportRect.top; + vportRect.top = temp; + } + + if (bounds->left > bounds->right) + { + /* first bounding rectangle */ + *bounds = vportRect; + } + else + { + bounds->left = min(bounds->left, vportRect.left); + bounds->top = min(bounds->top, vportRect.top); + bounds->right = max(bounds->right, vportRect.right); + bounds->bottom = max(bounds->bottom, vportRect.bottom); + } +} + +/********************************************************************** + * CreateEnhMetaFileA (GDI32.@) + */ +HDC WINAPI CreateEnhMetaFileA( + HDC hdc, /* [in] optional reference DC */ + LPCSTR filename, /* [in] optional filename for disk metafiles */ + const RECT *rect, /* [in] optional bounding rectangle */ + LPCSTR description /* [in] optional description */ + ) +{ + LPWSTR filenameW = NULL; + LPWSTR descriptionW = NULL; + HDC hReturnDC; + DWORD len1, len2, total; + + if(filename) + { + total = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 ); + filenameW = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, total ); + } + if(description) { + len1 = strlen(description); + len2 = strlen(description + len1 + 1); + total = MultiByteToWideChar( CP_ACP, 0, description, len1 + len2 + 3, NULL, 0 ); + descriptionW = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, description, len1 + len2 + 3, descriptionW, total ); + } + + hReturnDC = CreateEnhMetaFileW(hdc, filenameW, rect, descriptionW); + + HeapFree( GetProcessHeap(), 0, filenameW ); + HeapFree( GetProcessHeap(), 0, descriptionW ); + + return hReturnDC; +} + +/********************************************************************** + * CreateEnhMetaFileW (GDI32.@) + */ +HDC WINAPI CreateEnhMetaFileW( + HDC hdc, /* [in] optional reference DC */ + LPCWSTR filename, /* [in] optional filename for disk metafiles */ + const RECT* rect, /* [in] optional bounding rectangle */ + LPCWSTR description /* [in] optional description */ + ) +{ + static const WCHAR displayW[] = {'D','I','S','P','L','A','Y',0}; + HDC ret; + DC *dc; + EMFDRV_PDEVICE *physDev; + HANDLE hFile; + DWORD size = 0, length = 0; + DWORD bytes_written; + + TRACE("%s\n", debugstr_w(filename) ); + + if (!(dc = alloc_dc_ptr( OBJ_ENHMETADC ))) return 0; + + physDev = HeapAlloc(GetProcessHeap(),0,sizeof(*physDev)); + if (!physDev) { + free_dc_ptr( dc ); + return 0; + } + if(description) { /* App name\0Title\0\0 */ + length = lstrlenW(description); + length += lstrlenW(description + length + 1); + length += 3; + length *= 2; + } + size = sizeof(ENHMETAHEADER) + (length + 3) / 4 * 4; + + if (!(physDev->emh = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size))) { + HeapFree( GetProcessHeap(), 0, physDev ); + free_dc_ptr( dc ); + return 0; + } + + push_dc_driver( &dc->physDev, &physDev->dev, &EMFDRV_Funcs ); + + physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0])); + physDev->handles_size = HANDLE_LIST_INC; + physDev->cur_handles = 1; + physDev->hFile = 0; + physDev->dc_brush = 0; + physDev->dc_pen = 0; + physDev->screen_dc = 0; + physDev->restoring = 0; + if (hdc) /* if no ref, use current display */ + physDev->ref_dc = hdc; + else + physDev->ref_dc = physDev->screen_dc = CreateDCW( displayW, NULL, NULL, NULL ); + + SetVirtualResolution(physDev->dev.hdc, 0, 0, 0, 0); + + physDev->emh->iType = EMR_HEADER; + physDev->emh->nSize = size; + + physDev->emh->rclBounds.left = physDev->emh->rclBounds.top = 0; + physDev->emh->rclBounds.right = physDev->emh->rclBounds.bottom = -1; + + if(rect) { + physDev->emh->rclFrame.left = rect->left; + physDev->emh->rclFrame.top = rect->top; + physDev->emh->rclFrame.right = rect->right; + physDev->emh->rclFrame.bottom = rect->bottom; + } else { /* Set this to {0,0 - -1,-1} and update it at the end */ + physDev->emh->rclFrame.left = physDev->emh->rclFrame.top = 0; + physDev->emh->rclFrame.right = physDev->emh->rclFrame.bottom = -1; + } + + physDev->emh->dSignature = ENHMETA_SIGNATURE; + physDev->emh->nVersion = 0x10000; + physDev->emh->nBytes = physDev->emh->nSize; + physDev->emh->nRecords = 1; + physDev->emh->nHandles = 1; + + physDev->emh->sReserved = 0; /* According to docs, this is reserved and must be 0 */ + physDev->emh->nDescription = length / 2; + + physDev->emh->offDescription = length ? sizeof(ENHMETAHEADER) : 0; + + physDev->emh->nPalEntries = 0; /* I guess this should start at 0 */ + + /* Size in pixels */ + physDev->emh->szlDevice.cx = GetDeviceCaps( physDev->ref_dc, HORZRES ); + physDev->emh->szlDevice.cy = GetDeviceCaps( physDev->ref_dc, VERTRES ); + + /* Size in millimeters */ + physDev->emh->szlMillimeters.cx = GetDeviceCaps( physDev->ref_dc, HORZSIZE ); + physDev->emh->szlMillimeters.cy = GetDeviceCaps( physDev->ref_dc, VERTSIZE ); + + /* Size in micrometers */ + physDev->emh->szlMicrometers.cx = physDev->emh->szlMillimeters.cx * 1000; + physDev->emh->szlMicrometers.cy = physDev->emh->szlMillimeters.cy * 1000; + + memcpy((char *)physDev->emh + sizeof(ENHMETAHEADER), description, length); + + if (filename) /* disk based metafile */ + { + if ((hFile = CreateFileW(filename, GENERIC_WRITE | GENERIC_READ, 0, + NULL, CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { + free_dc_ptr( dc ); + return 0; + } + if (!WriteFile( hFile, physDev->emh, size, &bytes_written, NULL )) { + free_dc_ptr( dc ); + CloseHandle( hFile ); + return 0; + } + physDev->hFile = hFile; + } + + TRACE("returning %p\n", physDev->dev.hdc); + ret = physDev->dev.hdc; + release_dc_ptr( dc ); + + return ret; +} + +/****************************************************************** + * CloseEnhMetaFile (GDI32.@) + */ +HENHMETAFILE WINAPI CloseEnhMetaFile(HDC hdc) /* [in] metafile DC */ +{ + HENHMETAFILE hmf; + EMFDRV_PDEVICE *physDev; + DC *dc; + EMREOF emr; + HANDLE hMapping = 0; + + TRACE("(%p)\n", hdc ); + + if (!(dc = get_dc_ptr( hdc ))) return NULL; + if (GetObjectType( hdc ) != OBJ_ENHMETADC) + { + release_dc_ptr( dc ); + return NULL; + } + if (dc->refcount != 1) + { + FIXME( "not deleting busy DC %p refcount %u\n", hdc, dc->refcount ); + release_dc_ptr( dc ); + return NULL; + } + physDev = (EMFDRV_PDEVICE *)dc->physDev; + + if(dc->saveLevel) + RestoreDC(hdc, 1); + + if (physDev->dc_brush) DeleteObject( physDev->dc_brush ); + if (physDev->dc_pen) DeleteObject( physDev->dc_pen ); + if (physDev->screen_dc) DeleteDC( physDev->screen_dc ); + + emr.emr.iType = EMR_EOF; + emr.emr.nSize = sizeof(emr); + emr.nPalEntries = 0; + emr.offPalEntries = FIELD_OFFSET(EMREOF, nSizeLast); + emr.nSizeLast = emr.emr.nSize; + EMFDRV_WriteRecord( dc->physDev, &emr.emr ); + + /* Update rclFrame if not initialized in CreateEnhMetaFile */ + if(physDev->emh->rclFrame.left > physDev->emh->rclFrame.right) { + physDev->emh->rclFrame.left = physDev->emh->rclBounds.left * + physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx; + physDev->emh->rclFrame.top = physDev->emh->rclBounds.top * + physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy; + physDev->emh->rclFrame.right = physDev->emh->rclBounds.right * + physDev->emh->szlMillimeters.cx * 100 / physDev->emh->szlDevice.cx; + physDev->emh->rclFrame.bottom = physDev->emh->rclBounds.bottom * + physDev->emh->szlMillimeters.cy * 100 / physDev->emh->szlDevice.cy; + } + + if (physDev->hFile) /* disk based metafile */ + { + if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) + { + CloseHandle( physDev->hFile ); + free_dc_ptr( dc ); + return 0; + } + + if (!WriteFile(physDev->hFile, physDev->emh, sizeof(*physDev->emh), + NULL, NULL)) + { + CloseHandle( physDev->hFile ); + free_dc_ptr( dc ); + return 0; + } + HeapFree( GetProcessHeap(), 0, physDev->emh ); + hMapping = CreateFileMappingA(physDev->hFile, NULL, PAGE_READONLY, 0, + 0, NULL); + TRACE("hMapping = %p\n", hMapping ); + physDev->emh = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0); + TRACE("view = %p\n", physDev->emh ); + CloseHandle( hMapping ); + CloseHandle( physDev->hFile ); + } + + hmf = EMF_Create_HENHMETAFILE( physDev->emh, (physDev->hFile != 0) ); + physDev->emh = NULL; /* So it won't be deleted */ + free_dc_ptr( dc ); + return hmf; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/objects.c b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/objects.c new file mode 100644 index 00000000000..ee156a2ddde --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/enhmfdrv/objects.c @@ -0,0 +1,528 @@ +/* + * Enhanced MetaFile objects + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "enhmfdrv/enhmetafiledrv.h" +#include "gdi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(enhmetafile); + + +/****************************************************************** + * EMFDRV_AddHandle + */ +static UINT EMFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE *)dev; + UINT index; + + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index] == 0) break; + if(index == physDev->handles_size) { + physDev->handles_size += HANDLE_LIST_INC; + physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + physDev->handles, + physDev->handles_size * sizeof(physDev->handles[0])); + } + physDev->handles[index] = get_full_gdi_handle( obj ); + + physDev->cur_handles++; + if(physDev->cur_handles > physDev->emh->nHandles) + physDev->emh->nHandles++; + + return index + 1; /* index 0 is reserved for the hmf, so we increment everything by 1 */ +} + +/****************************************************************** + * EMFDRV_FindObject + */ +static UINT EMFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev; + UINT index; + + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index] == obj) break; + + if(index == physDev->handles_size) return 0; + + return index + 1; +} + + +/****************************************************************** + * EMFDRV_DeleteObject + */ +BOOL EMFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj ) +{ + EMRDELETEOBJECT emr; + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*) dev; + UINT index; + BOOL ret = TRUE; + + if(!(index = EMFDRV_FindObject(dev, obj))) return FALSE; + + emr.emr.iType = EMR_DELETEOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + ret = FALSE; + + physDev->handles[index - 1] = 0; + physDev->cur_handles--; + return ret; +} + + +/*********************************************************************** + * EMFDRV_SelectBitmap + */ +HBITMAP EMFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap ) +{ + return 0; +} + + +/*********************************************************************** + * EMFDRV_CreateBrushIndirect + */ +DWORD EMFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) +{ + DWORD index = 0; + LOGBRUSH logbrush; + + if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return 0; + + switch (logbrush.lbStyle) { + case BS_SOLID: + case BS_HATCHED: + case BS_NULL: + { + EMRCREATEBRUSHINDIRECT emr; + emr.emr.iType = EMR_CREATEBRUSHINDIRECT; + emr.emr.nSize = sizeof(emr); + emr.ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); + emr.lb.lbStyle = logbrush.lbStyle; + emr.lb.lbColor = logbrush.lbColor; + emr.lb.lbHatch = logbrush.lbHatch; + + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + index = 0; + } + break; + case BS_PATTERN: + case BS_DIBPATTERN: + { + EMRCREATEDIBPATTERNBRUSHPT *emr; + char buffer[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)]; // ros! + //char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *info = (BITMAPINFO *)buffer; + DWORD info_size; + void *bits; + UINT usage; + + if (!get_brush_bitmap_info( hBrush, info, &bits, &usage )) break; + info_size = get_dib_info_size( info, usage ); + + emr = HeapAlloc( GetProcessHeap(), 0, + sizeof(EMRCREATEDIBPATTERNBRUSHPT)+info_size+info->bmiHeader.biSizeImage ); + if(!emr) break; + + 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; + /* FIXME: There is an extra DWORD written by native before the BMI. + * Not sure what its meant to contain. + */ + emr->offBmi = sizeof( EMRCREATEDIBPATTERNBRUSHPT ) + sizeof(DWORD); + emr->cbBmi = sizeof( BITMAPINFOHEADER ); + } + else + { + emr->emr.iType = EMR_CREATEDIBPATTERNBRUSHPT; + emr->offBmi = sizeof( EMRCREATEDIBPATTERNBRUSHPT ); + emr->cbBmi = info_size; + } + emr->ihBrush = index = EMFDRV_AddHandle( dev, hBrush ); + emr->iUsage = usage; + emr->offBits = emr->offBmi + emr->cbBmi; + emr->cbBits = info->bmiHeader.biSizeImage; + emr->emr.nSize = emr->offBits + emr->cbBits; + + memcpy( (BYTE *)emr + emr->offBmi, info, emr->cbBmi ); + memcpy( (BYTE *)emr + emr->offBits, bits, emr->cbBits ); + + if(!EMFDRV_WriteRecord( dev, &emr->emr )) + index = 0; + HeapFree( GetProcessHeap(), 0, emr ); + } + break; + + default: + FIXME("Unknown style %x\n", logbrush.lbStyle); + break; + } + return index; +} + + +/*********************************************************************** + * EMFDRV_SelectBrush + */ +HBRUSH EMFDRV_SelectBrush( PHYSDEV dev, HBRUSH hBrush, const struct brush_pattern *pattern ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTOBJECT emr; + DWORD index; + int i; + + if (physDev->restoring) return hBrush; /* don't output SelectObject records during RestoreDC */ + + /* 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 (hBrush == GetStockObject(i)) + { + index = i | 0x80000000; + goto found; + } + } + if((index = EMFDRV_FindObject(dev, hBrush)) != 0) + goto found; + + if (!(index = EMFDRV_CreateBrushIndirect(dev, hBrush ))) return 0; + GDI_hdc_using_object(hBrush, dev->hdc); + + found: + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? hBrush : 0; +} + + +/****************************************************************** + * EMFDRV_CreateFontIndirect + */ +static BOOL EMFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont ) +{ + DWORD index = 0; + EMREXTCREATEFONTINDIRECTW emr; + int i; + + if (!GetObjectW( hFont, sizeof(emr.elfw.elfLogFont), &emr.elfw.elfLogFont )) return FALSE; + + emr.emr.iType = EMR_EXTCREATEFONTINDIRECTW; + emr.emr.nSize = (sizeof(emr) + 3) / 4 * 4; + emr.ihFont = index = EMFDRV_AddHandle( dev, hFont ); + emr.elfw.elfFullName[0] = '\0'; + emr.elfw.elfStyle[0] = '\0'; + emr.elfw.elfVersion = 0; + emr.elfw.elfStyleSize = 0; + emr.elfw.elfMatch = 0; + emr.elfw.elfReserved = 0; + for(i = 0; i < ELF_VENDOR_SIZE; i++) + emr.elfw.elfVendorId[i] = 0; + emr.elfw.elfCulture = PAN_CULTURE_LATIN; + emr.elfw.elfPanose.bFamilyType = PAN_NO_FIT; + emr.elfw.elfPanose.bSerifStyle = PAN_NO_FIT; + emr.elfw.elfPanose.bWeight = PAN_NO_FIT; + emr.elfw.elfPanose.bProportion = PAN_NO_FIT; + emr.elfw.elfPanose.bContrast = PAN_NO_FIT; + emr.elfw.elfPanose.bStrokeVariation = PAN_NO_FIT; + emr.elfw.elfPanose.bArmStyle = PAN_NO_FIT; + emr.elfw.elfPanose.bLetterform = PAN_NO_FIT; + emr.elfw.elfPanose.bMidline = PAN_NO_FIT; + emr.elfw.elfPanose.bXHeight = PAN_NO_FIT; + + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + index = 0; + return index; +} + + +/*********************************************************************** + * EMFDRV_SelectFont + */ +HFONT EMFDRV_SelectFont( PHYSDEV dev, HFONT hFont, UINT *aa_flags ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTOBJECT emr; + DWORD index; + int i; + + if (physDev->restoring) goto done; /* don't output SelectObject records during RestoreDC */ + + /* If the object is a stock font object, do not need to create it. + * See definitions in wingdi.h for range of stock fonts. + * We do however have to handle setting the higher order bit to + * designate that this is a stock object. + */ + + for (i = OEM_FIXED_FONT; i <= DEFAULT_GUI_FONT; i++) + { + if (i != DEFAULT_PALETTE && hFont == GetStockObject(i)) + { + index = i | 0x80000000; + goto found; + } + } + + if((index = EMFDRV_FindObject(dev, hFont)) != 0) + goto found; + + if (!(index = EMFDRV_CreateFontIndirect(dev, hFont ))) return 0; + GDI_hdc_using_object(hFont, dev->hdc); + + found: + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + return 0; +done: + *aa_flags = GGO_BITMAP; /* no point in anti-aliasing on metafiles */ + dev = GET_NEXT_PHYSDEV( dev, pSelectFont ); + dev->funcs->pSelectFont( dev, hFont, aa_flags ); + return hFont; +} + + + +/****************************************************************** + * EMFDRV_CreatePenIndirect + */ +static DWORD EMFDRV_CreatePenIndirect(PHYSDEV dev, 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 = EMFDRV_AddHandle( dev, hPen ); + + if(!EMFDRV_WriteRecord( dev, &emr.emr )) + index = 0; + return index; +} + +/****************************************************************** + * EMFDRV_SelectPen + */ +HPEN EMFDRV_SelectPen(PHYSDEV dev, HPEN hPen, const struct brush_pattern *pattern ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTOBJECT emr; + DWORD index; + int i; + + if (physDev->restoring) return hPen; /* don't output SelectObject records during RestoreDC */ + + /* 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 (hPen == GetStockObject(i)) + { + index = i | 0x80000000; + goto found; + } + } + if((index = EMFDRV_FindObject(dev, hPen)) != 0) + goto found; + + if (!(index = EMFDRV_CreatePenIndirect(dev, hPen))) return 0; + GDI_hdc_using_object(hPen, dev->hdc); + + found: + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? hPen : 0; +} + + +/****************************************************************** + * EMFDRV_CreatePalette + */ +static DWORD EMFDRV_CreatePalette(PHYSDEV dev, 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 = EMFDRV_AddHandle( dev, hPal ); + + if (!EMFDRV_WriteRecord( dev, &pal.hdr.emr )) + pal.hdr.ihPal = 0; + return pal.hdr.ihPal; +} + +/****************************************************************** + * EMFDRV_SelectPalette + */ +HPALETTE EMFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPal, BOOL force ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTPALETTE emr; + DWORD index; + + if (physDev->restoring) return hPal; /* don't output SelectObject records during RestoreDC */ + + if (hPal == GetStockObject( DEFAULT_PALETTE )) + { + index = DEFAULT_PALETTE | 0x80000000; + goto found; + } + + if ((index = EMFDRV_FindObject( dev, hPal )) != 0) + goto found; + + if (!(index = EMFDRV_CreatePalette( dev, hPal ))) return 0; + GDI_hdc_using_object( hPal, dev->hdc ); + +found: + emr.emr.iType = EMR_SELECTPALETTE; + emr.emr.nSize = sizeof(emr); + emr.ihPal = index; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? hPal : 0; +} + +/****************************************************************** + * EMFDRV_SetDCBrushColor + */ +COLORREF EMFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTOBJECT emr; + DWORD index; + + if (GetCurrentObject( dev->hdc, OBJ_BRUSH ) != GetStockObject( DC_BRUSH )) return color; + + if (physDev->dc_brush) DeleteObject( physDev->dc_brush ); + if (!(physDev->dc_brush = CreateSolidBrush( color ))) return CLR_INVALID; + if (!(index = EMFDRV_CreateBrushIndirect(dev, physDev->dc_brush ))) return CLR_INVALID; + GDI_hdc_using_object( physDev->dc_brush, dev->hdc ); + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID; +} + +/****************************************************************** + * EMFDRV_SetDCPenColor + */ +COLORREF EMFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) +{ + EMFDRV_PDEVICE *physDev = (EMFDRV_PDEVICE*)dev; + EMRSELECTOBJECT emr; + DWORD index; + LOGPEN logpen = { PS_SOLID, { 0, 0 }, color }; + + if (GetCurrentObject( dev->hdc, OBJ_PEN ) != GetStockObject( DC_PEN )) return color; + + if (physDev->dc_pen) DeleteObject( physDev->dc_pen ); + if (!(physDev->dc_pen = CreatePenIndirect( &logpen ))) return CLR_INVALID; + if (!(index = EMFDRV_CreatePenIndirect(dev, physDev->dc_pen))) return CLR_INVALID; + GDI_hdc_using_object( physDev->dc_pen, dev->hdc ); + emr.emr.iType = EMR_SELECTOBJECT; + emr.emr.nSize = sizeof(emr); + emr.ihObject = index; + return EMFDRV_WriteRecord( dev, &emr.emr ) ? color : CLR_INVALID; +} + +/****************************************************************** + * EMFDRV_GdiComment + */ +BOOL EMFDRV_GdiComment(PHYSDEV dev, UINT bytes, const BYTE *buffer) +{ + EMRGDICOMMENT *emr; + UINT total, rounded_size; + BOOL ret; + + rounded_size = (bytes+3) & ~3; + total = offsetof(EMRGDICOMMENT,Data) + rounded_size; + + emr = HeapAlloc(GetProcessHeap(), 0, total); + emr->emr.iType = EMR_GDICOMMENT; + emr->emr.nSize = total; + emr->cbData = bytes; + memset(&emr->Data[bytes], 0, rounded_size - bytes); + memcpy(&emr->Data[0], buffer, bytes); + + ret = EMFDRV_WriteRecord( dev, &emr->emr ); + + HeapFree(GetProcessHeap(), 0, emr); + + return ret; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/gdi_private.h b/reactos/win32ss/gdi/gdi32/wine/gdi_private.h new file mode 100644 index 00000000000..5d9390e537e --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/gdi_private.h @@ -0,0 +1,145 @@ +/* + * GDI definitions + * + * Copyright 1993 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_GDI_PRIVATE_H +#define __WINE_GDI_PRIVATE_H + +#include +#include +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include + +/* Metafile defines */ +#define META_EOF 0x0000 +/* values of mtType in METAHEADER. Note however that the disk image of a disk + based metafile has mtType == 1 */ +#define METAFILE_MEMORY 1 +#define METAFILE_DISK 2 +#define MFHEADERSIZE (sizeof(METAHEADER)) +#define MFVERSION 0x300 + +typedef struct { + EMR emr; + INT nBreakExtra; + INT nBreakCount; +} EMRSETTEXTJUSTIFICATION, *PEMRSETTEXTJUSTIFICATION; + +struct gdi_obj_funcs +{ + HGDIOBJ (*pSelectObject)( HGDIOBJ handle, HDC hdc ); + INT (*pGetObjectA)( HGDIOBJ handle, INT count, LPVOID buffer ); + INT (*pGetObjectW)( HGDIOBJ handle, INT count, LPVOID buffer ); + BOOL (*pUnrealizeObject)( HGDIOBJ handle ); + BOOL (*pDeleteObject)( HGDIOBJ handle ); +}; + +typedef struct tagWINEDC +{ + HDC hdc; + PHYSDEV physDev; /* current top of the physdev stack */ + LONG refcount; /* thread refcount */ + INT saveLevel; + struct gdi_physdev NullPhysDev; + HFONT hFont; + HBRUSH hBrush; + HPEN hPen; + HPALETTE hPalette; +} WINEDC, DC; + +/* brush.c */ +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; +extern void free_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; +extern DC *get_dc_ptr( HDC hdc ) DECLSPEC_HIDDEN; +extern void release_dc_ptr( DC *dc ) DECLSPEC_HIDDEN; + +/* dib.c */ +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; + +/* gdiobj.c */ +extern HGDIOBJ alloc_gdi_handle( void *obj, WORD type, const struct gdi_obj_funcs *funcs ) DECLSPEC_HIDDEN; +extern void *free_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN; +extern HGDIOBJ get_full_gdi_handle( HGDIOBJ handle ) DECLSPEC_HIDDEN; +extern void *GDI_GetObjPtr( HGDIOBJ, WORD ) DECLSPEC_HIDDEN; +extern void GDI_ReleaseObj( HGDIOBJ ) DECLSPEC_HIDDEN; +extern void GDI_hdc_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN; +extern void GDI_hdc_not_using_object(HGDIOBJ obj, HDC hdc) DECLSPEC_HIDDEN; + +/* metafile.c */ +extern HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) DECLSPEC_HIDDEN; +extern METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mr, LPCVOID filename, BOOL unicode ) DECLSPEC_HIDDEN; + +/* palette.c */ +extern HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg) DECLSPEC_HIDDEN; +extern UINT WINAPI GDIRealizePalette( HDC hdc ) DECLSPEC_HIDDEN; + +#define EMR_SETLINKEDUFI 119 + +/* Undocumented value for DIB's iUsage: Indicates a mono DIB w/o pal entries */ +#define DIB_PAL_MONO 2 + +BOOL WINAPI SetVirtualResolution(HDC hdc, DWORD horz_res, DWORD vert_res, DWORD horz_size, DWORD vert_size); + +static inline int get_dib_stride( int width, int bpp ) +{ + return ((width * bpp + 31) >> 3) & ~3; +} + +static inline int get_dib_image_size( const BITMAPINFO *info ) +{ + return get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount ) + * abs( info->bmiHeader.biHeight ); +} + +/* only for use on sanitized BITMAPINFO structures */ +static inline int get_dib_info_size( const BITMAPINFO *info, UINT coloruse ) +{ + if (info->bmiHeader.biCompression == BI_BITFIELDS) + return sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD); + if (coloruse == DIB_PAL_COLORS) + return sizeof(BITMAPINFOHEADER) + info->bmiHeader.biClrUsed * sizeof(WORD); + return FIELD_OFFSET( BITMAPINFO, bmiColors[info->bmiHeader.biClrUsed] ); +} + +/* Special sauce for reactos */ +#define GDIRealizePalette RealizePalette +#define GDISelectPalette SelectPalette + +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 + +BOOL WINAPI SetWorldTransformForMetafile(HDC hdc, const XFORM *pxform); +#define SetWorldTransform SetWorldTransformForMetafile + +#undef ASSERT +#define ASSERT(x) if (!(x)) __int2c() + +#endif /* __WINE_GDI_PRIVATE_H */ + diff --git a/reactos/win32ss/gdi/gdi32/wine/metafile.c b/reactos/win32ss/gdi/gdi32/wine/metafile.c new file mode 100644 index 00000000000..afead999c86 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/metafile.c @@ -0,0 +1,1451 @@ +/* + * Metafile functions + * + * Copyright David W. Metcalfe, 1994 + * Copyright Niels de Carpentier, 1996 + * Copyright Albrecht Kleine, 1996 + * Copyright Huw Davies, 1996 + * + * 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 + * + * NOTES + * + * These functions are primarily involved with metafile playback or anything + * that touches a HMETAFILE. + * For recording of metafiles look in graphics/metafiledrv/ + * + * Note that (32 bit) HMETAFILEs are GDI objects, while HMETAFILE16s are + * global memory handles so these cannot be interchanged. + * + * Memory-based metafiles are just stored as a continuous block of memory with + * a METAHEADER at the head with METARECORDs appended to it. mtType is + * METAFILE_MEMORY (1). Note this is identical to the disk image of a + * disk-based metafile - even mtType is METAFILE_MEMORY. + * 16bit HMETAFILE16s are global handles to this block + * 32bit HMETAFILEs are GDI handles METAFILEOBJs, which contains a ptr to + * the memory. + * Disk-based metafiles are rather different. HMETAFILE16s point to a + * METAHEADER which has mtType equal to METAFILE_DISK (2). Following the 9 + * WORDs of the METAHEADER there are a further 3 WORDs of 0, 1 of 0x117, 1 + * more 0, then 2 which may be a time stamp of the file and then the path of + * the file (METAHEADERDISK). I've copied this for 16bit compatibility. + * + * HDMD - 14/4/1999 + */ + +#include "config.h" + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "winreg.h" +#include "winnls.h" + +#include "winternl.h" +#include "gdi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +#include "pshpack1.h" +typedef struct +{ + DWORD dw1, dw2, dw3; + WORD w4; + CHAR filename[0x100]; +} METAHEADERDISK; +#include "poppack.h" + + +/****************************************************************** + * MF_AddHandle + * + * Add a handle to an external handle table and return the index + */ +static int MF_AddHandle(HANDLETABLE *ht, UINT htlen, HGDIOBJ hobj) +{ + int i; + + for (i = 0; i < htlen; i++) + { + if (*(ht->objectHandle + i) == 0) + { + *(ht->objectHandle + i) = hobj; + return i; + } + } + return -1; +} + + +/****************************************************************** + * MF_Create_HMETATFILE + * + * Creates a (32 bit) HMETAFILE object from a METAHEADER + * + * HMETAFILEs are GDI objects. + */ +HMETAFILE MF_Create_HMETAFILE(METAHEADER *mh) +{ + return alloc_gdi_handle( mh, OBJ_METAFILE, NULL ); +} + +/****************************************************************** + * convert_points + * + * Convert an array of POINTS to an array of POINT. + * Result must be freed by caller. + */ +static POINT *convert_points( UINT count, const POINTS *pts ) +{ + UINT i; + POINT *ret = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*ret) ); + if (ret) + { + for (i = 0; i < count; i++) + { + ret[i].x = pts[i].x; + ret[i].y = pts[i].y; + } + } + return ret; +} + +/****************************************************************** + * DeleteMetaFile (GDI32.@) + * + * Delete a memory-based metafile. + */ + +BOOL WINAPI DeleteMetaFile( HMETAFILE hmf ) +{ + METAHEADER *mh = free_gdi_handle( hmf ); + if (!mh) return FALSE; + return HeapFree( GetProcessHeap(), 0, mh ); +} + +/****************************************************************** + * MF_ReadMetaFile + * + * Returns a pointer to a memory based METAHEADER read in from file HFILE + * + */ +static METAHEADER *MF_ReadMetaFile(HANDLE hfile) +{ + METAHEADER *mh; + DWORD BytesRead, size; + + size = sizeof(METAHEADER); + mh = HeapAlloc( GetProcessHeap(), 0, size ); + if(!mh) return NULL; + if(ReadFile( hfile, mh, size, &BytesRead, NULL) == 0 || + BytesRead != size) { + HeapFree( GetProcessHeap(), 0, mh ); + return NULL; + } + if (mh->mtType != METAFILE_MEMORY || mh->mtVersion != MFVERSION || + mh->mtHeaderSize != size / 2) + { + HeapFree( GetProcessHeap(), 0, mh ); + return NULL; + } + size = mh->mtSize * 2; + mh = HeapReAlloc( GetProcessHeap(), 0, mh, size ); + if(!mh) return NULL; + size -= sizeof(METAHEADER); + if(ReadFile( hfile, (char *)mh + sizeof(METAHEADER), size, &BytesRead, + NULL) == 0 || + BytesRead != size) { + HeapFree( GetProcessHeap(), 0, mh ); + return NULL; + } + + if (mh->mtType != METAFILE_MEMORY) { + WARN("Disk metafile had mtType = %04x\n", mh->mtType); + mh->mtType = METAFILE_MEMORY; + } + return mh; +} + +/****************************************************************** + * GetMetaFileA (GDI32.@) + * + * Read a metafile from a file. Returns handle to a memory-based metafile. + */ +HMETAFILE WINAPI GetMetaFileA( LPCSTR lpFilename ) +{ + METAHEADER *mh; + HANDLE hFile; + + TRACE("%s\n", lpFilename); + + if(!lpFilename) + return 0; + + if((hFile = CreateFileA(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) + return 0; + + mh = MF_ReadMetaFile(hFile); + CloseHandle(hFile); + if(!mh) return 0; + return MF_Create_HMETAFILE( mh ); +} + +/****************************************************************** + * GetMetaFileW (GDI32.@) + */ +HMETAFILE WINAPI GetMetaFileW( LPCWSTR lpFilename ) +{ + METAHEADER *mh; + HANDLE hFile; + + TRACE("%s\n", debugstr_w(lpFilename)); + + if(!lpFilename) + return 0; + + if((hFile = CreateFileW(lpFilename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) + return 0; + + mh = MF_ReadMetaFile(hFile); + CloseHandle(hFile); + if(!mh) return 0; + return MF_Create_HMETAFILE( mh ); +} + + +/****************************************************************** + * MF_LoadDiskBasedMetaFile + * + * Creates a new memory-based metafile from a disk-based one. + */ +static METAHEADER *MF_LoadDiskBasedMetaFile(METAHEADER *mh) +{ + METAHEADERDISK *mhd; + HANDLE hfile; + METAHEADER *mh2; + + if(mh->mtType != METAFILE_DISK) { + ERR("Not a disk based metafile\n"); + return NULL; + } + mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER)); + + if((hfile = CreateFileA(mhd->filename, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) { + WARN("Can't open file of disk based metafile\n"); + return NULL; + } + mh2 = MF_ReadMetaFile(hfile); + CloseHandle(hfile); + return mh2; +} + +/****************************************************************** + * MF_CreateMetaHeaderDisk + * + * Take a memory based METAHEADER and change it to a disk based METAHEADER + * associated with filename. Note: Trashes contents of old one. + */ +METAHEADER *MF_CreateMetaHeaderDisk(METAHEADER *mh, LPCVOID filename, BOOL uni ) +{ + METAHEADERDISK *mhd; + + mh = HeapReAlloc( GetProcessHeap(), 0, mh, + sizeof(METAHEADER) + sizeof(METAHEADERDISK)); + mh->mtType = METAFILE_DISK; + mhd = (METAHEADERDISK *)((char *)mh + sizeof(METAHEADER)); + + if( uni ) + WideCharToMultiByte(CP_ACP, 0, filename, -1, + mhd->filename, sizeof mhd->filename, NULL, NULL); + else + lstrcpynA( mhd->filename, filename, sizeof mhd->filename ); + return mh; +} + +/* return a copy of the metafile bits, to be freed with HeapFree */ +static METAHEADER *get_metafile_bits( HMETAFILE hmf ) +{ + METAHEADER *ret, *mh = GDI_GetObjPtr( hmf, OBJ_METAFILE ); + + if (!mh) return NULL; + + if (mh->mtType != METAFILE_DISK) + { + ret = HeapAlloc( GetProcessHeap(), 0, mh->mtSize * 2 ); + if (ret) memcpy( ret, mh, mh->mtSize * 2 ); + } + else ret = MF_LoadDiskBasedMetaFile( mh ); + + GDI_ReleaseObj( hmf ); + return ret; +} + +/****************************************************************** + * CopyMetaFileW (GDI32.@) + * + * Copies the metafile corresponding to hSrcMetaFile to either + * a disk file, if a filename is given, or to a new memory based + * metafile, if lpFileName is NULL. + * + * PARAMS + * hSrcMetaFile [I] handle of metafile to copy + * lpFilename [I] filename if copying to a file + * + * RETURNS + * Handle to metafile copy on success, NULL on failure. + * + * BUGS + * Copying to disk returns NULL even if successful. + */ +HMETAFILE WINAPI CopyMetaFileW( HMETAFILE hSrcMetaFile, LPCWSTR lpFilename ) +{ + METAHEADER *mh = get_metafile_bits( hSrcMetaFile ); + HANDLE hFile; + + TRACE("(%p,%s)\n", hSrcMetaFile, debugstr_w(lpFilename)); + + if(!mh) return 0; + + if(lpFilename) { /* disk based metafile */ + DWORD w; + if((hFile = CreateFileW(lpFilename, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { + HeapFree( GetProcessHeap(), 0, mh ); + return 0; + } + WriteFile(hFile, mh, mh->mtSize * 2, &w, NULL); + CloseHandle(hFile); + } + + return MF_Create_HMETAFILE( mh ); +} + + +/****************************************************************** + * CopyMetaFileA (GDI32.@) + * + * See CopyMetaFileW. + */ +HMETAFILE WINAPI CopyMetaFileA( HMETAFILE hSrcMetaFile, LPCSTR lpFilename ) +{ + UNICODE_STRING lpFilenameW; + HMETAFILE ret = 0; + + if (lpFilename) RtlCreateUnicodeStringFromAsciiz(&lpFilenameW, lpFilename); + else lpFilenameW.Buffer = NULL; + + ret = CopyMetaFileW( hSrcMetaFile, lpFilenameW.Buffer ); + if (lpFilenameW.Buffer) + RtlFreeUnicodeString(&lpFilenameW); + return ret; +} + +/****************************************************************** + * PlayMetaFile (GDI32.@) + * + * Renders the metafile specified by hmf in the DC specified by + * hdc. Returns FALSE on failure, TRUE on success. + * + * PARAMS + * hdc [I] handle of DC to render in + * hmf [I] handle of metafile to render + * + * RETURNS + * Success: TRUE + * Failure: FALSE + */ +BOOL WINAPI PlayMetaFile( HDC hdc, HMETAFILE hmf ) +{ + METAHEADER *mh = get_metafile_bits( hmf ); + METARECORD *mr; + HANDLETABLE *ht; + unsigned int offset = 0; + WORD i; + HPEN hPen; + HBRUSH hBrush; + HPALETTE hPal; + HRGN hRgn; + + if (!mh) return FALSE; + + /* save DC */ + hPen = GetCurrentObject(hdc, OBJ_PEN); + hBrush = GetCurrentObject(hdc, OBJ_BRUSH); + hPal = GetCurrentObject(hdc, OBJ_PAL); + + hRgn = CreateRectRgn(0, 0, 0, 0); + if (!GetClipRgn(hdc, hRgn)) + { + DeleteObject(hRgn); + hRgn = 0; + } + + /* create the handle table */ + ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(HANDLETABLE) * mh->mtNoObjects); + if(!ht) + { + HeapFree( GetProcessHeap(), 0, mh ); + return FALSE; + } + + /* loop through metafile playing records */ + offset = mh->mtHeaderSize * 2; + while (offset < mh->mtSize * 2) + { + mr = (METARECORD *)((char *)mh + offset); + TRACE("offset=%04x,size=%08x\n", + offset, mr->rdSize); + if (mr->rdSize < 3) { /* catch illegal record sizes */ + TRACE("Entry got size %d at offset %d, total mf length is %d\n", + mr->rdSize,offset,mh->mtSize*2); + break; + } + + offset += mr->rdSize * 2; + if (mr->rdFunction == META_EOF) { + TRACE("Got META_EOF so stopping\n"); + break; + } + PlayMetaFileRecord( hdc, ht, mr, mh->mtNoObjects ); + } + + /* restore DC */ + SelectObject(hdc, hPen); + SelectObject(hdc, hBrush); + SelectPalette(hdc, hPal, FALSE); + ExtSelectClipRgn(hdc, hRgn, RGN_COPY); + DeleteObject(hRgn); + + /* free objects in handle table */ + for(i = 0; i < mh->mtNoObjects; i++) + if(*(ht->objectHandle + i) != 0) + DeleteObject(*(ht->objectHandle + i)); + + HeapFree( GetProcessHeap(), 0, ht ); + HeapFree( GetProcessHeap(), 0, mh ); + return TRUE; +} + +/****************************************************************** + * EnumMetaFile (GDI32.@) + * + * Loop through the metafile records in hmf, calling the user-specified + * function for each one, stopping when the user's function returns FALSE + * (which is considered to be failure) + * or when no records are left (which is considered to be success). + * + * RETURNS + * TRUE on success, FALSE on failure. + */ +BOOL WINAPI EnumMetaFile(HDC hdc, HMETAFILE hmf, MFENUMPROC lpEnumFunc, LPARAM lpData) +{ + METAHEADER *mh = get_metafile_bits( hmf ); + METARECORD *mr; + HANDLETABLE *ht; + BOOL result = TRUE; + int i; + unsigned int offset = 0; + HPEN hPen; + HBRUSH hBrush; + HFONT hFont; + + TRACE("(%p,%p,%p,%lx)\n", hdc, hmf, lpEnumFunc, lpData); + + if (!mh) return FALSE; + + /* save the current pen, brush and font */ + hPen = GetCurrentObject(hdc, OBJ_PEN); + hBrush = GetCurrentObject(hdc, OBJ_BRUSH); + hFont = GetCurrentObject(hdc, OBJ_FONT); + + ht = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(HANDLETABLE) * mh->mtNoObjects); + + /* loop through metafile records */ + offset = mh->mtHeaderSize * 2; + + while (offset < (mh->mtSize * 2)) + { + mr = (METARECORD *)((char *)mh + offset); + if(mr->rdFunction == META_EOF) { + TRACE("Got META_EOF so stopping\n"); + break; + } + TRACE("Calling EnumFunc with record type %x\n", + mr->rdFunction); + if (!lpEnumFunc( hdc, ht, mr, mh->mtNoObjects, lpData )) + { + result = FALSE; + break; + } + + offset += (mr->rdSize * 2); + } + + /* restore pen, brush and font */ + SelectObject(hdc, hBrush); + SelectObject(hdc, hPen); + SelectObject(hdc, hFont); + + /* free objects in handle table */ + for(i = 0; i < mh->mtNoObjects; i++) + if(*(ht->objectHandle + i) != 0) + DeleteObject(*(ht->objectHandle + i)); + + HeapFree( GetProcessHeap(), 0, ht); + HeapFree( GetProcessHeap(), 0, mh); + return result; +} + +static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn ); +static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr); +/****************************************************************** + * PlayMetaFileRecord (GDI32.@) + * + * Render a single metafile record specified by *mr in the DC hdc, while + * using the handle table *ht, of length handles, + * to store metafile objects. + * + * BUGS + * The following metafile records are unimplemented: + * + * DRAWTEXT, ANIMATEPALETTE, SETPALENTRIES, + * RESIZEPALETTE, EXTFLOODFILL, RESETDC, STARTDOC, STARTPAGE, ENDPAGE, + * ABORTDOC, ENDDOC, CREATEBRUSH, CREATEBITMAPINDIRECT, and CREATEBITMAP. + */ +BOOL WINAPI PlayMetaFileRecord( HDC hdc, HANDLETABLE *ht, METARECORD *mr, UINT handles ) +{ + short s1; + POINT *pt; + BITMAPINFOHEADER *infohdr; + + TRACE("(%p %p %p %u) function %04x\n", hdc, ht, mr, handles, mr->rdFunction); + + switch (mr->rdFunction) + { + case META_EOF: + break; + + case META_DELETEOBJECT: + DeleteObject(*(ht->objectHandle + mr->rdParm[0])); + *(ht->objectHandle + mr->rdParm[0]) = 0; + break; + + case META_SETBKCOLOR: + SetBkColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_SETBKMODE: + SetBkMode(hdc, mr->rdParm[0]); + break; + + case META_SETMAPMODE: + SetMapMode(hdc, mr->rdParm[0]); + break; + + case META_SETROP2: + SetROP2(hdc, mr->rdParm[0]); + break; + + case META_SETRELABS: + SetRelAbs(hdc, mr->rdParm[0]); + break; + + case META_SETPOLYFILLMODE: + SetPolyFillMode(hdc, mr->rdParm[0]); + break; + + case META_SETSTRETCHBLTMODE: + SetStretchBltMode(hdc, mr->rdParm[0]); + break; + + case META_SETTEXTCOLOR: + SetTextColor(hdc, MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_SETWINDOWORG: + SetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_SETWINDOWEXT: + SetWindowExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_SETVIEWPORTORG: + SetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_SETVIEWPORTEXT: + SetViewportExtEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_OFFSETWINDOWORG: + OffsetWindowOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_SCALEWINDOWEXT: + ScaleWindowExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_OFFSETVIEWPORTORG: + OffsetViewportOrgEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_SCALEVIEWPORTEXT: + ScaleViewportExtEx(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_LINETO: + LineTo(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_MOVETO: + MoveToEx(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0], NULL); + break; + + case META_EXCLUDECLIPRECT: + ExcludeClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); + break; + + case META_INTERSECTCLIPRECT: + IntersectClipRect( hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); + break; + + case META_ARC: + Arc(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], + (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_ELLIPSE: + Ellipse(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_FLOODFILL: + FloodFill(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_PIE: + Pie(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], + (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_RECTANGLE: + Rectangle(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_ROUNDRECT: + RoundRect(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_PATBLT: + PatBlt(hdc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_SAVEDC: + SaveDC(hdc); + break; + + case META_SETPIXEL: + SetPixel(hdc, (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_OFFSETCLIPRGN: + OffsetClipRgn( hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0] ); + break; + + case META_TEXTOUT: + s1 = mr->rdParm[0]; + TextOutA(hdc, (SHORT)mr->rdParm[((s1 + 1) >> 1) + 2], + (SHORT)mr->rdParm[((s1 + 1) >> 1) + 1], + (char *)(mr->rdParm + 1), s1); + break; + + case META_POLYGON: + if ((pt = convert_points( mr->rdParm[0], (POINTS *)(mr->rdParm + 1)))) + { + Polygon(hdc, pt, mr->rdParm[0]); + HeapFree( GetProcessHeap(), 0, pt ); + } + break; + + case META_POLYPOLYGON: + { + UINT i, total; + SHORT *counts = (SHORT *)(mr->rdParm + 1); + + for (i = total = 0; i < mr->rdParm[0]; i++) total += counts[i]; + pt = convert_points( total, (POINTS *)(counts + mr->rdParm[0]) ); + if (pt) + { + INT *cnt32 = HeapAlloc( GetProcessHeap(), 0, mr->rdParm[0] * sizeof(*cnt32) ); + if (cnt32) + { + for (i = 0; i < mr->rdParm[0]; i++) cnt32[i] = counts[i]; + PolyPolygon( hdc, pt, cnt32, mr->rdParm[0]); + HeapFree( GetProcessHeap(), 0, cnt32 ); + } + } + HeapFree( GetProcessHeap(), 0, pt ); + } + break; + + case META_POLYLINE: + if ((pt = convert_points( mr->rdParm[0], (POINTS *)(mr->rdParm + 1)))) + { + Polyline( hdc, pt, mr->rdParm[0] ); + HeapFree( GetProcessHeap(), 0, pt ); + } + break; + + case META_RESTOREDC: + RestoreDC(hdc, (SHORT)mr->rdParm[0]); + break; + + case META_SELECTOBJECT: + SelectObject(hdc, *(ht->objectHandle + mr->rdParm[0])); + break; + + case META_CHORD: + Chord(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], + (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_CREATEPATTERNBRUSH: + switch (mr->rdParm[0]) + { + case BS_PATTERN: + infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2); + MF_AddHandle(ht, handles, + CreatePatternBrush(CreateBitmap(infohdr->biWidth, + infohdr->biHeight, + infohdr->biPlanes, + infohdr->biBitCount, + mr->rdParm + + (sizeof(BITMAPINFOHEADER) / 2) + 4))); + break; + + case BS_DIBPATTERN: + infohdr = (BITMAPINFOHEADER *)(mr->rdParm + 2); + MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( infohdr, mr->rdParm[1] )); + break; + + default: + ERR("META_CREATEPATTERNBRUSH: Unknown pattern type %d\n", + mr->rdParm[0]); + break; + } + break; + + case META_CREATEPENINDIRECT: + { + LOGPEN pen; + pen.lopnStyle = mr->rdParm[0]; + pen.lopnWidth.x = (SHORT)mr->rdParm[1]; + pen.lopnWidth.y = (SHORT)mr->rdParm[2]; + pen.lopnColor = MAKELONG( mr->rdParm[3], mr->rdParm[4] ); + MF_AddHandle(ht, handles, CreatePenIndirect( &pen )); + } + break; + + case META_CREATEFONTINDIRECT: + { + LOGFONTA font; + font.lfHeight = (SHORT)mr->rdParm[0]; + font.lfWidth = (SHORT)mr->rdParm[1]; + font.lfEscapement = (SHORT)mr->rdParm[2]; + font.lfOrientation = (SHORT)mr->rdParm[3]; + font.lfWeight = (SHORT)mr->rdParm[4]; + font.lfItalic = LOBYTE(mr->rdParm[5]); + font.lfUnderline = HIBYTE(mr->rdParm[5]); + font.lfStrikeOut = LOBYTE(mr->rdParm[6]); + font.lfCharSet = HIBYTE(mr->rdParm[6]); + font.lfOutPrecision = LOBYTE(mr->rdParm[7]); + font.lfClipPrecision = HIBYTE(mr->rdParm[7]); + font.lfQuality = LOBYTE(mr->rdParm[8]); + font.lfPitchAndFamily = HIBYTE(mr->rdParm[8]); + memcpy( font.lfFaceName, mr->rdParm + 9, LF_FACESIZE ); + MF_AddHandle(ht, handles, CreateFontIndirectA( &font )); + } + break; + + case META_CREATEBRUSHINDIRECT: + { + LOGBRUSH brush; + brush.lbStyle = mr->rdParm[0]; + brush.lbColor = MAKELONG( mr->rdParm[1], mr->rdParm[2] ); + brush.lbHatch = mr->rdParm[3]; + MF_AddHandle(ht, handles, CreateBrushIndirect( &brush )); + } + break; + + case META_CREATEPALETTE: + MF_AddHandle(ht, handles, CreatePalette((LPLOGPALETTE)mr->rdParm)); + break; + + case META_SETTEXTALIGN: + SetTextAlign(hdc, mr->rdParm[0]); + break; + + case META_SELECTPALETTE: + GDISelectPalette(hdc, *(ht->objectHandle + mr->rdParm[1]), mr->rdParm[0]); + break; + + case META_SETMAPPERFLAGS: + SetMapperFlags(hdc, MAKELONG(mr->rdParm[0],mr->rdParm[1])); + break; + + case META_REALIZEPALETTE: + GDIRealizePalette(hdc); + break; + + case META_ESCAPE: + switch (mr->rdParm[0]) { + case GETSCALINGFACTOR: /* get function ... would just NULL dereference */ + case GETPHYSPAGESIZE: + case GETPRINTINGOFFSET: + return FALSE; + case SETABORTPROC: + FIXME("Filtering Escape(SETABORTPROC), possible virus?\n"); + return FALSE; + } + Escape(hdc, mr->rdParm[0], mr->rdParm[1], (LPCSTR)&mr->rdParm[2], NULL); + break; + + case META_EXTTEXTOUT: + MF_Play_MetaExtTextOut( hdc, mr ); + break; + + case META_STRETCHDIB: + { + LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[11]); + LPSTR bits = (LPSTR)info + bitmap_info_size( info, mr->rdParm[2] ); + StretchDIBits( hdc, (SHORT)mr->rdParm[10], (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], + (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], + (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], bits, info, + mr->rdParm[2],MAKELONG(mr->rdParm[0],mr->rdParm[1])); + } + break; + + case META_DIBSTRETCHBLT: + { + LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[10]); + LPSTR bits = (LPSTR)info + bitmap_info_size( info, DIB_RGB_COLORS ); + StretchDIBits( hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], + (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], bits, info, + DIB_RGB_COLORS,MAKELONG(mr->rdParm[0],mr->rdParm[1])); + } + break; + + case META_STRETCHBLT: + { + HDC hdcSrc = CreateCompatibleDC(hdc); + HBITMAP hbitmap = CreateBitmap(mr->rdParm[10], /*Width */ + mr->rdParm[11], /*Height*/ + mr->rdParm[13], /*Planes*/ + mr->rdParm[14], /*BitsPixel*/ + &mr->rdParm[15]); /*bits*/ + SelectObject(hdcSrc,hbitmap); + StretchBlt(hdc, (SHORT)mr->rdParm[9], (SHORT)mr->rdParm[8], + (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], + hdcSrc, (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], + (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + MAKELONG(mr->rdParm[0],mr->rdParm[1])); + DeleteDC(hdcSrc); + } + break; + + case META_BITBLT: + { + HDC hdcSrc = CreateCompatibleDC(hdc); + HBITMAP hbitmap = CreateBitmap(mr->rdParm[7]/*Width */, + mr->rdParm[8]/*Height*/, + mr->rdParm[10]/*Planes*/, + mr->rdParm[11]/*BitsPixel*/, + &mr->rdParm[12]/*bits*/); + SelectObject(hdcSrc,hbitmap); + BitBlt(hdc,(SHORT)mr->rdParm[6],(SHORT)mr->rdParm[5], + (SHORT)mr->rdParm[4],(SHORT)mr->rdParm[3], + hdcSrc, (SHORT)mr->rdParm[2],(SHORT)mr->rdParm[1], + MAKELONG(0,mr->rdParm[0])); + DeleteDC(hdcSrc); + } + break; + + case META_CREATEREGION: + { + HRGN hrgn = CreateRectRgn(0,0,0,0); + + MF_Play_MetaCreateRegion(mr, hrgn); + MF_AddHandle(ht, handles, hrgn); + } + break; + + case META_FILLREGION: + FillRgn(hdc, *(ht->objectHandle + mr->rdParm[1]), + *(ht->objectHandle + mr->rdParm[0])); + break; + + case META_FRAMEREGION: + FrameRgn(hdc, *(ht->objectHandle + mr->rdParm[3]), + *(ht->objectHandle + mr->rdParm[2]), + (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_INVERTREGION: + InvertRgn(hdc, *(ht->objectHandle + mr->rdParm[0])); + break; + + case META_PAINTREGION: + PaintRgn(hdc, *(ht->objectHandle + mr->rdParm[0])); + break; + + case META_SELECTCLIPREGION: + { + HRGN hrgn = 0; + + if (mr->rdParm[0]) hrgn = *(ht->objectHandle + mr->rdParm[0]); + SelectClipRgn(hdc, hrgn); + } + break; + + case META_DIBCREATEPATTERNBRUSH: + /* mr->rdParm[0] may be BS_PATTERN or BS_DIBPATTERN: + but there's no difference */ + MF_AddHandle(ht, handles, CreateDIBPatternBrushPt( mr->rdParm + 2, mr->rdParm[1] )); + break; + + case META_DIBBITBLT: + /* In practice I've found that there are two layouts for + META_DIBBITBLT, one (the first here) is the usual one when a src + dc is actually passed to it, the second occurs when the src dc is + passed in as NULL to the creating BitBlt. As the second case has + no dib, a size check will suffice to distinguish. + + Caolan.McNamara@ul.ie */ + + if (mr->rdSize > 12) { + LPBITMAPINFO info = (LPBITMAPINFO) &(mr->rdParm[8]); + LPSTR bits = (LPSTR)info + bitmap_info_size(info, mr->rdParm[0]); + + StretchDIBits(hdc, (SHORT)mr->rdParm[7], (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], + (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], (SHORT)mr->rdParm[2], + (SHORT)mr->rdParm[5], (SHORT)mr->rdParm[4], bits, info, + DIB_RGB_COLORS, MAKELONG(mr->rdParm[0], mr->rdParm[1])); + } + else /* equivalent to a PatBlt */ + PatBlt(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], + (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], + MAKELONG(mr->rdParm[0], mr->rdParm[1])); + break; + + case META_SETTEXTCHAREXTRA: + SetTextCharacterExtra(hdc, (SHORT)mr->rdParm[0]); + break; + + case META_SETTEXTJUSTIFICATION: + SetTextJustification(hdc, (SHORT)mr->rdParm[1], (SHORT)mr->rdParm[0]); + break; + + case META_EXTFLOODFILL: + ExtFloodFill(hdc, (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], + MAKELONG(mr->rdParm[1], mr->rdParm[2]), + mr->rdParm[0]); + break; + + case META_SETDIBTODEV: + { + BITMAPINFO *info = (BITMAPINFO *) &(mr->rdParm[9]); + char *bits = (char *)info + bitmap_info_size( info, mr->rdParm[0] ); + SetDIBitsToDevice(hdc, (SHORT)mr->rdParm[8], (SHORT)mr->rdParm[7], + (SHORT)mr->rdParm[6], (SHORT)mr->rdParm[5], + (SHORT)mr->rdParm[4], (SHORT)mr->rdParm[3], + mr->rdParm[2], mr->rdParm[1], bits, info, + mr->rdParm[0]); + break; + } + +#define META_UNIMP(x) case x: \ +FIXME("PlayMetaFileRecord:record type "#x" not implemented.\n"); \ +break; + META_UNIMP(META_DRAWTEXT) + META_UNIMP(META_ANIMATEPALETTE) + META_UNIMP(META_SETPALENTRIES) + META_UNIMP(META_RESIZEPALETTE) + META_UNIMP(META_RESETDC) + META_UNIMP(META_STARTDOC) + META_UNIMP(META_STARTPAGE) + META_UNIMP(META_ENDPAGE) + META_UNIMP(META_ABORTDOC) + META_UNIMP(META_ENDDOC) + META_UNIMP(META_CREATEBRUSH) + META_UNIMP(META_CREATEBITMAPINDIRECT) + META_UNIMP(META_CREATEBITMAP) +#undef META_UNIMP + + default: + WARN("PlayMetaFileRecord: Unknown record type %x\n", mr->rdFunction); + return FALSE; + } + return TRUE; +} + +/****************************************************************** + * SetMetaFileBitsEx (GDI32.@) + * + * Create a metafile from raw data. No checking of the data is performed. + * Use GetMetaFileBitsEx() to get raw data from a metafile. + * + * PARAMS + * size [I] size of metafile, in bytes + * lpData [I] pointer to metafile data + * + * RETURNS + * Success: Handle to metafile. + * Failure: NULL. + */ +HMETAFILE WINAPI SetMetaFileBitsEx( UINT size, const BYTE *lpData ) +{ + const METAHEADER *mh_in = (const METAHEADER *)lpData; + METAHEADER *mh_out; + + if (size & 1) return 0; + + if (!size || mh_in->mtType != METAFILE_MEMORY || mh_in->mtVersion != MFVERSION || + mh_in->mtHeaderSize != sizeof(METAHEADER) / 2) + { + SetLastError(ERROR_INVALID_DATA); + return 0; + } + + mh_out = HeapAlloc( GetProcessHeap(), 0, size ); + if (!mh_out) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return 0; + } + + memcpy(mh_out, mh_in, size); + mh_out->mtSize = size / 2; + return MF_Create_HMETAFILE(mh_out); +} + +/***************************************************************** + * GetMetaFileBitsEx (GDI32.@) + * + * Get raw metafile data. + * + * Copies the data from metafile _hmf_ into the buffer _buf_. + * + * PARAMS + * hmf [I] metafile + * nSize [I] size of buf + * buf [O] buffer to receive raw metafile data + * + * RETURNS + * If _buf_ is zero, returns size of buffer required. Otherwise, + * returns number of bytes copied. + */ +UINT WINAPI GetMetaFileBitsEx( HMETAFILE hmf, UINT nSize, LPVOID buf ) +{ + METAHEADER *mh = GDI_GetObjPtr( hmf, OBJ_METAFILE ); + UINT mfSize; + BOOL mf_copy = FALSE; + + TRACE("(%p,%d,%p)\n", hmf, nSize, buf); + if (!mh) return 0; /* FIXME: error code */ + if(mh->mtType == METAFILE_DISK) + { + mh = MF_LoadDiskBasedMetaFile( mh ); + if (!mh) + { + GDI_ReleaseObj( hmf ); + return 0; + } + mf_copy = TRUE; + } + mfSize = mh->mtSize * 2; + if (buf) + { + if(mfSize > nSize) mfSize = nSize; + memmove(buf, mh, mfSize); + } + if (mf_copy) HeapFree( GetProcessHeap(), 0, mh ); + GDI_ReleaseObj( hmf ); + TRACE("returning size %d\n", mfSize); + return mfSize; +} + +#include +typedef struct +{ + DWORD magic; /* WMFC */ + WORD unk04; /* 1 */ + WORD unk06; /* 0 */ + WORD unk08; /* 0 */ + WORD unk0a; /* 1 */ + WORD checksum; + DWORD unk0e; /* 0 */ + DWORD num_chunks; + DWORD chunk_size; + DWORD remaining_size; + DWORD emf_size; + BYTE *emf_data; +} mf_comment_chunk; +#include + +static const DWORD wmfc_magic = 0x43464d57; + +/****************************************************************** + * add_mf_comment + * + * Helper for GetWinMetaFileBits + * + * Add the MFCOMMENT record[s] which is essentially a copy + * of the original emf. + */ +static BOOL add_mf_comment(HDC hdc, HENHMETAFILE emf) +{ + DWORD size = GetEnhMetaFileBits(emf, 0, NULL), i; + BYTE *bits, *chunk_data; + mf_comment_chunk *chunk = NULL; + BOOL ret = FALSE; + static const DWORD max_chunk_size = 0x2000; + + if(!size) return FALSE; + chunk_data = bits = HeapAlloc(GetProcessHeap(), 0, size); + if(!bits) return FALSE; + if(!GetEnhMetaFileBits(emf, size, bits)) goto end; + + chunk = HeapAlloc(GetProcessHeap(), 0, max_chunk_size + FIELD_OFFSET(mf_comment_chunk, emf_data)); + if(!chunk) goto end; + + chunk->magic = wmfc_magic; + chunk->unk04 = 1; + chunk->unk06 = 0; + chunk->unk08 = 0; + chunk->unk0a = 1; + chunk->checksum = 0; /* We fixup the first chunk's checksum before returning from GetWinMetaFileBits */ + chunk->unk0e = 0; + chunk->num_chunks = (size + max_chunk_size - 1) / max_chunk_size; + chunk->chunk_size = max_chunk_size; + chunk->remaining_size = size; + chunk->emf_size = size; + + for(i = 0; i < chunk->num_chunks; i++) + { + if(i == chunk->num_chunks - 1) /* last chunk */ + chunk->chunk_size = chunk->remaining_size; + + chunk->remaining_size -= chunk->chunk_size; + memcpy(&chunk->emf_data, chunk_data, chunk->chunk_size); + chunk_data += chunk->chunk_size; + + if(!Escape(hdc, MFCOMMENT, chunk->chunk_size + FIELD_OFFSET(mf_comment_chunk, emf_data), (char*)chunk, NULL)) + goto end; + } + ret = TRUE; +end: + HeapFree(GetProcessHeap(), 0, chunk); + HeapFree(GetProcessHeap(), 0, bits); + return ret; +} + +/******************************************************************* + * muldiv + * + * Behaves somewhat differently to MulDiv when the answer is -ve + * and also rounds n.5 towards zero + */ +static INT muldiv(INT m1, INT m2, INT d) +{ + LONGLONG ret; + + ret = ((LONGLONG)m1 * m2 + d/2) / d; /* Always add d/2 even if ret will be -ve */ + + if((LONGLONG)m1 * m2 * 2 == (2 * ret - 1) * d) /* If the answer is exactly n.5 round towards zero */ + { + if(ret > 0) ret--; + else ret++; + } + return ret; +} + +/****************************************************************** + * set_window + * + * Helper for GetWinMetaFileBits + * + * Add the SetWindowOrg and SetWindowExt records + */ +static BOOL set_window(HDC hdc, HENHMETAFILE emf, HDC ref_dc, INT map_mode) +{ + ENHMETAHEADER header; + INT horz_res, vert_res, horz_size, vert_size; + POINT pt; + + if(!GetEnhMetaFileHeader(emf, sizeof(header), &header)) return FALSE; + + horz_res = GetDeviceCaps(ref_dc, HORZRES); + vert_res = GetDeviceCaps(ref_dc, VERTRES); + horz_size = GetDeviceCaps(ref_dc, HORZSIZE); + vert_size = GetDeviceCaps(ref_dc, VERTSIZE); + + switch(map_mode) + { + case MM_TEXT: + case MM_ISOTROPIC: + case MM_ANISOTROPIC: + pt.y = muldiv(header.rclFrame.top, vert_res, vert_size * 100); + pt.x = muldiv(header.rclFrame.left, horz_res, horz_size * 100); + break; + case MM_LOMETRIC: + pt.y = muldiv(-header.rclFrame.top, 1, 10) + 1; + pt.x = muldiv( header.rclFrame.left, 1, 10); + break; + case MM_HIMETRIC: + pt.y = -header.rclFrame.top + 1; + pt.x = (header.rclFrame.left >= 0) ? header.rclFrame.left : header.rclFrame.left + 1; /* See the tests */ + break; + case MM_LOENGLISH: + pt.y = muldiv(-header.rclFrame.top, 10, 254) + 1; + pt.x = muldiv( header.rclFrame.left, 10, 254); + break; + case MM_HIENGLISH: + pt.y = muldiv(-header.rclFrame.top, 100, 254) + 1; + pt.x = muldiv( header.rclFrame.left, 100, 254); + break; + case MM_TWIPS: + pt.y = muldiv(-header.rclFrame.top, 72 * 20, 2540) + 1; + pt.x = muldiv( header.rclFrame.left, 72 * 20, 2540); + break; + default: + WARN("Unknown map mode %d\n", map_mode); + return FALSE; + } + SetWindowOrgEx(hdc, pt.x, pt.y, NULL); + + pt.x = muldiv(header.rclFrame.right - header.rclFrame.left, horz_res, horz_size * 100); + pt.y = muldiv(header.rclFrame.bottom - header.rclFrame.top, vert_res, vert_size * 100); + SetWindowExtEx(hdc, pt.x, pt.y, NULL); + return TRUE; +} + +/****************************************************************** + * GetWinMetaFileBits [GDI32.@] + */ +UINT WINAPI GetWinMetaFileBits(HENHMETAFILE hemf, + UINT cbBuffer, LPBYTE lpbBuffer, + INT map_mode, HDC hdcRef) +{ + HDC hdcmf; + HMETAFILE hmf; + UINT ret, full_size; + RECT rc; + + GetClipBox(hdcRef, &rc); + + TRACE("(%p,%d,%p,%d,%p) rc=%s\n", hemf, cbBuffer, lpbBuffer, + map_mode, hdcRef, wine_dbgstr_rect(&rc)); + + hdcmf = CreateMetaFileW(NULL); + + add_mf_comment(hdcmf, hemf); + SetMapMode(hdcmf, map_mode); + if(!set_window(hdcmf, hemf, hdcRef, map_mode)) + goto error; + + PlayEnhMetaFile(hdcmf, hemf, &rc); + hmf = CloseMetaFile(hdcmf); + full_size = GetMetaFileBitsEx(hmf, 0, NULL); + ret = GetMetaFileBitsEx(hmf, cbBuffer, lpbBuffer); + DeleteMetaFile(hmf); + + if(ret && ret == full_size && lpbBuffer) /* fixup checksum, but only if retrieving all of the bits */ + { + WORD checksum = 0; + METARECORD *comment_rec = (METARECORD*)(lpbBuffer + sizeof(METAHEADER)); + UINT i; + + for(i = 0; i < full_size / 2; i++) + checksum += ((WORD*)lpbBuffer)[i]; + comment_rec->rdParm[8] = ~checksum + 1; + } + return ret; + +error: + DeleteMetaFile(CloseMetaFile(hdcmf)); + return 0; +} + +/****************************************************************** + * MF_Play_MetaCreateRegion + * + * Handles META_CREATEREGION for PlayMetaFileRecord(). + * + * The layout of the record looks something like this: + * + * rdParm meaning + * 0 Always 0? + * 1 Always 6? + * 2 Looks like a handle? - not constant + * 3 0 or 1 ?? + * 4 Total number of bytes + * 5 No. of separate bands = n [see below] + * 6 Largest number of x co-ords in a band + * 7-10 Bounding box x1 y1 x2 y2 + * 11-... n bands + * + * Regions are divided into bands that are uniform in the + * y-direction. Each band consists of pairs of on/off x-coords and is + * written as + * m y0 y1 x1 x2 x3 ... xm m + * into successive rdParm[]s. + * + * This is probably just a dump of the internal RGNOBJ? + * + * HDMD - 18/12/97 + * + */ + +static BOOL MF_Play_MetaCreateRegion( METARECORD *mr, HRGN hrgn ) +{ + WORD band, pair; + WORD *start, *end; + INT16 y0, y1; + HRGN hrgn2 = CreateRectRgn( 0, 0, 0, 0 ); + + for(band = 0, start = &(mr->rdParm[11]); band < mr->rdParm[5]; + band++, start = end + 1) { + if(*start / 2 != (*start + 1) / 2) { + WARN("Delimiter not even.\n"); + DeleteObject( hrgn2 ); + return FALSE; + } + + end = start + *start + 3; + if(end > (WORD *)mr + mr->rdSize) { + WARN("End points outside record.\n"); + DeleteObject( hrgn2 ); + return FALSE; + } + + if(*start != *end) { + WARN("Mismatched delimiters.\n"); + DeleteObject( hrgn2 ); + return FALSE; + } + + y0 = *(INT16 *)(start + 1); + y1 = *(INT16 *)(start + 2); + for(pair = 0; pair < *start / 2; pair++) { + SetRectRgn( hrgn2, *(INT16 *)(start + 3 + 2*pair), y0, + *(INT16 *)(start + 4 + 2*pair), y1 ); + CombineRgn(hrgn, hrgn, hrgn2, RGN_OR); + } + } + DeleteObject( hrgn2 ); + return TRUE; + } + + +/****************************************************************** + * MF_Play_MetaExtTextOut + * + * Handles META_EXTTEXTOUT for PlayMetaFileRecord(). + */ + +static BOOL MF_Play_MetaExtTextOut(HDC hdc, METARECORD *mr) +{ + INT *dx = NULL; + int i; + SHORT *dxx; + LPSTR sot; + DWORD len; + WORD s1; + RECT rect; + BOOL isrect = mr->rdParm[3] & (ETO_OPAQUE | ETO_CLIPPED); + + s1 = mr->rdParm[2]; /* String length */ + len = sizeof(METARECORD) + (((s1 + 1) >> 1) * 2) + 2 * sizeof(short) + + sizeof(UINT16) + (isrect ? 4 * sizeof(SHORT) : 0); + /* rec len without dx array */ + + sot = (LPSTR)&mr->rdParm[4]; /* start_of_text */ + if (isrect) + { + rect.left = (SHORT)mr->rdParm[4]; + rect.top = (SHORT)mr->rdParm[5]; + rect.right = (SHORT)mr->rdParm[6]; + rect.bottom = (SHORT)mr->rdParm[7]; + sot += 4 * sizeof(SHORT); /* there is a rectangle, so add offset */ + } + + if (mr->rdSize == len / 2) + dxx = NULL; /* determine if array is present */ + else + if (mr->rdSize == (len + s1 * sizeof(INT16)) / 2) + { + dxx = (SHORT *)(sot+(((s1+1)>>1)*2)); + dx = HeapAlloc( GetProcessHeap(), 0, s1*sizeof(INT)); + if (dx) for (i = 0; i < s1; i++) dx[i] = dxx[i]; + } + else { + TRACE("%s len: %d\n", sot, mr->rdSize); + WARN("Please report: ExtTextOut len=%d slen=%d rdSize=%d opt=%04x\n", + len, s1, mr->rdSize, mr->rdParm[3]); + dxx = NULL; /* shouldn't happen -- but if, we continue with NULL */ + } + ExtTextOutA( hdc, + (SHORT)mr->rdParm[1], /* X position */ + (SHORT)mr->rdParm[0], /* Y position */ + mr->rdParm[3], /* options */ + &rect, /* rectangle */ + sot, /* string */ + s1, dx); /* length, dx array */ + if (dx) + { + TRACE("%s len: %d dx0: %d\n", sot, mr->rdSize, dx[0]); + HeapFree( GetProcessHeap(), 0, dx ); + } + return TRUE; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/bitblt.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/bitblt.c new file mode 100644 index 00000000000..fd6c68fc115 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/bitblt.c @@ -0,0 +1,192 @@ +/* + * GDI bit-blit operations + * + * Copyright 1993, 1994 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "mfdrv/metafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +/*********************************************************************** + * MFDRV_PatBlt + */ +BOOL MFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) +{ + MFDRV_MetaParam6( dev, META_PATBLT, dst->log_x, dst->log_y, dst->log_width, dst->log_height, + HIWORD(rop), LOWORD(rop) ); + return TRUE; +} + + +/*********************************************************************** + * MFDRV_StretchBlt + * this function contains TWO ways for processing StretchBlt in metafiles, + * decide between rdFunction values META_STRETCHBLT or META_DIBSTRETCHBLT + * via #define STRETCH_VIA_DIB + */ +#define STRETCH_VIA_DIB + +BOOL MFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, + PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) +{ + BOOL ret; + DWORD len; + METARECORD *mr; + BITMAP BM; +#ifdef STRETCH_VIA_DIB + LPBITMAPINFOHEADER lpBMI; + WORD nBPP; +#endif + HBITMAP hBitmap = GetCurrentObject(devSrc->hdc, OBJ_BITMAP); + + if (devSrc->funcs == devDst->funcs) return FALSE; /* can't use a metafile DC as source */ + + if (GetObjectW(hBitmap, sizeof(BITMAP), &BM) != sizeof(BITMAP)) + { + WARN("bad bitmap object %p passed for hdc %p\n", hBitmap, devSrc->hdc); + return FALSE; + } +#ifdef STRETCH_VIA_DIB + nBPP = BM.bmPlanes * BM.bmBitsPixel; + if(nBPP > 8) nBPP = 24; /* FIXME Can't get 16bpp to work for some reason */ + len = sizeof(METARECORD) + 10 * sizeof(INT16) + + sizeof(BITMAPINFOHEADER) + (nBPP <= 8 ? 1 << nBPP: 0) * sizeof(RGBQUAD) + + get_dib_stride( BM.bmWidth, nBPP ) * BM.bmHeight; + if (!(mr = HeapAlloc( GetProcessHeap(), 0, len))) + return FALSE; + mr->rdFunction = META_DIBSTRETCHBLT; + lpBMI=(LPBITMAPINFOHEADER)(mr->rdParm+10); + lpBMI->biSize = sizeof(BITMAPINFOHEADER); + lpBMI->biWidth = BM.bmWidth; + lpBMI->biHeight = BM.bmHeight; + lpBMI->biPlanes = 1; + lpBMI->biBitCount = nBPP; + lpBMI->biSizeImage = get_dib_image_size( (BITMAPINFO *)lpBMI ); + lpBMI->biClrUsed = nBPP <= 8 ? 1 << nBPP : 0; + lpBMI->biCompression = BI_RGB; + lpBMI->biXPelsPerMeter = MulDiv(GetDeviceCaps(devSrc->hdc,LOGPIXELSX),3937,100); + lpBMI->biYPelsPerMeter = MulDiv(GetDeviceCaps(devSrc->hdc,LOGPIXELSY),3937,100); + lpBMI->biClrImportant = 0; /* 1 meter = 39.37 inch */ + + TRACE("MF_StretchBltViaDIB->len = %d rop=%x PixYPM=%d Caps=%d\n", + len,rop,lpBMI->biYPelsPerMeter,GetDeviceCaps(devSrc->hdc, LOGPIXELSY)); + + if (GetDIBits(devSrc->hdc, hBitmap, 0, (UINT)lpBMI->biHeight, + (LPSTR)lpBMI + get_dib_info_size( (BITMAPINFO *)lpBMI, DIB_RGB_COLORS ), + (LPBITMAPINFO)lpBMI, DIB_RGB_COLORS)) +#else + len = sizeof(METARECORD) + 15 * sizeof(INT16) + BM.bmWidthBytes * BM.bmHeight; + if (!(mr = HeapAlloc( GetProcessHeap(), 0, len ))) + return FALSE; + mr->rdFunction = META_STRETCHBLT; + *(mr->rdParm +10) = BM.bmWidth; + *(mr->rdParm +11) = BM.bmHeight; + *(mr->rdParm +12) = BM.bmWidthBytes; + *(mr->rdParm +13) = BM.bmPlanes; + *(mr->rdParm +14) = BM.bmBitsPixel; + TRACE("len = %ld rop=%lx\n", len, rop); + if (GetBitmapBits( hBitmap, BM.bmWidthBytes * BM.bmHeight, mr->rdParm + 15)) +#endif + { + mr->rdSize = len / sizeof(INT16); + *(mr->rdParm) = LOWORD(rop); + *(mr->rdParm + 1) = HIWORD(rop); + *(mr->rdParm + 2) = src->log_height; + *(mr->rdParm + 3) = src->log_width; + *(mr->rdParm + 4) = src->log_y; + *(mr->rdParm + 5) = src->log_x; + *(mr->rdParm + 6) = dst->log_height; + *(mr->rdParm + 7) = dst->log_width; + *(mr->rdParm + 8) = dst->log_y; + *(mr->rdParm + 9) = dst->log_x; + ret = MFDRV_WriteRecord( devDst, mr, mr->rdSize * 2); + } + else + ret = FALSE; + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + + +/*********************************************************************** + * MFDRV_StretchDIBits + */ +INT MFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, + INT heightDst, INT xSrc, INT ySrc, INT widthSrc, + INT heightSrc, const void *bits, + BITMAPINFO *info, UINT wUsage, DWORD dwRop ) +{ + DWORD infosize = get_dib_info_size(info, wUsage); + DWORD len = sizeof(METARECORD) + 10 * sizeof(WORD) + infosize + info->bmiHeader.biSizeImage; + METARECORD *mr = HeapAlloc( GetProcessHeap(), 0, len ); + if(!mr) return 0; + + mr->rdSize = len / 2; + mr->rdFunction = META_STRETCHDIB; + mr->rdParm[0] = LOWORD(dwRop); + mr->rdParm[1] = HIWORD(dwRop); + mr->rdParm[2] = wUsage; + mr->rdParm[3] = (INT16)heightSrc; + mr->rdParm[4] = (INT16)widthSrc; + mr->rdParm[5] = (INT16)ySrc; + mr->rdParm[6] = (INT16)xSrc; + mr->rdParm[7] = (INT16)heightDst; + mr->rdParm[8] = (INT16)widthDst; + mr->rdParm[9] = (INT16)yDst; + mr->rdParm[10] = (INT16)xDst; + memcpy(mr->rdParm + 11, info, infosize); + memcpy(mr->rdParm + 11 + infosize / 2, bits, info->bmiHeader.biSizeImage); + MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); + HeapFree( GetProcessHeap(), 0, mr ); + return heightSrc; +} + + +/*********************************************************************** + * MFDRV_SetDIBitsToDeivce + */ +INT MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDst, INT yDst, DWORD cx, + DWORD cy, INT xSrc, INT ySrc, UINT startscan, + UINT lines, LPCVOID bits, 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 = HeapAlloc( GetProcessHeap(), 0, len ); + if(!mr) return 0; + + mr->rdSize = len / 2; + mr->rdFunction = META_SETDIBTODEV; + mr->rdParm[0] = coloruse; + mr->rdParm[1] = lines; + mr->rdParm[2] = startscan; + mr->rdParm[3] = (INT16)ySrc; + mr->rdParm[4] = (INT16)xSrc; + mr->rdParm[5] = (INT16)cy; + mr->rdParm[6] = (INT16)cx; + mr->rdParm[7] = (INT16)yDst; + mr->rdParm[8] = (INT16)xDst; + memcpy(mr->rdParm + 9, info, infosize); + memcpy(mr->rdParm + 9 + infosize / 2, bits, info->bmiHeader.biSizeImage); + MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); + HeapFree( GetProcessHeap(), 0, mr ); + return lines; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/dc.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/dc.c new file mode 100644 index 00000000000..c00b5041f8d --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/dc.c @@ -0,0 +1,206 @@ +/* + * MetaFile driver DC value functions + * + * Copyright 1999 Huw D M Davies + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "mfdrv/metafiledrv.h" + +INT MFDRV_SaveDC( PHYSDEV dev ) +{ + return MFDRV_MetaParam0( dev, META_SAVEDC ); +} + +BOOL MFDRV_RestoreDC( PHYSDEV dev, INT level ) +{ + return MFDRV_MetaParam1( dev, META_RESTOREDC, level ); +} + +UINT MFDRV_SetTextAlign( PHYSDEV dev, UINT align ) +{ + return MFDRV_MetaParam2( dev, META_SETTEXTALIGN, HIWORD(align), LOWORD(align)) ? align : GDI_ERROR; +} + +INT MFDRV_SetBkMode( PHYSDEV dev, INT mode ) +{ + return MFDRV_MetaParam1( dev, META_SETBKMODE, (WORD)mode) ? mode : 0; +} + +COLORREF MFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) +{ + return MFDRV_MetaParam2(dev, META_SETBKCOLOR, HIWORD(color), LOWORD(color)) ? color : CLR_INVALID; +} + +COLORREF MFDRV_SetTextColor( PHYSDEV dev, COLORREF color ) +{ + return MFDRV_MetaParam2(dev, META_SETTEXTCOLOR, HIWORD(color), LOWORD(color)) ? color : CLR_INVALID; +} + +INT MFDRV_SetROP2( PHYSDEV dev, INT rop ) +{ + return MFDRV_MetaParam1( dev, META_SETROP2, (WORD)rop) ? rop : 0; +} + +INT MFDRV_SetRelAbs( PHYSDEV dev, INT mode ) +{ + return MFDRV_MetaParam1( dev, META_SETRELABS, (WORD)mode) ? mode : 0; +} + +INT MFDRV_SetPolyFillMode( PHYSDEV dev, INT mode ) +{ + return MFDRV_MetaParam1( dev, META_SETPOLYFILLMODE, (WORD)mode) ? mode : 0; +} + +INT MFDRV_SetStretchBltMode( PHYSDEV dev, INT mode ) +{ + return MFDRV_MetaParam1( dev, META_SETSTRETCHBLTMODE, (WORD)mode) ? mode : 0; +} + +INT MFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) +{ + return MFDRV_MetaParam4( dev, META_INTERSECTCLIPRECT, left, top, right, bottom ); +} + +INT MFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) +{ + return MFDRV_MetaParam4( dev, META_EXCLUDECLIPRECT, left, top, right, bottom ); +} + +INT MFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y ) +{ + return MFDRV_MetaParam2( dev, META_OFFSETCLIPRGN, x, y ); +} + +INT MFDRV_SetMapMode( PHYSDEV dev, INT mode ) +{ + return MFDRV_MetaParam1( dev, META_SETMAPMODE, mode ); +} + +BOOL MFDRV_SetViewportExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) +{ + return MFDRV_MetaParam2( dev, META_SETVIEWPORTEXT, x, y ); +} + +BOOL MFDRV_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + return MFDRV_MetaParam2( dev, META_SETVIEWPORTORG, x, y ); +} + +BOOL MFDRV_SetWindowExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) +{ + return MFDRV_MetaParam2( dev, META_SETWINDOWEXT, x, y ); +} + +BOOL MFDRV_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + return MFDRV_MetaParam2( dev, META_SETWINDOWORG, x, y ); +} + +BOOL MFDRV_OffsetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + return MFDRV_MetaParam2( dev, META_OFFSETVIEWPORTORG, x, y ); +} + +BOOL MFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) +{ + return MFDRV_MetaParam2( dev, META_OFFSETWINDOWORG, x, y ); +} + +BOOL MFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) +{ + return MFDRV_MetaParam4( dev, META_SCALEVIEWPORTEXT, xNum, xDenom, yNum, yDenom ); +} + +BOOL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) +{ + return MFDRV_MetaParam4( dev, META_SCALEWINDOWEXT, xNum, xDenom, yNum, yDenom ); +} + +BOOL MFDRV_SetTextJustification( PHYSDEV dev, INT extra, INT breaks ) +{ + return MFDRV_MetaParam2( dev, META_SETTEXTJUSTIFICATION, extra, breaks ); +} + +INT MFDRV_SetTextCharacterExtra( PHYSDEV dev, INT extra ) +{ + return MFDRV_MetaParam1( dev, META_SETTEXTCHAREXTRA, extra ) ? extra : 0x80000000; +} + +DWORD MFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags ) +{ + return MFDRV_MetaParam2( dev, META_SETMAPPERFLAGS, HIWORD(flags), LOWORD(flags) ) ? flags : GDI_ERROR; +} + +BOOL MFDRV_AbortPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_BeginPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_CloseFigure( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_EndPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_FillPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_FlattenPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) +{ + return FALSE; +} + +BOOL MFDRV_StrokeAndFillPath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_StrokePath( PHYSDEV dev ) +{ + return FALSE; +} + +BOOL MFDRV_WidenPath( PHYSDEV dev ) +{ + return FALSE; +} + +COLORREF MFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) +{ + return CLR_INVALID; +} + +COLORREF MFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) +{ + return CLR_INVALID; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/graphics.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/graphics.c new file mode 100644 index 00000000000..e26076fb649 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/graphics.c @@ -0,0 +1,441 @@ +/* + * Metafile driver graphics functions + * + * Copyright 1993, 1994 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "mfdrv/metafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +/********************************************************************** + * MFDRV_MoveTo + */ +BOOL MFDRV_MoveTo(PHYSDEV dev, INT x, INT y) +{ + return MFDRV_MetaParam2(dev,META_MOVETO,x,y); +} + +/*********************************************************************** + * MFDRV_LineTo + */ +BOOL MFDRV_LineTo( PHYSDEV dev, INT x, INT y ) +{ + return MFDRV_MetaParam2(dev, META_LINETO, x, y); +} + + +/*********************************************************************** + * MFDRV_Arc + */ +BOOL MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return MFDRV_MetaParam8(dev, META_ARC, left, top, right, bottom, + xstart, ystart, xend, yend); +} + + +/*********************************************************************** + * MFDRV_Pie + */ +BOOL MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return MFDRV_MetaParam8(dev, META_PIE, left, top, right, bottom, + xstart, ystart, xend, yend); +} + + +/*********************************************************************** + * MFDRV_Chord + */ +BOOL MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) +{ + return MFDRV_MetaParam8(dev, META_CHORD, left, top, right, bottom, + xstart, ystart, xend, yend); +} + +/*********************************************************************** + * MFDRV_Ellipse + */ +BOOL MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) +{ + return MFDRV_MetaParam4(dev, META_ELLIPSE, left, top, right, bottom); +} + +/*********************************************************************** + * MFDRV_Rectangle + */ +BOOL MFDRV_Rectangle(PHYSDEV dev, INT left, INT top, INT right, INT bottom) +{ + return MFDRV_MetaParam4(dev, META_RECTANGLE, left, top, right, bottom); +} + +/*********************************************************************** + * MFDRV_RoundRect + */ +BOOL MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, + INT bottom, INT ell_width, INT ell_height ) +{ + return MFDRV_MetaParam6(dev, META_ROUNDRECT, left, top, right, bottom, + ell_width, ell_height); +} + +/*********************************************************************** + * MFDRV_SetPixel + */ +COLORREF MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) +{ + return MFDRV_MetaParam4(dev, META_SETPIXEL, x, y,HIWORD(color), + LOWORD(color)); +} + + +/****************************************************************** + * MFDRV_MetaPoly - implements Polygon and Polyline + */ +static BOOL MFDRV_MetaPoly(PHYSDEV dev, short func, 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 = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + + +/********************************************************************** + * MFDRV_Polyline + */ +BOOL MFDRV_Polyline( PHYSDEV dev, const POINT* pt, INT count ) +{ + 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 = MFDRV_MetaPoly(dev, META_POLYLINE, pts, count); + + HeapFree( GetProcessHeap(), 0, pts ); + return ret; +} + + +/********************************************************************** + * MFDRV_Polygon + */ +BOOL MFDRV_Polygon( PHYSDEV dev, 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 = MFDRV_MetaPoly(dev, META_POLYGON, pts, count); + + HeapFree( GetProcessHeap(), 0, pts ); + return ret; +} + + +/********************************************************************** + * MFDRV_PolyPolygon + */ +BOOL MFDRV_PolyPolygon( PHYSDEV dev, 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;irdSize = len /2; + 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 = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); + + HeapFree( GetProcessHeap(), 0, pts ); + HeapFree( GetProcessHeap(), 0, pointcounts ); + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + + +/********************************************************************** + * MFDRV_ExtFloodFill + */ +BOOL MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) +{ + return MFDRV_MetaParam4(dev,META_FLOODFILL,x,y,HIWORD(color), + LOWORD(color)); +} + + +/****************************************************************** + * MFDRV_CreateRegion + * + * For explanation of the format of the record see MF_Play_MetaCreateRegion in + * objects/metafile.c + */ +static INT16 MFDRV_CreateRegion(PHYSDEV dev, HRGN hrgn) +{ + DWORD len; + METARECORD *mr; + RGNDATA *rgndata; + RECT *pCurRect, *pEndRect; + WORD Bands = 0, MaxBands = 0; + WORD *Param, *StartBand; + BOOL ret; + + if (!(len = GetRegionData( hrgn, 0, NULL ))) return -1; + if( !(rgndata = HeapAlloc( GetProcessHeap(), 0, len )) ) { + WARN("Can't alloc rgndata buffer\n"); + return -1; + } + GetRegionData( hrgn, len, rgndata ); + + /* Overestimate of length: + * Assume every rect is a separate band -> 6 WORDs per rect + */ + len = sizeof(METARECORD) + 20 + (rgndata->rdh.nCount * 12); + if( !(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len )) ) { + WARN("Can't alloc METARECORD buffer\n"); + HeapFree( GetProcessHeap(), 0, rgndata ); + return -1; + } + + Param = mr->rdParm + 11; + StartBand = NULL; + + pEndRect = (RECT *)rgndata->Buffer + rgndata->rdh.nCount; + for(pCurRect = (RECT *)rgndata->Buffer; pCurRect < pEndRect; pCurRect++) + { + if( StartBand && pCurRect->top == *(StartBand + 1) ) + { + *Param++ = pCurRect->left; + *Param++ = pCurRect->right; + } + else + { + if(StartBand) + { + *StartBand = Param - StartBand - 3; + *Param++ = *StartBand; + if(*StartBand > MaxBands) + MaxBands = *StartBand; + Bands++; + } + StartBand = Param++; + *Param++ = pCurRect->top; + *Param++ = pCurRect->bottom; + *Param++ = pCurRect->left; + *Param++ = pCurRect->right; + } + } + + if (StartBand) + { + *StartBand = Param - StartBand - 3; + *Param++ = *StartBand; + if(*StartBand > MaxBands) + MaxBands = *StartBand; + 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] = MaxBands; + mr->rdParm[7] = rgndata->rdh.rcBound.left; + mr->rdParm[8] = rgndata->rdh.rcBound.top; + mr->rdParm[9] = rgndata->rdh.rcBound.right; + mr->rdParm[10] = rgndata->rdh.rcBound.bottom; + mr->rdFunction = META_CREATEREGION; + mr->rdSize = Param - (WORD *)mr; + ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2 ); + HeapFree( GetProcessHeap(), 0, mr ); + HeapFree( GetProcessHeap(), 0, rgndata ); + if(!ret) + { + WARN("MFDRV_WriteRecord failed\n"); + return -1; + } + return MFDRV_AddHandle( dev, hrgn ); +} + + +/********************************************************************** + * MFDRV_PaintRgn + */ +BOOL MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) +{ + INT16 index; + index = MFDRV_CreateRegion( dev, hrgn ); + if(index == -1) + return FALSE; + return MFDRV_MetaParam1( dev, META_PAINTREGION, index ); +} + + +/********************************************************************** + * MFDRV_InvertRgn + */ +BOOL MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) +{ + INT16 index; + index = MFDRV_CreateRegion( dev, hrgn ); + if(index == -1) + return FALSE; + return MFDRV_MetaParam1( dev, META_INVERTREGION, index ); +} + + +/********************************************************************** + * MFDRV_FillRgn + */ +BOOL MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush ) +{ + INT16 iRgn, iBrush; + iRgn = MFDRV_CreateRegion( dev, hrgn ); + if(iRgn == -1) + return FALSE; + iBrush = MFDRV_CreateBrushIndirect( dev, hbrush ); + if(!iBrush) + return FALSE; + return MFDRV_MetaParam2( dev, META_FILLREGION, iRgn, iBrush ); +} + +/********************************************************************** + * MFDRV_FrameRgn + */ +BOOL MFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT x, INT y ) +{ + INT16 iRgn, iBrush; + iRgn = MFDRV_CreateRegion( dev, hrgn ); + if(iRgn == -1) + return FALSE; + iBrush = MFDRV_CreateBrushIndirect( dev, hbrush ); + if(!iBrush) + return FALSE; + return MFDRV_MetaParam4( dev, META_FRAMEREGION, iRgn, iBrush, x, y ); +} + + +/********************************************************************** + * MFDRV_ExtSelectClipRgn + */ +INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode ) +{ + INT16 iRgn; + INT ret; + + if (mode != RGN_COPY) return ERROR; + if (!hrgn) return NULLREGION; + iRgn = MFDRV_CreateRegion( dev, hrgn ); + if(iRgn == -1) return ERROR; + ret = MFDRV_MetaParam1( dev, META_SELECTOBJECT, iRgn ) ? NULLREGION : ERROR; + MFDRV_MetaParam1( dev, META_DELETEOBJECT, iRgn ); + MFDRV_RemoveHandle( dev, iRgn ); + return ret; +} + + +/********************************************************************** + * MFDRV_PolyBezier + * Since MetaFiles don't record Beziers and they don't even record + * approximations to them using lines, we need this stub function. + */ +BOOL MFDRV_PolyBezier( PHYSDEV dev, const POINT *pts, DWORD count ) +{ + return FALSE; +} + +/********************************************************************** + * MFDRV_PolyBezierTo + * Since MetaFiles don't record Beziers and they don't even record + * approximations to them using lines, we need this stub function. + */ +BOOL MFDRV_PolyBezierTo( PHYSDEV dev, const POINT *pts, DWORD count ) +{ + return FALSE; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/init.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/init.c new file mode 100644 index 00000000000..7b53244e213 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/init.c @@ -0,0 +1,627 @@ +/* + * Metafile driver initialisation functions + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winnls.h" +#include "gdi_private.h" +#include "mfdrv/metafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +static BOOL MFDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ); +static BOOL MFDRV_DeleteDC( PHYSDEV dev ); + + +/********************************************************************** + * MFDRV_ExtEscape + */ +static INT MFDRV_ExtEscape( PHYSDEV dev, INT nEscape, INT cbInput, LPCVOID in_data, + INT cbOutput, LPVOID out_data ) +{ + METARECORD *mr; + DWORD len; + INT ret; + + if (cbOutput) return 0; /* escapes that require output cannot work in metafiles */ + + len = sizeof(*mr) + sizeof(WORD) + ((cbInput + 1) & ~1); + mr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len); + mr->rdSize = len / 2; + mr->rdFunction = META_ESCAPE; + mr->rdParm[0] = nEscape; + mr->rdParm[1] = cbInput; + memcpy(&(mr->rdParm[2]), in_data, cbInput); + ret = MFDRV_WriteRecord( dev, mr, len); + HeapFree(GetProcessHeap(), 0, mr); + return ret; +} + + +/****************************************************************** + * MFDRV_GetBoundsRect + */ +static UINT MFDRV_GetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags ) +{ + return 0; +} + + +/****************************************************************** + * MFDRV_SetBoundsRect + */ +static UINT MFDRV_SetBoundsRect( PHYSDEV dev, RECT *rect, UINT flags ) +{ + return 0; +} + + +/****************************************************************** + * MFDRV_GetDeviceCaps + * + *A very simple implementation that returns DT_METAFILE + */ +static INT MFDRV_GetDeviceCaps(PHYSDEV dev, INT cap) +{ + switch(cap) + { + case TECHNOLOGY: + return DT_METAFILE; + case TEXTCAPS: + return 0; + default: + TRACE(" unsupported capability %d, will return 0\n", cap ); + } + return 0; +} + + +static const struct gdi_dc_funcs MFDRV_Funcs = +{ + NULL, /* pAbortDoc */ + MFDRV_AbortPath, /* pAbortPath */ + NULL, /* pAlphaBlend */ + NULL, /* pAngleArc */ + MFDRV_Arc, /* pArc */ + NULL, /* pArcTo */ + MFDRV_BeginPath, /* pBeginPath */ + NULL, /* pBlendImage */ + MFDRV_Chord, /* pChord */ + MFDRV_CloseFigure, /* pCloseFigure */ + MFDRV_CreateCompatibleDC, /* pCreateCompatibleDC */ + NULL, /* pCreateDC */ + MFDRV_DeleteDC, /* pDeleteDC */ + MFDRV_DeleteObject, /* pDeleteObject */ + NULL, /* pDeviceCapabilities */ + MFDRV_Ellipse, /* pEllipse */ + NULL, /* pEndDoc */ + NULL, /* pEndPage */ + MFDRV_EndPath, /* pEndPath */ + NULL, /* pEnumFonts */ + NULL, /* pEnumICMProfiles */ + MFDRV_ExcludeClipRect, /* pExcludeClipRect */ + NULL, /* pExtDeviceMode */ + MFDRV_ExtEscape, /* pExtEscape */ + MFDRV_ExtFloodFill, /* pExtFloodFill */ + MFDRV_ExtSelectClipRgn, /* pExtSelectClipRgn */ + MFDRV_ExtTextOut, /* pExtTextOut */ + MFDRV_FillPath, /* pFillPath */ + MFDRV_FillRgn, /* pFillRgn */ + MFDRV_FlattenPath, /* pFlattenPath */ + NULL, /* pFontIsLinked */ + MFDRV_FrameRgn, /* pFrameRgn */ + NULL, /* pGdiComment */ + NULL, /* pGdiRealizationInfo */ + MFDRV_GetBoundsRect, /* pGetBoundsRect */ + NULL, /* pGetCharABCWidths */ + NULL, /* pGetCharABCWidthsI */ + NULL, /* pGetCharWidth */ + MFDRV_GetDeviceCaps, /* pGetDeviceCaps */ + NULL, /* pGetDeviceGammaRamp */ + NULL, /* pGetFontData */ + NULL, /* pGetFontUnicodeRanges */ + NULL, /* pGetGlyphIndices */ + NULL, /* pGetGlyphOutline */ + NULL, /* pGetICMProfile */ + NULL, /* pGetImage */ + NULL, /* pGetKerningPairs */ + NULL, /* pGetNearestColor */ + NULL, /* pGetOutlineTextMetrics */ + NULL, /* pGetPixel */ + NULL, /* pGetSystemPaletteEntries */ + NULL, /* pGetTextCharsetInfo */ + NULL, /* pGetTextExtentExPoint */ + NULL, /* pGetTextExtentExPointI */ + NULL, /* pGetTextFace */ + NULL, /* pGetTextMetrics */ + NULL, /* pGradientFill */ + MFDRV_IntersectClipRect, /* pIntersectClipRect */ + MFDRV_InvertRgn, /* pInvertRgn */ + MFDRV_LineTo, /* pLineTo */ + NULL, /* pModifyWorldTransform */ + MFDRV_MoveTo, /* pMoveTo */ + MFDRV_OffsetClipRgn, /* pOffsetClipRgn */ + MFDRV_OffsetViewportOrgEx, /* pOffsetViewportOrgEx */ + MFDRV_OffsetWindowOrgEx, /* pOffsetWindowOrgEx */ + MFDRV_PaintRgn, /* pPaintRgn */ + MFDRV_PatBlt, /* pPatBlt */ + MFDRV_Pie, /* pPie */ + MFDRV_PolyBezier, /* pPolyBezier */ + MFDRV_PolyBezierTo, /* pPolyBezierTo */ + NULL, /* pPolyDraw */ + MFDRV_PolyPolygon, /* pPolyPolygon */ + NULL, /* pPolyPolyline */ + MFDRV_Polygon, /* pPolygon */ + MFDRV_Polyline, /* pPolyline */ + NULL, /* pPolylineTo */ + NULL, /* pPutImage */ + NULL, /* pRealizeDefaultPalette */ + MFDRV_RealizePalette, /* pRealizePalette */ + MFDRV_Rectangle, /* pRectangle */ + NULL, /* pResetDC */ + MFDRV_RestoreDC, /* pRestoreDC */ + MFDRV_RoundRect, /* pRoundRect */ + MFDRV_SaveDC, /* pSaveDC */ + MFDRV_ScaleViewportExtEx, /* pScaleViewportExtEx */ + MFDRV_ScaleWindowExtEx, /* pScaleWindowExtEx */ + MFDRV_SelectBitmap, /* pSelectBitmap */ + MFDRV_SelectBrush, /* pSelectBrush */ + MFDRV_SelectClipPath, /* pSelectClipPath */ + MFDRV_SelectFont, /* pSelectFont */ + MFDRV_SelectPalette, /* pSelectPalette */ + MFDRV_SelectPen, /* pSelectPen */ + NULL, /* pSetArcDirection */ + MFDRV_SetBkColor, /* pSetBkColor */ + MFDRV_SetBkMode, /* pSetBkMode */ + MFDRV_SetBoundsRect, /* pSetBoundsRect */ + MFDRV_SetDCBrushColor, /* pSetDCBrushColor*/ + MFDRV_SetDCPenColor, /* pSetDCPenColor*/ + MFDRV_SetDIBitsToDevice, /* pSetDIBitsToDevice */ + NULL, /* pSetDeviceClipping */ + NULL, /* pSetDeviceGammaRamp */ + NULL, /* pSetLayout */ + MFDRV_SetMapMode, /* pSetMapMode */ + MFDRV_SetMapperFlags, /* pSetMapperFlags */ + MFDRV_SetPixel, /* pSetPixel */ + MFDRV_SetPolyFillMode, /* pSetPolyFillMode */ + MFDRV_SetROP2, /* pSetROP2 */ + MFDRV_SetRelAbs, /* pSetRelAbs */ + MFDRV_SetStretchBltMode, /* pSetStretchBltMode */ + MFDRV_SetTextAlign, /* pSetTextAlign */ + MFDRV_SetTextCharacterExtra, /* pSetTextCharacterExtra */ + MFDRV_SetTextColor, /* pSetTextColor */ + MFDRV_SetTextJustification, /* pSetTextJustification */ + MFDRV_SetViewportExtEx, /* pSetViewportExtEx */ + MFDRV_SetViewportOrgEx, /* pSetViewportOrgEx */ + MFDRV_SetWindowExtEx, /* pSetWindowExtEx */ + MFDRV_SetWindowOrgEx, /* pSetWindowOrgEx */ + NULL, /* pSetWorldTransform */ + NULL, /* pStartDoc */ + NULL, /* pStartPage */ + MFDRV_StretchBlt, /* pStretchBlt */ + MFDRV_StretchDIBits, /* pStretchDIBits */ + MFDRV_StrokeAndFillPath, /* pStrokeAndFillPath */ + MFDRV_StrokePath, /* pStrokePath */ + NULL, /* pUnrealizePalette */ + MFDRV_WidenPath, /* pWidenPath */ + NULL, /* wine_get_wgl_driver */ + GDI_PRIORITY_GRAPHICS_DRV /* priority */ +}; + + + +/********************************************************************** + * MFDRV_AllocMetaFile + */ +static DC *MFDRV_AllocMetaFile(void) +{ + DC *dc; + METAFILEDRV_PDEVICE *physDev; + + if (!(dc = alloc_dc_ptr( OBJ_METADC ))) return NULL; + + physDev = HeapAlloc(GetProcessHeap(),0,sizeof(*physDev)); + if (!physDev) + { + free_dc_ptr( dc ); + return NULL; + } + if (!(physDev->mh = HeapAlloc( GetProcessHeap(), 0, sizeof(*physDev->mh) ))) + { + HeapFree( GetProcessHeap(), 0, physDev ); + free_dc_ptr( dc ); + return NULL; + } + + push_dc_driver( &dc->physDev, &physDev->dev, &MFDRV_Funcs ); + + physDev->handles = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, HANDLE_LIST_INC * sizeof(physDev->handles[0])); + physDev->handles_size = HANDLE_LIST_INC; + physDev->cur_handles = 0; + + physDev->hFile = 0; + + physDev->mh->mtHeaderSize = sizeof(METAHEADER) / sizeof(WORD); + physDev->mh->mtVersion = 0x0300; + physDev->mh->mtSize = physDev->mh->mtHeaderSize; + physDev->mh->mtNoObjects = 0; + physDev->mh->mtMaxRecord = 0; + physDev->mh->mtNoParameters = 0; + + SetVirtualResolution( physDev->dev.hdc, 0, 0, 0, 0); + + return dc; +} + + +/********************************************************************** + * MFDRV_CreateCompatibleDC + */ +static BOOL MFDRV_CreateCompatibleDC( PHYSDEV orig, PHYSDEV *pdev ) +{ + /* not supported on metafile DCs */ + return FALSE; +} + + +/********************************************************************** + * MFDRV_DeleteDC + */ +static BOOL MFDRV_DeleteDC( PHYSDEV dev ) +{ + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + DWORD index; + + HeapFree( GetProcessHeap(), 0, physDev->mh ); + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index]) + GDI_hdc_not_using_object(physDev->handles[index], dev->hdc); + HeapFree( GetProcessHeap(), 0, physDev->handles ); + HeapFree( GetProcessHeap(), 0, physDev ); + 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. + * + * PARAMS + * filename [I] Filename of disk metafile + * + * RETURNS + * A handle to the metafile DC if successful, NULL on failure. + */ +HDC WINAPI CreateMetaFileW( LPCWSTR filename ) +{ + HDC ret; + DC *dc; + METAFILEDRV_PDEVICE *physDev; + HANDLE hFile; + DWORD bytes_written; + + TRACE("%s\n", debugstr_w(filename) ); + + if (!(dc = MFDRV_AllocMetaFile())) return 0; + physDev = (METAFILEDRV_PDEVICE *)dc->physDev; + + if (filename) /* disk based metafile */ + { + physDev->mh->mtType = METAFILE_DISK; + if ((hFile = CreateFileW(filename, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, 0)) == INVALID_HANDLE_VALUE) { + free_dc_ptr( dc ); + return 0; + } + if (!WriteFile( hFile, physDev->mh, sizeof(*physDev->mh), + &bytes_written, NULL )) { + free_dc_ptr( dc ); + CloseHandle (hFile ); + return 0; + } + physDev->hFile = hFile; + + /* Grow METAHEADER to include filename */ + physDev->mh = MF_CreateMetaHeaderDisk(physDev->mh, filename, TRUE); + } + else /* memory based metafile */ + physDev->mh->mtType = METAFILE_MEMORY; + + TRACE("returning %p\n", physDev->dev.hdc); + ret = physDev->dev.hdc; + release_dc_ptr( dc ); + return ret; +} + +/********************************************************************** + * CreateMetaFileA (GDI32.@) + * + * See CreateMetaFileW. + */ +HDC WINAPI CreateMetaFileA(LPCSTR filename) +{ + LPWSTR filenameW; + DWORD len; + HDC hReturnDC; + + if (!filename) return CreateMetaFileW(NULL); + + len = MultiByteToWideChar( CP_ACP, 0, filename, -1, NULL, 0 ); + filenameW = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, filename, -1, filenameW, len ); + + hReturnDC = CreateMetaFileW(filenameW); + + HeapFree( GetProcessHeap(), 0, filenameW ); + + return hReturnDC; +} + + +/********************************************************************** + * MFDRV_CloseMetaFile + */ +static DC *MFDRV_CloseMetaFile( HDC hdc ) +{ + DC *dc; + METAFILEDRV_PDEVICE *physDev; + DWORD bytes_written; + + TRACE("(%p)\n", hdc ); + + if (!(dc = get_dc_ptr( hdc ))) return NULL; + if (GetObjectType( hdc ) != OBJ_METADC) + { + release_dc_ptr( dc ); + return NULL; + } + if (dc->refcount != 1) + { + FIXME( "not deleting busy DC %p refcount %u\n", hdc, dc->refcount ); + release_dc_ptr( dc ); + return NULL; + } + physDev = (METAFILEDRV_PDEVICE *)dc->physDev; + + /* Construct the end of metafile record - this is documented + * in SDK Knowledgebase Q99334. + */ + + if (!MFDRV_MetaParam0(dc->physDev, META_EOF)) + { + free_dc_ptr( dc ); + return 0; + } + + if (physDev->mh->mtType == METAFILE_DISK) /* disk based metafile */ + { + if (SetFilePointer(physDev->hFile, 0, NULL, FILE_BEGIN) != 0) { + free_dc_ptr( dc ); + return 0; + } + + physDev->mh->mtType = METAFILE_MEMORY; /* This is what windows does */ + if (!WriteFile(physDev->hFile, physDev->mh, sizeof(*physDev->mh), + &bytes_written, NULL)) { + free_dc_ptr( dc ); + return 0; + } + CloseHandle(physDev->hFile); + physDev->mh->mtType = METAFILE_DISK; + } + + return dc; +} + +/****************************************************************** + * CloseMetaFile (GDI32.@) + * + * Stop recording graphics operations in metafile associated with + * hdc and retrieve metafile. + * + * PARAMS + * hdc [I] Metafile DC to close + * + * RETURNS + * Handle of newly created metafile on success, NULL on failure. + */ +HMETAFILE WINAPI CloseMetaFile(HDC hdc) +{ + HMETAFILE hmf; + METAFILEDRV_PDEVICE *physDev; + DC *dc = MFDRV_CloseMetaFile(hdc); + if (!dc) return 0; + physDev = (METAFILEDRV_PDEVICE *)dc->physDev; + + /* Now allocate a global handle for the metafile */ + + hmf = MF_Create_HMETAFILE( physDev->mh ); + + physDev->mh = NULL; /* So it won't be deleted */ + free_dc_ptr( dc ); + return hmf; +} + + +/****************************************************************** + * MFDRV_WriteRecord + * + * Warning: this function can change the pointer to the metafile header. + */ +BOOL MFDRV_WriteRecord( PHYSDEV dev, METARECORD *mr, DWORD rlen) +{ + DWORD len, size; + METAHEADER *mh; + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + + switch(physDev->mh->mtType) + { + case METAFILE_MEMORY: + len = physDev->mh->mtSize * 2 + rlen; + /* reallocate memory if needed */ + size = HeapSize( GetProcessHeap(), 0, physDev->mh ); + if (len > size) + { + /*expand size*/ + size += size / 2 + rlen; + mh = HeapReAlloc( GetProcessHeap(), 0, physDev->mh, size); + if (!mh) return FALSE; + physDev->mh = mh; + TRACE("Reallocated metafile: new size is %d\n",size); + } + memcpy((WORD *)physDev->mh + physDev->mh->mtSize, mr, rlen); + break; + case METAFILE_DISK: + TRACE("Writing record to disk\n"); + if (!WriteFile(physDev->hFile, mr, rlen, NULL, NULL)) + return FALSE; + break; + default: + ERR("Unknown metafile type %d\n", physDev->mh->mtType ); + return FALSE; + } + + physDev->mh->mtSize += rlen / 2; + physDev->mh->mtMaxRecord = max(physDev->mh->mtMaxRecord, rlen / 2); + return TRUE; +} + + +/****************************************************************** + * MFDRV_MetaParam0 + */ + +BOOL MFDRV_MetaParam0(PHYSDEV dev, short func) +{ + char buffer[8]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = 3; + mr->rdFunction = func; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} + + +/****************************************************************** + * MFDRV_MetaParam1 + */ +BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1) +{ + char buffer[8]; + METARECORD *mr = (METARECORD *)&buffer; + WORD *params = mr->rdParm; + + mr->rdSize = 4; + mr->rdFunction = func; + params[0] = param1; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} + + +/****************************************************************** + * MFDRV_MetaParam2 + */ +BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2) +{ + char buffer[10]; + METARECORD *mr = (METARECORD *)&buffer; + WORD *params = mr->rdParm; + + mr->rdSize = 5; + mr->rdFunction = func; + params[0] = param2; + params[1] = param1; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} + + +/****************************************************************** + * MFDRV_MetaParam4 + */ + +BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4) +{ + char buffer[14]; + METARECORD *mr = (METARECORD *)&buffer; + WORD *params = mr->rdParm; + + mr->rdSize = 7; + mr->rdFunction = func; + params[0] = param4; + params[1] = param3; + params[2] = param2; + params[3] = param1; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} + + +/****************************************************************** + * MFDRV_MetaParam6 + */ + +BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4, short param5, short param6) +{ + char buffer[18]; + METARECORD *mr = (METARECORD *)&buffer; + WORD *params = mr->rdParm; + + mr->rdSize = 9; + mr->rdFunction = func; + params[0] = param6; + params[1] = param5; + params[2] = param4; + params[3] = param3; + params[4] = param2; + params[5] = param1; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} + + +/****************************************************************** + * MFDRV_MetaParam8 + */ +BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4, short param5, + short param6, short param7, short param8) +{ + char buffer[22]; + METARECORD *mr = (METARECORD *)&buffer; + WORD *params = mr->rdParm; + + mr->rdSize = 11; + mr->rdFunction = func; + params[0] = param8; + params[1] = param7; + params[2] = param6; + params[3] = param5; + params[4] = param4; + params[5] = param3; + params[6] = param2; + params[7] = param1; + return MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/metafiledrv.h b/reactos/win32ss/gdi/gdi32/wine/mfdrv/metafiledrv.h new file mode 100644 index 00000000000..e1a03bb0e21 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/metafiledrv.h @@ -0,0 +1,145 @@ +/* + * Metafile driver definitions + * + * Copyright 1996 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_METAFILEDRV_H +#define __WINE_METAFILEDRV_H + +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "gdi_private.h" + +/* Metafile driver physical DC */ + +typedef struct +{ + struct gdi_physdev dev; + METAHEADER *mh; /* Pointer to metafile header */ + UINT handles_size, cur_handles; + HGDIOBJ *handles; + HANDLE hFile; /* Handle for disk based MetaFile */ +} METAFILEDRV_PDEVICE; + +#define HANDLE_LIST_INC 20 + + +extern BOOL MFDRV_MetaParam0(PHYSDEV dev, short func) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MetaParam1(PHYSDEV dev, short func, short param1) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MetaParam2(PHYSDEV dev, short func, short param1, short param2) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MetaParam4(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MetaParam6(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4, short param5, + short param6) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MetaParam8(PHYSDEV dev, short func, short param1, short param2, + short param3, short param4, short param5, + short param6, short param7, short param8) DECLSPEC_HIDDEN; +extern BOOL MFDRV_WriteRecord(PHYSDEV dev, METARECORD *mr, DWORD rlen) DECLSPEC_HIDDEN; +extern UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index ) DECLSPEC_HIDDEN; +extern INT16 MFDRV_CreateBrushIndirect( PHYSDEV dev, HBRUSH hBrush ) DECLSPEC_HIDDEN; + +/* Metafile driver functions */ + +extern BOOL MFDRV_AbortPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Arc( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_BeginPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Chord( PHYSDEV dev, INT left, INT top, INT right, + INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_CloseFigure( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Ellipse( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_EndPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern INT MFDRV_ExcludeClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_ExtFloodFill( PHYSDEV dev, INT x, INT y, COLORREF color, UINT fillType ) DECLSPEC_HIDDEN; +extern INT MFDRV_ExtSelectClipRgn( PHYSDEV dev, HRGN hrgn, INT mode ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *lprect, LPCWSTR str, + UINT count, const INT *lpDx ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_FillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_FillRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_FlattenPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_FrameRgn( PHYSDEV dev, HRGN hrgn, HBRUSH hbrush, INT x, INT y ) DECLSPEC_HIDDEN; +extern INT MFDRV_IntersectClipRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_InvertRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_LineTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_MoveTo( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern INT MFDRV_OffsetClipRgn( PHYSDEV dev, INT x, INT y ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_OffsetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_OffsetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PatBlt( PHYSDEV dev, struct bitblt_coords *dst, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Pie( PHYSDEV dev, INT left, INT top, INT right, + INT bottom, INT xstart, INT ystart, INT xend, INT yend ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PolyBezier( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PolyBezierTo( PHYSDEV dev, const POINT* pt, DWORD count ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PolyPolygon( PHYSDEV dev, const POINT* pt, const INT* counts, UINT polygons) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Polygon( PHYSDEV dev, const POINT* pt, INT count ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Polyline( PHYSDEV dev, const POINT* pt,INT count) DECLSPEC_HIDDEN; +extern BOOL MFDRV_Rectangle( PHYSDEV dev, INT left, INT top, INT right, INT bottom) DECLSPEC_HIDDEN; +extern BOOL MFDRV_RestoreDC( PHYSDEV dev, INT level ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_RoundRect( PHYSDEV dev, INT left, INT top, INT right, INT bottom, + INT ell_width, INT ell_height ) DECLSPEC_HIDDEN; +extern INT MFDRV_SaveDC( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_ScaleViewportExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_ScaleWindowExtEx( PHYSDEV dev, INT xNum, INT xDenom, INT yNum, INT yDenom, SIZE *size ) DECLSPEC_HIDDEN; +extern HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP handle ) DECLSPEC_HIDDEN; +extern HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SelectClipPath( PHYSDEV dev, INT iMode ) DECLSPEC_HIDDEN; +extern HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT handle, UINT *aa_flags ) DECLSPEC_HIDDEN; +extern HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN handle, const struct brush_pattern *pattern ) DECLSPEC_HIDDEN; +extern HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground) DECLSPEC_HIDDEN; +extern UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL primary) DECLSPEC_HIDDEN; +extern COLORREF MFDRV_SetBkColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetBkMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern COLORREF MFDRV_SetDCBrushColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern COLORREF MFDRV_SetDCPenColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetMapMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern DWORD MFDRV_SetMapperFlags( PHYSDEV dev, DWORD flags ) DECLSPEC_HIDDEN; +extern COLORREF MFDRV_SetPixel( PHYSDEV dev, INT x, INT y, COLORREF color ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetPolyFillMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetROP2( PHYSDEV dev, INT rop ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetRelAbs( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetStretchBltMode( PHYSDEV dev, INT mode ) DECLSPEC_HIDDEN; +extern UINT MFDRV_SetTextAlign( PHYSDEV dev, UINT align ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetTextCharacterExtra( PHYSDEV dev, INT extra ) DECLSPEC_HIDDEN; +extern COLORREF MFDRV_SetTextColor( PHYSDEV dev, COLORREF color ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SetTextJustification( PHYSDEV dev, INT extra, INT breaks ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SetViewportExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SetViewportOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SetWindowExtEx( PHYSDEV dev, INT x, INT y, SIZE *size ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_SetWindowOrgEx( PHYSDEV dev, INT x, INT y, POINT *pt ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_StretchBlt( PHYSDEV devDst, struct bitblt_coords *dst, + PHYSDEV devSrc, struct bitblt_coords *src, DWORD rop ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_PaintRgn( PHYSDEV dev, HRGN hrgn ) DECLSPEC_HIDDEN; +extern INT MFDRV_SetDIBitsToDevice( PHYSDEV dev, INT xDest, INT yDest, DWORD cx, + DWORD cy, INT xSrc, INT ySrc, + UINT startscan, UINT lines, LPCVOID bits, + BITMAPINFO *info, UINT coloruse ) DECLSPEC_HIDDEN; +extern INT MFDRV_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, + INT heightDst, INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, + const void *bits, BITMAPINFO *info, UINT wUsage, DWORD dwRop ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_StrokeAndFillPath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_StrokePath( PHYSDEV dev ) DECLSPEC_HIDDEN; +extern BOOL MFDRV_WidenPath( PHYSDEV dev ) DECLSPEC_HIDDEN; + +#endif /* __WINE_METAFILEDRV_H */ diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/objects.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/objects.c new file mode 100644 index 00000000000..59fe08a71d4 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/objects.c @@ -0,0 +1,462 @@ +/* + * GDI objects + * + * Copyright 1993 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wingdi.h" +#include "wine/wingdi16.h" +#include "mfdrv/metafiledrv.h" +#include "gdi_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + +/****************************************************************** + * MFDRV_AddHandle + */ +UINT MFDRV_AddHandle( PHYSDEV dev, HGDIOBJ obj ) +{ + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + UINT16 index; + + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index] == 0) break; + if(index == physDev->handles_size) { + physDev->handles_size += HANDLE_LIST_INC; + physDev->handles = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + physDev->handles, + physDev->handles_size * sizeof(physDev->handles[0])); + } + physDev->handles[index] = get_full_gdi_handle( obj ); + + physDev->cur_handles++; + if(physDev->cur_handles > physDev->mh->mtNoObjects) + physDev->mh->mtNoObjects++; + + return index ; /* index 0 is not reserved for metafiles */ +} + +/****************************************************************** + * MFDRV_RemoveHandle + */ +BOOL MFDRV_RemoveHandle( PHYSDEV dev, UINT index ) +{ + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + BOOL ret = FALSE; + + if (index < physDev->handles_size && physDev->handles[index]) + { + physDev->handles[index] = 0; + physDev->cur_handles--; + ret = TRUE; + } + return ret; +} + +/****************************************************************** + * MFDRV_FindObject + */ +static INT16 MFDRV_FindObject( PHYSDEV dev, HGDIOBJ obj ) +{ + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + INT16 index; + + for(index = 0; index < physDev->handles_size; index++) + if(physDev->handles[index] == obj) break; + + if(index == physDev->handles_size) return -1; + + return index ; +} + + +/****************************************************************** + * MFDRV_DeleteObject + */ +BOOL MFDRV_DeleteObject( PHYSDEV dev, HGDIOBJ obj ) +{ + METARECORD mr; + METAFILEDRV_PDEVICE *physDev = (METAFILEDRV_PDEVICE *)dev; + INT16 index; + BOOL ret = TRUE; + + index = MFDRV_FindObject(dev, obj); + if( index < 0 ) + return FALSE; + + mr.rdSize = sizeof mr / 2; + mr.rdFunction = META_DELETEOBJECT; + mr.rdParm[0] = index; + + if(!MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 )) + ret = FALSE; + + physDev->handles[index] = 0; + physDev->cur_handles--; + return ret; +} + + +/*********************************************************************** + * MFDRV_SelectObject + */ +static BOOL MFDRV_SelectObject( PHYSDEV dev, INT16 index) +{ + METARECORD mr; + + mr.rdSize = sizeof mr / 2; + mr.rdFunction = META_SELECTOBJECT; + mr.rdParm[0] = index; + + return MFDRV_WriteRecord( dev, &mr, mr.rdSize*2 ); +} + + +/*********************************************************************** + * MFDRV_SelectBitmap + */ +HBITMAP MFDRV_SelectBitmap( PHYSDEV dev, HBITMAP hbitmap ) +{ + return 0; +} + +/****************************************************************** + * MFDRV_CreateBrushIndirect + */ + +INT16 MFDRV_CreateBrushIndirect(PHYSDEV dev, HBRUSH hBrush ) +{ + DWORD size; + METARECORD *mr; + LOGBRUSH logbrush; + BOOL r; + + if (!GetObjectA( hBrush, sizeof(logbrush), &logbrush )) return -1; + + switch(logbrush.lbStyle) + { + case BS_SOLID: + case BS_NULL: + case BS_HATCHED: + { + LOGBRUSH16 lb16; + + lb16.lbStyle = logbrush.lbStyle; + lb16.lbColor = logbrush.lbColor; + lb16.lbHatch = logbrush.lbHatch; + size = sizeof(METARECORD) + sizeof(LOGBRUSH16) - 2; + mr = HeapAlloc( GetProcessHeap(), 0, size ); + mr->rdSize = size / 2; + mr->rdFunction = META_CREATEBRUSHINDIRECT; + memcpy( mr->rdParm, &lb16, sizeof(LOGBRUSH16)); + break; + } + case BS_PATTERN: + case BS_DIBPATTERN: + { + char buffer[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)]; // ros + //char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )]; + BITMAPINFO *dst_info, *src_info = (BITMAPINFO *)buffer; + DWORD info_size; + char *dst_ptr; + void *bits; + UINT usage; + + if (!get_brush_bitmap_info( hBrush, src_info, &bits, &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 / 2; + mr->rdParm[0] = logbrush.lbStyle; + mr->rdParm[1] = usage; + dst_info = (BITMAPINFO *)(mr->rdParm + 2); + memcpy( dst_info, src_info, info_size ); + if (dst_info->bmiHeader.biClrUsed == 1 << dst_info->bmiHeader.biBitCount) + dst_info->bmiHeader.biClrUsed = 0; + dst_ptr = (char *)dst_info + info_size; + + /* always return a bottom-up DIB */ + if (dst_info->bmiHeader.biHeight < 0) + { + int i, width_bytes = get_dib_stride( dst_info->bmiHeader.biWidth, + dst_info->bmiHeader.biBitCount ); + dst_info->bmiHeader.biHeight = -dst_info->bmiHeader.biHeight; + dst_ptr += (dst_info->bmiHeader.biHeight - 1) * width_bytes; + for (i = 0; i < dst_info->bmiHeader.biHeight; i++, dst_ptr -= width_bytes) + memcpy( dst_ptr, (char *)bits + i * width_bytes, width_bytes ); + } + else memcpy( dst_ptr, bits, src_info->bmiHeader.biSizeImage ); + break; + } + + default: + FIXME("Unknown brush style %x\n", logbrush.lbStyle); + return 0; + } + r = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); + HeapFree(GetProcessHeap(), 0, mr); + if( !r ) + return -1; +done: + return MFDRV_AddHandle( dev, hBrush ); +} + + +/*********************************************************************** + * MFDRV_SelectBrush + */ +HBRUSH MFDRV_SelectBrush( PHYSDEV dev, HBRUSH hbrush, const struct brush_pattern *pattern ) +{ + INT16 index; + + index = MFDRV_FindObject(dev, hbrush); + if( index < 0 ) + { + index = MFDRV_CreateBrushIndirect( dev, hbrush ); + if( index < 0 ) + return 0; + GDI_hdc_using_object(hbrush, dev->hdc); + } + return MFDRV_SelectObject( dev, index ) ? hbrush : 0; +} + +/****************************************************************** + * MFDRV_CreateFontIndirect + */ + +static UINT16 MFDRV_CreateFontIndirect(PHYSDEV dev, HFONT hFont, 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 (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2))) + return 0; + return MFDRV_AddHandle( dev, hFont ); +} + + +/*********************************************************************** + * MFDRV_SelectFont + */ +HFONT MFDRV_SelectFont( PHYSDEV dev, HFONT hfont, UINT *aa_flags ) +{ + LOGFONTW font; + INT16 index; + + *aa_flags = GGO_BITMAP; /* no point in anti-aliasing on metafiles */ + index = MFDRV_FindObject(dev, hfont); + if( index < 0 ) + { + if (!GetObjectW( hfont, sizeof(font), &font )) + return 0; + index = MFDRV_CreateFontIndirect(dev, hfont, &font); + if( index < 0 ) + return 0; + GDI_hdc_using_object(hfont, dev->hdc); + } + return MFDRV_SelectObject( dev, index ) ? hfont : 0; +} + +/****************************************************************** + * MFDRV_CreatePenIndirect + */ +static UINT16 MFDRV_CreatePenIndirect(PHYSDEV dev, HPEN hPen, LOGPEN16 *logpen) +{ + char buffer[sizeof(METARECORD) - 2 + sizeof(*logpen)]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = (sizeof(METARECORD) + sizeof(*logpen) - 2) / 2; + mr->rdFunction = META_CREATEPENINDIRECT; + memcpy(&(mr->rdParm), logpen, sizeof(*logpen)); + if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * 2))) + return 0; + return MFDRV_AddHandle( dev, hPen ); +} + + +/*********************************************************************** + * MFDRV_SelectPen + */ +HPEN MFDRV_SelectPen( PHYSDEV dev, HPEN hpen, const struct brush_pattern *pattern ) +{ + LOGPEN16 logpen; + INT16 index; + + index = MFDRV_FindObject(dev, 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 = MFDRV_CreatePenIndirect( dev, hpen, &logpen ); + if( index < 0 ) + return 0; + GDI_hdc_using_object(hpen, dev->hdc); + } + return MFDRV_SelectObject( dev, index ) ? hpen : 0; +} + + +/****************************************************************** + * MFDRV_CreatePalette + */ +static BOOL MFDRV_CreatePalette(PHYSDEV dev, HPALETTE hPalette, LOGPALETTE* logPalette, int sizeofPalette) +{ + int index; + BOOL ret; + METARECORD *mr; + + mr = HeapAlloc( GetProcessHeap(), 0, sizeof(METARECORD) + sizeofPalette - sizeof(WORD) ); + mr->rdSize = (sizeof(METARECORD) + sizeofPalette - sizeof(WORD)) / sizeof(WORD); + mr->rdFunction = META_CREATEPALETTE; + memcpy(&(mr->rdParm), logPalette, sizeofPalette); + if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) + { + HeapFree(GetProcessHeap(), 0, mr); + return FALSE; + } + + mr->rdSize = sizeof(METARECORD) / sizeof(WORD); + mr->rdFunction = META_SELECTPALETTE; + + if ((index = MFDRV_AddHandle( dev, hPalette )) == -1) ret = FALSE; + else + { + *(mr->rdParm) = index; + ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)); + } + HeapFree(GetProcessHeap(), 0, mr); + return ret; +} + + +/*********************************************************************** + * MFDRV_SelectPalette + */ +HPALETTE MFDRV_SelectPalette( PHYSDEV dev, HPALETTE hPalette, BOOL bForceBackground ) +{ +#define PALVERSION 0x0300 + + PLOGPALETTE logPalette; + WORD wNumEntries = 0; + BOOL creationSucceed; + int sizeofPalette; + + GetObjectA(hPalette, sizeof(WORD), &wNumEntries); + + if (wNumEntries == 0) return 0; + + sizeofPalette = sizeof(LOGPALETTE) + ((wNumEntries-1) * sizeof(PALETTEENTRY)); + logPalette = HeapAlloc( GetProcessHeap(), 0, sizeofPalette ); + + if (logPalette == NULL) return 0; + + logPalette->palVersion = PALVERSION; + logPalette->palNumEntries = wNumEntries; + + GetPaletteEntries(hPalette, 0, wNumEntries, logPalette->palPalEntry); + + creationSucceed = MFDRV_CreatePalette( dev, hPalette, logPalette, sizeofPalette ); + + HeapFree( GetProcessHeap(), 0, logPalette ); + + if (creationSucceed) + return hPalette; + + return 0; +} + +/*********************************************************************** + * MFDRV_RealizePalette + */ +UINT MFDRV_RealizePalette(PHYSDEV dev, HPALETTE hPalette, BOOL dummy) +{ + char buffer[sizeof(METARECORD) - sizeof(WORD)]; + METARECORD *mr = (METARECORD *)&buffer; + + mr->rdSize = (sizeof(METARECORD) - sizeof(WORD)) / sizeof(WORD); + mr->rdFunction = META_REALIZEPALETTE; + + if (!(MFDRV_WriteRecord( dev, mr, mr->rdSize * sizeof(WORD)))) return 0; + + /* The return value is suppose to be the number of entries + in the logical palette mapped to the system palette or 0 + if the function failed. Since it's not trivial here to + get that kind of information and since it's of little + use in the case of metafiles, we'll always return 1. */ + return 1; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/mfdrv/text.c b/reactos/win32ss/gdi/gdi32/wine/mfdrv/text.c new file mode 100644 index 00000000000..c05ad267a84 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/mfdrv/text.c @@ -0,0 +1,153 @@ +/* + * metafile driver text functions + * + * Copyright 1993, 1994 Alexandre Julliard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wine/wingdi16.h" +#include "mfdrv/metafiledrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(metafile); + + +/****************************************************************** + * MFDRV_MetaExtTextOut + */ +static BOOL MFDRV_MetaExtTextOut( PHYSDEV dev, short x, short y, UINT16 flags, + const RECT16 *rect, LPCSTR str, short count, + const INT16 *lpDx) +{ + BOOL ret; + DWORD len; + METARECORD *mr; + BOOL isrect = flags & (ETO_CLIPPED | ETO_OPAQUE); + + len = sizeof(METARECORD) + (((count + 1) >> 1) * 2) + 2 * sizeof(short) + + sizeof(UINT16); + if (isrect) + len += sizeof(RECT16); + if (lpDx) + len+=count*sizeof(INT16); + if (!(mr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, len))) + return FALSE; + + mr->rdSize = len / 2; + mr->rdFunction = META_EXTTEXTOUT; + *(mr->rdParm) = y; + *(mr->rdParm + 1) = x; + *(mr->rdParm + 2) = count; + *(mr->rdParm + 3) = flags; + if (isrect) memcpy(mr->rdParm + 4, rect, sizeof(RECT16)); + memcpy(mr->rdParm + (isrect ? 8 : 4), str, count); + if (lpDx) + memcpy(mr->rdParm + (isrect ? 8 : 4) + ((count + 1) >> 1),lpDx, + count*sizeof(INT16)); + ret = MFDRV_WriteRecord( dev, mr, mr->rdSize * 2); + HeapFree( GetProcessHeap(), 0, mr); + return ret; +} + + + +/*********************************************************************** + * MFDRV_ExtTextOut + */ +BOOL MFDRV_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, + const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx ) +{ + RECT16 rect16; + LPINT16 lpdx16 = NULL; + BOOL ret; + unsigned int i, j; + LPSTR ascii; + DWORD len; + CHARSETINFO csi; + int charset = GetTextCharset( dev->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(lpDx) { + lpdx16 = HeapAlloc( GetProcessHeap(), 0, sizeof(INT16)*len ); + for(i = j = 0; i < len; ) + if(IsDBCSLeadByteEx(cp, ascii[i])) { + lpdx16[i++] = lpDx[j++]; + lpdx16[i++] = 0; + } else + lpdx16[i++] = lpDx[j++]; + } + + ret = MFDRV_MetaExtTextOut(dev,x,y,flags,lprect?&rect16:NULL,ascii,len,lpdx16); + HeapFree( GetProcessHeap(), 0, ascii ); + HeapFree( GetProcessHeap(), 0, lpdx16 ); + return ret; +} diff --git a/reactos/win32ss/gdi/gdi32/wine/rosglue.c b/reactos/win32ss/gdi/gdi32/wine/rosglue.c new file mode 100644 index 00000000000..345b4fc0426 --- /dev/null +++ b/reactos/win32ss/gdi/gdi32/wine/rosglue.c @@ -0,0 +1,1217 @@ + +#include +#include "gdi_private.h" +#undef SetWorldTransform + +#define NDEBUG +#include + +static +INT_PTR +NULL_Unused() +{ + __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 const struct gdi_dc_funcs DummyPhysDevFuncs = +{ + (PVOID)NULL_Unused, //INT (*pAbortDoc)(PHYSDEV); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //BOOL (*pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*); + (PVOID)NULL_Unused, //BOOL (*pFillPath)(PHYSDEV); + (PVOID)NULL_Unused, //BOOL (*pFillRgn)(PHYSDEV,HRGN,HBRUSH); + (PVOID)NULL_Unused, //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, //BOOL (*pGdiRealizationInfo)(PHYSDEV,void*); + (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, //INT (*pGetDeviceCaps)(PHYSDEV,INT); + (PVOID)NULL_Unused, //BOOL (*pGetDeviceGammaRamp)(PHYSDEV,LPVOID); + (PVOID)NULL_Unused, //DWORD (*pGetFontData)(PHYSDEV,DWORD,DWORD,LPVOID,DWORD); + (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); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //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*); + (PVOID)NULL_Unused, //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*); + (PVOID)NULL_Unused, //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); + (PVOID)NULL_Unused, //BOOL (*pStrokeAndFillPath)(PHYSDEV); + (PVOID)NULL_Unused, //BOOL (*pStrokePath)(PHYSDEV); + (PVOID)NULL_Unused, //BOOL (*pUnrealizePalette)(HPALETTE); + (PVOID)NULL_Unused, //BOOL (*pWidenPath)(PHYSDEV); + (PVOID)NULL_Unused, //struct opengl_funcs * (*wine_get_wgl_driver)(PHYSDEV,UINT); + 0 // UINT priority; +}; + +static +GDILOOBJTYPE +ConvertObjectType( + WORD wType) +{ + /* Get the GDI object type */ + switch (wType) + { + case OBJ_PEN: return GDILoObjType_LO_PEN_TYPE; + case OBJ_BRUSH: return GDILoObjType_LO_BRUSH_TYPE; + case OBJ_DC: return GDILoObjType_LO_DC_TYPE; + case OBJ_METADC: return GDILoObjType_LO_METADC16_TYPE; + case OBJ_PAL: return GDILoObjType_LO_PALETTE_TYPE; + case OBJ_FONT: return GDILoObjType_LO_FONT_TYPE; + case OBJ_BITMAP: return GDILoObjType_LO_BITMAP_TYPE; + case OBJ_REGION: return GDILoObjType_LO_REGION_TYPE; + case OBJ_METAFILE: return GDILoObjType_LO_METAFILE16_TYPE; + case OBJ_MEMDC: return GDILoObjType_LO_DC_TYPE; + case OBJ_EXTPEN: return GDILoObjType_LO_EXTPEN_TYPE; + case OBJ_ENHMETADC: return GDILoObjType_LO_ALTDC_TYPE; + case OBJ_ENHMETAFILE: return GDILoObjType_LO_METAFILE_TYPE; + case OBJ_COLORSPACE: return GDILoObjType_LO_ICMLCS_TYPE; + default: return 0; + } +} + +HGDIOBJ +alloc_gdi_handle( + PVOID pvObject, + WORD wType, + const struct gdi_obj_funcs *funcs) +{ + GDILOOBJTYPE eObjType; + + /* Get the GDI object type */ + eObjType = ConvertObjectType(wType); + if ((eObjType != GDILoObjType_LO_METAFILE_TYPE) && + (eObjType != GDILoObjType_LO_METAFILE16_TYPE) && + (eObjType != GDILoObjType_LO_METADC16_TYPE)) + { + /* This is not supported! */ + ASSERT(FALSE); + return NULL; + } + + /* Insert the client object */ + return GdiCreateClientObj(pvObject, eObjType); +} + +PVOID +free_gdi_handle(HGDIOBJ hobj) +{ + /* Should be a client object */ + return GdiDeleteClientObj(hobj); +} + +PVOID +GDI_GetObjPtr( + HGDIOBJ hobj, + WORD wType) +{ + GDILOOBJTYPE eObjType; + + /* Check if the object type matches */ + eObjType = ConvertObjectType(wType); + if ((eObjType == 0) || (GDI_HANDLE_GET_TYPE(hobj) != eObjType)) + { + return NULL; + } + + /* Check if we have an ALTDC */ + if (eObjType == GDILoObjType_LO_ALTDC_TYPE) + { + /* Object is stored as LDC */ + __debugbreak(); + return GdiGetLDC(hobj); + } + + /* Check for client objects */ + if ((eObjType == GDILoObjType_LO_METAFILE_TYPE) || + (eObjType == GDILoObjType_LO_METAFILE16_TYPE) || + (eObjType == GDILoObjType_LO_METADC16_TYPE)) + { + return GdiGetClientObjLink(hobj); + } + + /* This should never happen! */ + ASSERT(FALSE); + return NULL; +} + +VOID +GDI_ReleaseObj(HGDIOBJ hobj) +{ + /* We don't do any reference-counting */ +} + +WINEDC* +alloc_dc_ptr(WORD magic) +{ + WINEDC* pWineDc; + + /* Allocate the Wine DC */ + pWineDc = HeapAlloc(GetProcessHeap(), 0, sizeof(*pWineDc)); + if (pWineDc == NULL) + { + return NULL; + } + + ZeroMemory(pWineDc, sizeof(*pWineDc)); + pWineDc->refcount = 1; + pWineDc->hFont = GetStockObject(SYSTEM_FONT); + pWineDc->hBrush = GetStockObject(WHITE_BRUSH); + pWineDc->hPen = GetStockObject(BLACK_PEN); + pWineDc->hPalette = GetStockObject(DEFAULT_PALETTE); + + if (magic == OBJ_ENHMETADC) + { + /* We create a metafile DC, but we ignore the reference DC, this is + handled by the wine code */ + pWineDc->hdc = NtGdiCreateMetafileDC(NULL); + if (pWineDc->hdc == NULL) + { + HeapFree(GetProcessHeap(), 0, pWineDc); + return NULL; + } + + /* Set the Wine DC as LDC */ + GdiSetLDC(pWineDc->hdc, pWineDc); + } + else if (magic == OBJ_METADC) + { + pWineDc->hdc = GdiCreateClientObj(pWineDc, GDILoObjType_LO_METADC16_TYPE); + if (pWineDc->hdc == NULL) + { + HeapFree(GetProcessHeap(), 0, pWineDc); + return NULL; + } + } + else + { + // nothing else supported! + ASSERT(FALSE); + } + + pWineDc->physDev = &pWineDc->NullPhysDev; + pWineDc->NullPhysDev.funcs = &DummyPhysDevFuncs; + pWineDc->NullPhysDev.next = NULL; + + pWineDc->NullPhysDev.hdc = pWineDc->hdc; + return pWineDc; +} + +VOID +free_dc_ptr(WINEDC* pWineDc) +{ + /* Invoke the DeleteDC callback to clean up the DC */ + pWineDc->physDev->funcs->pDeleteDC(pWineDc->physDev); + + /* FIXME */ + if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_ALTDC_TYPE) + { + /* Get rid of the LDC */ + ASSERT((WINEDC*)GdiGetLDC(pWineDc->hdc) == pWineDc); + GdiSetLDC(pWineDc->hdc, NULL); + + /* Free the DC */ + NtGdiDeleteObjectApp(pWineDc->hdc); + } + else if (GDI_HANDLE_GET_TYPE(pWineDc->hdc) == GDILoObjType_LO_METADC16_TYPE) + { + GdiDeleteClientObj(pWineDc->hdc); + } + + /* Free the Wine DC */ + HeapFree(GetProcessHeap(), 0, pWineDc); +} + +WINEDC* +get_dc_ptr(HDC hdc) +{ + /* Check for EMF DC */ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_ALTDC_TYPE) + { + /* The Wine DC is stored as the LDC */ + return (WINEDC*)GdiGetLDC(hdc); + } + + /* Check for METADC16 */ + if (GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) + { + return GdiGetClientObjLink(hdc); + } + + return NULL; +} + +VOID +release_dc_ptr(WINEDC* dc) +{ + /* We don't do any reference-counting */ +} + +void +push_dc_driver_ros( + PHYSDEV *dev, + PHYSDEV physdev, + const struct gdi_dc_funcs *funcs) +{ + physdev->funcs = funcs; + physdev->next = *dev; + physdev->hdc = CONTAINING_RECORD(dev, WINEDC, physDev)->hdc; + *dev = physdev; +} + +VOID +GDI_hdc_using_object( + HGDIOBJ hobj, + HDC hdc) +{ + /* Record that we have an object in use by a METADC. We simply link the + object to the HDC that we use. Wine API does not give us a way to + respond to failure, so we silently ignore it */ + if (!GdiCreateClientObjLink(hobj, hdc)) + { + /* Ignore failure, and return */ + DPRINT1("Failed to create link for selected METADC object.\n"); + return; + } +} + +VOID +GDI_hdc_not_using_object( + HGDIOBJ hobj, + HDC hdc) +{ + HDC hdcLink; + + /* Remove the HDC link for the object */ + hdcLink = GdiRemoveClientObjLink(hobj); + ASSERT(hdcLink == hdc); +} + +int +bitmap_info_size( + const BITMAPINFO * info, + WORD coloruse) +{ + __debugbreak(); + return 0; +} + +BOOL +get_brush_bitmap_info( + HBRUSH hbr, + PBITMAPINFO pbmi, + PVOID *ppvBits, + PUINT puUsage) +{ + HBITMAP hbmp; + HDC hdc; + + /* Call win32k to get the bitmap handle and color usage */ + hbmp = NtGdiGetObjectBitmapHandle(hbr, puUsage); + if (hbmp == NULL) + return FALSE; + + hdc = GetDC(NULL); + if (hdc == NULL) + return FALSE; + + /* Initialize the BITMAPINFO */ + ZeroMemory(pbmi, sizeof(*pbmi)); + pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + + /* Retrieve information about the bitmap */ + if (!GetDIBits(hdc, hbmp, 0, 0, NULL, pbmi, *puUsage)) + return FALSE; + + /* Now allocate a buffer for the bits */ + *ppvBits = HeapAlloc(GetProcessHeap(), 0, pbmi->bmiHeader.biSizeImage); + if (*ppvBits == NULL) + return FALSE; + + /* Retrieve the bitmap bits */ + if (!GetDIBits(hdc, hbmp, 0, pbmi->bmiHeader.biHeight, *ppvBits, pbmi, *puUsage)) + { + HeapFree(GetProcessHeap(), 0, *ppvBits); + *ppvBits = NULL; + return FALSE; + } + + /* GetDIBits doesn't set biClrUsed, but wine code needs it, so we set it */ + if (pbmi->bmiHeader.biBitCount <= 8) + { + pbmi->bmiHeader.biClrUsed = 1 << pbmi->bmiHeader.biBitCount; + } + + return TRUE; +} + +BOOL +WINAPI +SetVirtualResolution( + HDC hdc, + DWORD cxVirtualDevicePixel, + DWORD cyVirtualDevicePixel, + DWORD cxVirtualDeviceMm, + DWORD cyVirtualDeviceMm) +{ + return NtGdiSetVirtualResolution(hdc, + cxVirtualDevicePixel, + cyVirtualDevicePixel, + cxVirtualDeviceMm, + cyVirtualDeviceMm); +} + +BOOL +WINAPI +DeleteColorSpace( + HCOLORSPACE hcs) +{ + return NtGdiDeleteColorSpace(hcs); +} + +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); +} + +void +_assert ( + const char *exp, + const char *file, + unsigned line) +{ + __int2c(); +} + +double +__cdecl +atan2( + double y, + double x) +{ + __debugbreak(); + return 0.; +} + +/******************************************************************************/ + +static +VOID +InitBitBltCoords( + struct bitblt_coords *coords, + HDC hdc, + int x, + int y, + int cx, + int cy) +{ + coords->log_x = x; + coords->log_y = y; + coords->log_width = cx; + coords->log_height = cy; + coords->layout = GetLayout(hdc); +} + +static +PHYSDEV +GetPhysDev( + HDC hdc) +{ + WINEDC *pWineDc; + + pWineDc = get_dc_ptr(hdc); + if (pWineDc == NULL) + { + return NULL; + } + + return pWineDc->physDev; +} + +static +BOOL +DRIVER_PatBlt( + _In_ PHYSDEV physdev, + _In_ HDC hdc, + _In_ INT xLeft, + _In_ INT yTop, + _In_ INT cx, + _In_ INT cy, + _In_ DWORD dwRop) +{ + struct bitblt_coords coords; + + InitBitBltCoords(&coords, hdc, xLeft, yTop, cx, cy); + + return physdev->funcs->pPatBlt(physdev, &coords, dwRop); +} + +static +BOOL +DRIVER_StretchBlt( + _In_ PHYSDEV physdev, + _In_ HDC hdcDst, + _In_ INT xDst, + _In_ INT yDst, + _In_ INT cxDst, + _In_ INT cyDst, + _In_opt_ HDC hdcSrc, + _In_ INT xSrc, + _In_ INT ySrc, + _In_ INT cxSrc, + _In_ INT cySrc, + _In_ DWORD dwRop) +{ + struct bitblt_coords coordsDst, coordsSrc; + struct gdi_physdev physdevSrc = {0}; + + /* Source cannot be a metafile */ + if (GDI_HANDLE_GET_TYPE(hdcSrc) != GDILoObjType_LO_DC_TYPE) + return FALSE; + + /* Source physdev uses only hdc and func */ + physdevSrc.hdc = hdcSrc; + + InitBitBltCoords(&coordsDst, hdcDst, xDst, yDst, cxDst, cyDst); + InitBitBltCoords(&coordsSrc, hdcSrc, xSrc, ySrc, cxSrc, cySrc); + + return physdev->funcs->pStretchBlt(physdev, &coordsDst, &physdevSrc, &coordsSrc, dwRop); +} + +static +BOOL +DRIVER_RestoreDC(PHYSDEV physdev, INT level) +{ + WINEDC *pWineDc = get_dc_ptr(physdev->hdc); + + if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_ALTDC_TYPE) + { + /* The Restore DC function needs the save level to be set correctly. + Note that wine's level is 0 based, while our's is (like win) 1 based. */ + pWineDc->saveLevel = GetDCDWord(physdev->hdc, GdiGetEMFRestorDc, 0) - 1; + + /* Fail if the level is not valid */ + if ((abs(level) > pWineDc->saveLevel) || (level == 0)) + return FALSE; + } + + return physdev->funcs->pRestoreDC(physdev,level); +} + +static +HFONT +DRIVER_SelectFont(PHYSDEV physdev, HFONT hFont, UINT *aa_flags) +{ + WINEDC *pWineDc = get_dc_ptr(physdev->hdc); + HFONT hOldFont; + + if (!physdev->funcs->pSelectFont(physdev, hFont, aa_flags)) + return 0; + + hOldFont = pWineDc->hFont; + pWineDc->hFont = hFont; + return hOldFont; +} + +static +HPEN +DRIVER_SelectPen(PHYSDEV physdev, HPEN hpen, const struct brush_pattern *pattern) +{ + WINEDC *pWineDc = get_dc_ptr(physdev->hdc); + HPEN hOldPen; + + if (!physdev->funcs->pSelectPen(physdev, hpen, pattern)) + return 0; + + hOldPen = pWineDc->hPen; + pWineDc->hPen = hpen; + return hOldPen; +} + +static +HBRUSH +DRIVER_SelectBrush(PHYSDEV physdev, HBRUSH hbrush, const struct brush_pattern *pattern) +{ + WINEDC *pWineDc = get_dc_ptr(physdev->hdc); + HBRUSH hOldBrush; + + if (!physdev->funcs->pSelectBrush(physdev, hbrush, pattern)) + return 0; + + hOldBrush = pWineDc->hBrush; + pWineDc->hBrush = hbrush; + return hOldBrush; +} + +static +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: + __debugbreak(); // not implemented + return physdev->funcs->pPolyDraw(physdev, + _va_arg_n(argptr, const POINT*, 1), + _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: + __debugbreak(); // not implemented + 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_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); + + + /* These are not implemented in wine */ + case DCFUNC_AlphaBlend: + case DCFUNC_AngleArc: + case DCFUNC_ArcTo: + case DCFUNC_GradientFill: + case DCFUNC_MaskBlt: + case DCFUNC_PathToRegion: + case DCFUNC_PlgBlt: + case DCFUNC_TransparentBlt: + UNIMPLEMENTED; + return 0; + + default: + __debugbreak(); + return 0; + } +} + +BOOL +METADC_Dispatch( + _In_ DCFUNC eFunction, + _Out_ PDWORD_PTR pdwResult, + _In_ DWORD_PTR dwError, + _In_ HDC hdc, + ...) +{ + PHYSDEV physdev; + va_list argptr; + + /* Handle only METADC16 and ALTDC */ + if ((GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) && + (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_METADC16_TYPE)) + { + /* Let the caller handle it */ + return FALSE; + } + + physdev = GetPhysDev(hdc); + if (physdev == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + *pdwResult = dwError; + return TRUE; + } + + va_start(argptr, hdc); + *pdwResult = DRIVER_Dispatch(physdev, eFunction, argptr); + va_end(argptr); + + /* Return TRUE to indicate that we want to return from the parent */ + return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) || + (*pdwResult == dwError)); +} + +BOOL +WINAPI +METADC_GetAndSetDCDWord( + _Out_ DWORD* pdwResult, + _In_ HDC hdc, + _In_ UINT uFunction, + _In_ DWORD dwIn, + _In_ ULONG ulMFId, + _In_ USHORT usMF16Id, + _In_ DWORD dwError) +{ + PHYSDEV physdev; + + /* Ignore these, we let wine code handle this */ + UNREFERENCED_PARAMETER(ulMFId); + UNREFERENCED_PARAMETER(usMF16Id); + + physdev = GetPhysDev(hdc); + if (physdev == NULL) + { + SetLastError(ERROR_INVALID_HANDLE); + *pdwResult = dwError; + return TRUE; + } + + /* Check the function */ + switch (uFunction) + { + case GdiGetSetMapMode: + *pdwResult = physdev->funcs->pSetMapMode(physdev, dwIn); + break; + + case GdiGetSetArcDirection: + if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE) + pdwResult = 0; + else + *pdwResult = physdev->funcs->pSetArcDirection(physdev, dwIn); + break; + + case GdiGetSetRelAbs: + if (GDI_HANDLE_GET_TYPE(physdev->hdc) == GDILoObjType_LO_METADC16_TYPE) + *pdwResult = physdev->funcs->pSetRelAbs(physdev, dwIn); + else + { + UNIMPLEMENTED; + *pdwResult = 0; + } + break; + + + default: + __debugbreak(); + } + + /* Return TRUE to indicate that we want to return from the parent */ + return ((GDI_HANDLE_GET_TYPE(hdc) == GDILoObjType_LO_METADC16_TYPE) || + (*pdwResult == dwError)); +} + +VOID +WINAPI +METADC_DeleteObject(HGDIOBJ hobj) +{ + GDILOOBJTYPE eObjectType; + HDC hdc; + PHYSDEV physdev; + + /* Check for one of the types we actually handle here */ + eObjectType = GDI_HANDLE_GET_TYPE(hobj); + if ((eObjectType != GDILoObjType_LO_BRUSH_TYPE) && + (eObjectType != GDILoObjType_LO_PEN_TYPE) && + (eObjectType != GDILoObjType_LO_EXTPEN_TYPE) && + (eObjectType != GDILoObjType_LO_PALETTE_TYPE) && + (eObjectType != GDILoObjType_LO_FONT_TYPE)) + { + return; + } + + /* Check if we have a client object link and remove it if it was found. + The link is the HDC that the object was selected into. */ + hdc = GdiRemoveClientObjLink(hobj); + if (hdc == NULL) + { + /* The link was not found, so we are not handling this object here */ + return; + } + + /* Get the physdev */ + physdev = GetPhysDev(hdc); + if (physdev == NULL) + { + /* This happens, when the METADC is already closed, when we delete + the object. Simply ignore it */ + DPRINT1("METADC was already closed, cannot delete object. Ignoring.\n"); + return; + } + + physdev->funcs->pDeleteObject(physdev, hobj); +} + +BOOL +WINAPI +METADC_DeleteDC( + _In_ HDC hdc) +{ + __debugbreak(); + + /* Only ALTDCs are supported */ + if (GDI_HANDLE_GET_TYPE(hdc) != GDILoObjType_LO_ALTDC_TYPE) + { + return FALSE; + } + // FIXME call the driver? + return NtGdiDeleteObjectApp(hdc); +} + +INT +WINAPI +METADC16_Escape( + _In_ HDC hdc, + _In_ INT nEscape, + _In_ INT cbInput, + _In_ LPCSTR lpvInData, + _Out_ LPVOID lpvOutData) +{ + DWORD_PTR dwResult; + + /* Do not record MFCOMMENT */ + if (nEscape == MFCOMMENT) + { + // HACK required by wine code... + //return 1; + } + + METADC_Dispatch(DCFUNC_ExtEscape, + &dwResult, + SP_ERROR, + hdc, + nEscape, + cbInput, + lpvInData, + lpvOutData); + + return (INT)dwResult; +} diff --git a/reactos/win32ss/include/ntgdihdl.h b/reactos/win32ss/include/ntgdihdl.h index 3264fa930d3..c2b31c885db 100644 --- a/reactos/win32ss/include/ntgdihdl.h +++ b/reactos/win32ss/include/ntgdihdl.h @@ -15,18 +15,15 @@ /* DEFINES *******************************************************************/ -/* Base address where the handle table is mapped to */ -#define GDI_HANDLE_TABLE_BASE_ADDRESS (0x400000) - /* GDI handle table can hold 0x10000 handles */ #define GDI_HANDLE_COUNT 0x10000 -#define GDI_GLOBAL_PROCESS (0x0) #define GDI_CFONT_MAX 16 /* Handle Masks and shifts */ #define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1) #define GDI_HANDLE_TYPE_MASK 0x007f0000 #define GDI_HANDLE_BASETYPE_MASK 0x001f0000 +#define GDI_HANDLE_EXTYPE_MASK 0x00600000 #define GDI_HANDLE_STOCK_MASK 0x00800000 #define GDI_HANDLE_REUSE_MASK 0xff000000 #define GDI_HANDLE_UPPER_MASK (GDI_HANDLE_TYPE_MASK|GDI_HANDLE_STOCK_MASK|GDI_HANDLE_REUSE_MASK) @@ -34,11 +31,7 @@ #define GDI_HANDLE_BASETYPE_SHIFT 16 #define GDI_ENTRY_STOCK_MASK 0x00000080 -#define GDI_ENTRY_REUSE_MASK 0x0000ff00 -#define GDI_ENTRY_REUSE_INC 0x00000100 #define GDI_ENTRY_BASETYPE_MASK 0x001f0000 -#define GDI_ENTRY_FLAGS_MASK 0xff000000 -#define GDI_ENTRY_REUSECNT_SHIFT 8 #define GDI_ENTRY_UPPER_SHIFT 16 /* GDI Entry Flags */ @@ -115,9 +108,6 @@ #define GDI_HANDLE_GET_REUSECNT(h) \ (((ULONG_PTR)(h)) >> GDI_HANDLE_REUSECNT_SHIFT) -#define GDI_ENTRY_GET_REUSECNT(e) \ - ((((ULONG_PTR)(e)) & GDI_ENTRY_REUSE_MASK) >> GDI_ENTRY_REUSECNT_SHIFT) - #define GDI_OBJECT_GET_TYPE_INDEX(t) \ ((t & GDI_HANDLE_BASETYPE_MASK) >> GDI_HANDLE_BASETYPE_SHIFT)