[SPAM] gdi: Better support for 1bpp dib sections
Huw D M Davies
h.davies1 at physics.ox.ac.uk
Thu Mar 2 06:13:28 CST 2006
Huw Davies <huw at codeweavers.com>
gdi: Better support for 1bpp dib sections
--
Huw Davies
huw at codeweavers.com
diff --git a/dlls/gdi/tests/bitmap.c b/dlls/gdi/tests/bitmap.c
index 5eeda35..7f2a59c 100644
--- a/dlls/gdi/tests/bitmap.c
+++ b/dlls/gdi/tests/bitmap.c
@@ -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();
}
diff --git a/dlls/x11drv/dib.c b/dlls/x11drv/dib.c
index f9321e6..5904f0a 100644
--- a/dlls/x11drv/dib.c
+++ b/dlls/x11drv/dib.c
@@ -272,6 +272,12 @@ static int DIB_GetBitmapInfo( const BITM
}
+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( X11D
const RGBQUAD * rgb = (const RGBQUAD *)colorPtr;
if (depth == 1) /* Monochrome */
- for (i = start; i < end; i++, rgb++)
- colorMapping[i] = (rgb->rgbRed + rgb->rgbGreen +
- rgb->rgbBlue > 255*3/2);
+ {
+ 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 && !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( X11D
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,8 +363,8 @@ static int *X11DRV_DIB_GenColorMap( X11D
* 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,
- const BITMAPINFO *info, int *nColors )
+static int *X11DRV_DIB_BuildColorMap( X11DRV_PDEVICE *physDev, WORD coloruse, WORD depth,
+ const BITMAPINFO *info, int *nColors )
{
unsigned int colors;
BOOL isInfo;
@@ -3852,7 +3878,7 @@ INT X11DRV_SetDIBitsToDevice( X11DRV_PDE
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 *ph
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_
/* 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_PDE
* 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,
diff --git a/dlls/x11drv/palette.c b/dlls/x11drv/palette.c
index 56ae55d..0c6ad12 100644
--- a/dlls/x11drv/palette.c
+++ b/dlls/x11drv/palette.c
@@ -808,6 +808,12 @@ static int X11DRV_SysPaletteLookupPixel(
return best;
}
+
+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_PD
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_PD
case 0: /* RGB */
if (physDev && (physDev->depth == 1) )
{
- GDI_ReleaseObj( hPal );
- return (((color >> 16) & 0xff) +
- ((color >> 8) & 0xff) + (color & 0xff) > 255*3/2) ? 1 : 0;
+ 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) ? white : 1 - white;
}
index = X11DRV_SysPaletteLookupPixel( color, FALSE);
diff --git a/dlls/x11drv/x11drv.h b/dlls/x11drv/x11drv.h
index 0339fad..98c0e93 100644
--- a/dlls/x11drv/x11drv.h
+++ b/dlls/x11drv/x11drv.h
@@ -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);
Subject: [SPAM] gdi: Better support for 1bpp dib sections
More information about the wine-patches
mailing list