gdi: Better support for 1bpp dib sections.

This commit is contained in:
Huw Davies 2006-03-02 12:13:28 +00:00 committed by Alexandre Julliard
parent d8bc6879be
commit b55746ab62
4 changed files with 281 additions and 18 deletions

View File

@ -342,6 +342,27 @@ static void test_dibsections(void)
SelectObject(hdcmem, oldbm); SelectObject(hdcmem, oldbm);
DeleteObject(hdib); 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; pbmi->bmiHeader.biBitCount = 4;
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
pbmi->bmiColors[i].rgbRed = i; pbmi->bmiColors[i].rgbRed = i;
@ -528,6 +549,200 @@ static void test_dibsections(void)
ReleaseDC(0, hdc); 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) START_TEST(bitmap)
{ {
HWND hWnd; HWND hWnd;
@ -541,4 +756,5 @@ START_TEST(bitmap)
test_createdibitmap(); test_createdibitmap();
test_dibsections(); test_dibsections();
test_mono_dibsection();
} }

View File

@ -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 * X11DRV_DIB_GenColorMap
* *
@ -291,9 +297,19 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
const RGBQUAD * rgb = (const RGBQUAD *)colorPtr; const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
if (depth == 1) /* Monochrome */ 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++) for (i = start; i < end; i++, rgb++)
colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen + colorMapping[i] = ((rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue > 255*3/2); rgb->rgbBlue > 255*3/2 && !invert) ||
(rgb->rgbRed + rgb->rgbGreen +
rgb->rgbBlue <= 255*3/2 && invert));
}
else else
for (i = start; i < end; i++, rgb++) for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbRed, 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; const RGBTRIPLE * rgb = (const RGBTRIPLE *)colorPtr;
if (depth == 1) /* Monochrome */ 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++) for (i = start; i < end; i++, rgb++)
colorMapping[i] = (rgb->rgbtRed + rgb->rgbtGreen + colorMapping[i] = ((rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue > 255*3/2); rgb->rgbtBlue > 255*3/2 && !invert) ||
(rgb->rgbtRed + rgb->rgbtGreen +
rgb->rgbtBlue <= 255*3/2 && invert));
}
else else
for (i = start; i < end; i++, rgb++) for (i = start; i < end; i++, rgb++)
colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed, colorMapping[i] = X11DRV_PALETTE_ToPhysical( physDev, RGB(rgb->rgbtRed,
@ -337,8 +363,8 @@ static int *X11DRV_DIB_GenColorMap( X11DRV_PDEVICE *physDev, int *colorMapping,
* Build the color map from the bitmap palette. Should not be called * Build the color map from the bitmap palette. Should not be called
* for a >8-bit deep bitmap. * 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 ) const BITMAPINFO *info, int *nColors )
{ {
unsigned int colors; unsigned int colors;
BOOL isInfo; BOOL isInfo;
@ -3852,7 +3878,7 @@ INT X11DRV_SetDIBitsToDevice( X11DRV_PDEVICE *physDev, INT xDest, INT yDest, DWO
case 4: case 4:
case 8: case 8:
descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap( descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
coloruse == DIB_PAL_COLORS ? physDev : NULL, coloruse, physDev, coloruse,
physDev->depth, info, &descr.nColorMap ); physDev->depth, info, &descr.nColorMap );
if (!descr.colorMap) return 0; if (!descr.colorMap) return 0;
descr.rMask = descr.gMask = descr.bMask = 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 4:
case 8: case 8:
descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap( descr.colorMap = (RGBQUAD *)X11DRV_DIB_BuildColorMap(
coloruse == DIB_PAL_COLORS ? descr.physDev : NULL, coloruse, descr.physDev, coloruse,
physBitmap->pixmap_depth, physBitmap->pixmap_depth,
info, &descr.nColorMap ); info, &descr.nColorMap );
if (!descr.colorMap) return 0; if (!descr.colorMap) return 0;
@ -4637,10 +4663,10 @@ HBITMAP X11DRV_CreateDIBSection( X11DRV_PDEVICE *physDev, HBITMAP hbitmap,
/* create color map */ /* create color map */
if (dib.dsBm.bmBitsPixel <= 8) 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, usage, dib.dsBm.bmBitsPixel, bmi,
&physBitmap->nColorMap ); &physBitmap->nColorMap );
physBitmap->colorTable = X11DRV_DIB_BuildColorTable( physDev, usage, dib.dsBm.bmBitsPixel, bmi );
} }
/* create pixmap and X image */ /* 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 * DIB colors and X11 colors and thus alter the visible state
* of the bitmap object. * 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 ); X11DRV_DIB_Lock( physBitmap, DIB_Status_AppMod, FALSE );
memcpy(physBitmap->colorTable + start, colors, (end - start) * sizeof(RGBQUAD)); memcpy(physBitmap->colorTable + start, colors, (end - start) * sizeof(RGBQUAD));
X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS, X11DRV_DIB_GenColorMap( physDev, physBitmap->colorMap, DIB_RGB_COLORS,

View File

@ -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 * X11DRV_PALETTE_ToPhysical
* *
@ -870,9 +876,16 @@ int X11DRV_PALETTE_ToPhysical( X11DRV_PDEVICE *physDev, COLORREF color )
case 0: /* RGB */ case 0: /* RGB */
if (physDev && (physDev->depth == 1) ) if (physDev && (physDev->depth == 1) )
{ {
int white = 1;
GDI_ReleaseObj( hPal ); 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) + 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 */ case 0: /* RGB */
if (physDev && (physDev->depth == 1) ) if (physDev && (physDev->depth == 1) )
{ {
int white = 1;
GDI_ReleaseObj( hPal ); GDI_ReleaseObj( hPal );
return (((color >> 16) & 0xff) + if (physDev->bitmap && physDev->bitmap->colorTable)
((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0; {
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) ? white : 1 - white;
} }
index = X11DRV_SysPaletteLookupPixel( color, FALSE); index = X11DRV_SysPaletteLookupPixel( color, FALSE);

View File

@ -421,9 +421,6 @@ typedef struct {
extern const dib_conversions dib_normal, dib_src_byteswap, dib_dst_byteswap; extern const dib_conversions dib_normal, dib_src_byteswap, dib_dst_byteswap;
extern INT X11DRV_DIB_MaskToShift(DWORD mask); 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_CoerceDIBSection(X11DRV_PDEVICE *physDev,INT,BOOL);
extern INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev,INT,BOOL); extern INT X11DRV_LockDIBSection(X11DRV_PDEVICE *physDev,INT,BOOL);
extern void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev,BOOL); extern void X11DRV_UnlockDIBSection(X11DRV_PDEVICE *physDev,BOOL);