DIB Engine: fixes against wine tests

From: Massimo Del Fedele <max@veneto.com>


---

 dlls/winedib.drv/bitblt.c             |   68 +++---
 dlls/winedib.drv/convert.c            |   16 +
 dlls/winedib.drv/dc.c                 |   32 +--
 dlls/winedib.drv/dib.c                |  405 ++++++++++++++++++++++++++++++++-
 dlls/winedib.drv/dibdrv.h             |   27 ++
 dlls/winedib.drv/dibdrvbitmap.c       |  124 ++++++++++
 dlls/winedib.drv/graphics.c           |   10 +
 dlls/winedib.drv/palette.c            |   63 +++++
 dlls/winedib.drv/pen_brush.c          |   95 ++++++--
 dlls/winedib.drv/primitives_bitblt.c  |   18 +
 dlls/winedib.drv/primitives_color.c   |   71 ++++--
 dlls/winedib.drv/primitives_convert.c |   66 ++++-
 dlls/winedib.drv/primitives_pixel.c   |   44 ++--
 13 files changed, 883 insertions(+), 156 deletions(-)


diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index db66142..97feefd 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -82,7 +82,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
     ys1 = ps->y;
     xs2 = xs1 + w;
     ys2 = ys1 + h;
-        
+
     /* if source clip area is not null, do first clipping on it */
     if(srcClip)
     {
@@ -91,7 +91,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
         ysc1 = srcClip->top;
         xsc2 = srcClip->right;
         ysc2 = srcClip->bottom;
-        
+
         /* order clip area rectangle points */
         if(xsc1 > xsc2) intSwap(&xsc1, &xsc2);
         if(ysc1 > ysc2) intSwap(&ysc1, &ysc2);
@@ -103,13 +103,12 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
         /* clip on source clipping end point */
         if(xs2 > xsc2) { dx = xs2 - xsc2; w -= dx; xd2 -= dx; xs2 = xsc2; }
         if(ys2 > ysc2) { dy = ys2 - ysc2; h -= dy; yd2 -= dy; ys2 = ysc2; }
-        
+
         /* if already zero area, return false */
         if(w <= 0 || h <= 0)
             return FALSE;
     }
     /* now do clipping on destination area */
-
     if(dstClip)
     {    
         /* extract destination clipping area */
@@ -117,7 +116,7 @@ static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*
         ydc1 = dstClip->top;
         xdc2 = dstClip->right;
         ydc2 = dstClip->bottom;
-        
+
         /* order clip area rectangle points */
         if(xdc1 > xdc2) intSwap(&xdc1, &xdc2);
         if(ydc1 > ydc2) intSwap(&ydc1, &ydc2);
@@ -267,6 +266,13 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     _DIBDRV_Sizes_ws2ds(physDevDst, &widthDst, &heightDst);
     _DIBDRV_Position_ws2ds(physDevSrc, &xSrc, &ySrc);
     _DIBDRV_Sizes_ws2ds(physDevSrc, &widthSrc, &heightSrc);
+    
+    /* from tests, it seems that negative coords on phys space are not allowed */
+    if(xDst < 0 || yDst < 0 || xSrc < 0 || ySrc < 0)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
 
     /* first clip on physical DC sizes */
     setPoint(&pd, xDst, yDst);
@@ -282,7 +288,7 @@ BOOL _DIBDRV_InternalAlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     else
         res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
     if(!res)
-        return FALSE;
+        return TRUE;
     xDst = pd.x; yDst = pd.y;
     xSrc = ps.x; ySrc = ps.y;
     widthDst = szDst.cx; heightDst = szDst.cy;
@@ -317,9 +323,7 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
     BOOL res;
     
     POINT pd = {xDst, yDst};
-    POINT ps = {xSrc, ySrc};
     SIZE szDst = {widthDst, heightDst};
-    SIZE szSrc = {widthSrc, heightSrc};
 
     MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
           physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
@@ -327,10 +331,12 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
           physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
           xSrc, ySrc, widthSrc, heightSrc));
 
-    /* if sizes are null or negative, returns false */
-    if(widthSrc <= 0 || heightSrc <= 0 || widthDst <= 0 || heightDst <= 0)
+    /* if sizes are null or negative, or source positions are negatives, returns false */
+    if(widthSrc <= 0 || heightSrc <= 0 ||
+       widthDst <= 0 || heightDst <= 0)
     {
         res = FALSE;
+        SetLastError(ERROR_INVALID_PARAMETER);
         goto fin;
     }
           
@@ -360,18 +366,25 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
         /* DDB selected on dest DC -- must double-convert */
         HBITMAP tmpDIB, stock;
         HDC tmpDC;
-        RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
         MAYBE(TRACE("Blending DIB->DDB\n"));
         
-        /* clip blit area */
-        res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
-        if(!res)
+        /* we should anyways convert dest to physical coordinates here before processing
+           in order to check its consistency -- source coords will be converted/clipped later
+           As we do a conversion to a temporary DIB for destination, we don't care about it */
+        _DIBDRV_Position_ws2ds(physDevDst, &pd.x, &pd.y);
+        _DIBDRV_Sizes_ws2ds(physDevDst, &szDst.cx, &szDst.cy);
+        
+        /* test shows that negatives origins are not allowed */
+        if(pd.x < 0 || pd.y < 0)
+        {
+            SetLastError(ERROR_INVALID_PARAMETER);
+            res = FALSE;
             goto fin;
-        xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy; 
-        xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+        }
 
         /* converts dest DDB onto a temporary DIB -- just the needed part */
-        tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, xDst, yDst, widthDst, heightDst);
+        /* WARNING -- that one could fail if rectangle on dest id out of range */
+        tmpDIB = _DIBDRV_ConvertDevDDBtoDIB(physDevDst->hdc, physDevSrc->hdc, pd.x, pd.y, szDst.cx, szDst.cy);
         if(!tmpDIB)
         {
             ERR("Couldn't convert dest DDB to DIB\n");
@@ -399,7 +412,7 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
         }
         
         /* blends source DIB onto temp DIB and re-blits onto dest DC */
-        res = GdiAlphaBlend(tmpDC, 0, 0, widthDst, heightDst, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
+        res = GdiAlphaBlend(tmpDC, 0, 0, szDst.cx, szDst.cy, physDevSrc->hdc, xSrc, ySrc, widthSrc, heightSrc, blendfn);
         if(!res)
             MAYBE(TRACE("AlphaBlend failed\n"));
         else
@@ -438,6 +451,7 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     setPoint(&ps, xSrc, ySrc);
     setSize(&sz, width, height);
     setRect(&dstClip, 0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height);
+
     if(physDevSrc)
     {
         setRect(&srcClip, 0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height);
@@ -446,13 +460,13 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
     else
         res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
     if(!res)
-        return FALSE;
+        return TRUE;
     xDst = pd.x; yDst = pd.y;
     xSrc = ps.x; ySrc = ps.y;
     width = sz.cx; height = sz.cy;
     
     /* then, do blitting for each dest clip area (no clipping on source) */
-    res = FALSE;
+    res = TRUE;
     for(iRec = 0; iRec < physDevDst->regionRectCount; iRec++)
     {
         RECT *r = physDevDst->regionRects + iRec;
@@ -462,8 +476,8 @@ BOOL _DIBDRV_InternalBitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         setSize(&sz, width, height);
         if(!BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip))
             continue;
-        if(physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
-            res = TRUE;
+        if(!physDevDst->physBitmap.funcs->BitBlt(physDevDst, pd.x, pd.y, sz.cx, sz.cy, physDevSrc, ps.x, ps.y, rop))
+            res = FALSE;
     }
     return res;
 }
@@ -503,8 +517,8 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
             /* source is a DDB, must convert it to DIB */
 
             /* don't clip on source */            
-            res = BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
-            if(!res)
+            res = !BitBlt_ClipAreas(&ps, &pd, &sz, 0, &dstClip);
+            if(res)
                 goto noBlt2;
             xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
 
@@ -596,11 +610,11 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
             if(physDevSrc)
             {
                 RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
-                res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0);
+                res = !BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0);
             }
             else
-                res = TRUE;
-            if(!res)
+                res = FALSE;
+            if(res)
                 goto noBlt3;
             xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
 
diff --git a/dlls/winedib.drv/convert.c b/dlls/winedib.drv/convert.c
index dc18e14..2f20ac1 100644
--- a/dlls/winedib.drv/convert.c
+++ b/dlls/winedib.drv/convert.c
@@ -51,7 +51,7 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca
     HDC tmpHdc;
     HBITMAP tmpBmp;
     int res;
