Commit b55746ab authored by Huw Davies's avatar Huw Davies Committed by Alexandre Julliard

gdi: Better support for 1bpp dib sections.

parent d8bc6879
......@@ -342,6 +342,27 @@ static void test_dibsections(void)
SelectObject(hdcmem, oldbm);
DeleteObject(hdib);
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0xff;
pbmi->bmiColors[0].rgbBlue = 0xff;
pbmi->bmiColors[1].rgbRed = 0;
pbmi->bmiColors[1].rgbGreen = 0;
pbmi->bmiColors[1].rgbBlue = 0;
hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
ok(hdib != NULL, "CreateDIBSection failed\n");
oldbm = SelectObject(hdcmem, hdib);
ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
"GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
SelectObject(hdcmem, oldbm);
DeleteObject(hdib);
pbmi->bmiHeader.biBitCount = 4;
for (i = 0; i < 16; i++) {
pbmi->bmiColors[i].rgbRed = i;
......@@ -528,6 +549,200 @@ static void test_dibsections(void)
ReleaseDC(0, hdc);
}
void test_mono_dibsection(void)
{
HDC hdc, memdc;
HBITMAP old_bm, mono_ds;
char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
BYTE bits[10 * 4];
BYTE *ds_bits;
int num;
hdc = GetDC(0);
memdc = CreateCompatibleDC(hdc);
memset(pbmi, 0, sizeof(bmibuf));
pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
pbmi->bmiHeader.biHeight = 10;
pbmi->bmiHeader.biWidth = 10;
pbmi->bmiHeader.biBitCount = 1;
pbmi->bmiHeader.biPlanes = 1;
pbmi->bmiHeader.biCompression = BI_RGB;
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0xff;
pbmi->bmiColors[0].rgbBlue = 0xff;
pbmi->bmiColors[1].rgbRed = 0x0;
pbmi->bmiColors[1].rgbGreen = 0x0;
pbmi->bmiColors[1].rgbBlue = 0x0;
/*
* First dib section is 'inverted' ie color[0] is white, color[1] is black
*/
mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
old_bm = SelectObject(memdc, mono_ds);
/* black border, white interior */
Rectangle(memdc, 0, 0, 10, 10);
ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
/* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
memset(bits, 0, sizeof(bits));
bits[0] = 0xaa;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
/* SetDIBitsToDevice with a normal bmi -> inverted dib section */
pbmi->bmiColors[0].rgbRed = 0x0;
pbmi->bmiColors[0].rgbGreen = 0x0;
pbmi->bmiColors[0].rgbBlue = 0x0;
pbmi->bmiColors[1].rgbRed = 0xff;
pbmi->bmiColors[1].rgbGreen = 0xff;
pbmi->bmiColors[1].rgbBlue = 0xff;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
SelectObject(memdc, old_bm);
DeleteObject(mono_ds);
/*
* Next dib section is 'normal' ie color[0] is black, color[1] is white
*/
pbmi->bmiColors[0].rgbRed = 0x0;
pbmi->bmiColors[0].rgbGreen = 0x0;
pbmi->bmiColors[0].rgbBlue = 0x0;
pbmi->bmiColors[1].rgbRed = 0xff;
pbmi->bmiColors[1].rgbGreen = 0xff;
pbmi->bmiColors[1].rgbBlue = 0xff;
mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
old_bm = SelectObject(memdc, mono_ds);
/* black border, white interior */
Rectangle(memdc, 0, 0, 10, 10);
ok(ds_bits[0] == 0x00, "out_bits %02x\n", ds_bits[0]);
ok(ds_bits[4] == 0x7f, "out_bits %02x\n", ds_bits[4]);
/* SetDIBitsToDevice with a normal bmi -> normal dib section */
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
/* SetDIBitsToDevice with a inverted bmi -> normal dib section */
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0xff;
pbmi->bmiColors[0].rgbBlue = 0xff;
pbmi->bmiColors[1].rgbRed = 0x0;
pbmi->bmiColors[1].rgbGreen = 0x0;
pbmi->bmiColors[1].rgbBlue = 0x0;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
/*
* Take that 'normal' dibsection and change its colour table to an 'inverted' one
*/
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0xff;
pbmi->bmiColors[0].rgbBlue = 0xff;
pbmi->bmiColors[1].rgbRed = 0x0;
pbmi->bmiColors[1].rgbGreen = 0x0;
pbmi->bmiColors[1].rgbBlue = 0x0;
num = SetDIBColorTable(memdc, 0, 2, pbmi->bmiColors);
ok(num == 2, "num = %d\n", num);
/* black border, white interior */
Rectangle(memdc, 0, 0, 10, 10);
todo_wine {
ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
}
/* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
memset(bits, 0, sizeof(bits));
bits[0] = 0xaa;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
/* SetDIBitsToDevice with a normal bmi -> inverted dib section */
pbmi->bmiColors[0].rgbRed = 0x0;
pbmi->bmiColors[0].rgbGreen = 0x0;
pbmi->bmiColors[0].rgbBlue = 0x0;
pbmi->bmiColors[1].rgbRed = 0xff;
pbmi->bmiColors[1].rgbGreen = 0xff;
pbmi->bmiColors[1].rgbBlue = 0xff;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
SelectObject(memdc, old_bm);
DeleteObject(mono_ds);
/*
* Now a dib section with a strange colour map just for fun. This behaves just like an inverted one.
*/
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0x0;
pbmi->bmiColors[0].rgbBlue = 0x0;
pbmi->bmiColors[1].rgbRed = 0xfe;
pbmi->bmiColors[1].rgbGreen = 0x0;
pbmi->bmiColors[1].rgbBlue = 0x0;
mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
old_bm = SelectObject(memdc, mono_ds);
/* black border, white interior */
Rectangle(memdc, 0, 0, 10, 10);
ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
/* SetDIBitsToDevice with a normal bmi -> inverted dib section */
pbmi->bmiColors[0].rgbRed = 0x0;
pbmi->bmiColors[0].rgbGreen = 0x0;
pbmi->bmiColors[0].rgbBlue = 0x0;
pbmi->bmiColors[1].rgbRed = 0xff;
pbmi->bmiColors[1].rgbGreen = 0xff;
pbmi->bmiColors[1].rgbBlue = 0xff;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
/* SetDIBitsToDevice with a inverted bmi -> inverted dib section */
pbmi->bmiColors[0].rgbRed = 0xff;
pbmi->bmiColors[0].rgbGreen = 0xff;
pbmi->bmiColors[0].rgbBlue = 0xff;
pbmi->bmiColors[1].rgbRed = 0x0;
pbmi->bmiColors[1].rgbGreen = 0x0;
pbmi->bmiColors[1].rgbBlue = 0x0;
SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
SelectObject(memdc, old_bm);
DeleteObject(mono_ds);
DeleteDC(memdc);
ReleaseDC(0, hdc);
}
START_TEST(bitmap)
{
HWND hWnd;
......@@ -541,4 +756,5 @@ START_TEST(bitmap)
test_createdibitmap();
test_dibsections();
test_mono_dibsection();
}
......@@ -272,6 +272,12 @@ static int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
}
static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
{
return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) >
(c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
}
/***********************************************************************
* X11DRV_DIB_GenColorMap
*
......@@ -291,9 +297,19 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
if (depth == 1) /* Monochrome */
{
BOOL invert = FALSE;
if(physDev && physDev->bitmap && physDev->bitmap->colorTable)
{
if(!colour_is_brighter(physDev->bitmap->colorTable[1], physDev->bitmap->colorTable[0]))
invert = TRUE;
}
for (i = start; i < end; i++, rgb++)
colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue > 255*3/2);
colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue > 255*3/2 && !invert) ||
(rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue <= 255*3/2 && invert));
}
else
for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed,
......@@ -305,9 +321,19 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
const RGBTRIPLE * rgb = (const RGBTRIPLE *)colorPtr;
if (depth == 1) /* Monochrome */
{
BOOL invert = FALSE;
if(physDev && physDev->bitmap && physDev->bitmap->colorTable)
{
if(!colour_is_brighter(physDev->bitmap->colorTable[1], physDev->bitmap->colorTable[0]))
invert = TRUE;
}
for (i = start; i < end; i++, rgb++)
colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue > 255*3/2);
colorMapping[i] = ((rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue > 255*3/2 && !invert) ||
(rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue <= 255*3/2 && invert));
}
else
for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
......@@ -337,7 +363,7 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
* Build the color map from the bitmap palette. Should not be called
* for a >8-bit deep bitmap.
*/
int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
const BITMAPINFO *info, int *nColors )
{
unsigned int colors;
......@@ -3852,7 +3878,7 @@ INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWO
case 4:
case 8:
descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse,
physDev, coloruse,
physDev->depth, info, &descr.nColorMap );
if (!descr.colorMap) return 0;
descr.rMask = descr.gMask = descr.bMask = 0;
......@@ -3938,7 +3964,7 @@ INT X11DRV_SetDIBits( X11DRV_PDEVICE *physDev, HBITMAP hbitmap, UINT startscan,
case 4:
case 8:
descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse,
descr.physDev, coloruse,
physBitmap->pixmap_depth,
info, &descr.nColorMap );
if (!descr.colorMap) return 0;
......@@ -4637,10 +4663,10 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
/* create color map */
if (dib.dsBm.bmBitsPixel <= 8)
{
physBitmap->colorMap = X11DRV_DIB_BuildColorMap( usage == DIB_PAL_COLORS ? physDev : NULL,
physBitmap->colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, dib.dsBm.bmBitsPixel, bmi );
physBitmap->colorMap = X11DRV_DIB_BuildColorMap( physDev,
usage, dib.dsBm.bmBitsPixel, bmi,
&physBitmap->nColorMap );
physBitmap->colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, dib.dsBm.bmBitsPixel, bmi );
}
/* create pixmap and X image */
......@@ -4740,6 +4766,10 @@ UINT X11DRV_SetDIBColorTable( X11DRV_PDEVICE *physDev, UINT start, UINT count, c
* DIB colors and X11 colors and thus alter the visible state
* of the bitmap object.
*/
/*
* FIXME we need to recalculate the pen, brush, text and bkgnd pixels here,
* at least for a 1 bpp dibsection
*/
X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod, FALSE );
memcpy(physBitmap->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,
......
......@@ -809,6 +809,12 @@ static int X11DRV_SysPaletteLookupPixel( COLORREF col, BOOL skipReserved )
}
static inline BOOL colour_is_brighter(RGBQUAD c1, RGBQUAD c2)
{
return (c1.rgbRed * c1.rgbRed + c1.rgbGreen * c1.rgbGreen + c1.rgbBlue * c1.rgbBlue) >
(c2.rgbRed * c2.rgbRed + c2.rgbGreen * c2.rgbGreen + c2.rgbBlue * c2.rgbBlue);
}
/***********************************************************************
* X11DRV_PALETTE_ToPhysical
*
......@@ -870,9 +876,16 @@ int X11DRV_PALETTE_ToPhysical( X11DRV_PDEVICE *physDev, COLORREF color )
case 0: /* RGB */
if (physDev && (physDev->depth == 1) )
{
int white = 1;
GDI_ReleaseObj( hPal );
if (physDev->bitmap && physDev->bitmap->colorTable)
{
if(!colour_is_brighter(physDev->bitmap->colorTable[1], physDev->bitmap->colorTable[0]))
white = 0;
}
return (((color >> 16) & 0xff) +
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? white : 1 - white;
}
}
......@@ -923,9 +936,16 @@ int X11DRV_PALETTE_ToPhysical( X11DRV_PDEVICE *physDev, COLORREF color )
case 0: /* RGB */
if (physDev && (physDev->depth == 1) )
{
int white = 1;
GDI_ReleaseObj( hPal );
if (physDev->bitmap && physDev->bitmap->colorTable)
{
if(!colour_is_brighter(physDev->bitmap->colorTable[1], physDev->bitmap->colorTable[0]))
white = 0;
}
return (((color >> 16) & 0xff) +
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? white : 1 - white;
}
index = X11DRV_SysPaletteLookupPixel( color, FALSE);
......
......@@ -421,9 +421,6 @@ typedef struct {
extern const dib_conversions dib_normal, dib_src_byteswap, dib_dst_byteswap;
extern INT X11DRV_DIB_MaskToShift(DWORD mask);
extern int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse,
WORD depth, const BITMAPINFO *info,
int *nColors );
extern INT X11DRV_CoerceDIBSection(X11DRV_PDEVICE *physDev,INT,BOOL);
extern INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev,INT,BOOL);
extern void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev,BOOL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment