Authors: Michael Kaufmann <hallo@michael-kaufmann.ch>, Huw Davies <huw@codeweavers.com>
CreateDIBitmap should return bitmaps at the depth of the supplied dc. Add a test to exercise this behaviour.
This commit is contained in:
parent
37f2cc8274
commit
cdcdbe5495
@ -773,13 +773,15 @@ INT WINAPI GetDIBits(
|
|||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* CreateDIBitmap (GDI32.@)
|
* CreateDIBitmap (GDI32.@)
|
||||||
|
*
|
||||||
|
* Creates a DDB (device dependent bitmap) from a DIB.
|
||||||
|
* The DDB will have the same color depth as the reference DC.
|
||||||
*/
|
*/
|
||||||
HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
|
HBITMAP WINAPI CreateDIBitmap( 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;
|
||||||
@ -789,91 +791,26 @@ HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
|
|||||||
if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
|
if (DIB_GetBitmapInfo( header, &width, &height, &bpp, &compr ) == -1) return 0;
|
||||||
if (height < 0) height = -height;
|
if (height < 0) height = -height;
|
||||||
|
|
||||||
/* Check if we should create a monochrome or color bitmap. */
|
if (hdc == NULL)
|
||||||
/* We create a monochrome bitmap only if it has exactly 2 */
|
handle = CreateBitmap( width, height, 1, 1, NULL );
|
||||||
/* colors, which are black followed by white, nothing else. */
|
|
||||||
/* In all other cases, we create a color bitmap. */
|
|
||||||
|
|
||||||
if (bpp != 1) fColor = TRUE;
|
|
||||||
else if ((coloruse != DIB_RGB_COLORS) || !data) fColor = FALSE;
|
|
||||||
else
|
else
|
||||||
{
|
handle = CreateCompatibleBitmap( hdc, width, height );
|
||||||
if (data->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
/* Note : If the first color of the colormap is white
|
|
||||||
followed by black, we have to create a color bitmap.
|
|
||||||
If we don't the white will be displayed in black later on!*/
|
|
||||||
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 if (data->bmiHeader.biSize == sizeof(BITMAPV4HEADER))
|
|
||||||
{ /* FIXME: correct ? */
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
/* Note : If the first color of the colormap is white
|
|
||||||
followed by black, we have to create a color bitmap.
|
|
||||||
If we don't the white will be displayed in black later on!*/
|
|
||||||
else fColor = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ERR("(%ld): wrong/unknown size for data\n",
|
|
||||||
data->bmiHeader.biSize );
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Now create the bitmap */
|
|
||||||
|
|
||||||
if (!(dc = DC_GetDCPtr( hdc ))) return 0;
|
|
||||||
|
|
||||||
if (fColor)
|
|
||||||
handle = CreateBitmap( width, height, GetDeviceCaps( hdc, PLANES ),
|
|
||||||
GetDeviceCaps( hdc, BITSPIXEL ), NULL );
|
|
||||||
else handle = CreateBitmap( width, height, 1, 1, NULL );
|
|
||||||
|
|
||||||
if (handle)
|
if (handle)
|
||||||
{
|
{
|
||||||
if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
|
if (init == CBM_INIT) SetDIBits( hdc, handle, 0, height, bits, data, coloruse );
|
||||||
else if (!BITMAP_SetOwnerDC( handle, dc ))
|
|
||||||
|
else if (hdc && ((dc = DC_GetDCPtr( hdc )) != NULL) )
|
||||||
{
|
{
|
||||||
DeleteObject( handle );
|
if (!BITMAP_SetOwnerDC( handle, dc ))
|
||||||
handle = 0;
|
{
|
||||||
|
DeleteObject( handle );
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
GDI_ReleaseObj( hdc );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GDI_ReleaseObj( hdc );
|
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +196,55 @@ static const char *get_emr_name(DWORD type)
|
|||||||
return NULL;
|
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 BOOL is_dib_monochrome( const BITMAPINFO* info )
|
||||||
|
{
|
||||||
|
if (info->bmiHeader.biBitCount != 1) return FALSE;
|
||||||
|
|
||||||
|
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||||
|
{
|
||||||
|
RGBTRIPLE *rgb = ((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 */
|
||||||
|
{
|
||||||
|
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
|
* EMF_Create_HENHMETAFILE
|
||||||
*/
|
*/
|
||||||
@ -1619,11 +1668,30 @@ BOOL WINAPI PlayEnhMetaFileRecord(
|
|||||||
|
|
||||||
case EMR_CREATEMONOBRUSH:
|
case EMR_CREATEMONOBRUSH:
|
||||||
{
|
{
|
||||||
PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
|
PEMRCREATEMONOBRUSH pCreateMonoBrush = (PEMRCREATEMONOBRUSH)mr;
|
||||||
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
|
BITMAPINFO *pbi = (BITMAPINFO *)((BYTE *)mr + pCreateMonoBrush->offBmi);
|
||||||
HBITMAP hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
HBITMAP hBmp;
|
||||||
(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
|
|
||||||
|
/* Need to check if the bitmap is monochrome, and if the
|
||||||
|
two colors are really black and white */
|
||||||
|
if (is_dib_monochrome(pbi))
|
||||||
|
{
|
||||||
|
/* Top-down DIBs have a negative height */
|
||||||
|
LONG height = pbi->bmiHeader.biHeight;
|
||||||
|
if (height < 0) height = -height;
|
||||||
|
|
||||||
|
hBmp = CreateBitmap(pbi->bmiHeader.biWidth, height, 1, 1, NULL);
|
||||||
|
SetDIBits(hdc, hBmp, 0, pbi->bmiHeader.biHeight,
|
||||||
|
(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
||||||
|
(BYTE *)mr + pCreateMonoBrush->offBits, pbi, pCreateMonoBrush->iUsage);
|
||||||
|
}
|
||||||
|
|
||||||
(handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
|
(handletable->objectHandle)[pCreateMonoBrush->ihBrush] = CreatePatternBrush(hBmp);
|
||||||
|
|
||||||
/* CreatePatternBrush created a copy of the bitmap */
|
/* CreatePatternBrush created a copy of the bitmap */
|
||||||
DeleteObject(hBmp);
|
DeleteObject(hBmp);
|
||||||
break;
|
break;
|
||||||
@ -1652,7 +1720,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
|
|||||||
SelectObject(hdcSrc, hBrushOld);
|
SelectObject(hdcSrc, hBrushOld);
|
||||||
DeleteObject(hBrush);
|
DeleteObject(hBrush);
|
||||||
|
|
||||||
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
||||||
(BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
|
(BYTE *)mr + pBitBlt->offBitsSrc, pbi, pBitBlt->iUsageSrc);
|
||||||
hBmpOld = SelectObject(hdcSrc, hBmp);
|
hBmpOld = SelectObject(hdcSrc, hBmp);
|
||||||
|
|
||||||
@ -1694,7 +1762,7 @@ BOOL WINAPI PlayEnhMetaFileRecord(
|
|||||||
SelectObject(hdcSrc, hBrushOld);
|
SelectObject(hdcSrc, hBrushOld);
|
||||||
DeleteObject(hBrush);
|
DeleteObject(hBrush);
|
||||||
|
|
||||||
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
||||||
(BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
|
(BYTE *)mr + pStretchBlt->offBitsSrc, pbi, pStretchBlt->iUsageSrc);
|
||||||
hBmpOld = SelectObject(hdcSrc, hBmp);
|
hBmpOld = SelectObject(hdcSrc, hBmp);
|
||||||
|
|
||||||
@ -1728,11 +1796,13 @@ BOOL WINAPI PlayEnhMetaFileRecord(
|
|||||||
DeleteObject(hBrush);
|
DeleteObject(hBrush);
|
||||||
|
|
||||||
pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiMask);
|
pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiMask);
|
||||||
hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
|
||||||
(BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
|
1, 1, NULL);
|
||||||
|
SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
|
||||||
|
(BYTE *)mr + pMaskBlt->offBitsMask, pbi, pMaskBlt->iUsageMask);
|
||||||
|
|
||||||
pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiSrc);
|
pbi = (BITMAPINFO *)((BYTE *)mr + pMaskBlt->offBmiSrc);
|
||||||
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
||||||
(BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
|
(BYTE *)mr + pMaskBlt->offBitsSrc, pbi, pMaskBlt->iUsageSrc);
|
||||||
hBmpOld = SelectObject(hdcSrc, hBmp);
|
hBmpOld = SelectObject(hdcSrc, hBmp);
|
||||||
MaskBlt(hdc,
|
MaskBlt(hdc,
|
||||||
@ -1778,11 +1848,13 @@ BOOL WINAPI PlayEnhMetaFileRecord(
|
|||||||
DeleteObject(hBrush);
|
DeleteObject(hBrush);
|
||||||
|
|
||||||
pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiMask);
|
pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiMask);
|
||||||
hBmpMask = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmpMask = CreateBitmap(pbi->bmiHeader.biWidth, pbi->bmiHeader.biHeight,
|
||||||
(BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
|
1, 1, NULL);
|
||||||
|
SetDIBits(hdc, hBmpMask, 0, pbi->bmiHeader.biHeight,
|
||||||
|
(BYTE *)mr + pPlgBlt->offBitsMask, pbi, pPlgBlt->iUsageMask);
|
||||||
|
|
||||||
pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiSrc);
|
pbi = (BITMAPINFO *)((BYTE *)mr + pPlgBlt->offBmiSrc);
|
||||||
hBmp = CreateDIBitmap(0, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
hBmp = CreateDIBitmap(hdc, (BITMAPINFOHEADER *)pbi, CBM_INIT,
|
||||||
(BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
|
(BYTE *)mr + pPlgBlt->offBitsSrc, pbi, pPlgBlt->iUsageSrc);
|
||||||
hBmpOld = SelectObject(hdcSrc, hBmp);
|
hBmpOld = SelectObject(hdcSrc, hBmp);
|
||||||
PlgBlt(hdc,
|
PlgBlt(hdc,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
Makefile
|
Makefile
|
||||||
|
bitmap.ok
|
||||||
gdiobj.ok
|
gdiobj.ok
|
||||||
generated.ok
|
generated.ok
|
||||||
metafile.ok
|
metafile.ok
|
||||||
|
@ -6,6 +6,7 @@ TESTDLL = gdi32.dll
|
|||||||
IMPORTS = user32 gdi32
|
IMPORTS = user32 gdi32
|
||||||
|
|
||||||
CTESTS = \
|
CTESTS = \
|
||||||
|
bitmap.c \
|
||||||
gdiobj.c \
|
gdiobj.c \
|
||||||
generated.c \
|
generated.c \
|
||||||
metafile.c
|
metafile.c
|
||||||
|
161
dlls/gdi/tests/bitmap.c
Normal file
161
dlls/gdi/tests/bitmap.c
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Unit test suite for bitmaps
|
||||||
|
*
|
||||||
|
* Copyright 2004 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "windef.h"
|
||||||
|
#include "winbase.h"
|
||||||
|
#include "wingdi.h"
|
||||||
|
#include "winuser.h"
|
||||||
|
|
||||||
|
#include "wine/test.h"
|
||||||
|
|
||||||
|
|
||||||
|
static void test_createdibitmap(void)
|
||||||
|
{
|
||||||
|
HDC hdc, hdcmem;
|
||||||
|
BITMAPINFOHEADER bmih;
|
||||||
|
BITMAP bm;
|
||||||
|
HBITMAP hbm, hbm_colour, hbm_old;
|
||||||
|
INT screen_depth;
|
||||||
|
|
||||||
|
hdc = GetDC(0);
|
||||||
|
screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
|
||||||
|
memset(&bmih, 0, sizeof(bmih));
|
||||||
|
bmih.biSize = sizeof(bmih);
|
||||||
|
bmih.biWidth = 10;
|
||||||
|
bmih.biHeight = 10;
|
||||||
|
bmih.biPlanes = 1;
|
||||||
|
bmih.biBitCount = 32;
|
||||||
|
bmih.biCompression = BI_RGB;
|
||||||
|
|
||||||
|
/* First create an un-initialised bitmap. The depth of the bitmap
|
||||||
|
should match that of the hdc and not that supplied in bmih.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* First try 32 bits */
|
||||||
|
hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 16 */
|
||||||
|
bmih.biBitCount = 16;
|
||||||
|
hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 1 */
|
||||||
|
bmih.biBitCount = 1;
|
||||||
|
hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Now with a monochrome dc we expect a monochrome bitmap */
|
||||||
|
hdcmem = CreateCompatibleDC(hdc);
|
||||||
|
|
||||||
|
/* First try 32 bits */
|
||||||
|
bmih.biBitCount = 32;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 16 */
|
||||||
|
bmih.biBitCount = 16;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 1 */
|
||||||
|
bmih.biBitCount = 1;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Now select a polychrome bitmap into the dc and we expect
|
||||||
|
screen_depth bitmaps again */
|
||||||
|
hbm_colour = CreateCompatibleBitmap(hdc, 1, 1);
|
||||||
|
hbm_old = SelectObject(hdcmem, hbm_colour);
|
||||||
|
|
||||||
|
/* First try 32 bits */
|
||||||
|
bmih.biBitCount = 32;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 16 */
|
||||||
|
bmih.biBitCount = 16;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
/* Then 1 */
|
||||||
|
bmih.biBitCount = 1;
|
||||||
|
hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == screen_depth, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, screen_depth);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
SelectObject(hdcmem, hbm_old);
|
||||||
|
DeleteObject(hbm_colour);
|
||||||
|
DeleteDC(hdcmem);
|
||||||
|
|
||||||
|
/* If hdc == 0 then we get a 1 bpp bitmap */
|
||||||
|
bmih.biBitCount = 32;
|
||||||
|
hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0);
|
||||||
|
ok(hbm != NULL, "CreateDIBitmap failed\n");
|
||||||
|
ok(GetObject(hbm, sizeof(bm), &bm), "GetObject failed\n");
|
||||||
|
|
||||||
|
ok(bm.bmBitsPixel == 1, "CreateDIBitmap created bitmap of incorrect depth %d != %d\n", bm.bmBitsPixel, 1);
|
||||||
|
DeleteObject(hbm);
|
||||||
|
|
||||||
|
ReleaseDC(0, hdc);
|
||||||
|
}
|
||||||
|
|
||||||
|
START_TEST(bitmap)
|
||||||
|
{
|
||||||
|
test_createdibitmap();
|
||||||
|
}
|
@ -224,6 +224,56 @@ static int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* 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 BOOL is_dib_monochrome( const BITMAPINFO* info )
|
||||||
|
{
|
||||||
|
if (info->bmiHeader.biBitCount != 1) return FALSE;
|
||||||
|
|
||||||
|
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
|
||||||
|
{
|
||||||
|
RGBTRIPLE *rgb = ((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 */
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* CURSORICON_FindSharedIcon
|
* CURSORICON_FindSharedIcon
|
||||||
*/
|
*/
|
||||||
@ -657,8 +707,17 @@ static HICON CURSORICON_CreateFromResource( HMODULE16 hModule, HGLOBAL16 hObj, L
|
|||||||
}
|
}
|
||||||
if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
|
if (!res) { DeleteObject(hXorBits); hXorBits = 0; }
|
||||||
}
|
}
|
||||||
} else hXorBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
|
} else {
|
||||||
CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS );
|
if (is_dib_monochrome(bmi)) {
|
||||||
|
hXorBits = CreateBitmap(width, height, 1, 1, NULL);
|
||||||
|
SetDIBits(screen_dc, hXorBits, 0, height,
|
||||||
|
(char*)bmi + size, pInfo, DIB_RGB_COLORS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hXorBits = CreateDIBitmap(screen_dc, &pInfo->bmiHeader,
|
||||||
|
CBM_INIT, (char*)bmi + size, pInfo, DIB_RGB_COLORS);
|
||||||
|
}
|
||||||
|
|
||||||
if( hXorBits )
|
if( hXorBits )
|
||||||
{
|
{
|
||||||
char* xbits = (char *)bmi + size +
|
char* xbits = (char *)bmi + size +
|
||||||
@ -700,9 +759,13 @@ static HICON CURSORICON_CreateFromResource( HMODULE16 hModule, HGLOBAL16 hObj, L
|
|||||||
}
|
}
|
||||||
if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
|
if (!res) { DeleteObject(hAndBits); hAndBits = 0; }
|
||||||
}
|
}
|
||||||
} else hAndBits = CreateDIBitmap( screen_dc, &pInfo->bmiHeader,
|
} else {
|
||||||
CBM_INIT, xbits, pInfo, DIB_RGB_COLORS );
|
hAndBits = CreateBitmap(width, height, 1, 1, NULL);
|
||||||
|
|
||||||
|
if (hAndBits) SetDIBits(screen_dc, hAndBits, 0, height,
|
||||||
|
xbits, pInfo, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
}
|
||||||
if( !hAndBits ) DeleteObject( hXorBits );
|
if( !hAndBits ) DeleteObject( hXorBits );
|
||||||
}
|
}
|
||||||
HeapFree( GetProcessHeap(), 0, pInfo );
|
HeapFree( GetProcessHeap(), 0, pInfo );
|
||||||
@ -1170,7 +1233,7 @@ HICON WINAPI CreateIcon(
|
|||||||
iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
|
iinfo.hbmColor = CreateDIBitmap( hdc, &bmi.bmiHeader,
|
||||||
CBM_INIT, lpXORbits,
|
CBM_INIT, lpXORbits,
|
||||||
&bmi, DIB_RGB_COLORS );
|
&bmi, DIB_RGB_COLORS );
|
||||||
|
|
||||||
hIcon=CreateIconIndirect(&iinfo);
|
hIcon=CreateIconIndirect(&iinfo);
|
||||||
DeleteObject(iinfo.hbmMask);
|
DeleteObject(iinfo.hbmMask);
|
||||||
DeleteObject(iinfo.hbmColor);
|
DeleteObject(iinfo.hbmColor);
|
||||||
@ -1957,7 +2020,7 @@ static void DIB_FixColorsToLoadflags(BITMAPINFO * bmi, UINT loadflags, BYTE pix)
|
|||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
* BITMAP_Load
|
* BITMAP_Load
|
||||||
*/
|
*/
|
||||||
static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
|
static HBITMAP BITMAP_Load( HINSTANCE instance, LPCWSTR name, UINT loadflags )
|
||||||
{
|
{
|
||||||
HBITMAP hbitmap = 0;
|
HBITMAP hbitmap = 0;
|
||||||
HRSRC hRsrc;
|
HRSRC hRsrc;
|
||||||
@ -1975,6 +2038,7 @@ static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
|
|||||||
if (HIWORD(name)) return 0;
|
if (HIWORD(name)) return 0;
|
||||||
instance = user32_module;
|
instance = user32_module;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(hRsrc = FindResourceW( instance, name, (LPWSTR)RT_BITMAP ))) return 0;
|
if (!(hRsrc = FindResourceW( instance, name, (LPWSTR)RT_BITMAP ))) return 0;
|
||||||
if (!(handle = LoadResource( instance, hRsrc ))) return 0;
|
if (!(handle = LoadResource( instance, hRsrc ))) return 0;
|
||||||
|
|
||||||
@ -1985,8 +2049,10 @@ static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
|
|||||||
if (!(ptr = map_fileW( name ))) return 0;
|
if (!(ptr = map_fileW( name ))) return 0;
|
||||||
info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
|
info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
|
||||||
}
|
}
|
||||||
|
|
||||||
size = bitmap_info_size(info, DIB_RGB_COLORS);
|
size = bitmap_info_size(info, DIB_RGB_COLORS);
|
||||||
if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
|
if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
|
||||||
|
|
||||||
if (fix_info) {
|
if (fix_info) {
|
||||||
BYTE pix;
|
BYTE pix;
|
||||||
|
|
||||||
@ -1994,9 +2060,11 @@ static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
|
|||||||
pix = *((LPBYTE)info + size);
|
pix = *((LPBYTE)info + size);
|
||||||
DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
|
DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
|
||||||
if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
|
if (!screen_dc) screen_dc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
|
||||||
|
|
||||||
if (screen_dc)
|
if (screen_dc)
|
||||||
{
|
{
|
||||||
char *bits = (char *)info + size;
|
char *bits = (char *)info + size;
|
||||||
|
|
||||||
if (loadflags & LR_CREATEDIBSECTION) {
|
if (loadflags & LR_CREATEDIBSECTION) {
|
||||||
DIBSECTION dib;
|
DIBSECTION dib;
|
||||||
hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
|
hbitmap = CreateDIBSection(screen_dc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
|
||||||
@ -2005,14 +2073,28 @@ static HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
|
|||||||
DIB_RGB_COLORS);
|
DIB_RGB_COLORS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
hbitmap = CreateDIBitmap( screen_dc, &fix_info->bmiHeader, CBM_INIT,
|
/* If it's possible, create a monochrome bitmap */
|
||||||
bits, fix_info, DIB_RGB_COLORS );
|
|
||||||
|
LONG height = fix_info->bmiHeader.biHeight;
|
||||||
|
if (height < 0) height = -height;
|
||||||
|
|
||||||
|
if (is_dib_monochrome(fix_info))
|
||||||
|
hbitmap = CreateBitmap(fix_info->bmiHeader.biWidth, height, 1, 1, NULL);
|
||||||
|
else
|
||||||
|
hbitmap = CreateBitmap(fix_info->bmiHeader.biWidth, height,
|
||||||
|
GetDeviceCaps(screen_dc, PLANES),
|
||||||
|
GetDeviceCaps(screen_dc, BITSPIXEL), NULL);
|
||||||
|
|
||||||
|
SetDIBits(screen_dc, hbitmap, 0, height, bits, info, DIB_RGB_COLORS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GlobalUnlock(hFix);
|
GlobalUnlock(hFix);
|
||||||
GlobalFree(hFix);
|
GlobalFree(hFix);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
|
if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
|
||||||
|
|
||||||
return hbitmap;
|
return hbitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user