-    
+
     /* gets DIBSECTION data from source DIB */
     if(GetObjectW(srcBmp, sizeof(DIBSECTION), &ds) != sizeof(DIBSECTION))
     {
@@ -87,13 +87,10 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca
         
     /* gets the size of DIB palette and bitfields, if any */
     bitFields = 0;
-    if(ds.dsBmih.biBitCount > 8)
-    {
-        colorUsed = 0;
-        if(ds.dsBmih.biCompression == BI_BITFIELDS)
+    colorUsed = 0;
+    if(ds.dsBmih.biCompression == BI_BITFIELDS)
             bitFields = 3;
-    }
-    else
+    else if(ds.dsBmih.biBitCount <= 8)
     {
         colorUsed = ds.dsBmih.biClrUsed;
         if(!colorUsed)
@@ -131,9 +128,11 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca
             HeapFree(GetProcessHeap(), 0, bmi);
             return 0;
         }
-        GetDIBColorTable(tmpHdc, 0, colorUsed, bmi->bmiColors);
+        if(!GetDIBColorTable(tmpHdc, 0, colorUsed, bmi->bmiColors))
+            ERR("GetDIBColorTable failed\n");
         SelectObject(tmpHdc, tmpBmp);
         DeleteDC(tmpHdc);
+        
     }
     
     /* fill the bitfields part, if any */
@@ -165,6 +164,7 @@ HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int sca
         DeleteObject( hBmp );
         return 0;
     }
+    
     return hBmp;
 }
 
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
index 9ffceee..f5324b0 100644
--- a/dlls/winedib.drv/dc.c
+++ b/dlls/winedib.drv/dc.c
@@ -80,6 +80,10 @@ static DWORD get_dpi( void )
     return dpi;
 }
 
+/* dummy function for pen/brush drawing primitives initializations */
+static void dummy4(DIBDRVPHYSDEV *physDev, int a, int b, int c) {} ;
+static void dummy5(DIBDRVPHYSDEV *physDev, int a, int b, int c, int d) {} ;
+
 /**********************************************************************
  *       device_init
  *
@@ -120,10 +124,6 @@ static void device_init(void)
     device_init_done = TRUE;
 }
 
-/* dummy null function for pen and brush */
-static void dummy3(DIBDRVPHYSDEV *p, int a, int b, int c) {}
-static void dummy4(DIBDRVPHYSDEV *p, int a, int b, int c, int d) {}
-
 /**********************************************************************
  *           DIBDRV_CreateDC
  */
@@ -180,22 +180,24 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
     physDev->backgroundColor = 0;
     _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor);
     
+    /* stock pen */
+    physDev->penStyle = PS_NULL;
     physDev->penColor = 0;
+    physDev->penColorref = 0;
     _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->penAnd, &physDev->penXor);
-    
-    physDev->penStyle = PS_NULL;
-    physDev->penHLine = dummy3;
-    physDev->penVLine = dummy3;
-    physDev->penLine  = dummy4;
+    physDev->penHLine = dummy4;
+    physDev->penVLine = dummy4;
+    physDev->penLine = dummy5;
     physDev->penPattern = NULL;
     
-    physDev->brushColor = 0;
-    _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->brushAnd, &physDev->brushXor);
+    /* stock brush */
+    physDev->brushStyle = BS_NULL;
+    physDev->brushColor = 0x0;
+    physDev->brushColorref = 0x0;
+    _DIBDRV_CalcAndXorMasks(physDev->rop2, 0x0, &physDev->brushAnd, &physDev->brushXor);
     physDev->brushAnds = NULL;
     physDev->brushXors = NULL;
-    
-    physDev->brushStyle = BS_NULL;
-    physDev->brushHLine = dummy3;
+    physDev->brushHLine = dummy4;
     
     physDev->isBrushBitmap = FALSE;
     _DIBDRVBITMAP_Clear(&physDev->brushBitmap);
@@ -215,7 +217,7 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
 
     /* sets the result value and returns */
     *pdev = physDev;
-
+    
     return TRUE;
 }
 
diff --git a/dlls/winedib.drv/dib.c b/dlls/winedib.drv/dib.c
index 653148d..41fb158 100644
--- a/dlls/winedib.drv/dib.c
+++ b/dlls/winedib.drv/dib.c
@@ -25,6 +25,43 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+/* Default 1 BPP palette */
+static DWORD pal1[] =
+{
+    0x000000,
+    0xffffff
+};
+
+/* Default 4 BPP palette */
+static DWORD pal4[] =
+{
+    0x000000,0x800000,0x008000,0x808000,
+    0x000080,0x800080,0x008080,0x808080,
+    0xc0c0c0,0xff0000,0x00ff00,0xffff00,
+    0x0000ff,0xff00ff,0x00ffff,0xffffff
+};
+
+/* Default 8 BPP palette */
+static DWORD pal8[] =
+{
+    0x000000,0x800000,0x008000,0x808000,0x000080,0x800080,0x008080,0xc0c0c0,0xc0dcc0,0xa6caf0,0x000000,0x000033,0x000066,0x000099,0x0000cc,0x0000ff,
+    0x003300,0x003333,0x003366,0x003399,0x0033cc,0x0033ff,0x006600,0x006633,0x006666,0x006699,0x0066cc,0x0066ff,0x009900,0x009933,0x009966,0x009999,
+    0x0099cc,0x0099ff,0x00cc00,0x00cc33,0x00cc66,0x00cc99,0x00cccc,0x00ccff,0x00ff00,0x00ff33,0x00ff66,0x00ff99,0x00ffcc,0x00ffff,0x330000,0x330033,
+    0x330066,0x330099,0x3300cc,0x3300ff,0x333300,0x333333,0x333366,0x333399,0x3333cc,0x3333ff,0x336600,0x336633,0x336666,0x336699,0x3366cc,0x3366ff,
+    0x339900,0x339933,0x339966,0x339999,0x3399cc,0x3399ff,0x33cc00,0x33cc33,0x33cc66,0x33cc99,0x33cccc,0x33ccff,0x33ff00,0x33ff33,0x33ff66,0x33ff99,
+    0x33ffcc,0x33ffff,0x660000,0x660033,0x660066,0x660099,0x6600cc,0x6600ff,0x663300,0x663333,0x663366,0x663399,0x6633cc,0x6633ff,0x666600,0x666633,
+    0x666666,0x666699,0x6666cc,0x6666ff,0x669900,0x669933,0x669966,0x669999,0x6699cc,0x6699ff,0x66cc00,0x66cc33,0x66cc66,0x66cc99,0x66cccc,0x66ccff,
+    0x66ff00,0x66ff33,0x66ff66,0x66ff99,0x66ffcc,0x66ffff,0x990000,0x990033,0x990066,0x990099,0x9900cc,0x9900ff,0x993300,0x993333,0x993366,0x993399,
+    0x9933cc,0x9933ff,0x996600,0x996633,0x996666,0x996699,0x9966cc,0x9966ff,0x999900,0x999933,0x999966,0x999999,0x9999cc,0x9999ff,0x99cc00,0x99cc33,
+    0x99cc66,0x99cc99,0x99cccc,0x99ccff,0x99ff00,0x99ff33,0x99ff66,0x99ff99,0x99ffcc,0x99ffff,0xcc0000,0xcc0033,0xcc0066,0xcc0099,0xcc00cc,0xcc00ff,
+    0xcc3300,0xcc3333,0xcc3366,0xcc3399,0xcc33cc,0xcc33ff,0xcc6600,0xcc6633,0xcc6666,0xcc6699,0xcc66cc,0xcc66ff,0xcc9900,0xcc9933,0xcc9966,0xcc9999,
+    0xcc99cc,0xcc99ff,0xcccc00,0xcccc33,0xcccc66,0xcccc99,0xcccccc,0xccccff,0xccff00,0xccff33,0xccff66,0xccff99,0xccffcc,0xccffff,0xff0000,0xff0033,
+    0xff0066,0xff0099,0xff00cc,0xff00ff,0xff3300,0xff3333,0xff3366,0xff3399,0xff33cc,0xff33ff,0xff6600,0xff6633,0xff6666,0xff6699,0xff66cc,0xff66ff,
+    0xff9900,0xff9933,0xff9966,0xff9999,0xff99cc,0xff99ff,0xffcc00,0xffcc33,0xffcc66,0xffcc99,0xffcccc,0xffccff,0xffff00,0xffff33,0xffff66,0xffff99,
+    0xffffcc,0xffffff,0x050500,0x050501,0x050502,0x050503,0x050504,0x050505,0xe8e8e8,0xe9e9e9,0xeaeaea,0xebebeb,0xececec,0xededed,0xeeeeee,0xefefef,
+    0xf0f0f0,0xf1f1f1,0xf2f2f2,0xf3f3f3,0xf4f4f4,0xf5f5f5,0xfffbf0,0xa0a0a4,0x808080,0xf00000,0x00ff00,0xffff00,0x0000ff,0xff00ff,0x00ffff,0xffffff
+};
+
 /***********************************************************************
  *           DIBDRV_CreateDIBSection
  */
@@ -46,15 +83,206 @@ HBITMAP DIBDRV_CreateDIBSection( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap,
  *           DIBDRV_GetDIBits
 */
 INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
-                      UINT lines, LPCVOID bits, const BITMAPINFO *bmi, UINT coloruse )
+                      UINT lines, LPVOID bits, BITMAPINFO *info, UINT coloruse )
 {
     INT res;
-    
-    MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
-        physDev, hbitmap, startscan, lines, bits, bmi, coloruse));
+    DIBSECTION ds;
+    DIBDRVBITMAP sBmp, dBmp;
+    DWORD *buf;
+    int iLine;
+    int size;
+    BOOL justInfo, justInfoHeader;
+    int requestedBpp;
+    RGBQUAD *colorTable;
+    int colorTableSize;
+    BITMAPINFO *sourceInfo;
 
-    /* GetDIBits reads bits from a DDB, so we should use the X11 driver */
-    res = _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, bmi, coloruse);
+    MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
+        physDev, hbitmap, startscan, lines, bits, info, coloruse));
+    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &ds) == sizeof(DIBSECTION))
+    {
+        /* GetDIBits reads bits from a DIB, so we should use the engine driver */
+        
+        /* for the moment, we don't support startscan != 0 */
+        if(startscan != 0)
+        {
+            FIXME("startscan != 0 still not supported\n");
+            return 0;
+        }
+        
+        /* sanity check */
+        size = info->bmiHeader.biSize;
+        if(size != sizeof(BITMAPINFOHEADER) && size != sizeof(BITMAPCOREHEADER))
+        {
+            ERR("Unknown header size %d\n", size);
+            return 0;
+        }
+        
+        /* get requested BPP */
+        requestedBpp = info->bmiHeader.biBitCount;
+        
+        /* check wetrher we wants just the BITMAPINFO data */
+        justInfo = (bits == NULL);
+        
+        /* check wether we wants just to get BITMAPINFOHEADER data */
+        justInfoHeader = (requestedBpp == 0);
+        
+        if(!justInfo && justInfoHeader)
+        {
+            ERR("Bad requested BPP\n");
+            return 0;
+        }
+
+        /* copy / set missing DIB info */
+        if(justInfo)
+        {
+            info->bmiHeader.biWidth = ds.dsBmih.biWidth;
+            info->bmiHeader.biHeight = ds.dsBmih.biHeight;
+        }
+        info->bmiHeader.biPlanes = 1;
+        if(justInfoHeader)
+            info->bmiHeader.biBitCount = ds.dsBmih.biBitCount;
+        if(size == sizeof(BITMAPINFOHEADER))
+        {
+            if(justInfoHeader)
+            {
+                info->bmiHeader.biCompression = ds.dsBmih.biCompression;
+                info->bmiHeader.biXPelsPerMeter = ds.dsBmih.biXPelsPerMeter;
+                info->bmiHeader.biYPelsPerMeter = ds.dsBmih.biYPelsPerMeter;
+                info->bmiHeader.biClrUsed = ds.dsBmih.biClrUsed;
+                info->bmiHeader.biClrImportant = ds.dsBmih.biClrImportant;
+            }
+            info->bmiHeader.biSizeImage = ds.dsBmih.biSizeImage;
+        }
+
+        /* width and height *must* match source's ones */
+        if(info->bmiHeader.biWidth != ds.dsBmih.biWidth ||
+           abs(info->bmiHeader.biHeight) != abs(ds.dsBmih.biHeight))
+        {
+            ERR("Size of requested bitmap data don't match source's ones\n");
+            return 0;
+        }
+
+        /* if we just wants the BITMAPINFOHEADER data, we're done */
+        if(justInfoHeader || (justInfo && ds.dsBmih.biBitCount > 8))
+            return abs(info->bmiHeader.biHeight);
+            
+        /* we now have to get source data -- we need it for palette, for example */
+        colorTableSize = 0;
+        if(ds.dsBmih.biBitCount <= 8)
+            colorTableSize = (1 << ds.dsBmih.biBitCount);
+        else if(ds.dsBmih.biCompression == BI_BITFIELDS)
+            colorTableSize = 3;
+        sourceInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + colorTableSize * sizeof(RGBQUAD));
+        if(!sourceInfo)
+        {
+            ERR("HeapAlloc failed\n");
+            return 0;
+        }
+        memcpy(sourceInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
+        if(ds.dsBmih.biBitCount <= 8)
+        {
+            /* grab palette - well, we should. No way to do it by now....
+               we should add a list HBITMAP <--> DIBDRVBITMAP and fiddle to many
+               , many parts of the engine. Not worth the effort by now.
+               So, we just synthesize the table */
+            switch(requestedBpp)
+            {
+                case 1:
+                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal1, 2*sizeof(DWORD));
+                    break;
+                    
+                case 4:
+                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal4, 16*sizeof(DWORD));
+                    break;
+                
+                case 8:
+                    memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), pal8, 256*sizeof(DWORD));
+                    break;
+                    
+                default:
+                    ERR("Unknown requested bith depth %d\n", requestedBpp);
+                    _DIBDRVBITMAP_Free(&sBmp);
+                    return 0;
+            }
+        }
+        else if(ds.dsBmih.biCompression == BI_BITFIELDS)
+            memcpy((BYTE *)sourceInfo + sizeof(BITMAPINFOHEADER), ds.dsBitfields, 3 * sizeof(RGBQUAD));
+        _DIBDRVBITMAP_Clear(&sBmp);
+        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, sourceInfo))
+        {
+            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+            HeapFree(GetProcessHeap(), 0, sourceInfo);
+            return 0;
+        }
+        _DIBDRVBITMAP_Set_Bits(&sBmp, ds.dsBm.bmBits, FALSE);
+        HeapFree(GetProcessHeap(), 0, sourceInfo);
+                
+        /* now grab / synthesize the color table if needed */
+        if(requestedBpp <= 8)
+        {
+            colorTable = (RGBQUAD *)((BYTE *)info + size);
+            if(requestedBpp == ds.dsBmih.biBitCount)
+            {
+                /* same source and dest format - copy color tables */
+                memcpy(colorTable, sBmp.colorTable, colorTableSize);
+            }
+            else
+            {
+                /* different formats -- synthesize color table */
+                switch(requestedBpp)
+                {
+                    case 1:
+                        memcpy(colorTable, pal1, 2*sizeof(DWORD));
+                        break;
+                        
+                    case 4:
+                        memcpy(colorTable, pal4, 16*sizeof(DWORD));
+                        break;
+                    
+                    case 8:
+                        memcpy(colorTable, pal8, 256*sizeof(DWORD));
+                        break;
+                        
+                    default:
+                        ERR("Unknown requested bith depth %d\n", requestedBpp);
+                        _DIBDRVBITMAP_Free(&sBmp);
+                        return 0;
+                }
+            }
+        }
+        
+        /* if we just wanted DIB info, job is done */
+        if(justInfo)
+        {
+            _DIBDRVBITMAP_Free(&sBmp);
+            return abs(info->bmiHeader.biHeight);
+        }
+        
+        /* Creates a DIBDRVBITMAP from dest dib */
+        _DIBDRVBITMAP_Clear(&dBmp);
+        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&dBmp, info))
+        {
+            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+            _DIBDRVBITMAP_Free(&sBmp);
+            return 0;
+        }
+        _DIBDRVBITMAP_Set_Bits(&dBmp, bits, FALSE);
+        
+        /* now we can do the bit conversion */
+        buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD));
+        for(iLine = 0; iLine < lines; iLine++)
+        {
+            sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+        }
+        _DIBDRVBITMAP_Free(&sBmp);
+        _DIBDRVBITMAP_Free(&dBmp);
+        return lines;
+    }
+    else
+        /* GetDIBits reads bits from a DDB, use X11 driver */
+        res = _DIBDRV_GetDisplayDriver()->pGetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse);
     
     return res;
 }
@@ -66,7 +294,10 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
                               const RGBQUAD *colors )
 {
     DIBDRVBITMAP *dib = &physDev->physBitmap;
-    
+#if 0
+    HBITMAP thisDIB;
+#endif
+
     MAYBE(TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev, start, count, colors));
 
     /* SetDIBColorTable operates on a DIB, so we use the engine */
@@ -80,7 +311,7 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
     
     /* if dib hasn't a color table, or has a small one, we must before
        create/extend it */
-    if(!(dib->colorTable))
+    if(!dib->colorTable)
     {
         dib->colorTableSize = (1 << dib->bitCount);
         dib->colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(RGBQUAD) * dib->colorTableSize);
@@ -104,6 +335,13 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
     memcpy(dib->colorTable + start, colors, sizeof(RGBQUAD) * count);
     dib->colorTableGrabbed = TRUE;
 
+    /* hack to make GDI32 sense the DIB color table change
+       (fixes a couple of todos in bitmap test suite */
+#if 0
+    thisDIB = SelectObject(physDev->hdc, GetStockObject(OBJ_BITMAP));
+    SelectObject(physDev->hdc, thisDIB);
+#endif
+
     return TRUE;
 }
 
@@ -114,13 +352,59 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
                       UINT lines, LPCVOID bits, const BITMAPINFO *info, UINT coloruse )
 {
     INT res;
+    DIBSECTION ds;
+    DIBDRVBITMAP sBmp, dBmp;
+    DWORD *buf;
+    int iLine;
     
     MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
         physDev, hbitmap, startscan, lines, bits, info, coloruse));
 
-    /* SetDIBits writes bits to a DDB, so we should use the X11 driver */
-    res =  _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse);
 
+    if(GetObjectW(hbitmap, sizeof(DIBSECTION), &ds) == sizeof(DIBSECTION))
+    {
+        /* SetDIBits writes bits to a DIB, so we should use the engine driver */
+
+        /* for the moment, we don't support startscan != 0 */
+        if(startscan != 0)
+        {
+            FIXME("startscan != 0 still not supported\n");
+            return 0;
+        }
+        
+        /* Creates a DIBDRVBITMAP from source dib */
+        _DIBDRVBITMAP_Clear(&sBmp);
+        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, info))
+        {
+            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+            return 0;
+        }
+        _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE);
+        
+        /* same for destination dib */
+        if(!_DIBDRVBITMAP_InitFromHBITMAP(&dBmp, hbitmap, FALSE))
+        {
+            ERR("_DIBDRVBITMAP_InitFromHBITMAP failed\n");
+            _DIBDRVBITMAP_Free(&sBmp);
+            return 0;
+        }
+        
+        /* now we can do the bit conversion */
+        buf = HeapAlloc(GetProcessHeap(), 0, ds.dsBmih.biWidth * sizeof(RGBQUAD));
+        for(iLine = 0; iLine < lines; iLine++)
+        {
+            sBmp.funcs->GetLine(&sBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+            dBmp.funcs->PutLine(&dBmp, iLine, 0, ds.dsBmih.biWidth, buf);
+        }
+        _DIBDRVBITMAP_Free(&sBmp);
+        _DIBDRVBITMAP_Free(&dBmp);
+        return lines;
+    }
+    else
+    {
+        /* SetDIBits writes bits to a DDB, so we should use the X11 driver */
+        res =  _DIBDRV_GetDisplayDriver()->pSetDIBits(physDev->X11PhysDev, hbitmap, startscan, lines, bits, info, coloruse);
+    }
     return res;
 }
 
@@ -132,14 +416,105 @@ INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDest, INT yDest, DWOR
                               UINT startscan, UINT lines, LPCVOID bits,
                               const BITMAPINFO *info, UINT coloruse )
 {
-    INT res;
+    BITMAPINFO *bitmapInfo;
+    int bmInfoSize;
+    int dibHeight, dibWidth;
+    DIBDRVBITMAP sBmp;
+    int sLine, dLine, iLine;
+    void *buf;
     
     MAYBE(TRACE("physDev:%p, xDest:%d, yDest:%d, cx:%x, cy:%x, xSrc:%d, ySrc:%d, startscan:%d, lines:%d, bits:%p, info:%p, coloruse:%d\n",
         physDev, xDest, yDest, cx, cy, xSrc, ySrc, startscan, lines, bits, info, coloruse));
 
-    /* SetDIBitsToDevice operates on a physical device, so we should use the X11 driver */
-    res = _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDest, yDest, cx, cy, xSrc, ySrc,
-                                                          startscan, lines, bits, info, coloruse);
+    if(physDev->hasDIB)
+    {
+        /* DIB section selected in, use DIB Engine */
+        
+        /* inverts y on source -- FIXME: check if right with some tests, it seems so */
+        ySrc = abs(info->bmiHeader.biHeight) - ySrc - cy;
+        
+        dibHeight = info->bmiHeader.biHeight;
+        dibWidth = info->bmiHeader.biWidth;
 
-    return res;
+        /* sanity check and source clipping on physical sizes */
+        if(startscan >= abs(dibHeight))
+            return 0;
+        if(startscan + lines > abs(dibHeight))
+            lines = abs(dibHeight) - startscan;
+
+        /* adjust height because of startscan */
+        dibHeight += (dibHeight > 0 ? -startscan : startscan);
+
+        if(xSrc >= dibWidth)
+            return 0;
+        if(xSrc + cx > dibWidth)
+            cx = dibWidth - xSrc;
+        if(ySrc > abs(dibHeight))
+            return 0;
+        if(ySrc + cy > abs(dibHeight))
+            cy = abs(dibHeight) - ySrc;
+            
+        ySrc -= startscan;
+        cy -= startscan;
+        if(cy <= 0)
+            return 0;
+        if(ySrc < 0)
+        {
+            yDest += ySrc;
+            cy += ySrc;
+            ySrc = 0;
+        }
+        if(cy <= 0)
+            return 0;
+
+        /* grab a copy of BITMAPINFO */
+        bmInfoSize = sizeof(BITMAPINFOHEADER);
+        if(info->bmiHeader.biCompression == BI_BITFIELDS)
+            bmInfoSize += 3 * sizeof(RGBQUAD);
+        else if (info->bmiHeader.biBitCount <= 8)
+        {
+            if(info->bmiHeader.biClrUsed)
+                bmInfoSize += info->bmiHeader.biClrUsed * sizeof(RGBQUAD);
+            else
+                bmInfoSize += (1 << info->bmiHeader.biBitCount) * sizeof(RGBQUAD);
+        }
+        if(!(bitmapInfo = HeapAlloc(GetProcessHeap(), 0, bmInfoSize)))
+        {
+            ERR("HeapAlloc failed\n");
+            return 0;
+        }
+        memcpy(bitmapInfo, info, bmInfoSize);
+        bitmapInfo->bmiHeader.biHeight = dibHeight;
+
+        /* create a DIBDRVBITMAP from BITMAPINFO data */
+        _DIBDRVBITMAP_Clear(&sBmp);
+        if(!_DIBDRVBITMAP_InitFromBitmapinfo(&sBmp, bitmapInfo))
+        {
+            ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+            HeapFree(GetProcessHeap, 0, bitmapInfo);
+            return 0;
+        }
+        HeapFree(GetProcessHeap(), 0, bitmapInfo);
+        _DIBDRVBITMAP_Set_Bits(&sBmp, (LPVOID)bits, FALSE);
+        
+        /* transfer lines to dest bitmap */
+        if(!(buf = HeapAlloc(GetProcessHeap(), 0, cx * sizeof(RGBQUAD))))
+        {
+            ERR("HeapAlloc failed\n");
+            return 0;
+        }
+        for(sLine = ySrc, dLine = yDest, iLine = 0; iLine < cy; sLine++, dLine++, iLine++)
+        {
+            sBmp.funcs->GetLine(&sBmp, sLine, xSrc, cx, buf); 
+            physDev->physBitmap.funcs->PutLine(&physDev->physBitmap, dLine, xDest, cx, buf);
+        }
+        HeapFree(GetProcessHeap(), 0, buf);
+
+        return cy;
+    }
+    else
+    {
+        return _DIBDRV_GetDisplayDriver()->pSetDIBitsToDevice(physDev->X11PhysDev, xDest, yDest, cx, cy, xSrc, ySrc,
+                                                            startscan, lines, bits, info, coloruse);
+    }
 }
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index 66cc114..8243d4b 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -312,6 +312,11 @@ DWORD _DIBDRV_ROP3(DWORD p, DWORD s, DWORD d, BYTE rop);
 /* gets human-readable dib format name */
 const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp);
 
+/* sets/gets bits of a DIBDRVBITMAP taking in account if it's a top down
+   or a bottom-up DIB */
+void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP *dib, void *bits, BOOL owns);
+void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP *dib);
+
 /* initializes dib from a bitmap : 
     dib           dib being initialized
     bi            source BITMAPINFOHEADER with required DIB format info
@@ -322,7 +327,7 @@ const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp);
 BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
                                 const RGBQUAD *color_table, void *bits);
 
-BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi);
+BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi);
 
 /* initializes a DIBRDVBITMAP copying it from a source one
    Parameters :
@@ -331,6 +336,13 @@ BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi);
       copy      TRUE->copy source pixel array FALSE->link to source pixel array */
 BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy);
 
+/* initializes a DIBRDVBITMAP from a DIB HBITMAP
+   Parameters :
+      bmp           destination DIBDRVBITMAP
+      hbmp          source HBITMAP
+      copyPixels    TRUE->copy source pixel array FALSE->link to source pixel array */
+BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels);
+
 /* creates a DIBRDVBITMAP copying format info from a source one
    Parameters :
       dib            destination DIBDRVBITMAP
@@ -413,4 +425,17 @@ void _DIBDRV_Sizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h);
 /* converts a rectangle form Word space to Device space */
 void _DIBDRV_Rect_ws2ds(DIBDRVPHYSDEV *physDev, const RECT *src, RECT *dst);
 
+/* *********************************************************************
+ * COLOR UTILITIES
+ * ********************************************************************/
+
+/* maps a colorref to actual color */
+COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color);
+
+/* gets nearest color index in DIB palette of a given colorref */
+DWORD _DIBDRV_GetNearestColorIndex(const DIBDRVBITMAP *dib, COLORREF color);
+
+/* gets nearest color to DIB palette color */
+DWORD _DIBDRV_GetNearestColor(const DIBDRVBITMAP *dib, COLORREF color);
+
 #endif
diff --git a/dlls/winedib.drv/dibdrvbitmap.c b/dlls/winedib.drv/dibdrvbitmap.c
index 2c8c367..8e6b653 100644
--- a/dlls/winedib.drv/dibdrvbitmap.c
+++ b/dlls/winedib.drv/dibdrvbitmap.c
@@ -107,6 +107,41 @@ static void InitBitFields(DIBDRVBITMAP *dib, const DWORD *bit_fields)
     CalcShiftAndLen(dib->blueMask,  &dib->blueShift,  &dib->blueLen);
 }
 
+/* sets/gets bits of a DIBDRVBITMAP taking in account if it's a top down
+   or a bottom-up DIB */
+void _DIBDRVBITMAP_Set_Bits(DIBDRVBITMAP *dib, void *bits, BOOL owns)
+{
+    /* checks whether dib is top-down or bottom-up one */
+    if(dib->stride > 0)
+    {
+        /* top-down dib */
+        dib->bits = bits;
+    }
+    else
+    {
+        /* bottom-up dib */
+        /* data->bits always points to the top-left corner and the stride is -ve */
+        dib->bits    = (BYTE*)bits - (dib->height - 1) * dib->stride;
+    }
+    dib->ownsBits = owns;
+}
+
+void *_DIBDRVBITMAP_Get_Bits(DIBDRVBITMAP * dib)
+{
+    /* checks whether dib is top-down or bottom-up one */
+    if(dib->stride > 0)
+    {
+        /* top-down dib */
+        return dib->bits;
+    }
+    else
+    {
+        /* bottom-up dib */
+        /* data->bits always points to the top-left corner and the stride is -ve */
+        return  (BYTE*)dib->bits + (dib->height - 1) * dib->stride;
+    }
+}
+
 /* initializes dib from a bitmap : 
     dib           dib being initialized
     bi            source BITMAPINFOHEADER with required DIB format info
@@ -238,7 +273,7 @@ BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, c
     return TRUE;
 }
 
-BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi)
+BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, const BITMAPINFO *bmi)
 {
     static const DWORD bit_fields_DIB32_RGB[3] = {0xff0000, 0x00ff00, 0x0000ff};
     static const DWORD bit_fields_DIB16_RGB[3] = {0x7c00, 0x03e0, 0x001f};
@@ -343,6 +378,93 @@ BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *s
     return TRUE;
 }
 
+/* initializes a DIBRDVBITMAP from a DIB HBITMAP
+   Parameters :
+      bmp           destination DIBDRVBITMAP
+      hbmp          source HBITMAP
+      copyPixels    TRUE->copy source pixel array FALSE->link to source pixel array */
+BOOL _DIBDRVBITMAP_InitFromHBITMAP(DIBDRVBITMAP *bmp, const HBITMAP hbmp, BOOL copyPixels)
+{
+    BITMAPINFO *destInfo;
+    DIBSECTION ds;
+    int size;
+    
+    MAYBE(TRACE("bmp=%p, hbmp=%p, copyPixels = %s\n", bmp, hbmp, copyPixels ? "TRUE" : "FALSE"));
+
+    /* be sure bitmap is empty */
+    _DIBDRVBITMAP_Clear(bmp);
+    
+    /* gets source bitmap data */
+    if(!(size = GetObjectW(hbmp, sizeof(DIBSECTION), &ds)))
+    {
+        ERR("Failed getting bitmap object\n");
+        return FALSE;
+    }
+    if(size != sizeof(DIBSECTION))
+    {
+        ERR("Bitmap is not a DIB section\n");
+        return FALSE;
+    }
+    
+    destInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
+    if(!destInfo)
+    {
+        ERR("HeapAlloc failed\n");
+        return FALSE;
+    }
+    
+    memcpy(destInfo, &ds.dsBmih, sizeof(BITMAPINFOHEADER));
+    if(ds.dsBmih.biCompression == BI_BITFIELDS)
+        memcpy((BITMAPINFOHEADER *)destInfo + 1, ds.dsBitfields, 3 * sizeof(RGBQUAD));
+    else if(ds.dsBmih.biBitCount <= 8)
+    {
+        FIXME("Can't grab color table here.... syslvel lock\n");
+        return FALSE;
+#if 0
+        HDC refDC = CreateCompatibleDC(0);
+        if(!refDC)
+        {
+            ERR("CreateCompatibleDC() failed\n");
+            return FALSE;
+        }
+        if(!GetDIBits(refDC, hbmp, 0, 1, NULL, destInfo, DIB_RGB_COLORS))
+        {
+            DeleteDC(refDC);
+            HeapFree(GetProcessHeap(), 0, destInfo);
+            ERR("GetDIBits failed\n");
+            return FALSE;
+        }
+        DeleteDC(refDC);
+#endif
+    }
+    if(!_DIBDRVBITMAP_InitFromBitmapinfo(bmp, destInfo))
+    {
+        HeapFree(GetProcessHeap(), 0, destInfo);
+        ERR("_DIBDRVBITMAP_InitFromBitmapinfo failed\n");
+        return FALSE;
+    }
+    HeapFree(GetProcessHeap(), 0, destInfo);
+    if(copyPixels)
+    {
+        size = abs(bmp->stride) * bmp->height;
+        if(!(bmp->bits = HeapAlloc(GetProcessHeap(), 0, size)))
+        {
+            ERR("HeapAlloc failed\n");
+            _DIBDRVBITMAP_Free(bmp);
+            return FALSE;
+        }
+        memcpy(bmp->bits, ds.dsBm.bmBits, size);
+        bmp->ownsBits = TRUE;
+    }
+    else
+        bmp->bits = ds.dsBm.bmBits;
+    if(bmp->stride < 0)
+        bmp->bits    = (BYTE*)bmp->bits - (bmp->height - 1) * bmp->stride;
+    
+    return TRUE;
+}
+
+
 /* creates a DIBRDVBITMAP copying format info from a source one
    Parameters :
       dib            destination DIBDRVBITMAP
diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c
index af264d0..4aebe8e 100644
--- a/dlls/winedib.drv/graphics.c
+++ b/dlls/winedib.drv/graphics.c
@@ -132,7 +132,7 @@ static inline void SideIntersect(const POINT *p1, const POINT *p2, const RECT *r
 			break;
 		case TOP_SIDE: /* top */
             inters->x = MulDiv(p2->x - p1->x, r->top - p1->y, p2->y - p1->y) + p1->x;
-            inters->y = r->bottom;
+            inters->y = r->top;
 			break;
 		case RIGHT_SIDE: /* right */
             inters->x = r->right - 1;
