From aea7bd761584ba91acc7d2ab0e65570e1a11fb46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Mon, 15 Mar 2004 22:06:55 +0000 Subject: [PATCH] - Handle 1bpp DIBs in NtGdiCreateDIBitmap - Fix double lock of DC in routines called by NtGdiCreateDIBSection svn path=/trunk/; revision=8757 --- reactos/include/win32k/bitmaps.h | 2 + reactos/subsys/win32k/objects/bitmaps.c | 73 +++++++----- reactos/subsys/win32k/objects/dib.c | 151 ++++++++++++++++++------ 3 files changed, 163 insertions(+), 63 deletions(-) diff --git a/reactos/include/win32k/bitmaps.h b/reactos/include/win32k/bitmaps.h index 0f627991cbb..bbd9f917e87 100644 --- a/reactos/include/win32k/bitmaps.h +++ b/reactos/include/win32k/bitmaps.h @@ -46,6 +46,8 @@ INT STDCALL BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer); BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp ); HBITMAP FASTCALL BitmapToSurf(PBITMAPOBJ BitmapObj, HDEV GDIDevice); +HBITMAP FASTCALL IntCreateCompatibleBitmap(PDC Dc, INT Width, INT Height); + /* User Entry Points */ BOOL STDCALL diff --git a/reactos/subsys/win32k/objects/bitmaps.c b/reactos/subsys/win32k/objects/bitmaps.c index 5eb5d2a8ccb..bcd662db230 100644 --- a/reactos/subsys/win32k/objects/bitmaps.c +++ b/reactos/subsys/win32k/objects/bitmaps.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * 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 #include #include @@ -363,41 +363,56 @@ BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp ) } -HBITMAP STDCALL NtGdiCreateCompatibleBitmap(HDC hDC, - INT Width, - INT Height) +HBITMAP FASTCALL +IntCreateCompatibleBitmap(PDC Dc, + INT Width, + INT Height) { - HBITMAP hbmpRet; - PDC dc; + HBITMAP Bmp; - hbmpRet = 0; - dc = DC_LockDc(hDC); + Bmp = NULL; + + 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); - if (!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) + if (NULL == Dc) { - hbmpRet = NtGdiCreateBitmap (1, 1, 1, 1, NULL); + return NULL; } - else - { - hbmpRet = NtGdiCreateBitmap(Width, Height, 1, dc->w.bitsPerPixel, NULL); - } - } - DPRINT ("\t\t%04x\n", hbmpRet); - DC_UnlockDc( hDC ); - return hbmpRet; + + Bmp = IntCreateCompatibleBitmap(Dc, Width, Height); + + DPRINT ("\t\t%04x\n", Bmp); + DC_UnlockDc(hDC); + return Bmp; } HBITMAP STDCALL NtGdiCreateBitmapIndirect(CONST BITMAP *BM) diff --git a/reactos/subsys/win32k/objects/dib.c b/reactos/subsys/win32k/objects/dib.c index 1992312c169..b45b63dcfd7 100644 --- a/reactos/subsys/win32k/objects/dib.c +++ b/reactos/subsys/win32k/objects/dib.c @@ -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 * 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 -INT STDCALL -NtGdiSetDIBits( - HDC hDC, +static INT FASTCALL +IntSetDIBits( + PDC DC, HBITMAP hBitmap, UINT StartScan, UINT ScanLines, @@ -97,7 +97,6 @@ NtGdiSetDIBits( CONST BITMAPINFO *bmi, UINT ColorUse) { - DC *dc; BITMAPOBJ *bitmap; HBITMAP SourceBitmap, DestBitmap; INT result = 0; @@ -116,12 +115,8 @@ NtGdiSetDIBits( INT scanDirection = 1, DIBWidth; // Check parameters - if (!(dc = DC_LockDc(hDC))) - return 0; - if (!(bitmap = BITMAPOBJ_LockBitmap(hBitmap))) { - DC_UnlockDc(hDC); return 0; } @@ -132,7 +127,7 @@ NtGdiSetDIBits( // lpRGB = &bmi->bmiColors[0]; // Create a temporary surface for the destination bitmap - DestBitmap = BitmapToSurf(bitmap, dc->GDIDevice); + DestBitmap = BitmapToSurf(bitmap, DC->GDIDevice); DestSurf = (PSURFOBJ) AccessUserObject( (ULONG)DestBitmap ); DestGDI = (PSURFGDI) AccessInternalObject( (ULONG)DestBitmap ); @@ -159,19 +154,18 @@ NtGdiSetDIBits( SourceSurf = (PSURFOBJ)AccessUserObject((ULONG)SourceBitmap); // Destination palette obtained from the hDC - hDCPalette = PALETTE_LockPalette(dc->DevInfo->hpalDefault); + hDCPalette = PALETTE_LockPalette(DC->DevInfo->hpalDefault); if (NULL == hDCPalette) { EngDeleteSurface(SourceBitmap); EngDeleteSurface(DestBitmap); BITMAPOBJ_UnlockBitmap(hBitmap); - DC_UnlockDc(hDC); SetLastWin32Error(ERROR_INVALID_HANDLE); return 0; } DDB_Palette_Type = hDCPalette->Mode; - DDB_Palette = dc->DevInfo->hpalDefault; - PALETTE_UnlockPalette(dc->DevInfo->hpalDefault); + DDB_Palette = DC->DevInfo->hpalDefault; + PALETTE_UnlockPalette(DC->DevInfo->hpalDefault); // Source palette obtained from the BITMAPINFO DIB_Palette = BuildDIBPalette ( (PBITMAPINFO)bmi, (PINT)&DIB_Palette_Type ); @@ -180,7 +174,6 @@ NtGdiSetDIBits( EngDeleteSurface(SourceBitmap); EngDeleteSurface(DestBitmap); BITMAPOBJ_UnlockBitmap(hBitmap); - DC_UnlockDc(hDC); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); return 0; } @@ -193,7 +186,6 @@ NtGdiSetDIBits( EngDeleteSurface(SourceBitmap); EngDeleteSurface(DestBitmap); BITMAPOBJ_UnlockBitmap(hBitmap); - DC_UnlockDc(hDC); SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES); return 0; } @@ -226,11 +218,38 @@ NtGdiSetDIBits( // WinFree((LPSTR)lpRGB); BITMAPOBJ_UnlockBitmap(hBitmap); - DC_UnlockDc(hDC); 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 NtGdiSetDIBitsToDevice( HDC hDC, @@ -873,13 +892,13 @@ LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap, return ret; } -// 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) +static HBITMAP FASTCALL +IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header, + DWORD init, LPCVOID bits, const BITMAPINFO *data, + UINT coloruse) { HBITMAP handle; + BOOL fColor; DWORD width; int height; 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 // colors, which are black followed by white, nothing else. In all other cases, we create a color bitmap. - // Now create the bitmap - if (init == CBM_INIT) - { - handle = NtGdiCreateCompatibleBitmap(hdc, width, height); - if (!handle) - { - return 0; - } - NtGdiSetDIBits(hdc, handle, 0, height, bits, data, coloruse); - } + if (bpp != 1) fColor = TRUE; + else if ((coloruse != DIB_RGB_COLORS) || + (init != CBM_INIT) || !data) fColor = FALSE; 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; } +// 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, CONST BITMAPINFO *bmi, UINT Usage, @@ -1036,7 +1119,7 @@ DIB_CreateDIBSection( // Create Device Dependent Bitmap and add DIB pointer if (dib) { - res = NtGdiCreateDIBitmap(dc->hSelf, bi, 0, NULL, bmi, usage); + res = IntCreateDIBitmap(dc, bi, 0, NULL, bmi, usage); if (! res) { return NULL;