[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