@@ -698,7 +698,7 @@ BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* ptw, int count )
             {
                 /* gets polygon bounding box -- for ytop and ybottom */
                 PolygonBoundingBox(clipped, clippedCount, &bBox);
-                
+
                 /* gets all ordered intersections of polygon with
                    current scanline */
                 for(ys = bBox.top; ys < bBox.bottom; ys++)
@@ -972,6 +972,12 @@ COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
 
     if(physDev->hasDIB)
     {
+        /* get real colorref */
+        color = _DIBDRV_MapColor(physDev, color);
+        
+        /* map to pixel color / palette index */
+        color = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color);
+        
         _DIBDRV_Position_ws2ds(physDev, &x, &y);
 
         /* gets previous pixel */
diff --git a/dlls/winedib.drv/palette.c b/dlls/winedib.drv/palette.c
index a1aa648..87016da 100644
--- a/dlls/winedib.drv/palette.c
+++ b/dlls/winedib.drv/palette.c
@@ -25,6 +25,69 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+/* maps a colorref to actual color */
+COLORREF _DIBDRV_MapColor(DIBDRVPHYSDEV *physDev, COLORREF color)
+{
+    WORD index;
+    RGBQUAD *palColor;
+    HPALETTE hPal;
+    PALETTEENTRY paletteEntry;
+    
+    switch(color >> 24)
+    {
+        case 0x10 : /* DIBINDEX */
+            MAYBE(TRACE("DIBINDEX Color is %08x\n", color));
+            index =  color & 0xffff;
+            if(index >= physDev->physBitmap.colorTableSize)
+            {
+                WARN("DIBINDEX color out of range\n");
+                return 0;
+            }
+            palColor = physDev->physBitmap.colorTable + index;
+            MAYBE(TRACE("Returning color %08x\n", RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue)));
+            return RGB(palColor->rgbRed, palColor->rgbGreen, palColor->rgbBlue);
+            
+        case 0x01: /* PALETTEINDEX */
+            MAYBE(TRACE("PALETTEINDEX Color is %08x\n", color));
+            index =  color & 0xffff;
+            if(!(hPal = GetCurrentObject(physDev->hdc, OBJ_PAL)))
+            {
+                ERR("Couldn't get palette\n");
+                return 0;
+            }
+            if (!GetPaletteEntries(hPal, index, 1, &paletteEntry))
+            {
+                WARN("PALETTEINDEX(%x) : index %d is out of bounds, assuming black\n", color, index);
+                return 0;
+            }
+            MAYBE(TRACE("Returning color %08x\n", RGB(paletteEntry.peRed, paletteEntry.peGreen, paletteEntry.peBlue)));
+            return RGB(paletteEntry.peRed, paletteEntry.peGreen, paletteEntry.peBlue);
+        
+        case 0x02: /* PALETTERGB */
+            return _DIBDRV_GetNearestColor(&physDev->physBitmap, color & 0xffffff);
+        
+        default:
+            /* RGB color -- we must process special case for monochrome bitmaps */
+            if(physDev->physBitmap.bitCount == 1)
+            {
+                RGBQUAD *back = physDev->physBitmap.colorTable;
+                RGBQUAD *fore = back+1;
+                if(fore->rgbRed * fore->rgbRed + fore->rgbGreen * fore->rgbGreen + fore->rgbBlue * fore->rgbBlue <
+                   back->rgbRed * back->rgbRed + back->rgbGreen * back->rgbGreen + back->rgbBlue * back->rgbBlue)
+                {
+                    fore = back;
+                    back = fore + 1;
+                }
+                if ( ((color >> 16) & 0xff) + ((color >>  8) & 0xff) + (color & 0xff) > 255*3/2)
+                    return RGB(fore->rgbRed, fore->rgbGreen, fore->rgbBlue);
+                else
+                    return RGB(back->rgbRed, back->rgbGreen, back->rgbBlue);
+            }
+            else
+                return color;
+    }
+}
+
 /***********************************************************************
  *              DIBDRV_RealizePalette
  */
diff --git a/dlls/winedib.drv/pen_brush.c b/dlls/winedib.drv/pen_brush.c
index 7b15ece..c40bfaf 100644
--- a/dlls/winedib.drv/pen_brush.c
+++ b/dlls/winedib.drv/pen_brush.c
@@ -51,7 +51,7 @@ static void SolidPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
     physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->penAnd, physDev->penXor);
 }
 
-static void SolidPenVline(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
+static void SolidPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
 {
     OrderEndPoints(&y1, &y2);
     physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y1, y2, physDev->penAnd, physDev->penXor);
@@ -65,7 +65,7 @@ static void WINAPI SolidPenLineCallback(int x, int y, LPARAM lparam)
     return;
 }
 
-void SolidPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
+static void SolidPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
 {
     LineDDA(x1, y1, x2, y2, SolidPenLineCallback, (LPARAM)physDev);
 }
@@ -216,22 +216,29 @@ void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV *physDev)
     physDev->markSpace = mark;
 }
 
-
+#if 0
 /* For 1bpp bitmaps, unless the selected foreground color exactly
    matches foreground's colortable OR it's the WHITE color,
    the background color is used -- tested on WinXP */
 static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color)
 {
+    RGBQUAD *back = physDev->physBitmap.colorTable;
     RGBQUAD *fore = physDev->physBitmap.colorTable+1;
     
-    if((color & 0x00ffffff) == 0x00ffffff ||
-       (
-           fore->rgbRed   == GetRValue(color) &&
-           fore->rgbGreen == GetGValue(color) &&
-           fore->rgbBlue  == GetBValue(color)
-    ))
-       return 1;
-    return 0;
+    if(
+      fore->rgbRed   == GetRValue(color) &&
+      fore->rgbGreen == GetGValue(color) &&
+      fore->rgbBlue  == GetBValue(color))
+        return 1;
+    else if(
+      back->rgbRed   == GetRValue(color) &&
+      back->rgbGreen == GetGValue(color) &&
+      back->rgbBlue  == GetBValue(color))
+        return 0;
+    else if((color & 0x00ffffff) == 0x00ffffff)
+        return 1;
+    else
+        return 0;
 }
 
 static void FixupFgColors1(DIBDRVPHYSDEV *physDev)
@@ -248,6 +255,45 @@ static void FixupFgColors1(DIBDRVPHYSDEV *physDev)
     physDev->brushAnds = NULL;
     physDev->brushXors = NULL;
 }
+#endif
+
+#if 0
+/* For 1bpp bitmaps, unless the selected foreground color exactly
+   matches one of the colors in the colortable, then the color that
+   isn't the bkgnd color is used. */
+static DWORD AdjustFgColor(DIBDRVPHYSDEV *physDev, COLORREF color)
+{
+    RGBQUAD rgb;
+    int i;
+
+    rgb.rgbRed   = GetRValue(color);
+    rgb.rgbGreen = GetGValue(color);
+    rgb.rgbBlue  = GetBValue(color);
+
+    for(i = 0; i < physDev->physBitmap.colorTableSize; i++)
+    {
+        RGBQUAD *cur = physDev->physBitmap.colorTable + i;
+        if((rgb.rgbRed == cur->rgbRed) && (rgb.rgbGreen == cur->rgbGreen) && (rgb.rgbBlue == cur->rgbBlue))
+            return i;
+    }
+    return ~physDev->backgroundColor & 1;
+}
+
+static void FixupFgColors1(DIBDRVPHYSDEV *physDev)
+{
+    int rop = GetROP2(physDev->hdc);
+
+    physDev->penColor   = AdjustFgColor(physDev, physDev->penColorref);
+    physDev->brushColor = AdjustFgColor(physDev, physDev->brushColorref);
+
+    _DIBDRV_CalcAndXorMasks(rop, physDev->penColor, &physDev->penAnd, &physDev->penXor);
+    _DIBDRV_CalcAndXorMasks(rop, physDev->brushColor, &physDev->brushAnd, &physDev->brushXor);
+    HeapFree(GetProcessHeap(), 0, physDev->brushAnds);
+    HeapFree(GetProcessHeap(), 0, physDev->brushXors);
+    physDev->brushAnds = NULL;
+    physDev->brushXors = NULL;
+}
+#endif
 
 static void SolidBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
 {
@@ -310,23 +356,21 @@ HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen )
     {
         GetObjectW(hpen, sizeof(logpen), &logpen);
 
-        physDev->penColorref = logpen.lopnColor;
-
-        if(physDev->physBitmap.bitCount == 1)
-            FixupFgColors1(physDev);
-        else
-            physDev->penColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, logpen.lopnColor);
+        physDev->penColorref = _DIBDRV_MapColor(physDev, logpen.lopnColor);
+        physDev->penColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->penColorref);
 
         _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), physDev->penColor, &physDev->penAnd, &physDev->penXor);
 
