diff --git a/configure b/configure index 11aefae817..a61c726a58 100755 --- a/configure +++ b/configure @@ -14858,6 +14858,8 @@ test "$srcdir" = "." || wine_fn_config_symlink tools/l_intl.nls ac_config_links="$ac_config_links wine:tools/winewrapper" wine_fn_config_symlink wine +ac_config_commands="$ac_config_commands dlls/gdi32/dibdrv" + ac_config_commands="$ac_config_commands dlls/gdi32/enhmfdrv" ac_config_commands="$ac_config_commands dlls/gdi32/mfdrv" @@ -16320,6 +16322,7 @@ do "fonts/tahomabd.ttf") CONFIG_LINKS="$CONFIG_LINKS fonts/tahomabd.ttf:fonts/tahomabd.ttf" ;; "tools/l_intl.nls") CONFIG_LINKS="$CONFIG_LINKS tools/l_intl.nls:tools/l_intl.nls" ;; "wine") CONFIG_LINKS="$CONFIG_LINKS wine:tools/winewrapper" ;; + "dlls/gdi32/dibdrv") CONFIG_COMMANDS="$CONFIG_COMMANDS dlls/gdi32/dibdrv" ;; "dlls/gdi32/enhmfdrv") CONFIG_COMMANDS="$CONFIG_COMMANDS dlls/gdi32/enhmfdrv" ;; "dlls/gdi32/mfdrv") CONFIG_COMMANDS="$CONFIG_COMMANDS dlls/gdi32/mfdrv" ;; "dlls/kernel32/nls") CONFIG_COMMANDS="$CONFIG_COMMANDS dlls/kernel32/nls" ;; @@ -16957,6 +16960,8 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} case $ac_file$ac_mode in "include/stamp-h":C) echo timestamp > include/stamp-h ;; + "dlls/gdi32/dibdrv":C) test -d "dlls/gdi32/dibdrv" || { { $as_echo "$as_me:${as_lineno-$LINENO}: creating dlls/gdi32/dibdrv" >&5 +$as_echo "$as_me: creating dlls/gdi32/dibdrv" >&6;}; as_dir="dlls/gdi32/dibdrv"; as_fn_mkdir_p; } ;; "dlls/gdi32/enhmfdrv":C) test -d "dlls/gdi32/enhmfdrv" || { { $as_echo "$as_me:${as_lineno-$LINENO}: creating dlls/gdi32/enhmfdrv" >&5 $as_echo "$as_me: creating dlls/gdi32/enhmfdrv" >&6;}; as_dir="dlls/gdi32/enhmfdrv"; as_fn_mkdir_p; } ;; "dlls/gdi32/mfdrv":C) test -d "dlls/gdi32/mfdrv" || { { $as_echo "$as_me:${as_lineno-$LINENO}: creating dlls/gdi32/mfdrv" >&5 diff --git a/configure.ac b/configure.ac index 4290a728a7..3f293030f0 100644 --- a/configure.ac +++ b/configure.ac @@ -2347,6 +2347,7 @@ WINE_CONFIG_SYMLINK(fonts/tahomabd.ttf,,enable_fonts) WINE_CONFIG_SYMLINK(tools/l_intl.nls) WINE_CONFIG_SYMLINK(wine,tools/winewrapper) +WINE_CONFIG_EXTRA_DIR(dlls/gdi32/dibdrv) WINE_CONFIG_EXTRA_DIR(dlls/gdi32/enhmfdrv) WINE_CONFIG_EXTRA_DIR(dlls/gdi32/mfdrv) WINE_CONFIG_EXTRA_DIR(dlls/kernel32/nls) diff --git a/dlls/gdi32/Makefile.in b/dlls/gdi32/Makefile.in index 173deddb70..13b1a72cbe 100644 --- a/dlls/gdi32/Makefile.in +++ b/dlls/gdi32/Makefile.in @@ -14,6 +14,7 @@ C_SRCS = \ clipping.c \ dc.c \ dib.c \ + dibdrv/dc.c \ driver.c \ enhmetafile.c \ enhmfdrv/bitblt.c \ @@ -44,6 +45,7 @@ C_SRCS = \ RC_SRCS = version.rc EXTRASUBDIRS = \ + dibdrv \ enhmfdrv \ mfdrv diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 9f4f737749..460f47934f 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -592,7 +592,7 @@ BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev ) if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE; - if (bitmap->funcs != physdev->funcs) + if (!bitmap->dib && bitmap->funcs != physdev->funcs) { /* we can only change from the null driver to some other driver */ if (bitmap->funcs == &null_driver) @@ -627,7 +627,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) HGDIOBJ ret; BITMAPOBJ *bitmap; DC *dc; - PHYSDEV physdev; + PHYSDEV physdev = NULL, old_physdev = NULL; if (!(dc = get_dc_ptr( hdc ))) return 0; @@ -653,7 +653,17 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) goto done; } - physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); + old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); + if(old_physdev == &dc->dibdrv.dev) + pop_dc_driver( dc, old_physdev ); + + if(bitmap->dib) + { + physdev = &dc->dibdrv.dev; + push_dc_driver( dc, physdev, physdev->funcs ); + } + else + physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); if (!BITMAP_SetOwnerDC( handle, physdev )) { @@ -682,6 +692,11 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) } done: + if(!ret) + { + if(physdev == &dc->dibdrv.dev) pop_dc_driver( dc, physdev ); + if(old_physdev == &dc->dibdrv.dev) push_dc_driver( dc, old_physdev, old_physdev->funcs ); + } release_dc_ptr( dc ); return ret; } diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c index 064c9eeff8..86b6a4602e 100644 --- a/dlls/gdi32/dc.c +++ b/dlls/gdi32/dc.c @@ -79,6 +79,8 @@ DC *alloc_dc_ptr( WORD magic ) dc->nulldrv.funcs = &null_driver; dc->nulldrv.next = NULL; + dc->dibdrv.dev.funcs = &dib_driver; + dc->dibdrv.dev.next = NULL; dc->physDev = &dc->nulldrv; dc->thread = GetCurrentThreadId(); dc->refcount = 1; diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c new file mode 100644 index 0000000000..d105f603a3 --- /dev/null +++ b/dlls/gdi32/dibdrv/dc.c @@ -0,0 +1,221 @@ +/* + * DIB driver initialization and DC functions. + * + * Copyright 2011 Huw 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 "gdi_private.h" +#include "dibdrv.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dib); + +/*********************************************************************** + * dibdrv_DeleteDC + */ +static BOOL CDECL dibdrv_DeleteDC( PHYSDEV dev ) +{ + TRACE("(%p)\n", dev); + return 0; +} + +static BOOL init_dib(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, void *bits) +{ + dib->bit_count = bi->biBitCount; + dib->width = bi->biWidth; + dib->height = bi->biHeight; + dib->stride = ((dib->width * dib->bit_count + 31) >> 3) & ~3; + dib->bits = bits; + + if(dib->height < 0) /* top-down */ + { + dib->height = -dib->height; + } + else /* bottom-up */ + { + /* bits always points to the top-left corner and the stride is -ve */ + dib->bits = (BYTE*)dib->bits + (dib->height - 1) * dib->stride; + dib->stride = -dib->stride; + } + + switch(dib->bit_count) + { + default: + TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count); + return FALSE; + } + + return TRUE; +} + +/*********************************************************************** + * dibdrv_SelectBitmap + */ +static HBITMAP CDECL dibdrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap ) +{ + PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectBitmap ); + dibdrv_physdev *pdev = get_dibdrv_pdev(dev); + BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP ); + TRACE("(%p, %p)\n", dev, bitmap); + + if (!bmp) return 0; + assert(bmp->dib); + + init_dib(&pdev->dib, &bmp->dib->dsBmih, bmp->dib->dsBitfields, bmp->dib->dsBm.bmBits); + + GDI_ReleaseObj( bitmap ); + + return next->funcs->pSelectBitmap( next, bitmap ); +} + +const DC_FUNCTIONS dib_driver = +{ + NULL, /* pAbortDoc */ + NULL, /* pAbortPath */ + NULL, /* pAlphaBlend */ + NULL, /* pAngleArc */ + NULL, /* pArc */ + NULL, /* pArcTo */ + NULL, /* pBeginPath */ + NULL, /* pChoosePixelFormat */ + NULL, /* pChord */ + NULL, /* pCloseFigure */ + NULL, /* pCreateBitmap */ + NULL, /* pCreateDC */ + NULL, /* pCreateDIBSection */ + NULL, /* pDeleteBitmap */ + dibdrv_DeleteDC, /* pDeleteDC */ + NULL, /* pDeleteObject */ + NULL, /* pDescribePixelFormat */ + NULL, /* pDeviceCapabilities */ + NULL, /* pEllipse */ + NULL, /* pEndDoc */ + NULL, /* pEndPage */ + NULL, /* pEndPath */ + NULL, /* pEnumDeviceFonts */ + NULL, /* pEnumICMProfiles */ + NULL, /* pExcludeClipRect */ + NULL, /* pExtDeviceMode */ + NULL, /* pExtEscape */ + NULL, /* pExtFloodFill */ + NULL, /* pExtSelectClipRgn */ + NULL, /* pExtTextOut */ + NULL, /* pFillPath */ + NULL, /* pFillRgn */ + NULL, /* pFlattenPath */ + NULL, /* pFrameRgn */ + NULL, /* pGdiComment */ + NULL, /* pGetBitmapBits */ + NULL, /* pGetCharWidth */ + NULL, /* pGetDIBits */ + NULL, /* pGetDeviceCaps */ + NULL, /* pGetDeviceGammaRamp */ + NULL, /* pGetICMProfile */ + NULL, /* pGetNearestColor */ + NULL, /* pGetPixel */ + NULL, /* pGetPixelFormat */ + NULL, /* pGetSystemPaletteEntries */ + NULL, /* pGetTextExtentExPoint */ + NULL, /* pGetTextMetrics */ + NULL, /* pIntersectClipRect */ + NULL, /* pInvertRgn */ + NULL, /* pLineTo */ + NULL, /* pModifyWorldTransform */ + NULL, /* pMoveTo */ + NULL, /* pOffsetClipRgn */ + NULL, /* pOffsetViewportOrg */ + NULL, /* pOffsetWindowOrg */ + NULL, /* pPaintRgn */ + NULL, /* pPatBlt */ + NULL, /* pPie */ + NULL, /* pPolyBezier */ + NULL, /* pPolyBezierTo */ + NULL, /* pPolyDraw */ + NULL, /* pPolyPolygon */ + NULL, /* pPolyPolyline */ + NULL, /* pPolygon */ + NULL, /* pPolyline */ + NULL, /* pPolylineTo */ + NULL, /* pRealizeDefaultPalette */ + NULL, /* pRealizePalette */ + NULL, /* pRectangle */ + NULL, /* pResetDC */ + NULL, /* pRestoreDC */ + NULL, /* pRoundRect */ + NULL, /* pSaveDC */ + NULL, /* pScaleViewportExt */ + NULL, /* pScaleWindowExt */ + dibdrv_SelectBitmap, /* pSelectBitmap */ + NULL, /* pSelectBrush */ + NULL, /* pSelectClipPath */ + NULL, /* pSelectFont */ + NULL, /* pSelectPalette */ + NULL, /* pSelectPen */ + NULL, /* pSetArcDirection */ + NULL, /* pSetBitmapBits */ + NULL, /* pSetBkColor */ + NULL, /* pSetBkMode */ + NULL, /* pSetDCBrushColor */ + NULL, /* pSetDCPenColor */ + NULL, /* pSetDIBColorTable */ + NULL, /* pSetDIBits */ + NULL, /* pSetDIBitsToDevice */ + NULL, /* pSetDeviceClipping */ + NULL, /* pSetDeviceGammaRamp */ + NULL, /* pSetLayout */ + NULL, /* pSetMapMode */ + NULL, /* pSetMapperFlags */ + NULL, /* pSetPixel */ + NULL, /* pSetPixelFormat */ + NULL, /* pSetPolyFillMode */ + NULL, /* pSetROP2 */ + NULL, /* pSetRelAbs */ + NULL, /* pSetStretchBltMode */ + NULL, /* pSetTextAlign */ + NULL, /* pSetTextCharacterExtra */ + NULL, /* pSetTextColor */ + NULL, /* pSetTextJustification */ + NULL, /* pSetViewportExt */ + NULL, /* pSetViewportOrg */ + NULL, /* pSetWindowExt */ + NULL, /* pSetWindowOrg */ + NULL, /* pSetWorldTransform */ + NULL, /* pStartDoc */ + NULL, /* pStartPage */ + NULL, /* pStretchBlt */ + NULL, /* pStretchDIBits */ + NULL, /* pStrokeAndFillPath */ + NULL, /* pStrokePath */ + NULL, /* pSwapBuffers */ + NULL, /* pUnrealizePalette */ + NULL, /* pWidenPath */ + NULL, /* pwglCopyContext */ + NULL, /* pwglCreateContext */ + NULL, /* pwglCreateContextAttribsARB */ + NULL, /* pwglDeleteContext */ + NULL, /* pwglGetProcAddress */ + NULL, /* pwglGetPbufferDCARB */ + NULL, /* pwglMakeCurrent */ + NULL, /* pwglMakeContextCurrentARB */ + NULL, /* pwglSetPixelFormatWINE */ + NULL, /* pwglShareLists */ + NULL, /* pwglUseFontBitmapsA */ + NULL /* pwglUseFontBitmapsW */ +}; diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h new file mode 100644 index 0000000000..9dca50fc9e --- /dev/null +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -0,0 +1,24 @@ +/* + * DIB driver include file. + * + * Copyright 2011 Huw 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 + */ + +static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev ) +{ + return (dibdrv_physdev *)dev; +} diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h index abb958872b..5849d882c0 100644 --- a/dlls/gdi32/gdi_private.h +++ b/dlls/gdi32/gdi_private.h @@ -79,6 +79,21 @@ typedef struct gdi_physdev HDC hdc; } *PHYSDEV; +typedef struct +{ + int bit_count, width, height; + int stride; /* stride in bytes. Will be -ve for bottom-up dibs (see bits). */ + void *bits; /* points to the top-left corner of the dib. */ + + DWORD red_mask, green_mask, blue_mask; +} dib_info; + +typedef struct dibdrv_physdev +{ + struct gdi_physdev dev; + dib_info dib; +} dibdrv_physdev; + typedef struct tagDC_FUNCS { INT (CDECL *pAbortDoc)(PHYSDEV); @@ -246,6 +261,7 @@ typedef struct tagDC GDIOBJHDR header; HDC hSelf; /* Handle to this DC */ struct gdi_physdev nulldrv; /* physdev for the null driver */ + struct dibdrv_physdev dibdrv; /* physdev for the dib driver */ PHYSDEV physDev; /* Physical device (driver-specific) */ DWORD thread; /* thread owning the DC */ LONG refcount; /* thread refcount */ @@ -391,6 +407,7 @@ extern int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width, /* driver.c */ extern const DC_FUNCTIONS null_driver DECLSPEC_HIDDEN; +extern const DC_FUNCTIONS dib_driver DECLSPEC_HIDDEN; extern const DC_FUNCTIONS *DRIVER_get_display_driver(void) DECLSPEC_HIDDEN; extern const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN; extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN;