From a51b2c8bd594199bf1a3de36a20845f5b604d366 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Tue, 10 Jan 2012 14:37:48 +0100 Subject: [PATCH] gdi32: Add a separate set of GDI object functions for DIBs. --- dlls/gdi32/bitmap.c | 45 ++------------ dlls/gdi32/dib.c | 146 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 41 deletions(-) diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c index 0d637ec833b..dcccd3dd553 100644 --- a/dlls/gdi32/bitmap.c +++ b/dlls/gdi32/bitmap.c @@ -566,7 +566,7 @@ static BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev ) if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE; - if (!bitmap->dib && bitmap->funcs != physdev->funcs) + if (bitmap->funcs != physdev->funcs) { /* we can only change from the null driver to some other driver */ if (bitmap->funcs == &null_driver) @@ -634,7 +634,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc ) old_physdev = pop_dc_driver( &dc->physDev ); physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); - if (bitmap->dib || physdev->funcs == &null_driver) + if (physdev->funcs == &null_driver) { physdev = dc->dibdrv; if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs ); @@ -701,26 +701,6 @@ static BOOL BITMAP_DeleteObject( HGDIOBJ handle ) if (!(bmp = free_gdi_handle( handle ))) return FALSE; HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits ); - - if (bmp->dib) - { - DIBSECTION *dib = bmp->dib; - - if (dib->dsBm.bmBits) - { - if (dib->dshSection) - { - SYSTEM_INFO SystemInfo; - GetSystemInfo( &SystemInfo ); - UnmapViewOfFile( (char *)dib->dsBm.bmBits - - (dib->dsOffset % SystemInfo.dwAllocationGranularity) ); - } - else if (!dib->dsOffset) - VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE ); - } - HeapFree(GetProcessHeap(), 0, dib); - HeapFree(GetProcessHeap(), 0, bmp->color_table); - } return HeapFree( GetProcessHeap(), 0, bmp ); } @@ -730,30 +710,13 @@ static BOOL BITMAP_DeleteObject( HGDIOBJ handle ) */ static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ) { - INT ret; + INT ret = 0; BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP ); if (!bmp) return 0; if (!buffer) ret = sizeof(BITMAP); - else if (count < sizeof(BITMAP)) ret = 0; - else if (bmp->dib) - { - if (count >= sizeof(DIBSECTION)) - { - DIBSECTION *dib = buffer; - *dib = *bmp->dib; - dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight ); - ret = sizeof(DIBSECTION); - } - else /* if (count >= sizeof(BITMAP)) */ - { - DIBSECTION *dib = bmp->dib; - memcpy( buffer, &dib->dsBm, sizeof(BITMAP) ); - ret = sizeof(BITMAP); - } - } - else + else if (count >= sizeof(BITMAP)) { memcpy( buffer, &bmp->bitmap, sizeof(BITMAP) ); ((BITMAP *) buffer)->bmBits = NULL; diff --git a/dlls/gdi32/dib.c b/dlls/gdi32/dib.c index 5aab9569040..0f179725dda 100644 --- a/dlls/gdi32/dib.c +++ b/dlls/gdi32/dib.c @@ -72,6 +72,19 @@ WINE_DEFAULT_DEBUG_CHANNEL(bitmap); +static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc ); +static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ); +static BOOL DIB_DeleteObject( HGDIOBJ handle ); + +static const struct gdi_obj_funcs dib_funcs = +{ + DIB_SelectObject, /* pSelectObject */ + DIB_GetObject, /* pGetObjectA */ + DIB_GetObject, /* pGetObjectW */ + NULL, /* pUnrealizeObject */ + DIB_DeleteObject /* pDeleteObject */ +}; + /*********************************************************************** * bitmap_info_size * @@ -1576,6 +1589,7 @@ HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage, { PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection ); bmp->dib = dib; + bmp->header.funcs = &dib_funcs; bmp->funcs = physdev->funcs; bmp->color_table = color_table; GDI_ReleaseObj( ret ); @@ -1600,3 +1614,135 @@ error: HeapFree( GetProcessHeap(), 0, dib ); return 0; } + + +/*********************************************************************** + * DIB_SelectObject + */ +static HGDIOBJ DIB_SelectObject( HGDIOBJ handle, HDC hdc ) +{ + HGDIOBJ ret; + BITMAPOBJ *bitmap; + DC *dc; + PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL; + + if (!(dc = get_dc_ptr( hdc ))) return 0; + + if (GetObjectType( hdc ) != OBJ_MEMDC) + { + ret = 0; + goto done; + } + ret = dc->hBitmap; + if (handle == dc->hBitmap) goto done; /* nothing to do */ + + if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP ))) + { + ret = 0; + goto done; + } + + if (bitmap->header.selcount) + { + WARN( "Bitmap already selected in another DC\n" ); + GDI_ReleaseObj( handle ); + ret = 0; + goto done; + } + + if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev ); + + old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap ); + physdev = dc->dibdrv; + if (old_physdev != dc->dibdrv) + { + if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs ); + else + { + if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done; + dc->dibdrv = physdev = dc->physDev; + } + } + + if (!physdev->funcs->pSelectBitmap( physdev, handle )) + { + GDI_ReleaseObj( handle ); + ret = 0; + } + else + { + dc->hBitmap = handle; + GDI_inc_ref_count( handle ); + dc->dirty = 0; + dc->vis_rect.left = 0; + dc->vis_rect.top = 0; + dc->vis_rect.right = bitmap->bitmap.bmWidth; + dc->vis_rect.bottom = bitmap->bitmap.bmHeight; + GDI_ReleaseObj( handle ); + DC_InitDC( dc ); + GDI_dec_ref_count( ret ); + } + + done: + if(!ret) + { + if (old_physdev && old_physdev != dc->dibdrv) pop_dc_driver( &dc->physDev ); + } + if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs ); + release_dc_ptr( dc ); + return ret; +} + + +/*********************************************************************** + * DIB_GetObject + */ +static INT DIB_GetObject( HGDIOBJ handle, INT count, LPVOID buffer ) +{ + INT ret = 0; + BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP ); + + if (!bmp) return 0; + + if (!buffer) ret = sizeof(BITMAP); + else if (count >= sizeof(DIBSECTION)) + { + DIBSECTION *dib = buffer; + *dib = *bmp->dib; + dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight ); + ret = sizeof(DIBSECTION); + } + else if (count >= sizeof(BITMAP)) + { + BITMAP *bitmap = buffer; + *bitmap = bmp->dib->dsBm; + ret = sizeof(BITMAP); + } + + GDI_ReleaseObj( handle ); + return ret; +} + + +/*********************************************************************** + * DIB_DeleteObject + */ +static BOOL DIB_DeleteObject( HGDIOBJ handle ) +{ + BITMAPOBJ *bmp; + + if (!(bmp = free_gdi_handle( handle ))) return FALSE; + + if (bmp->dib->dshSection) + { + SYSTEM_INFO SystemInfo; + GetSystemInfo( &SystemInfo ); + UnmapViewOfFile( (char *)bmp->dib->dsBm.bmBits - + (bmp->dib->dsOffset % SystemInfo.dwAllocationGranularity) ); + } + else VirtualFree( bmp->dib->dsBm.bmBits, 0, MEM_RELEASE ); + + HeapFree(GetProcessHeap(), 0, bmp->dib); + HeapFree(GetProcessHeap(), 0, bmp->color_table); + return HeapFree( GetProcessHeap(), 0, bmp ); +}