- Handle 1bpp DIBs in NtGdiCreateDIBitmap

- Fix double lock of DC in routines called by NtGdiCreateDIBSection

svn path=/trunk/; revision=8757
This commit is contained in:
Gé van Geldorp 2004-03-15 22:06:55 +00:00
parent 52f0a740aa
commit aea7bd7615
3 changed files with 163 additions and 63 deletions

View file

@ -46,6 +46,8 @@ INT STDCALL BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer);
BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp ); BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp );
HBITMAP FASTCALL BitmapToSurf(PBITMAPOBJ BitmapObj, HDEV GDIDevice); HBITMAP FASTCALL BitmapToSurf(PBITMAPOBJ BitmapObj, HDEV GDIDevice);
HBITMAP FASTCALL IntCreateCompatibleBitmap(PDC Dc, INT Width, INT Height);
/* User Entry Points */ /* User Entry Points */
BOOL BOOL
STDCALL STDCALL

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: bitmaps.c,v 1.61 2004/03/14 00:11:28 gvg Exp $ */ /* $Id: bitmaps.c,v 1.62 2004/03/15 22:06:55 gvg Exp $ */
#undef WIN32_LEAN_AND_MEAN #undef WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
#include <stdlib.h> #include <stdlib.h>
@ -363,41 +363,56 @@ BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp )
} }
HBITMAP STDCALL NtGdiCreateCompatibleBitmap(HDC hDC, HBITMAP FASTCALL
INT Width, IntCreateCompatibleBitmap(PDC Dc,
INT Height) INT Width,
INT Height)
{ {
HBITMAP hbmpRet; HBITMAP Bmp;
PDC dc;
hbmpRet = 0; Bmp = NULL;
dc = DC_LockDc(hDC);
if ((Width >= 0x10000) || (Height >= 0x10000))
{
DPRINT1("got bad width %d or height %d, please look for reason\n", Width, Height);
return NULL;
}
/* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
if (0 == Width || 0 == Height)
{
Bmp = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
}
else
{
Bmp = NtGdiCreateBitmap(Width, Height, 1, Dc->w.bitsPerPixel, NULL);
}
return Bmp;
}
HBITMAP STDCALL
NtGdiCreateCompatibleBitmap(HDC hDC,
INT Width,
INT Height)
{
HBITMAP Bmp;
PDC Dc;
Dc = DC_LockDc(hDC);
DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel); DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, dc->w.bitsPerPixel);
if (!dc) if (NULL == Dc)
{
return 0;
}
if ((Width >= 0x10000) || (Height >= 0x10000))
{
DPRINT("got bad width %d or height %d, please look for reason\n", Width, Height);
}
else
{
/* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
if (!Width || !Height)
{ {
hbmpRet = NtGdiCreateBitmap (1, 1, 1, 1, NULL); return NULL;
} }
else
{ Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
hbmpRet = NtGdiCreateBitmap(Width, Height, 1, dc->w.bitsPerPixel, NULL);
} DPRINT ("\t\t%04x\n", Bmp);
} DC_UnlockDc(hDC);
DPRINT ("\t\t%04x\n", hbmpRet); return Bmp;
DC_UnlockDc( hDC );
return hbmpRet;
} }
HBITMAP STDCALL NtGdiCreateBitmapIndirect(CONST BITMAP *BM) HBITMAP STDCALL NtGdiCreateBitmapIndirect(CONST BITMAP *BM)

View file

@ -1,5 +1,5 @@
/* /*
* $Id: dib.c,v 1.42 2004/02/19 21:12:10 weiden Exp $ * $Id: dib.c,v 1.43 2004/03/15 22:06:55 gvg Exp $
* *
* ReactOS W32 Subsystem * ReactOS W32 Subsystem
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
@ -87,9 +87,9 @@ UINT STDCALL NtGdiSetDIBColorTable(HDC hDC,
} }
// Converts a DIB to a device-dependent bitmap // Converts a DIB to a device-dependent bitmap
INT STDCALL static INT FASTCALL
NtGdiSetDIBits( IntSetDIBits(
HDC hDC, PDC DC,
HBITMAP hBitmap, HBITMAP hBitmap,
UINT StartScan, UINT StartScan,
UINT ScanLines, UINT ScanLines,
@ -97,7 +97,6 @@ NtGdiSetDIBits(
CONST BITMAPINFO *bmi, CONST BITMAPINFO *bmi,
UINT ColorUse) UINT ColorUse)
{ {
DC *dc;
BITMAPOBJ *bitmap; BITMAPOBJ *bitmap;
HBITMAP SourceBitmap, DestBitmap; HBITMAP SourceBitmap, DestBitmap;
INT result = 0; INT result = 0;
@ -116,12 +115,8 @@ NtGdiSetDIBits(
INT scanDirection = 1, DIBWidth; INT scanDirection = 1, DIBWidth;
// Check parameters // Check parameters
if (!(dc = DC_LockDc(hDC)))
return 0;
if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap))) if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap)))
{ {
DC_UnlockDc(hDC);
return 0; return 0;
} }
@ -132,7 +127,7 @@ NtGdiSetDIBits(
// lpRGB = &bmi->bmiColors[0]; // lpRGB = &bmi->bmiColors[0];
// Create a temporary surface for the destination bitmap // Create a temporary surface for the destination bitmap
DestBitmap = BitmapToSurf(bitmap, dc->GDIDevice); DestBitmap = BitmapToSurf(bitmap, DC->GDIDevice);
DestSurf = (PSURFOBJ) AccessUserObject( (ULONG)DestBitmap ); DestSurf = (PSURFOBJ) AccessUserObject( (ULONG)DestBitmap );
DestGDI = (PSURFGDI) AccessInternalObject( (ULONG)DestBitmap ); DestGDI = (PSURFGDI) AccessInternalObject( (ULONG)DestBitmap );
@ -159,19 +154,18 @@ NtGdiSetDIBits(
SourceSurf = (PSURFOBJ)AccessUserObject((ULONG)SourceBitmap); SourceSurf = (PSURFOBJ)AccessUserObject((ULONG)SourceBitmap);
// Destination palette obtained from the hDC // Destination palette obtained from the hDC
hDCPalette = PALETTE_LockPalette(dc->DevInfo->hpalDefault); hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault);
if (NULL == hDCPalette) if (NULL == hDCPalette)
{ {
EngDeleteSurface(SourceBitmap); EngDeleteSurface(SourceBitmap);
EngDeleteSurface(DestBitmap); EngDeleteSurface(DestBitmap);
BITMAPOBJ_UnlockBitmap(hBitmap); BITMAPOBJ_UnlockBitmap(hBitmap);
DC_UnlockDc(hDC);
SetLastWin32Error(ERROR_INVALID_HANDLE); SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0; return 0;
} }
DDB_Palette_Type = hDCPalette->Mode; DDB_Palette_Type = hDCPalette->Mode;
DDB_Palette = dc->DevInfo->hpalDefault; DDB_Palette = DC->DevInfo->hpalDefault;
PALETTE_UnlockPalette(dc->DevInfo->hpalDefault); PALETTE_UnlockPalette(DC->DevInfo->hpalDefault);
// Source palette obtained from the BITMAPINFO // Source palette obtained from the BITMAPINFO
DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type ); DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type );
@ -180,7 +174,6 @@ NtGdiSetDIBits(
EngDeleteSurface(SourceBitmap); EngDeleteSurface(SourceBitmap);
EngDeleteSurface(DestBitmap); EngDeleteSurface(DestBitmap);
BITMAPOBJ_UnlockBitmap(hBitmap); BITMAPOBJ_UnlockBitmap(hBitmap);
DC_UnlockDc(hDC);
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0; return 0;
} }
@ -193,7 +186,6 @@ NtGdiSetDIBits(
EngDeleteSurface(SourceBitmap); EngDeleteSurface(SourceBitmap);
EngDeleteSurface(DestBitmap); EngDeleteSurface(DestBitmap);
BITMAPOBJ_UnlockBitmap(hBitmap); BITMAPOBJ_UnlockBitmap(hBitmap);
DC_UnlockDc(hDC);
SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
return 0; return 0;
} }
@ -226,11 +218,38 @@ NtGdiSetDIBits(
// WinFree((LPSTR)lpRGB); // WinFree((LPSTR)lpRGB);
BITMAPOBJ_UnlockBitmap(hBitmap); BITMAPOBJ_UnlockBitmap(hBitmap);
DC_UnlockDc(hDC);
return result; return result;
} }
// Converts a DIB to a device-dependent bitmap
INT STDCALL
NtGdiSetDIBits(
HDC hDC,
HBITMAP hBitmap,
UINT StartScan,
UINT ScanLines,
CONST VOID *Bits,
CONST BITMAPINFO *bmi,
UINT ColorUse)
{
PDC Dc;
INT Ret;
Dc = DC_LockDc(hDC);
if (NULL == Dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
DC_UnlockDc(hDC);
return Ret;
}
INT STDCALL INT STDCALL
NtGdiSetDIBitsToDevice( NtGdiSetDIBitsToDevice(
HDC hDC, HDC hDC,
@ -873,13 +892,13 @@ LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
return ret; return ret;
} }
// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits static HBITMAP FASTCALL
// The DDB that is created will be whatever bit depth your reference DC is IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,
HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header, DWORD init, LPCVOID bits, const BITMAPINFO *data,
DWORD init, LPCVOID bits, const BITMAPINFO *data, UINT coloruse)
UINT coloruse)
{ {
HBITMAP handle; HBITMAP handle;
BOOL fColor;
DWORD width; DWORD width;
int height; int height;
WORD bpp; WORD bpp;
@ -891,24 +910,88 @@ HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hdc, const BITMAPINFOHEADER *header,
// Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2 // Check if we should create a monochrome or color bitmap. We create a monochrome bitmap only if it has exactly 2
// colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap. // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap.
// Now create the bitmap if (bpp != 1) fColor = TRUE;
if (init == CBM_INIT) else if ((coloruse != DIB_RGB_COLORS) ||
{ (init != CBM_INIT) || !data) fColor = FALSE;
handle = NtGdiCreateCompatibleBitmap(hdc, width, height);
if (!handle)
{
return 0;
}
NtGdiSetDIBits(hdc, handle, 0, height, bits, data, coloruse);
}
else else
{
if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
{ {
handle = NtGdiCreateBitmap(width, height, 1, bpp, NULL); RGBQUAD *rgb = data->bmiColors;
DWORD col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
// Check if the first color of the colormap is black
if ((col == RGB(0, 0, 0)))
{
rgb++;
col = RGB( rgb->rgbRed, rgb->rgbGreen, rgb->rgbBlue );
// If the second color is white, create a monochrome bitmap
fColor = (col != RGB(0xff,0xff,0xff));
}
else fColor = TRUE;
}
else if (data->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
RGBTRIPLE *rgb = ((BITMAPCOREINFO *)data)->bmciColors;
DWORD col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue);
if ((col == RGB(0,0,0)))
{
rgb++;
col = RGB( rgb->rgbtRed, rgb->rgbtGreen, rgb->rgbtBlue );
fColor = (col != RGB(0xff,0xff,0xff));
} }
else fColor = TRUE;
}
else
{
DPRINT("(%ld): wrong size for data\n", data->bmiHeader.biSize );
return 0;
}
}
// Now create the bitmap
if (fColor)
{
handle = IntCreateCompatibleBitmap(Dc, width, height);
}
else
{
handle = NtGdiCreateBitmap( width, height, 1, 1, NULL);
}
if (NULL != handle && CBM_INIT == init)
{
IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
}
return handle; return handle;
} }
// The CreateDIBitmap function creates a device-dependent bitmap (DDB) from a DIB and, optionally, sets the bitmap bits
// The DDB that is created will be whatever bit depth your reference DC is
HBITMAP STDCALL NtGdiCreateDIBitmap(HDC hDc, const BITMAPINFOHEADER *Header,
DWORD Init, LPCVOID Bits, const BITMAPINFO *Data,
UINT ColorUse)
{
PDC Dc;
HBITMAP Bmp;
Dc = DC_LockDc(hDc);
if (NULL == Dc)
{
SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL;
}
Bmp = IntCreateDIBitmap(Dc, Header, Init, Bits, Data, ColorUse);
DC_UnlockDc(hDc);
return Bmp;
}
HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC, HBITMAP STDCALL NtGdiCreateDIBSection(HDC hDC,
CONST BITMAPINFO *bmi, CONST BITMAPINFO *bmi,
UINT Usage, UINT Usage,
@ -1036,7 +1119,7 @@ DIB_CreateDIBSection(
// Create Device Dependent Bitmap and add DIB pointer // Create Device Dependent Bitmap and add DIB pointer
if (dib) if (dib)
{ {
res = NtGdiCreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage); res = IntCreateDIBitmap(dc, bi, 0, NULL, bmi, usage);
if (! res) if (! res)
{ {
return NULL; return NULL;