+        physDev->penStyle = logpen.lopnStyle;
         switch(logpen.lopnStyle)
         {
             default:
                 ONCE(FIXME("Unhandled pen style %d\n", logpen.lopnStyle));
+                physDev->penStyle = PS_SOLID;
                 /* fall through */
             case PS_SOLID:
                 physDev->penHLine = SolidPenHLine;
-                physDev->penVLine = SolidPenVline;
+                physDev->penVLine = SolidPenVLine;
                 physDev->penLine  = SolidPenLine;
                 physDev->penPattern = NULL;
                 break;
@@ -415,16 +459,13 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
                 goto solid;
                 
             case BS_SOLID:
-                physDev->brushColorref = logbrush.lbColor;
+                physDev->brushColorref = _DIBDRV_MapColor(physDev, logbrush.lbColor);
     solid:
                 MAYBE(TRACE("SOLID Pattern -- color is %x\n", physDev->brushColorref));
                 physDev->brushStyle = BS_SOLID;
                 physDev->brushHLine = SolidBrushHLine;
 
-                if(physDev->physBitmap.bitCount == 1)
-                    FixupFgColors1(physDev);
-                else
-                    physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, logbrush.lbColor);
+                physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->brushColorref);
 
                 _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->brushColor,
                                            &physDev->brushAnd, &physDev->brushXor);
@@ -496,8 +537,9 @@ HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
             {
                 MAYBE(TRACE("NULL Pattern\n"));
                 physDev->brushColorref = 0;
+                physDev->brushColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, 0);
                 physDev->brushHLine = NullBrushHLine;
-                goto solid;
+                break;
             }
                 
             case BS_PATTERN:
@@ -601,10 +643,9 @@ COLORREF DIBDRV_SetBkColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 
     if(physDev->hasDIB)
     {
-        physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color);
+        physDev->backgroundColor = _DIBDRV_MapColor(physDev, color);
+        physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, physDev->backgroundColor);
 
-        if(physDev->physBitmap.bitCount == 1)
-            FixupFgColors1(physDev);
         _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->backgroundColor, &physDev->backgroundAnd, &physDev->backgroundXor);
         
         res = TRUE;
diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c
index 7feeb49..27d573f 100644
--- a/dlls/winedib.drv/primitives_bitblt.c
+++ b/dlls/winedib.drv/primitives_bitblt.c
@@ -25,6 +25,12 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+static inline COLORREF SwapColors(DWORD c)
+{
+    return ((c & 0x0000ff) << 16) | (c & 0x00ff00) | ((c & 0xff0000) >> 16);
+    
+}
+
 /* shrinks a line -- srcWidth >= dstWidth */
 static void ShrinkLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth)
 {
@@ -407,9 +413,11 @@ BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         srcBmp = NULL;
     dstBmp = &physDevDst->physBitmap;
     
-    /* gets pattern color, in case it's needed */
+    /* gets pattern color, in case it's needed
+       it's NOT the COLORREF value (colors are swapped
+       NOR the pixel value (it's applied to a 32 BPP BI_RGB */
     if(usePat)
-        patColor = physDevDst->brushColor;
+        patColor = SwapColors(physDevDst->brushColorref);
     else
         patColor = 0;
 
@@ -658,9 +666,11 @@ BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
         srcBmp = NULL;
     dstBmp = &physDevDst->physBitmap;
     
-    /* gets pattern color, in case it's needed */
+    /* gets pattern color, in case it's needed
+       it's NOT the COLORREF value (colors are swapped
+       NOR the pixel value (it's applied to a 32 BPP BI_RGB */
     if(usePat)
-        patColor = physDevDst->brushColor;
+        patColor = SwapColors(physDevDst->brushColorref);
     else
         patColor = 0;
 
diff --git a/dlls/winedib.drv/primitives_color.c b/dlls/winedib.drv/primitives_color.c
index 3ccc2e0..6c42b44 100644
--- a/dlls/winedib.drv/primitives_color.c
+++ b/dlls/winedib.drv/primitives_color.c
@@ -94,31 +94,30 @@ DWORD _DIBDRV_ColorToPixel16_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color)
            PutField16(b, dib->blueShift,  dib->blueLen);
 }
 
-DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color)
+/* gets nearest color to DIB palette color */
+DWORD _DIBDRV_GetNearestColor(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    RGBQUAD *c;
+
+    if(dib->bitCount > 8)
+        return color;
+        
+    c = dib->colorTable + _DIBDRV_GetNearestColorIndex(dib, color);
+    return RGB(c->rgbRed, c->rgbGreen, c->rgbBlue);
+
+}
+
+/* gets nearest color index in DIB palette of a given colorref */
+DWORD _DIBDRV_GetNearestColorIndex(const DIBDRVBITMAP *dib, COLORREF color)
 {
-    int i, best_index = 0;
     DWORD r, g, b;
+    int i, best_index = 0;
     DWORD diff, best_diff = 0xffffffff;
-
+    
     r = GetRValue(color);
     g = GetGValue(color);
     b = GetBValue(color);
     
-    /* just in case it's being called without color table
-       properly initialized */
-    if(!dib->colorTableGrabbed)
-        return 0;
-        
-    /* for monochrome bitmaps, color is background
-       if not matching foreground */
-    if(dib->colorTableSize == 2)
-    {
-        RGBQUAD *fore = dib->colorTable + 1;
-        if(r == fore->rgbRed && g == fore->rgbGreen && b == fore->rgbBlue)
-            return 1;
-        return 0;
-    }
-
     for(i = 0; i < dib->colorTableSize; i++)
     {
         RGBQUAD *cur = dib->colorTable + i;
@@ -140,3 +139,39 @@ DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color)
     }
     return best_index;
 }
+
+DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    DWORD r, g, b;
+
+    r = GetRValue(color);
+    g = GetGValue(color);
+    b = GetBValue(color);
+    
+    /* just in case it's being called without color table
+       properly initialized */
+    if(!dib->colorTableGrabbed)
+        return 0;
+        
+    /* for monochrome bitmaps, color is :
+           foreground if matching foreground ctable
+           else background if matching background ctable
+           else foreground ix 0xffffff
+           else background */
+    if(dib->colorTableSize == 2)
+    {
+        RGBQUAD *back = dib->colorTable;
+        RGBQUAD *fore = dib->colorTable + 1;
+        if(r == fore->rgbRed && g == fore->rgbGreen && b == fore->rgbBlue)
+            return 1;
+        else if(r == back->rgbRed && g == back->rgbGreen && b == back->rgbBlue)
+            return 0;
+        if((color & 0xffffff) == 0xffffff)
+            return 1;
+        else
+            return 0;
+    }
+    
+    /* otherwise looks for nearest color in palette */
+    return _DIBDRV_GetNearestColorIndex(dib, color);
+}
diff --git a/dlls/winedib.drv/primitives_convert.c b/dlls/winedib.drv/primitives_convert.c
index f8f87ce..24a5e77 100644
--- a/dlls/winedib.drv/primitives_convert.c
+++ b/dlls/winedib.drv/primitives_convert.c
@@ -31,6 +31,33 @@ static inline COLORREF SwapColors(DWORD c)
     
 }
 
+static inline DWORD PlaceField32(BYTE c, int shift, int len)
+{
+    DWORD res = c;
+    if(len < 8)
+        res >>= (8 - len);
+    else
+        res <<= (len - 8);
+    return res << shift;
+}
+
+static inline WORD PlaceField16(BYTE c, int shift, int len)
+{
+    WORD res = c;
+    if(len < 8)
+        res >>= (8 - len);
+    else
+        res <<= (len - 8);
+    return res << shift;
+}
+
+static inline BYTE GetField32(DWORD dwColor, int shift, int len)
+{
+    dwColor = dwColor & (((1 << (len)) - 1) << shift);
+    dwColor = dwColor << (32 - (shift + len)) >> 24;
+    return dwColor;
+}
+
 /* ----------------------------------------------------------------*/
 /*                         CONVERT PRIMITIVES                      */
 /* converts (part of) line of any DIB format from/to DIB32_RGB one */
@@ -63,7 +90,7 @@ BOOL _DIBDRV_GetLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int wi
 
 BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
 {
-    BYTE *bBuf = (BYTE *)buf;
+    DWORD *dwBuf = (DWORD *)buf;
     DWORD *src;
 
 #ifdef DIBDRV_CHECK_RANGES
@@ -85,10 +112,10 @@ BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx,
     src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
     for(; width ; width--)
     {
-        *bBuf++ = (*src & bmp->blueMask ) >> bmp->blueShift;
-        *bBuf++ = (*src & bmp->greenMask) >> bmp->greenShift;
-        *bBuf++ = (*src & bmp->redMask  ) >> bmp->redShift;
-        *bBuf++ = 0x0;
+        *dwBuf++ =
+            GetField32(*src, bmp->redShift  , bmp->redLen  ) << 16 |
+            GetField32(*src, bmp->greenShift, bmp->greenLen) <<  8 |
+            GetField32(*src, bmp->blueShift , bmp->blueLen );
         src++;
     }
     return TRUE;
@@ -184,6 +211,7 @@ BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx,
     for(; width ; width--)
     {
         b = *src++;
+
         *dwBuf++ =((( b & bmp->blueMask) >> bmp->blueShift ) << ( 8 - bmp->blueLen )) |
                   (((b & bmp->greenMask) >> bmp->greenShift) << (16 - bmp->greenLen)) |
                   (((b & bmp->redMask  ) >> bmp->redShift  ) << (24 - bmp->redLen  ));
@@ -350,14 +378,14 @@ BOOL _DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx,
 {
     DWORD *dwBuf = (DWORD *)buf;
     DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
-    DWORD c;
+    RGBQUAD *c;
     for(; width; width--)
     {
-        c = *dwBuf++;
+        c = (RGBQUAD *)dwBuf++;
         *dst++ =
-            ((( c & 0x000000ff)        << bmp->blueShift)  & bmp->blueMask) |
-            ((((c & 0x0000ff00) >>  8) << bmp->greenShift) & bmp->greenMask) |
-            ((((c & 0x00ff0000) >> 16) << bmp->redShift)   & bmp->redMask);
+            PlaceField32(c->rgbRed  , bmp->redShift  , bmp->redLen  ) |
+            PlaceField32(c->rgbGreen, bmp->greenShift, bmp->greenLen) |
+            PlaceField32(c->rgbBlue , bmp->blueShift , bmp->blueLen );
     }
     return TRUE;
 }
@@ -386,6 +414,7 @@ BOOL _DIBDRV_PutLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int wi
     {
         c = *dwBuf++;
         *dst++ =
+        /* 0RRR|RRGG|GGGB|BBBB */
             ((c & 0x000000f8) >> 3) |
             ((c & 0x0000f800) >> 6) |
             ((c & 0x00f80000) >> 9);
@@ -506,8 +535,9 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
     DWORD c;
 
     /* get foreground color */
+    DWORD back = *(DWORD *)bmp->colorTable       & 0x00ffffff;
     DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff;
-    
+
     /* put first partial byte, if any */
     startx &= 0x07;
     mask = 0x80 >> startx;
@@ -519,7 +549,11 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
         while(startx--)
         {
             c = *dwBuf++ & 0x00ffffff;
-            if(c == 0x00ffffff || c == fore)
+            if(c == fore)
+                b |= mask;
+            else if(c == back)
+                b &= !mask;
+            else if(c == 0x00ffffff)
                 b |= mask;
             else
                 b &= !mask;
@@ -536,7 +570,7 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
         for(i = 0 ; i < 8 ; i++)
         {
             c = *dwBuf++ & 0x00ffffff;
-            if(c == 0x00ffffff || c == fore)
+            if(c == fore || (c == 0x00ffffff && c != back))
                 b |= mask;
             mask >>= 1;
         }
@@ -551,7 +585,11 @@ BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width,
         while(width--)
         {
             c = *dwBuf++ & 0x00ffffff;
-            if(c == 0x00ffffff || c == fore)
+            if(c == fore)
+                b |= mask;
+            else if(c == back)
+                b &= !mask;
+            else if(c == 0x00ffffff)
                 b |= mask;
             else
                 b &= !mask;
diff --git a/dlls/winedib.drv/primitives_pixel.c b/dlls/winedib.drv/primitives_pixel.c
index ca68cf1..78e68c7 100644
--- a/dlls/winedib.drv/primitives_pixel.c
+++ b/dlls/winedib.drv/primitives_pixel.c
@@ -25,24 +25,15 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
-
 /* ------------------------------------------------------------*/
 /*                     BITFIELD HELPERS                        */
-static DWORD GetField32 (DWORD pixel, int shift, int len)
+static inline DWORD GetField32 (DWORD pixel, int shift, int len)
 {
     pixel = pixel & (((1 << (len)) - 1) << shift);
     pixel = pixel << (32 - (shift + len)) >> 24;
     return pixel;
 }
 
-static WORD GetField16 (WORD pixel, int shift, int len)
-{
-    FIXME("TODO\n");
-    return 0;
-}
-
-
-
 /* ------------------------------------------------------------*/
 /*                     PIXEL POINTER READING                   */
 void *_DIBDRV_GetPixelPointer32(const DIBDRVBITMAP *dib, int x, int y)
@@ -174,45 +165,50 @@ void _DIBDRV_SetPixel1(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
 /*                     PIXEL READING                           */
 DWORD _DIBDRV_GetPixel32_RGB(const DIBDRVBITMAP *dib, int x, int y)
 {
-    DWORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
-    return *ptr;
+    DWORD c = *(DWORD *)dib->funcs->GetPixelPointer(dib, x, y);
+    return
+        ((c & 0x000000ff) << 16) |
+        ((c & 0x0000ff00)      ) |
+        ((c & 0x00ff0000) >> 16) |
+        ( c & 0xff000000       );   /* last one for alpha channel */
 }
 
 DWORD _DIBDRV_GetPixel32_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y)
 {
     DWORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
 
-    return GetField32(*ptr, dib->redShift,   dib->redLen)   << 16 |
+    return GetField32(*ptr, dib->redShift,   dib->redLen)         |
            GetField32(*ptr, dib->greenShift, dib->greenLen) <<  8 |
-           GetField32(*ptr, dib->blueShift,  dib->blueLen);
+           GetField32(*ptr, dib->blueShift,  dib->blueLen)  << 16;
 }
 
 DWORD _DIBDRV_GetPixel24(const DIBDRVBITMAP *dib, int x, int y)
 {
     BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y);
-    return (ptr[0] << 16) | (ptr[1] << 8) | ptr[2];
+    return ((WORD)ptr[0] << 16) | ((WORD)ptr[1] << 8) | (WORD)ptr[2];
 }
 
 DWORD _DIBDRV_GetPixel16_RGB(const DIBDRVBITMAP *dib, int x, int y)
 {
-    WORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
-    return ((*ptr & 0x7c00) << 9) | ((*ptr & 0x03e0) << 6) | ((*ptr & 0x001f) << 3);
+    WORD c = *(WORD *)dib->funcs->GetPixelPointer(dib, x, y);
+   /* 0RRR|RRGG|GGGB|BBBB */
+   return ((c & 0x7c00) >> 7) | ((c & 0x03e0) << 6) | ((c & 0x001f) << 19);
 }
 
 DWORD _DIBDRV_GetPixel16_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y)
 {
-    WORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    WORD c = *(WORD *)dib->funcs->GetPixelPointer(dib, x, y);
 
-    return GetField16(*ptr, dib->redShift,   dib->redLen)   << 16 |
-           GetField16(*ptr, dib->greenShift, dib->greenLen) <<  8 |
-           GetField16(*ptr, dib->blueShift,  dib->blueLen);
+    return (((c & dib->blueMask ) >> dib->blueShift ) << (24 - dib->blueLen )) |
+           (((c & dib->greenMask) >> dib->greenShift) << (16 - dib->greenLen)) |
+           (((c & dib->redMask  ) >> dib->redShift  ) << ( 8 - dib->redLen  ));
 }
 
 DWORD _DIBDRV_GetPixel8(const DIBDRVBITMAP *dib, int x, int y)
 {
     BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y);
     RGBQUAD *color = dib->colorTable + *ptr;
-    return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue;
+    return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16);
 }
 
 DWORD _DIBDRV_GetPixel4(const DIBDRVBITMAP *dib, int x, int y)
@@ -226,7 +222,7 @@ DWORD _DIBDRV_GetPixel4(const DIBDRVBITMAP *dib, int x, int y)
         pix = *ptr >> 4;
 
     color = dib->colorTable + pix;
-    return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue;
+    return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16);
 }
 
 DWORD _DIBDRV_GetPixel1(const DIBDRVBITMAP *dib, int x, int y)
@@ -240,5 +236,5 @@ DWORD _DIBDRV_GetPixel1(const DIBDRVBITMAP *dib, int x, int y)
     pix &= 1;
 
     color = dib->colorTable + pix;
-    return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue;
+    return (color->rgbRed) | (color->rgbGreen << 8) | (color->rgbBlue << 16);
 }