DIB Engine: implement most engine functions

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


---

 dlls/winedib.drv/Makefile.in          |   12 
 dlls/winedib.drv/bitblt.c             |  525 ++++++++++++++--
 dlls/winedib.drv/bitmap.c             |   49 +-
 dlls/winedib.drv/clipping.c           |    6 
 dlls/winedib.drv/convert.c            |  309 +++++++++
 dlls/winedib.drv/dc.c                 |  280 ++++++++-
 dlls/winedib.drv/dib.c                |   24 -
 dlls/winedib.drv/dibdrv.h             |  292 +++++++++
 dlls/winedib.drv/dibdrv_gdi32.h       |  168 +++++
 dlls/winedib.drv/dibdrv_main.c        |   11 
 dlls/winedib.drv/dibdrvbitmap.c       |  650 ++++++++++++++++++++
 dlls/winedib.drv/driver.c             |  254 ++++++++
 dlls/winedib.drv/font.c               |  116 +++-
 dlls/winedib.drv/freetype.c           |  136 ++++
 dlls/winedib.drv/freetype.h           |  186 ++++++
 dlls/winedib.drv/graphics.c           |  264 +++++---
 dlls/winedib.drv/opengl.c             |   32 -
 dlls/winedib.drv/palette.c            |   51 +-
 dlls/winedib.drv/pen_brush.c          |  492 ++++++++++++++-
 dlls/winedib.drv/primitives.c         |  274 ++++++++
 dlls/winedib.drv/primitives_bitblt.c  | 1075 +++++++++++++++++++++++++++++++++
 dlls/winedib.drv/primitives_color.c   |  142 ++++
 dlls/winedib.drv/primitives_convert.c |  559 +++++++++++++++++
 dlls/winedib.drv/primitives_font.c    |  310 ++++++++++
 dlls/winedib.drv/primitives_line.c    |  434 +++++++++++++
 dlls/winedib.drv/primitives_pixel.c   |  244 +++++++
 dlls/winedib.drv/primitives_rop2.c    |  112 +++
 dlls/winedib.drv/primitives_rop3.c    |  786 ++++++++++++++++++++++++
 dlls/winedib.drv/text.c               |  179 +++++
 dlls/winedib.drv/video.c              |    8 
 30 files changed, 7706 insertions(+), 274 deletions(-)
 create mode 100644 dlls/winedib.drv/convert.c
 create mode 100644 dlls/winedib.drv/dibdrv_gdi32.h
 create mode 100644 dlls/winedib.drv/dibdrvbitmap.c
 create mode 100644 dlls/winedib.drv/driver.c
 create mode 100644 dlls/winedib.drv/freetype.c
 create mode 100644 dlls/winedib.drv/freetype.h
 create mode 100644 dlls/winedib.drv/primitives.c
 create mode 100644 dlls/winedib.drv/primitives_bitblt.c
 create mode 100644 dlls/winedib.drv/primitives_color.c
 create mode 100644 dlls/winedib.drv/primitives_convert.c
 create mode 100644 dlls/winedib.drv/primitives_font.c
 create mode 100644 dlls/winedib.drv/primitives_line.c
 create mode 100644 dlls/winedib.drv/primitives_pixel.c
 create mode 100644 dlls/winedib.drv/primitives_rop2.c
 create mode 100644 dlls/winedib.drv/primitives_rop3.c


diff --git a/dlls/winedib.drv/Makefile.in b/dlls/winedib.drv/Makefile.in
index 66ad14f..722785e 100644
--- a/dlls/winedib.drv/Makefile.in
+++ b/dlls/winedib.drv/Makefile.in
@@ -11,15 +11,27 @@ C_SRCS = \
     bitblt.c \
     bitmap.c \
     clipping.c \
+    convert.c \
     dc.c \
     dib.c \
     dibdrv_main.c \
+    dibdrvbitmap.c \
     driver.c \
     font.c \
+    freetype.c \
     graphics.c \
     opengl.c \
     palette.c \
     pen_brush.c \
+    primitives.c \
+    primitives_bitblt.c \
+    primitives_color.c \
+    primitives_convert.c \
+    primitives_font.c \
+    primitives_line.c \
+    primitives_pixel.c \
+    primitives_rop2.c \
+    primitives_rop3.c \
     text.c \
     video.c
 
diff --git a/dlls/winedib.drv/bitblt.c b/dlls/winedib.drv/bitblt.c
index 022f223..20cdcaa 100644
--- a/dlls/winedib.drv/bitblt.c
+++ b/dlls/winedib.drv/bitblt.c
@@ -25,6 +25,117 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+static inline void intSwap(int *a, int *b)
+{
+    int tmp;
+    tmp = *a;
+    *a = *b;
+    *b = tmp;
+}
+
+/* clips a source and destination areas to their respective clip rectangles
+   returning both source and dest modified; result is TRUE if clipping
+   leads to a non null rectangle, FALSE otherwise */
+static BOOL BitBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *sz, RECT*srcClip, RECT*dstClip)
+{
+    int xs1, ys1, xs2, ys2;
+    int xsc1, ysc1, xsc2, ysc2;
+    int xd1, yd1, xd2, yd2;
+    int xdc1, ydc1, xdc2, ydc2;
+    int w, h, dx, dy;
+    
+    /* extract sizes */
+    w = sz->cx; h = sz->cy;
+    
+    /* if sizes null or negative, just return false */
+    if(w <= 0 || h <= 0)
+        return FALSE;
+        
+    /* extract dest area data */
+    xd1 = pd->x;
+    yd1 = pd->y;
+    xd2 = xd1 + w;
+    yd2 = yd1 + h;
+    
+    /* extract source data */
+    xs1 = ps->x;
+    ys1 = ps->y;
+    xs2 = xs1 + w;
+    ys2 = ys1 + h;
+        
+    /* if source clip area is not null, do first clipping on it */
+    if(srcClip)
+    {
+        /* extract source clipping area */
+        xsc1 = srcClip->left;
+        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);
+        
+        /* clip on source clipping start point */
+        if(xs1 < xsc1) { dx = xsc1 - xs1; w -= dx; xd1 += dx; xs1 = xsc1; }
+        if(ys1 < ysc1) { dy = ysc1 - ys1; h -= dy; yd1 += dy; ys1 = ysc1; }
+        
+        /* 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 */
+        xdc1 = dstClip->left;
+        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);
+            
+        /* clip on dest clipping start point */
+        if(xd1 < xdc1) { dx = xdc1 - xd1; w -= dx; xs1 += dx; xd1 = xdc1; }
+        if(yd1 < ydc1) { dy = ydc1 - yd1; h -= dy; ys1 += dy; yd1 = ydc1; }
+        
+        /* clip on dest clipping end point */
+        if(xd2 > xdc2) { dx = xd2 - xdc2; w -= dx; xs2 -= dx; xd2 = xdc2; }
+        if(yd2 > ydc2) { dy = yd2 - ydc2; h -= dy; ys2 -= dy; yd2 = ydc2; }
+        
+        /* if already zero area, return false */
+        if(w <= 0 || h <= 0)
+            return FALSE;
+    }
+        
+    /* sets clipped/translated points and sizes and returns TRUE */
+    ps->x = xs1; ps->y = ys1;
+    pd->x = xd1; pd->y = yd1;
+    sz->cx = w; sz->cy = h;
+    
+    return TRUE;
+        
+}
+
+
+/* clips a source and destination areas to their respective clip rectangles
+   returning both source and dest modified; result is TRUE if clipping
+   leads to a non null rectangle, FALSE otherwise */
+static BOOL StretchBlt_ClipAreas(POINT *ps, POINT *pd, SIZE *szSrc, SIZE *szDst, RECT*srcClip, RECT*dstClip)
+{
+    ONCE(FIXME("TO DO\n"));
+
+    return TRUE;
+
+}
+
 /***********************************************************************
  *           DIBDRV_AlphaBlend
  */
@@ -34,16 +145,17 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
 {
     BOOL res;
     
-    TRACE("physDevDst:%p, xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p, xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d\n",
-          physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, 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) : "",
+          xDst, yDst, widthDst, heightDst,
+          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          xSrc, ySrc, widthSrc, heightSrc));
 
     if(physDevDst->hasDIB && physDevSrc->hasDIB)
     {
         /* DIB section selected in both source and dest DC, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res =  _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
-                                                   physDevSrc->X11PhysDev, xSrc, ySrc, widthSrc, heightSrc,
-                                                   blendfn);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else if(!physDevDst->hasDIB && !physDevSrc->hasDIB)
     {
@@ -63,10 +175,8 @@ BOOL DIBDRV_AlphaBlend( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst, INT width
     else /* if(physDevDst->hasDIB) */
     {
         /* DDB on source, DIB on dest -- must convert source DDB to DIB and use the engine for blit */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res =  _DIBDRV_GetDisplayDriver()->pAlphaBlend(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
-                                                   physDevSrc->X11PhysDev, xSrc, ySrc, widthSrc, heightSrc,
-                                                   blendfn);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE; 
     }
     return res;
 }
@@ -80,35 +190,171 @@ BOOL DIBDRV_BitBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
 {
     BOOL res;
     
-    TRACE("physDevDst:%p, xDst:%d, yDst:%d, width:%d, height:%d, physDevSrc:%p, xSrc:%d, ySrc:%d, rop:%08x\n",
-          physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
+    /* clip blit area */
+    POINT pd = {xDst, yDst};
+    POINT ps = {xSrc, ySrc};
+    SIZE sz = {width, height};
 
-    if(physDevDst->hasDIB && physDevSrc->hasDIB)
-    {
-        /* DIB section selected in both source and dest DC, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
-                                                      physDevSrc->X11PhysDev, xSrc, ySrc, rop);
-    }
-    else if(!physDevDst->hasDIB && !physDevSrc->hasDIB)
-    {
-        /* DDB selected in noth source and dest DC, use X11 driver */
-        res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
-                                                   physDevSrc->X11PhysDev, xSrc, ySrc, rop);
-    }
-    else if(physDevSrc->hasDIB)
+    MAYBE(TRACE("physDevDst:%p(%s%s), xDst:%d, yDst:%d, width:%d, height:%d, physDevSrc:%p(%s%s), xSrc:%d, ySrc:%d, rop:%08x\n",
+          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
+          xDst, yDst, width, height,
+          physDevSrc, physDevSrc ? (physDevSrc->hasDIB ? "DIB-" : "DDB"): "---", physDevSrc && physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          xSrc, ySrc, rop));
+
+    if(physDevDst->hasDIB)
     {
-        /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
-                                                   physDevSrc->X11PhysDev, xSrc, ySrc, rop);
+        /* DIB section selected in dest DC, use DIB Engine */
+
+        /* clip blit area */
+        RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
+        
+        if(!physDevSrc || physDevSrc->hasDIB)
+        {
+            /* clip blit area */
+            if(physDevSrc)
+            {
+                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, &dstClip);
+            }
+            else
+                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;
+
+            /* source is null or has a DIB, no need to convert anyting */
+            res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height, physDevSrc, xSrc, ySrc, rop);
+        }
+        else
+        {
+            /* source is a DDB, must convert it to DIB */
+
+            /* don't clip on source */            
+            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;
+
+            /* we must differentiate from 2 cases :
+               1) source DC is a memory DC
+               2) source DC is a device DC */
+            if(GetObjectType(physDevSrc->hdc) == OBJ_MEMDC)
+            {
+                /* memory DC */
+                HBITMAP dib, ddb;
+
+                ddb = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
+                if(!ddb)
+                {
+                    ERR("Couldn't select out DDB from source HDC\n");
+                    res = 0;
+                    goto noBlt1;
+                }
+                dib = _DIBDRV_ConvertDDBtoDIB(physDevSrc->hdc, ddb, ySrc, height);
+                if(!dib)
+                {
+                    ERR("Failed converting source DDB to DIB\n");
+                    SelectObject(physDevSrc->hdc, ddb);
+                    res = 0;
+                    goto noBlt1;
+                }
+                SelectObject(physDevSrc->hdc, dib);
+                res = physDevDst->physBitmap.funcs->BitBlt(physDevDst, xDst, yDst, width, height,
+                                                           physDevSrc, xSrc, 0, rop);
+                SelectObject(physDevSrc->hdc, ddb);
+                DeleteObject(dib);
+    noBlt1:
+                ;
+            }
+            else
+            {
+                /* device DC */
+                HBITMAP dib, stock;
+                HDC memHdc;
+
+                dib = _DIBDRV_ConvertDevDDBtoDIB(physDevSrc->hdc, physDevDst->hdc, xSrc, ySrc, width, height);
+                if(!dib)
+                {
+                    ERR("Failed converting source DDB tp DIB for device DC\n");
+                    res = 0;
+                    goto noBlt2;
+                }
+                memHdc = CreateCompatibleDC(physDevDst->hdc);
+                if(!memHdc)
+                {
+                    ERR("Failed creating temporary memory DC\n");
+                    DeleteObject(dib);
+                    res = 0;
+                    goto noBlt2;
+                }
+                stock = SelectObject(memHdc, dib);
+                if(!stock)
+                {
+                    ERR("Failed selecting converted DIB into temporary memory DC\n");
+                    DeleteObject(dib);
+                    DeleteDC(memHdc);
+                    res = 0;
+                    goto noBlt2;
+                }
+                res = BitBlt(physDevDst->hdc, xDst, yDst, width, height, memHdc, 0, 0, rop);
+
+                SelectObject(memHdc, stock);
+                DeleteObject(dib);
+                DeleteDC(memHdc);
+    noBlt2:
+                ;
+            }
+        }
     }
-    else /* if(physDevDst->hasDIB) */
+    else /* dest is a DDB */
     {
-        /* DDB on source, DIB on dest -- must convert source DDB to DIB and use the engine for blit */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
-                                                   physDevSrc->X11PhysDev, xSrc, ySrc, rop);
+        /* DDB selected on dest DC, use X11 Driver */
+        if(!physDevSrc || !physDevSrc->hasDIB)
+        {
+            /* source is null or has also a DDB, no need to convert anything */
+            res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
+                                                      physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, ySrc, rop);
+        }
+        else
+        {
+            /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
+            HBITMAP dib, ddb;
+
+            /* clip blit area */
+            if(physDevSrc)
+            {
+                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                res = BitBlt_ClipAreas(&ps, &pd, &sz, &srcClip, 0);
+            }
+            else
+                res = TRUE;
+            if(!res)
+                goto noBlt3;
+            xDst = pd.x; yDst = pd.y; width = sz.cx; height = sz.cy; xSrc = ps.x; ySrc = ps.y;
+
+            dib = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
+            if(!dib)
+            {
+                ERR("Couldn't select out DIB from source HDC\n");
+                res = 0;
+                goto noBlt3;
+            }
+            ddb = _DIBDRV_ConvertDIBtoDDB(physDevSrc->hdc, dib, ySrc, height);
+            if(!ddb)
+            {
+                ERR("Failed converting source DIB to DDB\n");
+                SelectObject(physDevSrc->hdc, dib);
+                res = 0;
+                goto noBlt3;
+            }
+            SelectObject(physDevSrc->hdc, ddb);
+            res = _DIBDRV_GetDisplayDriver()->pBitBlt(physDevDst->X11PhysDev, xDst, yDst, width, height,
+                                                      physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, 0, rop);
+            SelectObject(physDevSrc->hdc, dib);
+            DeleteObject(ddb);
+noBlt3:
+            ;
+        }
     }
     return res;
 }
@@ -123,35 +369,186 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
 {
     BOOL res;
     
-    TRACE("physDevDst:%p, xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, physDevSrc:%p, xSrc:%d, ySrc:%d, widthSrc:%d, heightSrc:%d, rop:%8x\n",
-          physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
+    /* clip blit area */
+    POINT pd = {xDst, yDst};
+    POINT ps = {xSrc, ySrc};
+    SIZE szDst = {widthDst, heightDst};
+    SIZE szSrc = {widthSrc, heightSrc};
 
-    if(physDevDst->hasDIB && physDevSrc->hasDIB)
-    {
-        /* DIB section selected in both source and dest DC, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res =  _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthSrc, heightSrc,
-                                                          physDevSrc->X11PhysDev, xSrc, ySrc, widthDst, heightDst, rop);
-    }
-    else if(!physDevDst->hasDIB && !physDevSrc->hasDIB)
-    {
-        /* DDB selected in noth source and dest DC, use X11 driver */
-        res =  _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthSrc, heightSrc,
-                                                       physDevSrc->X11PhysDev, xSrc, ySrc, widthDst, heightDst, rop);
-    }
-    else if(physDevSrc->hasDIB)
+    /* if source and dest sizes match, just call BitBlt(), it's faster */
+    if(!physDevSrc || (widthDst == widthSrc && heightDst == heightSrc))
+        return DIBDRV_BitBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, rop);
+
+    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, rop:%08x\n",
+          physDevDst, physDevDst->hasDIB ? "DIB-" : "DDB", physDevDst->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevDst->physBitmap) : "",
+          xDst, yDst, widthDst, heightDst,
+          physDevSrc, physDevSrc->hasDIB ? "DIB-" : "DDB", physDevSrc->hasDIB ? _DIBDRVBITMAP_GetFormatName(&physDevSrc->physBitmap) : "",
+          xSrc, ySrc, widthSrc, heightSrc, rop));
+
+    if(physDevDst->hasDIB)
     {
-        /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res =  _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthSrc, heightSrc,
-                                                          physDevSrc->X11PhysDev, xSrc, ySrc, widthDst, heightDst, rop);
+        /* DIB section selected in dest DC, use DIB Engine */
+
+        /* clip blit area */
+        RECT dstClip = {0, 0, physDevDst->physBitmap.width, physDevDst->physBitmap.height};
+        
+        if(!physDevSrc || physDevSrc->hasDIB)
+        {
+            /* clip blit area */
+            if(physDevSrc)
+            {
+                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, &dstClip);
+            }
+            else
+                res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+            if(!res)
+                goto noBlt2;
+            xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy; 
+            xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+            /* source is null or has a DIB, no need to convert anyting */
+            res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst, physDevSrc, xSrc, ySrc, widthSrc, heightSrc, rop);
+        }
+        else
+        {
+            /* source is a DDB, must convert it to DIB */
+
+            /* don't clip on source */            
+            res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, 0, &dstClip);
+            if(!res)
+                goto noBlt2;
+            xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy; 
+            xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+            /* we must differentiate from 2 cases :
+               1) source DC is a memory DC
+               2) source DC is a device DC */
+            if(GetObjectType(physDevSrc->hdc) == OBJ_MEMDC)
+            {
+                /* memory DC */
+                HBITMAP dib, ddb;
+
+                ddb = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
+                if(!ddb)
+                {
+                    ERR("Couldn't select out DDB from source HDC\n");
+                    res = 0;
+                    goto noBlt1;
+                }
+                dib = _DIBDRV_ConvertDDBtoDIB(physDevSrc->hdc, ddb, ySrc, heightSrc);
+                if(!dib)
+                {
+                    ERR("Failed converting source DDB to DIB\n");
+                    SelectObject(physDevSrc->hdc, ddb);
+                    res = 0;
+                    goto noBlt1;
+                }
+                SelectObject(physDevSrc->hdc, dib);
+                res = physDevDst->physBitmap.funcs->StretchBlt(physDevDst, xDst, yDst, widthDst, heightDst,
+                                                           physDevSrc, xSrc, 0, widthSrc, heightSrc, rop);
+                SelectObject(physDevSrc->hdc, ddb);
+                DeleteObject(dib);
+    noBlt1:
+                ;
+            }
+            else
+            {
+                /* device DC */
+                HBITMAP dib, stock;
+                HDC memHdc;
+
+                dib = _DIBDRV_ConvertDevDDBtoDIB(physDevSrc->hdc, physDevDst->hdc, xSrc, ySrc, widthSrc, heightSrc);
+                if(!dib)
+                {
+                    ERR("Failed converting source DDB tp DIB for device DC\n");
+                    res = 0;
+                    goto noBlt2;
+                }
+                memHdc = CreateCompatibleDC(physDevDst->hdc);
+                if(!memHdc)
+                {
+                    ERR("Failed creating temporary memory DC\n");
+                    DeleteObject(dib);
+                    res = 0;
+                    goto noBlt2;
+                }
+                stock = SelectObject(memHdc, dib);
+                if(!stock)
+                {
+                    ERR("Failed selecting converted DIB into temporary memory DC\n");
+                    DeleteObject(dib);
+                    DeleteDC(memHdc);
+                    res = 0;
+                    goto noBlt2;
+                }
+                res = StretchBlt(physDevDst->hdc, xDst, yDst, widthDst, heightDst, memHdc, 0, 0, widthSrc, widthDst, rop);
+
+                SelectObject(memHdc, stock);
+                DeleteObject(dib);
+                DeleteDC(memHdc);
+    noBlt2:
+                ;
+            }
+        }
     }
-    else /* if(physDevDst->hasDIB) */
+    else /* dest is a DDB */
     {
-        /* DDB on source, DIB on dest -- must convert source DDB to DIB and use the engine for blit */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res =  _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthSrc, heightSrc,
-                                                          physDevSrc->X11PhysDev, xSrc, ySrc, widthDst, heightDst, rop);
+        /* DDB selected on dest DC, use X11 Driver */
+        if(!physDevSrc || !physDevSrc->hasDIB)
+        {
+            /* source is null or has also a DDB, no need to convert anything */
+            res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
+                                                      physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, ySrc, widthSrc, heightSrc, rop);
+        }
+        else
+        {
+            /* DIB on source, DDB on dest -- must convert source DIB to DDB and use X11 driver for blit */
+            HBITMAP dib, ddb;
+            
+            /* clip blit area */
+            if(physDevSrc)
+            {
+                RECT srcClip = {0, 0, physDevSrc->physBitmap.width, physDevSrc->physBitmap.height};
+                res = StretchBlt_ClipAreas(&ps, &pd, &szSrc, &szDst, &srcClip, 0);
+            }
+            else
+                res = TRUE;
+            if(!res)
+                goto noBlt3;
+            xDst = pd.x; yDst = pd.y; widthDst = szDst.cx; heightDst = szDst.cy; 
+            xSrc = ps.x; ySrc = ps.y; widthSrc = szSrc.cx; heightSrc = szSrc.cy;
+
+            dib = SelectObject(physDevSrc->hdc, GetStockObject(DEFAULT_BITMAP));
+            if(!dib)
+            {
+                ERR("Couldn't select out DIB from source HDC\n");
+                res = 0;
+                goto noBlt3;
+            }
+            ddb = _DIBDRV_ConvertDIBtoDDB(physDevSrc->hdc, dib, ySrc, heightSrc);
+            if(!ddb)
+            {
+                ERR("Failed converting source DIB to DDB\n");
+                SelectObject(physDevSrc->hdc, dib);
+                res = 0;
+                goto noBlt3;
+            }
+            if(!SelectObject(physDevSrc->hdc, ddb))
+            {
+                ERR("Failed to select converted DDB into source HDC\n");
+                SelectObject(physDevSrc->hdc, dib);
+                DeleteObject(ddb);
+                res = 0;
+                goto noBlt3;
+            }
+            res = _DIBDRV_GetDisplayDriver()->pStretchBlt(physDevDst->X11PhysDev, xDst, yDst, widthDst, heightDst,
+                                                      physDevSrc ? physDevSrc->X11PhysDev : 0, xSrc, 0, widthSrc, heightSrc, rop);
+            SelectObject(physDevSrc->hdc, dib);
+            DeleteObject(ddb);
+noBlt3:
+            ;
+        }
     }
     return res;
 }
@@ -162,14 +559,14 @@ BOOL DIBDRV_StretchBlt( DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
 BOOL DIBDRV_PatBlt( DIBDRVPHYSDEV *physDev, INT left, INT top, INT width, INT height, DWORD rop )
 {
     BOOL res;
-    
-    TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev, left, top, width, height, rop);
+
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, width:%d, height:%d, rop:%06x\n", physDev, left, top, width, height, rop));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPatBlt(physDev->X11PhysDev, left, top, width, height, rop);
+        ONCE(FIXME("TEMPORARY - use BitBlt by now\n"));
+        res = DIBDRV_BitBlt(physDev, left, top, width, height, NULL, 0, 0, rop);
     }
     else
     {
diff --git a/dlls/winedib.drv/bitmap.c b/dlls/winedib.drv/bitmap.c
index df7c03a..f3d3b9c 100644
--- a/dlls/winedib.drv/bitmap.c
+++ b/dlls/winedib.drv/bitmap.c
@@ -34,12 +34,12 @@ HBITMAP DIBDRV_SelectBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap )
     DIBSECTION dibSection;
     HBITMAP res;
     
-    TRACE("physDev:%p, hbitmap:%p\n", physDev, hbitmap);
-
     /* try to get the DIBSECTION data from the bitmap */
     if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) == sizeof(BITMAP))
     {
         /* not a DIB section, sets it on physDev and use X11 behaviour */
+
+        MAYBE(TRACE("physDev:%p, hbitmap:%p\n", physDev, hbitmap));
         physDev->hasDIB = FALSE;
         res = _DIBDRV_GetDisplayDriver()->pSelectBitmap(physDev->X11PhysDev, hbitmap);
         if(res)
@@ -48,11 +48,30 @@ HBITMAP DIBDRV_SelectBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap )
     else
     {
         /* it's a DIB section, sets it on physDev and use DIB Engine behaviour */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        physDev->hasDIB = TRUE;
-        res = _DIBDRV_GetDisplayDriver()->pSelectBitmap(physDev->X11PhysDev, hbitmap);
-        if(res)
+        
+        MAYBE(TRACE("physDev:%p, hbitmap:%p, physBitmap=%p\n", physDev, hbitmap, &physDev->physBitmap));
+
+        /* frees any previously physical bitmap */
+        _DIBDRVBITMAP_Free(&physDev->physBitmap);
+
+        /* WARNING : the color table can't be grabbed here, since it's still
+           not initialized. It'll be grabbed on RealizeDefaultPalette(),
+           which is presumably the first call made after palette initialization.
+           So, by now we just set up palette size and leave NULL the palette pointer */
+        if(_DIBDRVBITMAP_InitFromBMIH(&physDev->physBitmap, &dibSection.dsBmih, dibSection.dsBitfields, NULL, dibSection.dsBm.bmBits))
+        {
+            /* stores the active bitmap */
+            res = physDev->hbitmap;
             physDev->hbitmap = hbitmap;
+            
+            /* remember there's a DIB selected in */
+            physDev->hasDIB = TRUE;
+        }
+        else
+        {
+            ERR("Failed to initialize physical bitmap\n");
+            res = 0;
+        }
     }
     return res;
     
@@ -66,7 +85,7 @@ BOOL DIBDRV_CreateBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, LPVOID bmBits
     DIBSECTION dibSection;
     BOOL res;
     
-    TRACE("physDev:%p, hbitmap:%p, bmBits:%p\n", physDev, hbitmap, bmBits);
+    MAYBE(TRACE("physDev:%p, hbitmap:%p, bmBits:%p\n", physDev, hbitmap, bmBits));
 
     /* try to get the DIBSECTION data from the bitmap */
     if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) == sizeof(BITMAP))
@@ -76,9 +95,9 @@ BOOL DIBDRV_CreateBitmap( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, LPVOID bmBits
     }
     else
     {
-        /* it's a DIB section, use DIB Engine behaviour */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pCreateBitmap(physDev->X11PhysDev, hbitmap, bmBits);
+        /* it's a DIB section, use DIB Engine behaviour - should not happen, but.... */
+        ONCE(FIXME("CreateBitmap() called for a DIB section - shouldn't happen\n"));
+        res = TRUE;
     }
     return res;
 }
@@ -91,7 +110,7 @@ BOOL DIBDRV_DeleteBitmap( HBITMAP hbitmap )
     DIBSECTION dibSection;
     BOOL res;
     
-    TRACE("hbitmap:%p\n", hbitmap);
+    MAYBE(TRACE("hbitmap:%p\n", hbitmap));
 
     /* try to get the DIBSECTION data from the bitmap */
     if(GetObjectW(hbitmap, sizeof(DIBSECTION), &dibSection) == sizeof(BITMAP))
@@ -102,8 +121,8 @@ BOOL DIBDRV_DeleteBitmap( HBITMAP hbitmap )
     else
     {
         /* it's a DIB section, use DIB Engine behaviour */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pDeleteBitmap(hbitmap);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     return res;
 }
@@ -115,7 +134,7 @@ LONG DIBDRV_GetBitmapBits( HBITMAP hbitmap, void *buffer, LONG count )
 {
     LONG res;
     
-    TRACE("hbitmap:%p, buffer:%p, count:%d\n", hbitmap, buffer, count);
+    MAYBE(TRACE("hbitmap:%p, buffer:%p, count:%d\n", hbitmap, buffer, count));
 
     /* GetBitmapBits is only valid for DDBs, so use X11 driver */
     res =  _DIBDRV_GetDisplayDriver()->pGetBitmapBits(hbitmap, buffer, count);
@@ -130,7 +149,7 @@ LONG DIBDRV_SetBitmapBits( HBITMAP hbitmap, const void *bits, LONG count )
 {
     LONG res;
     
-    TRACE("hbitmap:%p, bits:%p, count:%d\n", hbitmap, bits, count);
+    MAYBE(TRACE("hbitmap:%p, bits:%p, count:%d\n", hbitmap, bits, count));
 
     /* SetBitmapBits is only valid for DDBs, so use X11 driver */
     res = _DIBDRV_GetDisplayDriver()->pSetBitmapBits(hbitmap, bits, count);
diff --git a/dlls/winedib.drv/clipping.c b/dlls/winedib.drv/clipping.c
index 1ddbb1b..81dec25 100644
--- a/dlls/winedib.drv/clipping.c
+++ b/dlls/winedib.drv/clipping.c
@@ -25,18 +25,18 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+
 /***********************************************************************
  *           DIBDRV_SetDeviceClipping
  */
 void DIBDRV_SetDeviceClipping( DIBDRVPHYSDEV *physDev, HRGN vis_rgn, HRGN clip_rgn )
 {
-    TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn);
+    MAYBE(TRACE("physDev:%p, vis_rgn:%p, clip_rgn:%p\n", physDev, vis_rgn, clip_rgn));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        _DIBDRV_GetDisplayDriver()->pSetDeviceClipping(physDev->X11PhysDev, vis_rgn, clip_rgn);
+        ONCE(FIXME("STUB\n"));
     }
     else
     {
diff --git a/dlls/winedib.drv/convert.c b/dlls/winedib.drv/convert.c
new file mode 100644
index 0000000..dc18e14
--- /dev/null
+++ b/dlls/winedib.drv/convert.c
@@ -0,0 +1,309 @@
+/*
+ * DIB Engine conversion routines
+ * Converts DDB <--> DIB
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+#include "winuser.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/***********************************************************************
+ * Creates DDB that is compatible with source hdc.
+ * hdc is the HDC on where the DIB MUST be selected in
+ * srcBmp is the source DIB
+ * startScan and scanLines specify the portion of DIB to convert
+ * in order to avoid unneeded conversion of large DIBs on blitting
+ * 
+ * NOTE : the srcBmp DIB MUST NOT be selected in any DC */
+HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int scanLines )
+{
+    DIBSECTION ds;
+    BITMAPINFO *bmi;
+    HBITMAP hBmp = NULL;
+    
+    int dibWidth, dibHeight;
+    BOOL topDown;
+    void *bits;
+    int stride;
+    UINT colorUsed;
+    int bitFields;
+    HDC tmpHdc;
+    HBITMAP tmpBmp;
+    int res;
+    
+    /* gets DIBSECTION data from source DIB */
+    if(GetObjectW(srcBmp, sizeof(DIBSECTION), &ds) != sizeof(DIBSECTION))
+    {
+        ERR("Couldn't get DIBSECTION data\n");
+        return 0;
+    }
+
+    /* gets DIB info */
+    dibWidth  = ds.dsBmih.biWidth;
+    dibHeight = ds.dsBmih.biHeight;
+    bits = ds.dsBm.bmBits;
+    stride = ((dibWidth * ds.dsBmih.biBitCount +31) &~31) / 8;
+    
+    /* adjust bits to point at needed starting stripe */
+    if(dibHeight < 0)
+    {
+        /* top-down DIB */
+        topDown = TRUE;
+        dibHeight = -dibHeight;
+        bits = (BYTE *)bits + startScan * stride;
+    }
+    else
+    {
+        topDown = FALSE;
+        bits = (BYTE *)bits + (dibHeight - startScan - scanLines) * stride;
+    }
+    
+    /* if requested part is out of source bitmap, returns 0 */
+    if(startScan >= dibHeight)
+        return 0;
+    if(startScan + scanLines >= dibHeight)
+        scanLines = dibHeight - startScan;
+        
+    /* 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)
+            bitFields = 3;
+    }
+    else
+    {
+        colorUsed = ds.dsBmih.biClrUsed;
+        if(!colorUsed)
+            colorUsed = 1 << ds.dsBmih.biBitCount;
+    }
+
+    /* builds the needed BITMAPINFOHEADER */
+    bmi = HeapAlloc( GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER)+
+                     sizeof(RGBQUAD)*colorUsed + sizeof(DWORD) * bitFields );
+    if (!bmi)
+    {
+        ERR("HeapAlloc failed\n");
+        return 0;
+    }
+        
+    /* copy the header part */
+    memcpy( &bmi->bmiHeader, &ds.dsBmih, sizeof(BITMAPINFOHEADER) );
+    
+    /* gets the color table part, if any */
+    if(colorUsed)
+    {
+        /* create a temporary DC, GetDIBColorTable() requests that
+           the DIB is selected in a DC.... */
+        if(!(tmpHdc = CreateCompatibleDC(hdc)))
+        {
+            ERR("Couldn't create the temporary HDC\n");
+            HeapFree(GetProcessHeap(), 0, bmi);
+            return 0;
+        }
+        /* selects the DIB into the temporary DC */
+        if( !(tmpBmp = SelectObject(tmpHdc, srcBmp)))
+        {
+            ERR("Couldn't select source DIB into temporary DC\n");
+            DeleteDC(tmpHdc);
+            HeapFree(GetProcessHeap(), 0, bmi);
+            return 0;
+        }
+        GetDIBColorTable(tmpHdc, 0, colorUsed, bmi->bmiColors);
+        SelectObject(tmpHdc, tmpBmp);
+        DeleteDC(tmpHdc);
+    }
+    
+    /* fill the bitfields part, if any */
+    if(bitFields)
+        memcpy(bmi->bmiColors, ds.dsBitfields, 3 * sizeof(DWORD));
+
+    /* adjust dib size for SetDIBits, as it needs it to reverse top-down dibs
+       it must be set to the number of scanLines to transfer */
+    bmi->bmiHeader.biHeight = topDown ? -scanLines : scanLines;
+    
+    /* creates destination compatible bitmap */
+    tmpHdc = GetDC(NULL);
+    hBmp = CreateCompatibleBitmap(tmpHdc, dibWidth, scanLines);
+    ReleaseDC(NULL, tmpHdc);
+    if(!hBmp)
+    {
+        ERR("CreateCompatibleBitmap failed\n");
+        HeapFree( GetProcessHeap(), 0, bmi );
+        return 0;
+    }
+    
+    /* copies the requested scan lines from DIB to DDB */
+    /* FIXME : still no support for RLE packed DIBs */
+    res = SetDIBits( hdc, hBmp, 0, scanLines, bits, bmi, DIB_RGB_COLORS );
+    HeapFree( GetProcessHeap(), 0, bmi );
+    if(!res)
+    {
+        ERR("SetDIBits failed\n");
+        DeleteObject( hBmp );
+        return 0;
+    }
+    return hBmp;
+}
+
+/***********************************************************************
+ * Creates DIB that is compatible with the target hdc.
+ * startScan and scanLines specify the portion of DDB to convert
+ * in order to avoid unneeded conversion of large DDBs on blitting
+ * 
+ * NOTE : the srcBmp DDB MUST NOT be selected in any DC */
+HBITMAP _DIBDRV_ConvertDDBtoDIB( HDC hdc, HBITMAP srcBmp, int startScan, int scanLines )
+{
+    HBITMAP hBmp = NULL;
+    BITMAP bitmap;
+    BITMAPINFO *bi;
+    void *bits = NULL;
+
+    if (!GetObjectW( srcBmp, sizeof(bitmap), &bitmap ))
+    {
+        ERR("Couldn't retrieve source bitmap\n");
+        return 0;
+    }
+
+    if(startScan + scanLines >= bitmap.bmHeight)
+        scanLines = bitmap.bmHeight - startScan;
+
+    bi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) /* + 256 * sizeof(RGBQUAD) */);
+    if (!bi)
+    {
+        ERR("HeapAlloc failed\n");
+        return 0;
+    }
+    
+    bi->bmiHeader.biSize        = sizeof(BITMAPINFOHEADER);
+    bi->bmiHeader.biWidth       = bitmap.bmWidth;
+    bi->bmiHeader.biHeight      = scanLines;
+    bi->bmiHeader.biPlanes      = bitmap.bmPlanes;
+    bi->bmiHeader.biBitCount    = 32; /* bitmap.bmBitsPixel; */
+    bi->bmiHeader.biCompression = BI_RGB;
+    bi->bmiHeader.biSizeImage   = 0;
+    
+    /* Get the color table or the color masks */
+    /* NO NEED -- WE'RE REQUESTING A 32 bit DIB */
+#if 0
+    if (!GetDIBits(hdc, srcBmp, startScan, scanLines, NULL, bi, DIB_RGB_COLORS))
+    {
+        ERR("Couldn't get the color table/masks\n");
+        HeapFree( GetProcessHeap(), 0, bi );
+        return 0;
+    }
+#endif
+
+    /* Create bitmap and fill in bits */
+    hBmp = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
+    if(!hBmp)
+    {
+        ERR("Failed to create DIB section\n");
+        HeapFree( GetProcessHeap(), 0, bi );
+        return 0;
+    }
+    if (bits)
+    {
+        if(!GetDIBits(hdc, srcBmp, startScan, scanLines, bits, bi, DIB_RGB_COLORS))
+        {
+            ERR("GetDIBits failed\n");
+            DeleteObject( hBmp );
+            HeapFree( GetProcessHeap(), 0, bi );
+            return 0;
+        }
+    }
+    else
+    {
+        ERR("CreateDibSection couldn't allocate DIB bits\n");
+        DeleteObject( hBmp );
+        HeapFree( GetProcessHeap(), 0, bi );
+        return 0;
+    }
+    HeapFree( GetProcessHeap(), 0, bi );
+    return hBmp;
+}
+
+/***********************************************************************
+ *           BITBLT_ConvertDevDDBtoDIB
+ *
+ * Creates DIB that is compatible with the target hdc for a device (non memory) source DC */
+HBITMAP _DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc, HDC hdcDst, int xSrc, int ySrc, int width, int height )
+{
+    HBITMAP bmp, dib;
+    HDC memHDC = NULL;
+    
+    /* at first, we create a compatible DC and a bitmap with needed sizes */
+    memHDC = CreateCompatibleDC(hdcSrc);
+    if(!memHDC)
+    {
+        ERR("CreateCompatibleDC failed\n");
+        return 0;
+    }
+    bmp = CreateCompatibleBitmap(hdcSrc, width, height);
+    if(!bmp)
+    {
+        ERR("CreateCompatibleBitmap failed\n");
+        DeleteDC(memHDC);
+        return 0;
+    }
+    
+    /* select the newly created DDB into the temporary DC */
+    bmp = SelectObject(memHDC, bmp);
+    if(!bmp)
+    {
+        ERR("Failed selecting DDB into temporary DC\n");
+        DeleteObject(bmp);
+        DeleteDC(memHDC);
+        return 0;
+    }
+    
+    /* next, we blit pixels from device to the compatible bitmap */
+    if(!BitBlt(memHDC, 0, 0, width, height, hdcSrc, xSrc, ySrc, SRCCOPY))
+    {
+        ERR("BitBlt failed\n");
+        DeleteObject(bmp);
+        DeleteDC(memHDC);
+        return 0;
+    }
+    
+    /* select out the DDB from the temporary DC */
+    bmp = SelectObject(memHDC, bmp);
+    DeleteDC(memHDC);
+    if(!bmp)
+    {
+        ERR("Failed selecting DDB out temporary DC\n");
+        DeleteObject(bmp);
+        return 0;
+    }
+
+    /*now we can convert the bitmap to a DIB */
+    dib = _DIBDRV_ConvertDDBtoDIB( hdcDst, bmp, 0, height );
+    if(!dib)
+        FIXME("ConvertDDBtoDIB failed\n");
+    
+    /* free resources and return the created dib */
+    DeleteObject(bmp);
+    return dib;
+}
diff --git a/dlls/winedib.drv/dc.c b/dlls/winedib.drv/dc.c
index c8e3b91..6184677 100644
--- a/dlls/winedib.drv/dc.c
+++ b/dlls/winedib.drv/dc.c
@@ -25,6 +25,100 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+
+/* some screen caps */
+static unsigned int screen_width;
+static unsigned int screen_height;
+static unsigned int screen_bpp;
+static unsigned int screen_depth;
+static RECT virtual_screen_rect;
+
+/* a few dynamic device caps */
+static int log_pixels_x;  /* pixels per logical inch in x direction */
+static int log_pixels_y;  /* pixels per logical inch in y direction */
+static int horz_size;     /* horz. size of screen in millimeters */
+static int vert_size;     /* vert. size of screen in millimeters */
+static int palette_size;
+static int device_init_done;
+
+/* NOTE :
+    Removing TC_RA_ABLE avoids bitmapped fonts, so FT_Face is always non-NULL
+    Adding TC_VA_ABLE forces to use gdi fonts always, so we can get an FT_Face
+*/
+unsigned int text_caps = (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
+                          TC_CR_ANY | TC_SA_DOUBLE | TC_SA_INTEGER |
+                          TC_SA_CONTIN | TC_UA_ABLE | TC_SO_ABLE /* | TC_RA_ABLE */ | TC_VA_ABLE);
+                          /* X11R6 adds TC_SF_X_YINDEP, Xrender adds TC_VA_ABLE */
+
+
+static const WCHAR dpi_key_name[] = {'S','o','f','t','w','a','r','e','\\','F','o','n','t','s','\0'};
+static const WCHAR dpi_value_name[] = {'L','o','g','P','i','x','e','l','s','\0'};
+
+/******************************************************************************
+ *      get_dpi
+ *
+ * get the dpi from the registry
+ */
+static DWORD get_dpi( void )
+{
+    DWORD dpi = 96;
+    HKEY hkey;
+
+    if (RegOpenKeyW(HKEY_CURRENT_CONFIG, dpi_key_name, &hkey) == ERROR_SUCCESS)
+    {
+        DWORD type, size, new_dpi;
+
+        size = sizeof(new_dpi);
+        if(RegQueryValueExW(hkey, dpi_value_name, NULL, &type, (void *)&new_dpi, &size) == ERROR_SUCCESS)
+        {
+            if(type == REG_DWORD && new_dpi != 0)
+                dpi = new_dpi;
+        }
+        RegCloseKey(hkey);
+    }
+    return dpi;
+}
+
+/**********************************************************************
+ *       device_init
+ *
+ * Perform initializations needed upon creation of the first device.
+ */
+static void device_init(void)
+{
+    Display *display;
+    Screen *screen;
+
+    /* opens default X11 Display */
+    if( (display = XOpenDisplay(NULL)) == NULL)
+        return;
+
+    /* gets default screen */
+    screen = XDefaultScreenOfDisplay(display);
+
+    /* gets screen sizes */
+    screen_width = XWidthOfScreen(screen);
+    screen_height = XHeightOfScreen(screen);
+
+    /* not sure about these ones... */
+    screen_bpp = XDefaultDepthOfScreen(screen);
+    screen_depth = XPlanesOfScreen(screen);
+    virtual_screen_rect.left = 0;
+    virtual_screen_rect.top = 0;
+    virtual_screen_rect.right = screen_width;
+    virtual_screen_rect.bottom = screen_height;
+
+    /* dummy ? */
+    palette_size = 0;
+
+    /* Initialize device caps */
+    log_pixels_x = log_pixels_y = get_dpi();
+    horz_size = MulDiv( screen_width, 254, log_pixels_x * 10 );
+    vert_size = MulDiv( screen_height, 254, log_pixels_y * 10 );
+
+    device_init_done = TRUE;
+}
+
 /**********************************************************************
  *           DIBDRV_CreateDC
  */
@@ -34,8 +128,8 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
     DIBDRVPHYSDEV *physDev;
     PHYSDEV X11PhysDev;
     
-    TRACE("hdc:%p, pdev:%p, driver:%s, device:%s, output:%s, initData:%p\n",
-          hdc, pdev, debugstr_w(driver), debugstr_w(device), debugstr_w(output), initData);
+    MAYBE(TRACE("hdc:%p, pdev:%p, driver:%s, device:%s, output:%s, initData:%p\n",
+          hdc, pdev, debugstr_w(driver), debugstr_w(device), debugstr_w(output), initData));
 
     /* allocates physical device */
     physDev = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DIBDRVPHYSDEV) );
@@ -52,12 +146,53 @@ BOOL DIBDRV_CreateDC( HDC hdc, DIBDRVPHYSDEV **pdev, LPCWSTR driver, LPCWSTR dev
     /* sets X11 Device pointer in DIB Engine device */
     physDev->X11PhysDev = X11PhysDev;
     
+    /* stores the HDC */
+    physDev->hdc = hdc;
+    
+    /* initializes device data (for GetDeviceCaps() )
+       on first DC creation */
+    if (!device_init_done)
+       device_init();
+    
     /* stock bitmap selected on DC creation */
     physDev->hbitmap = GetStockObject(DEFAULT_BITMAP);
     
     /* no DIB selected into DC on creation */
     physDev->hasDIB = FALSE;
     
+    /* clear physical bitmap */
+    _DIBDRVBITMAP_Clear(&physDev->physBitmap);
+    
+    /* clears pen and brush */
+    physDev->rop2 = R2_COPYPEN;
+
+    physDev->backgroundColor = 0;
+    _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->backgroundAnd, &physDev->backgroundXor);
+    
+    physDev->penColor = 0;
+    _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->penAnd, &physDev->penXor);
+    
+    physDev->brushColor = 0;
+    _DIBDRV_CalcAndXorMasks(physDev->rop2, 0, &physDev->brushAnd, &physDev->brushXor);
+    physDev->brushAnds = NULL;
+    physDev->brushXors = NULL;
+    
+    physDev->brushStyle = BS_NULL;
+    
+    physDev->isBrushBitmap = FALSE;
+    _DIBDRVBITMAP_Clear(&physDev->brushBitmap);
+    _DIBDRVBITMAP_Clear(&physDev->brushBmpCache);
+    
+    /* text color */
+    physDev->textColor = 0;
+    physDev->textBackground = 0;
+
+    /* text color table for antialiased fonts */
+    memset(physDev->textColorTable, 0, 256);
+
+    /* freetype face associated to current DC HFONT */
+    physDev->face = NULL;
+
     /* sets the result value and returns */
     *pdev = physDev;
 
@@ -71,16 +206,31 @@ BOOL DIBDRV_DeleteDC( DIBDRVPHYSDEV *physDev )
 {
     BOOL res;
     
-    TRACE("physDev:%p\n", physDev);
+    MAYBE(TRACE("physDev:%p\n", physDev));
 
     /* frees X11 device */
     res = _DIBDRV_GetDisplayDriver()->pDeleteDC(physDev->X11PhysDev);
     physDev->X11PhysDev = NULL;
     
+    /* frees physical bitmap */
+    _DIBDRVBITMAP_Free(&physDev->physBitmap);
+    
+    /* frees brush bitmap */
+    _DIBDRVBITMAP_Free(&physDev->brushBitmap);
+    _DIBDRVBITMAP_Free(&physDev->brushBmpCache);
+    
+    /* free brush ands and xors */
+    if(physDev->brushAnds)
+    {
+        HeapFree(GetProcessHeap(), 0, physDev->brushAnds);
+        HeapFree(GetProcessHeap(), 0, physDev->brushXors);
+    }
+    physDev->brushAnds = NULL;
+    physDev->brushXors = NULL;
+    
     /* frees DIB Engine device */
     HeapFree(GetProcessHeap(), 0, physDev);
     
-    ONCE(FIXME("stub\n"));
     return res;
 }
 
@@ -92,8 +242,8 @@ INT DIBDRV_ExtEscape( DIBDRVPHYSDEV *physDev, INT escape, INT in_count, LPCVOID
 {
     INT res;
     
-    TRACE("physDev:%p, escape:%d, in_count:%d, in_data:%p, out_count:%d, out_data:%p\n",
-          physDev, escape, in_count, in_data, out_count, out_data);
+    MAYBE(TRACE("physDev:%p, escape:%d, in_count:%d, in_data:%p, out_count:%d, out_data:%p\n",
+          physDev, escape, in_count, in_data, out_count, out_data));
 
     if(physDev->hasDIB)
     {
@@ -116,13 +266,125 @@ INT DIBDRV_GetDeviceCaps( DIBDRVPHYSDEV *physDev, INT cap )
 {
     INT res;
     
-    TRACE("physDev:%p, cap:%d\n", physDev, cap); 
+    MAYBE(TRACE("physDev:%p, cap:%d\n", physDev, cap)); 
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetDeviceCaps(physDev->X11PhysDev, cap);
+        switch(cap)
+        {
+        case DRIVERVERSION:
+            res = 0x300;
+            break;
+        case TECHNOLOGY:
+            res = DT_RASDISPLAY;
+            break;
+        case HORZSIZE:
+            res = horz_size;
+            break;
+        case VERTSIZE:
+            res = vert_size;
+            break;
+        case HORZRES:
+            res = screen_width;
+            break;
+        case VERTRES:
+            res = screen_height;
+            break;
+        case DESKTOPHORZRES:
+            res = virtual_screen_rect.right - virtual_screen_rect.left;
+            break;
+        case DESKTOPVERTRES:
+            res = virtual_screen_rect.bottom - virtual_screen_rect.top;
+            break;
+        case BITSPIXEL:
+            res = screen_bpp;
+            break;
+        case PLANES:
+            res = 1;
+            break;
+        case NUMBRUSHES:
+            res = -1;
+            break;
+        case NUMPENS:
+            res = -1;
+            break;
+        case NUMMARKERS:
+            res = 0;
+            break;
+        case NUMFONTS:
+            res = 0;
+            break;
+        case NUMCOLORS:
+            /* MSDN: Number of entries in the device's color table, if the device has
+             * a color depth of no more than 8 bits per pixel.For devices with greater
+             * color depths, -1 is returned. */
+            res = (screen_depth > 8) ? -1 : (1 << screen_depth);
+            break;
+        case CURVECAPS:
+            res = (CC_CIRCLES | CC_PIE | CC_CHORD | CC_ELLIPSES | CC_WIDE |
+                    CC_STYLED | CC_WIDESTYLED | CC_INTERIORS | CC_ROUNDRECT);
+            break;
+        case LINECAPS:
+            res = (LC_POLYLINE | LC_MARKER | LC_POLYMARKER | LC_WIDE |
+                    LC_STYLED | LC_WIDESTYLED | LC_INTERIORS);
+            break;
+        case POLYGONALCAPS:
+            res = (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
+                    PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
+            break;
+        case TEXTCAPS:
+            res = text_caps;
+            break;
+        case CLIPCAPS:
+            res = CP_REGION;
+            break;
+        case RASTERCAPS:
+            res = (RC_BITBLT | RC_BANDING | RC_SCALING | RC_BITMAP64 | RC_DI_BITMAP |
+                    RC_DIBTODEV | RC_BIGFONT | RC_STRETCHBLT | RC_STRETCHDIB | RC_DEVBITS |
+                    (palette_size ? RC_PALETTE : 0));
+            break;
+        case SHADEBLENDCAPS:
+            res = (SB_GRAD_RECT | SB_GRAD_TRI | SB_CONST_ALPHA | SB_PIXEL_ALPHA);
+        case ASPECTX:
+        case ASPECTY:
+            res = 36;
+            break;
+        case ASPECTXY:
+            res = 51;
+            break;
+        case LOGPIXELSX:
+            res = log_pixels_x;
+            break;
+        case LOGPIXELSY:
+            res = log_pixels_y;
+            break;
+        case CAPS1:
+            FIXME("(%p): CAPS1 is unimplemented, will return 0\n", physDev->hdc );
+            /* please see wingdi.h for the possible bit-flag values that need
+               to be returned. */
+            res = 0;
+            break;
+        case SIZEPALETTE:
+            res = palette_size;
+            break;
+        case NUMRESERVED:
+        case COLORRES:
+        case PHYSICALWIDTH:
+        case PHYSICALHEIGHT:
+        case PHYSICALOFFSETX:
+        case PHYSICALOFFSETY:
+        case SCALINGFACTORX:
+        case SCALINGFACTORY:
+        case VREFRESH:
+        case BLTALIGNMENT:
+            res = 0;
+            break;
+        default:
+            FIXME("(%p): unsupported capability %d, will return 0\n", physDev->hdc, cap );
+            res = 0;
+            break;
+        }
     }
     else
     {
diff --git a/dlls/winedib.drv/dib.c b/dlls/winedib.drv/dib.c
index 28330fa..b72c34a 100644
--- a/dlls/winedib.drv/dib.c
+++ b/dlls/winedib.drv/dib.c
@@ -33,11 +33,11 @@ HBITMAP DIBDRV_CreateDIBSection( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap,
 {
     HBITMAP res;
     
-    TRACE("physDev:%p, hbitmap:%p, bmi:%p, usage:%d\n", physDev, hbitmap, bmi, usage);
+    MAYBE(TRACE("physDev:%p, hbitmap:%p, bmi:%p, usage:%d\n", physDev, hbitmap, bmi, usage));
 
     /* createDIBSection is only DIB-related, so we just use the engine */
-    ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-    res = _DIBDRV_GetDisplayDriver()->pCreateDIBSection(physDev->X11PhysDev, hbitmap, bmi, usage);
+    ONCE(FIXME("STUB\n"));
+    res = hbitmap;
 
     return res;
 }
@@ -50,8 +50,8 @@ INT DIBDRV_GetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 {
     INT res;
     
-    TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
-        physDev, hbitmap, startscan, lines, bits, bmi, coloruse);
+    MAYBE(TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
+        physDev, hbitmap, startscan, lines, bits, bmi, coloruse));
 
     /* 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);
@@ -67,11 +67,11 @@ UINT DIBDRV_SetDIBColorTable( DIBDRVPHYSDEV *physDev, UINT start, UINT count,
 {
     UINT res;
     
-    TRACE("physDev:%p, start:%d, count:%d, colors:%p\n", physDev, start, count, colors);
+    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 */
-    ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-    res = _DIBDRV_GetDisplayDriver()->pSetDIBColorTable(physDev->X11PhysDev, start, count, colors);
+    ONCE(FIXME("STUB\n"));
+    res = 0;
 
     return res;
 }
@@ -84,8 +84,8 @@ INT DIBDRV_SetDIBits( DIBDRVPHYSDEV *physDev, HBITMAP hbitmap, UINT startscan,
 {
     INT res;
     
-    TRACE("physDev:%p, hbitmap:%p, startscan:%d, lines:%d, bits:%p, bmi:%p, coloruse:%d\n",
-        physDev, hbitmap, startscan, lines, bits, info, coloruse);
+    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);
@@ -103,8 +103,8 @@ INT DIBDRV_SetDIBitsToDevice( DIBDRVPHYSDEV *physDev, INT xDest, INT yDest, DWOR
 {
     INT res;
     
-    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);
+    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,
diff --git a/dlls/winedib.drv/dibdrv.h b/dlls/winedib.drv/dibdrv.h
index 8a2e139..773941e 100644
--- a/dlls/winedib.drv/dibdrv.h
+++ b/dlls/winedib.drv/dibdrv.h
@@ -35,10 +35,15 @@
 #include "winreg.h"
 #include "wine/winbase16.h" /* GlobalLock16 */
 
+#include "freetype.h"
+
 /* data structures needed to access opaque pointers
  * defined in gdi32.h */
 #include "dibdrv_gdi32.h"
 
+/* enable this if you want debugging (i.e. TRACEs) output */
+#define DIBDRV_ENABLE_MAYBE
+
 /* provide a way to make debugging output appear
    only once. Usage example:
    ONCE(FIXME("Some message\n")); */
@@ -52,25 +57,197 @@
     } \
 }
 
+/* provide a way to make debugging output appear
+   only if enabled here. Can speed up stuffs
+   avoiding long traces.Usage example:
+   MAYBE(TRACE("Some message\n")); */
+#ifdef DIBDRV_ENABLE_MAYBE
+#define MAYBE(x) x
+#else
+#define MAYBE(x)
+#endif
+
+
 /* extra stock object: default 1x1 bitmap for memory DCs
    grabbed from gdi_private.h */
 #define DEFAULT_BITMAP (STOCK_LAST+1)
 
+struct _DIBDRVBITMAP;
+struct _DIBDRVPHYSDEV;
+typedef struct _DIBDRV_PRIMITIVE_FUNCS
+{
+    /* color to pixel data conversion */
+    DWORD (* ColorToPixel)     (const struct _DIBDRVBITMAP *bmp, COLORREF color);
+    
+    /* pixel primitives */
+    void* (* GetPixelPointer)  (const struct _DIBDRVBITMAP *bmp, int x, int y);
+    void  (* SetPixel)         (      struct _DIBDRVBITMAP *bmp, int x, int y, DWORD and, DWORD xor);
+    DWORD (* GetPixel)         (const struct _DIBDRVBITMAP *bmp, int x, int y);
+    
+    /* line drawing primitives */
+    void  (* SolidHLine)       (      struct _DIBDRVBITMAP *bmp, int x1, int x2, int y, DWORD and, DWORD xor);
+    void  (* PatternHLine)     (      struct _DIBDRVBITMAP *bmp, int x1, int x2, int y, const void *and, const void *xor, DWORD offset, DWORD count);
+    void  (* SolidVLine)       (      struct _DIBDRVBITMAP *bmp, int x, int y1, int y2, DWORD and, DWORD xor);
+    
+    /* bitmap conversion helpers */
+    BOOL  (* GetLine)          (const struct _DIBDRVBITMAP *bmp, int line, int startx, int width, void *buf);
+    BOOL  (* PutLine)          (      struct _DIBDRVBITMAP *bmp, int line, int startx, int width, void *buf);
+    
+    /* BitBlt primitives */
+    BOOL  (* BitBlt)           (      struct _DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, int width, int height,
+                                const struct _DIBDRVPHYSDEV *physDevSrc, int xSrc, int ySrc, DWORD rop );
+    BOOL  (* StretchBlt)       (      struct _DIBDRVPHYSDEV *physDevDst, int xDst, int yDst, int widthDst, int heightDst,
+                                const struct _DIBDRVPHYSDEV *physDevSrc, int xSrc, int ySrc, int widthSrc, int heightSrc, DWORD rop );
+                                
+    /* font drawing helper */
+    void  (* FreetypeBlit)     (      struct _DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp);
+
+} DIBDRV_PRIMITIVE_FUNCS;
+
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_RGB;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_BITFIELDS;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB24;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_RGB;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_BITFIELDS;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB8;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB4;
+extern DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB1;
+
+/* DIB bitmaps formats */
+typedef enum _DIBFORMAT
+{
+    DIBFMT_UNKNOWN          =   0,
+    DIBFMT_DIB1             =   1,
+    DIBFMT_DIB4             =   2,
+    DIBFMT_DIB4_RLE         =   3,
+    DIBFMT_DIB8             =   4,
+    DIBFMT_DIB8_RLE         =   5,
+    DIBFMT_DIB16_RGB        =   6,
+    DIBFMT_DIB16_BITFIELDS  =   7,
+    DIBFMT_DIB24            =   8,
+    DIBFMT_DIB32_RGB        =   9,
+    DIBFMT_DIB32_BITFIELDS  =  10
+} DIBFORMAT;
+
+/* DIB driver's generic bitmap structure */
+typedef struct _DIBDRVBITMAP
+{
+    /* bitmap format of dib */
+    DIBFORMAT format;
+
+    /* pointer to top left corner of bitmap */
+    void *bits;
+
+    /* flags indicating if bits array is owned
+       by the bitmap */
+    BOOL ownsBits;
+
+    /* bitmap dimensions */
+    int width;
+    int height;
+
+    /* bitmap stride (== width in bytes) of a bitmap line */
+    /* negative for a bottom-up bitmap */
+    int stride;
+
+    /* number of bits/pixel in bitmap */
+    int bitCount;
+
+    /* calculated numbers for bitfields */
+    
+    /* bitfields masks */
+    DWORD redMask, greenMask, blueMask;
+    /* shifting required within a COLORREF's BYTE */
+    int redShift, greenShift, blueShift;
+    /* size of the fields */
+    int redLen, greenLen, blueLen;
+
+    /* color table and its size */
+    RGBQUAD *colorTable;
+    DWORD colorTableSize;
+    
+    /* flag indicating that color table has been grabbed */
+    BOOL colorTableGrabbed;
+
+    /* primitive function pointers */
+    DIBDRV_PRIMITIVE_FUNCS *funcs;
+
+} DIBDRVBITMAP;
+
+/* dash patterns */
+typedef struct _DASHPATTERN
+{
+    DWORD count;
+    DWORD dashes[6];
+
+} DASHPATTERN;
+
 /* DIB driver physical device */
 typedef struct _DIBDRVPHYSDEV
 {
     /* X11 driver physical device */
     PHYSDEV X11PhysDev;
     
+    /* HDC associated with physDev */
+    HDC hdc;
+    
     /* is a DIB selected into DC ? */
     BOOL hasDIB;
     
     /* currently selected HBITMAP */
     HBITMAP hbitmap;
+    
+    /* physical bitmap */
+    DIBDRVBITMAP physBitmap;
 
     /* active ROP2 */
     INT rop2;
 
+    /* background color and active ROP2 precalculated
+       AND and XOR values for it */
+    COLORREF backgroundColor;
+    DWORD backgroundAnd, backgroundXor;
+    
+    /* pen color and active ROP2 precalculated
+       AND and XOR values for it */
+    COLORREF penColorref;
+    DWORD penColor;
+    DWORD penAnd, penXor;
+    const DASHPATTERN *penPattern;
+    DWORD curDash, leftInDash;
+    enum MARKSPACE { mark, space } markSpace;
+    
+    /* pen drawing functions */
+    void (* penHLine)  (struct _DIBDRVPHYSDEV *physDev, int x1, int x2, int y);
+    void (* penVLine)  (struct _DIBDRVPHYSDEV *physDev, int x, int y1, int y2);
+    void (* penLine)   (struct _DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2);
+    void (* brushHLine)(struct _DIBDRVPHYSDEV *physDev, int x1, int x2, int y);
+
+    /* brush color and active ROP2 precalculated
+       AND and XOR values for it */
+    COLORREF brushColorref;
+    DWORD brushColor;
+    DWORD brushAnd, brushXor;
+    DWORD *brushAnds, *brushXors;
+    
+    /* brush style */
+    UINT brushStyle;
+    
+    /* brush bitmap, if needed, and its converted/resized cache copy */
+    BOOL isBrushBitmap;
+    DIBDRVBITMAP brushBitmap;
+    DIBDRVBITMAP brushBmpCache;
+    
+    /* text color */
+    COLORREF textColor;
+    COLORREF textBackground;
+
+    /* text color table for antialiased fonts */
+    COLORREF textColorTable[256];
+
+    /* freetype face associated to current DC HFONT */
+    FT_Face face;
+
 } DIBDRVPHYSDEV;
 
 
@@ -90,4 +267,117 @@ void _DIBDRV_FreeDisplayDriver(void);
    Gets a pointer to display drives'function table */
 inline DC_FUNCTIONS *_DIBDRV_GetDisplayDriver(void);
 
-#endif /* __WINE_DIBDRV_H */
+/* *********************************************************************
+ * ROP2 AND OTHER DRAWING RELATED FUNCTIONS
+ * ********************************************************************/
+
+void _DIBDRV_CalcAndXorMasks(INT rop, DWORD color, DWORD *and, DWORD *xor);
+
+inline void _DIBDRV_rop32(DWORD *ptr, DWORD and, DWORD xor);
+inline void _DIBDRV_rop16(WORD *ptr, WORD and, WORD xor);
+inline void _DIBDRV_rop8(BYTE *ptr, BYTE and, BYTE xor);
+
+void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV *physDev);
+
+/* *********************************************************************
+ * ROP2 FUNCTIONS
+ * ********************************************************************/
+
+/* the ROP3 operations
+   this is a BIG case block; beware that some
+   commons ROP3 operations will be optimized
+   from inside blt routines */
+DWORD _DIBDRV_ROP3(DWORD p, DWORD s, DWORD d, BYTE rop);
+
+/* *********************************************************************
+ * PHYSICAL BITMAP  FUNCTIONS
+ * ********************************************************************/
+
+/* gets human-readable dib format name */
+const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp);
+
+/* initializes dib from a bitmap : 
+    dib           dib being initialized
+    bi            source BITMAPINFOHEADER with required DIB format info
+    bit_fields    color masks
+    color_table   color table, if any
+    bits          pointer to image data array
+    NOTE : DIBDRVBITMAP doesn't owns bits, but do own color table */
+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);
+
+/* initializes a DIBRDVBITMAP copying it from a source one
+   Parameters :
+      dib       destination DIBDRVBITMAP
+      src       source DIBDRVBITMAP
+      copy      TRUE->copy source pixel array FALSE->link to source pixel array */
+BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy);
+
+/* creates a DIBRDVBITMAP copying format info from a source one
+   Parameters :
+      dib            destination DIBDRVBITMAP
+      src            source DIBDRVBITMAP
+      widht, height  sizes of newly created bitmap  */
+BOOL _DIBDRVBITMAP_CreateFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, int width, int height);
+
+/* Clears a DIBDRVBITMAP structure data
+   WARNING : doesn't free anything */
+void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp);
+
+/* Frees a DIBDRVBITMAP structure data */
+void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp);
+
+/* checks whether the format of 2 DIBs are identical
+   it checks the pixel bit count and the color table size
+   and content, if needed */
+BOOL _DIBDRVBITMAP_FormatMatch(const DIBDRVBITMAP *d1, const DIBDRVBITMAP *d2);
+
+/* convert a given dib into another format given by 'format' parameter */
+BOOL _DIBDRVBITMAP_Convert(DIBDRVBITMAP *dst, const DIBDRVBITMAP *src, const DIBDRVBITMAP *format);
+
+/* creates a solid-filled DIB of given color and format
+   DIB format is given by 'format' parameter */
+BOOL _DIBDRVBITMAP_CreateSolid(DIBDRVBITMAP *bmp, DIBDRVBITMAP *format, int width, int height, DWORD Color);
+
+/* expands horizontally a bitmap to reach a minimum size,
+   keeping its width as a multiple of a base width
+   Used to widen brushes in order to optimize blitting */
+BOOL _DIBDRVBITMAP_ExpandHoriz(DIBDRVBITMAP *dib, int baseWidth, int minWidth);
+
+/* *********************************************************************
+ * DIB <--> DDB CONVERSION ROUTINES
+ * ********************************************************************/
+
+/***********************************************************************
+ * Creates DDB that is compatible with source hdc.
+ * hdc is the HDC on where the DIB MUST be selected in
+ * srcBmp is the source DIB
+ * startScan and scanLines specify the portion of DIB to convert
+ * in order to avoid unneeded conversion of large DIBs on blitting
+ * 
+ * NOTE : the srcBmp DIB MUST NOT be selected in any DC */
+HBITMAP _DIBDRV_ConvertDIBtoDDB( HDC hdc, HBITMAP srcBmp, int startScan, int scanLines );
+
+/***********************************************************************
+ * Creates DIB that is compatible with the target hdc.
+ * startScan and scanLines specify the portion of DDB to convert
+ * in order to avoid unneeded conversion of large DDBs on blitting
+ * 
+ * NOTE : the srcBmp DDB MUST NOT be selected in any DC */
+HBITMAP _DIBDRV_ConvertDDBtoDIB( HDC hdc, HBITMAP srcBmp, int startScan, int scanLines );
+
+/***********************************************************************
+ * Creates DIB that is compatible with the target hdc for a device (non memory) source DC */
+HBITMAP _DIBDRV_ConvertDevDDBtoDIB( HDC hdcSrc, HDC hdcDst, int xSrc, int ySrc, int width, int height );
+
+/* *********************************************************************
+ * QUERY FUNCTIONS
+ * ********************************************************************/
+
+/***********************************************************************
+ *           DIBDRV_GetDeviceCaps */
+INT DIBDRV_GetDeviceCaps( DIBDRVPHYSDEV *physDev, INT cap );
+
+#endif
diff --git a/dlls/winedib.drv/dibdrv_gdi32.h b/dlls/winedib.drv/dibdrv_gdi32.h
new file mode 100644
index 0000000..8e4eb05
--- /dev/null
+++ b/dlls/winedib.drv/dibdrv_gdi32.h
@@ -0,0 +1,168 @@
+/*
+ * GDI structures - grabbed from dlls/gdi32/gdi_private.h
+ * Those are needed to access some opaque gdi32 pointers
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_DIBDRV_GDI32_H
+#define __WINE_DIBDRV_GDI32_H
+
+
+/* driver function pointers - used here to forward calls to X11 driver when needed */
+typedef struct { int opaque; } *PHYSDEV;  /* PHYSDEV is an opaque pointer */
+typedef struct tagDC_FUNCS
+{
+    INT      (CDECL *pAbortDoc)(PHYSDEV);
+    BOOL     (CDECL *pAbortPath)(PHYSDEV);
+    BOOL     (CDECL *pAlphaBlend)(PHYSDEV,INT,INT,INT,INT,PHYSDEV,INT,INT,INT,INT,BLENDFUNCTION);
+    BOOL     (CDECL *pAngleArc)(PHYSDEV,INT,INT,DWORD,FLOAT,FLOAT);
+    BOOL     (CDECL *pArc)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
+    BOOL     (CDECL *pArcTo)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
+    BOOL     (CDECL *pBeginPath)(PHYSDEV);
+    BOOL     (CDECL *pBitBlt)(PHYSDEV,INT,INT,INT,INT,PHYSDEV,INT,INT,DWORD);
+    INT      (CDECL *pChoosePixelFormat)(PHYSDEV,const PIXELFORMATDESCRIPTOR *);
+    BOOL     (CDECL *pChord)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
+    BOOL     (CDECL *pCloseFigure)(PHYSDEV);
+    BOOL     (CDECL *pCreateBitmap)(PHYSDEV,HBITMAP,LPVOID);
+    BOOL     (CDECL *pCreateDC)(HDC,PHYSDEV *,LPCWSTR,LPCWSTR,LPCWSTR,const DEVMODEW*);
+    HBITMAP  (CDECL *pCreateDIBSection)(PHYSDEV,HBITMAP,const BITMAPINFO *,UINT);
+    BOOL     (CDECL *pDeleteBitmap)(HBITMAP);
+    BOOL     (CDECL *pDeleteDC)(PHYSDEV);
+    BOOL     (CDECL *pDeleteObject)(PHYSDEV,HGDIOBJ);
+    INT      (CDECL *pDescribePixelFormat)(PHYSDEV,INT,UINT,PIXELFORMATDESCRIPTOR *);
+    DWORD    (CDECL *pDeviceCapabilities)(LPSTR,LPCSTR,LPCSTR,WORD,LPSTR,LPDEVMODEA);
+    BOOL     (CDECL *pEllipse)(PHYSDEV,INT,INT,INT,INT);
+    INT      (CDECL *pEndDoc)(PHYSDEV);
+    INT      (CDECL *pEndPage)(PHYSDEV);
+    BOOL     (CDECL *pEndPath)(PHYSDEV);
+    BOOL     (CDECL *pEnumDeviceFonts)(PHYSDEV,LPLOGFONTW,FONTENUMPROCW,LPARAM);
+    INT      (CDECL *pExcludeClipRect)(PHYSDEV,INT,INT,INT,INT);
+    INT      (CDECL *pExtDeviceMode)(LPSTR,HWND,LPDEVMODEA,LPSTR,LPSTR,LPDEVMODEA,LPSTR,DWORD);
+    INT      (CDECL *pExtEscape)(PHYSDEV,INT,INT,LPCVOID,INT,LPVOID);
+    BOOL     (CDECL *pExtFloodFill)(PHYSDEV,INT,INT,COLORREF,UINT);
+    INT      (CDECL *pExtSelectClipRgn)(PHYSDEV,HRGN,INT);
+    BOOL     (CDECL *pExtTextOut)(PHYSDEV,INT,INT,UINT,const RECT*,LPCWSTR,UINT,const INT*);
+    BOOL     (CDECL *pFillPath)(PHYSDEV);
+    BOOL     (CDECL *pFillRgn)(PHYSDEV,HRGN,HBRUSH);
+    BOOL     (CDECL *pFlattenPath)(PHYSDEV);
+    BOOL     (CDECL *pFrameRgn)(PHYSDEV,HRGN,HBRUSH,INT,INT);
+    BOOL     (CDECL *pGdiComment)(PHYSDEV,UINT,CONST BYTE*);
+    LONG     (CDECL *pGetBitmapBits)(HBITMAP,void*,LONG);
+    BOOL     (CDECL *pGetCharWidth)(PHYSDEV,UINT,UINT,LPINT);
+    BOOL     (CDECL *pGetDCOrgEx)(PHYSDEV,LPPOINT);
+    UINT     (CDECL *pGetDIBColorTable)(PHYSDEV,UINT,UINT,RGBQUAD*);
+    INT      (CDECL *pGetDIBits)(PHYSDEV,HBITMAP,UINT,UINT,LPCVOID,const BITMAPINFO*,UINT);
+    INT      (CDECL *pGetDeviceCaps)(PHYSDEV,INT);
+    BOOL     (CDECL *pGetDeviceGammaRamp)(PHYSDEV,LPVOID);
+    BOOL     (CDECL *pGetICMProfile)(PHYSDEV,LPDWORD,LPWSTR);
+    COLORREF (CDECL *pGetNearestColor)(PHYSDEV,COLORREF);
+    COLORREF (CDECL *pGetPixel)(PHYSDEV,INT,INT);
+    INT      (CDECL *pGetPixelFormat)(PHYSDEV);
+    UINT     (CDECL *pGetSystemPaletteEntries)(PHYSDEV,UINT,UINT,LPPALETTEENTRY);
+    BOOL     (CDECL *pGetTextExtentExPoint)(PHYSDEV,LPCWSTR,INT,INT,LPINT,LPINT,LPSIZE);
+    BOOL     (CDECL *CDECL pGetTextMetrics)(PHYSDEV,TEXTMETRICW*);
+    INT      (CDECL *pIntersectClipRect)(PHYSDEV,INT,INT,INT,INT);
+    BOOL     (CDECL *pInvertRgn)(PHYSDEV,HRGN);
+    BOOL     (CDECL *pLineTo)(PHYSDEV,INT,INT);
+    BOOL     (CDECL *pModifyWorldTransform)(PHYSDEV,const XFORM*,INT);
+    BOOL     (CDECL *pMoveTo)(PHYSDEV,INT,INT);
+    INT      (CDECL *pOffsetClipRgn)(PHYSDEV,INT,INT);
+    INT      (CDECL *pOffsetViewportOrg)(PHYSDEV,INT,INT);
+    INT      (CDECL *pOffsetWindowOrg)(PHYSDEV,INT,INT);
+    BOOL     (CDECL *pPaintRgn)(PHYSDEV,HRGN);
+    BOOL     (CDECL *pPatBlt)(PHYSDEV,INT,INT,INT,INT,DWORD);
+    BOOL     (CDECL *pPie)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT);
+    BOOL     (CDECL *pPolyBezier)(PHYSDEV,const POINT*,DWORD);
+    BOOL     (CDECL *pPolyBezierTo)(PHYSDEV,const POINT*,DWORD);
+    BOOL     (CDECL *pPolyDraw)(PHYSDEV,const POINT*,const BYTE *,DWORD);
+    BOOL     (CDECL *pPolyPolygon)(PHYSDEV,const POINT*,const INT*,UINT);
+    BOOL     (CDECL *pPolyPolyline)(PHYSDEV,const POINT*,const DWORD*,DWORD);
+    BOOL     (CDECL *pPolygon)(PHYSDEV,const POINT*,INT);
+    BOOL     (CDECL *pPolyline)(PHYSDEV,const POINT*,INT);
+    BOOL     (CDECL *pPolylineTo)(PHYSDEV,const POINT*,INT);
+    UINT     (CDECL *pRealizeDefaultPalette)(PHYSDEV);
+    UINT     (CDECL *pRealizePalette)(PHYSDEV,HPALETTE,BOOL);
+    BOOL     (CDECL *pRectangle)(PHYSDEV,INT,INT,INT,INT);
+    HDC      (CDECL *pResetDC)(PHYSDEV,const DEVMODEW*);
+    BOOL     (CDECL *pRestoreDC)(PHYSDEV,INT);
+    BOOL     (CDECL *pRoundRect)(PHYSDEV,INT,INT,INT,INT,INT,INT);
+    INT      (CDECL *pSaveDC)(PHYSDEV);
+    INT      (CDECL *pScaleViewportExt)(PHYSDEV,INT,INT,INT,INT);
+    INT      (CDECL *pScaleWindowExt)(PHYSDEV,INT,INT,INT,INT);
+    HBITMAP  (CDECL *pSelectBitmap)(PHYSDEV,HBITMAP);
+    HBRUSH   (CDECL *pSelectBrush)(PHYSDEV,HBRUSH);
+    BOOL     (CDECL *pSelectClipPath)(PHYSDEV,INT);
+    HFONT    (CDECL *pSelectFont)(PHYSDEV,HFONT,HANDLE);
+    HPALETTE (CDECL *pSelectPalette)(PHYSDEV,HPALETTE,BOOL);
+    HPEN     (CDECL *pSelectPen)(PHYSDEV,HPEN);
+    INT      (CDECL *pSetArcDirection)(PHYSDEV,INT);
+    LONG     (CDECL *pSetBitmapBits)(HBITMAP,const void*,LONG);
+    COLORREF (CDECL *pSetBkColor)(PHYSDEV,COLORREF);
+    INT      (CDECL *pSetBkMode)(PHYSDEV,INT);
+    COLORREF (CDECL *pSetDCBrushColor)(PHYSDEV, COLORREF);
+    DWORD    (CDECL *pSetDCOrg)(PHYSDEV,INT,INT);
+    COLORREF (CDECL *pSetDCPenColor)(PHYSDEV, COLORREF);
+    UINT     (CDECL *pSetDIBColorTable)(PHYSDEV,UINT,UINT,const RGBQUAD*);
+    INT      (CDECL *pSetDIBits)(PHYSDEV,HBITMAP,UINT,UINT,LPCVOID,const BITMAPINFO*,UINT);
+    INT      (CDECL *pSetDIBitsToDevice)(PHYSDEV,INT,INT,DWORD,DWORD,INT,INT,UINT,UINT,LPCVOID,
+                                           const BITMAPINFO*,UINT);
+    VOID     (CDECL *pSetDeviceClipping)(PHYSDEV,HRGN,HRGN);
+    BOOL     (CDECL *pSetDeviceGammaRamp)(PHYSDEV,LPVOID);
+    INT      (CDECL *pSetMapMode)(PHYSDEV,INT);
+    DWORD    (CDECL *pSetMapperFlags)(PHYSDEV,DWORD);
+    COLORREF (CDECL *pSetPixel)(PHYSDEV,INT,INT,COLORREF);
+    BOOL     (CDECL *pSetPixelFormat)(PHYSDEV,INT,const PIXELFORMATDESCRIPTOR *);
+    INT      (CDECL *pSetPolyFillMode)(PHYSDEV,INT);
+    INT      (CDECL *pSetROP2)(PHYSDEV,INT);
+    INT      (CDECL *pSetRelAbs)(PHYSDEV,INT);
+    INT      (CDECL *pSetStretchBltMode)(PHYSDEV,INT);
+    UINT     (CDECL *pSetTextAlign)(PHYSDEV,UINT);
+    INT      (CDECL *pSetTextCharacterExtra)(PHYSDEV,INT);
+    DWORD    (CDECL *pSetTextColor)(PHYSDEV,DWORD);
+    INT      (CDECL *pSetTextJustification)(PHYSDEV,INT,INT);
+    INT      (CDECL *pSetViewportExt)(PHYSDEV,INT,INT);
+    INT      (CDECL *pSetViewportOrg)(PHYSDEV,INT,INT);
+    INT      (CDECL *pSetWindowExt)(PHYSDEV,INT,INT);
+    INT      (CDECL *pSetWindowOrg)(PHYSDEV,INT,INT);
+    BOOL     (CDECL *pSetWorldTransform)(PHYSDEV,const XFORM*);
+    INT      (CDECL *pStartDoc)(PHYSDEV,const DOCINFOW*);
+    INT      (CDECL *pStartPage)(PHYSDEV);
+    BOOL     (CDECL *pStretchBlt)(PHYSDEV,INT,INT,INT,INT,PHYSDEV,INT,INT,INT,INT,DWORD);
+    INT      (CDECL *pStretchDIBits)(PHYSDEV,INT,INT,INT,INT,INT,INT,INT,INT,const void *,
+                                       const BITMAPINFO*,UINT,DWORD);
+    BOOL     (CDECL *pStrokeAndFillPath)(PHYSDEV);
+    BOOL     (CDECL *pStrokePath)(PHYSDEV);
+    BOOL     (CDECL *pSwapBuffers)(PHYSDEV);
+    BOOL     (CDECL *pUnrealizePalette)(HPALETTE);
+    BOOL     (CDECL *pWidenPath)(PHYSDEV);
+
+    /* OpenGL32 */
+    BOOL     (CDECL *pwglCopyContext)(HGLRC, HGLRC, UINT);
+    HGLRC    (CDECL *pwglCreateContext)(PHYSDEV);
+    BOOL     (CDECL *pwglDeleteContext)(HGLRC);
+    PROC     (CDECL *pwglGetProcAddress)(LPCSTR);
+    HDC      (CDECL *pwglGetPbufferDCARB)(PHYSDEV, void*);
+    BOOL     (CDECL *pwglMakeCurrent)(PHYSDEV, HGLRC);
+    BOOL     (CDECL *pwglMakeContextCurrentARB)(PHYSDEV, PHYSDEV, HGLRC);
+    BOOL     (CDECL *pwglSetPixelFormatWINE)(PHYSDEV,INT,const PIXELFORMATDESCRIPTOR *);
+    BOOL     (CDECL *pwglShareLists)(HGLRC hglrc1, HGLRC hglrc2);
+    BOOL     (CDECL *pwglUseFontBitmapsA)(PHYSDEV, DWORD, DWORD, DWORD);
+    BOOL     (CDECL *pwglUseFontBitmapsW)(PHYSDEV, DWORD, DWORD, DWORD);
+} DC_FUNCTIONS;
+
+#endif
diff --git a/dlls/winedib.drv/dibdrv_main.c b/dlls/winedib.drv/dibdrv_main.c
index 28429d2..e436440 100644
--- a/dlls/winedib.drv/dibdrv_main.c
+++ b/dlls/winedib.drv/dibdrv_main.c
@@ -35,15 +35,26 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
     switch(reason)
     {
     case DLL_PROCESS_ATTACH:
+
         /* Loads display driver */
         _DIBDRV_LoadDisplayDriver();
+
+        /* initializes freetype library */
+        if(!_DIBDRV_FreeType_Init())
+            ERR("Couldn't initialize freetype library.\n");
+
         break;
     case DLL_THREAD_DETACH:
         /* do thread detach */
         break;
     case DLL_PROCESS_DETACH:
+
+        /* terminates freetype library */
+        _DIBDRV_FreeType_Terminate();
+
         /* unloads display driver */
         _DIBDRV_FreeDisplayDriver();
+
         break;
     }
     return ret;
diff --git a/dlls/winedib.drv/dibdrvbitmap.c b/dlls/winedib.drv/dibdrvbitmap.c
new file mode 100644
index 0000000..2c8c367
--- /dev/null
+++ b/dlls/winedib.drv/dibdrvbitmap.c
@@ -0,0 +1,650 @@
+/*
+ * DIB Engine DIBDRVBITMAP handling
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* gets human-readable dib format name */
+const char *_DIBDRVBITMAP_GetFormatName(DIBDRVBITMAP const *bmp)
+{
+   if(!bmp)
+   {
+       ERR("Null bitmap\n");
+       return "NULL BITMAP DETECTED";
+   }
+   switch(bmp->format)
+   {
+       case DIBFMT_DIB1:
+           return "DIBFMT_DIB1";
+       case DIBFMT_DIB4:
+           return "DIBFMT_DIB4";
+       case DIBFMT_DIB4_RLE:
+           return "DIBFMT_DIB4_RLE";
+       case DIBFMT_DIB8:
+           return "DIBFMT_DIB8";
+       case DIBFMT_DIB8_RLE:
+           return "DIBFMT_DIB8_RLE";
+       case DIBFMT_DIB16_RGB:
+           return "DIBFMT_DIB_RGB";
+       case DIBFMT_DIB16_BITFIELDS:
+           return "DIBFMT_DIB16_BITFIELDS";
+       case DIBFMT_DIB24:
+           return "DIBFMT_DIB24";
+       case DIBFMT_DIB32_RGB:
+           return "DIBFMT_DIB32_RGB";
+       case DIBFMT_DIB32_BITFIELDS:
+           return "DIBFMT_DIB32_BITFIELDS";
+       case DIBFMT_UNKNOWN:
+       default:
+           return "DIBFMT_UNKNOWN";
+   }
+}
+
+/* calculates shift and length given a bit mask */
+static void CalcShiftAndLen(DWORD mask, int *shift, int *len)
+{
+    int s, l;
+
+    /* FIXME----*/
+    if(mask == 0)
+    {
+        FIXME("color mask == 0 -- problem on init_dib\n");
+        *shift = 0;
+        *len = 0;
+        return;
+    }
+    
+    /* calculates bit shift
+       (number of 0's on right of bit field */
+    s = 0;
+    while ((mask & 1) == 0)
+    {
+        mask >>= 1;
+        s++;
+    }
+
+    /* calculates bitfield length
+       (number of 1's in bit field */
+    l = 0;
+    while ((mask & 1) == 1)
+    {
+        mask >>= 1;
+        l++;
+    }
+    *shift = s;
+    *len = l;
+}
+
+/* initializes bit fields from bit masks */
+static void InitBitFields(DIBDRVBITMAP *dib, const DWORD *bit_fields)
+{
+    dib->redMask    = bit_fields[0];
+    dib->greenMask  = bit_fields[1];
+    dib->blueMask   = bit_fields[2];
+    CalcShiftAndLen(dib->redMask,   &dib->redShift,   &dib->redLen);
+    CalcShiftAndLen(dib->greenMask, &dib->greenShift, &dib->greenLen);
+    CalcShiftAndLen(dib->blueMask,  &dib->blueShift,  &dib->blueLen);
+}
+
+/* initializes dib from a bitmap : 
+    dib           dib being initialized
+    bi            source BITMAPINFOHEADER with required DIB format info
+    bit_fields    color masks
+    colorTable    color table, if any
+    bits          pointer to image data array
+    NOTE : DIBDRVBITMAP doesn't owns bits, but do own color table
+*/
+BOOL _DIBDRVBITMAP_InitFromBMIH(DIBDRVBITMAP *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields,
+                     const RGBQUAD *colorTable, void *bits)
+{
+    MAYBE(TRACE("dib=%p, bi=%p, bit_fields=%p, colorTable=%p, bits=%p\n", dib, bi, bit_fields, colorTable, bits));
+    
+    /* initializes DIB dimensions and color depth */
+    dib->bitCount = bi->biBitCount;
+    dib->width     = bi->biWidth;
+    dib->height    = bi->biHeight;
+    dib->stride    = ((dib->width * dib->bitCount + 31) >> 3) & ~3;
+
+    /* initializes image data pointer */
+    dib->bits      = bits;
+    dib->ownsBits = FALSE;
+
+    /* initializes color table */
+    dib->colorTableSize = 0;
+    dib->colorTable = NULL;
+    dib->colorTableGrabbed = FALSE;
+
+    /* checks whether dib is top-down or bottom-up one */
+    if(dib->height < 0)
+    {
+        /* top-down dib */
+        dib->height = -dib->height;
+    }
+    else
+    {
+        /* bottom-up dib */
+        /* data->bits always points to the top-left corner and the stride is -ve */
+        dib->bits    = (BYTE*)dib->bits + (dib->height - 1) * dib->stride;
+        dib->stride  = -dib->stride;
+    }
+
+    /* gets and stores bitmap format */
+    switch(dib->bitCount)
+    {
+        case 24:
+            dib->format = DIBFMT_DIB24;
+            dib->funcs = &DIBDRV_funcs_DIB24;
+            break;
+    
+        case 32:
+    
+            if(bi->biCompression == BI_RGB)
+            {
+                dib->format = DIBFMT_DIB32_RGB;
+                dib->funcs = &DIBDRV_funcs_DIB32_RGB;
+            }
+            else
+            {
+                InitBitFields(dib, bit_fields);
+                dib->format = DIBFMT_DIB32_BITFIELDS;
+                dib->funcs = &DIBDRV_funcs_DIB32_BITFIELDS;
+            }
+            break;
+    
+        case 16:
+            if(bi->biCompression == BI_RGB)
+            {
+                dib->format = DIBFMT_DIB16_RGB;
+                dib->funcs = &DIBDRV_funcs_DIB16_RGB;
+            }
+            else
+            {
+                InitBitFields(dib, bit_fields);
+                dib->format = DIBFMT_DIB16_BITFIELDS;
+                dib->funcs = &DIBDRV_funcs_DIB16_BITFIELDS;
+            }
+            break;
+    
+        case 8:
+            dib->format = DIBFMT_DIB8;
+            dib->funcs = &DIBDRV_funcs_DIB8;
+            dib->colorTableSize = 256;
+            if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
+            break;
+    
+        case 4:
+            dib->format = DIBFMT_DIB4;
+            dib->funcs = &DIBDRV_funcs_DIB4;
+            dib->colorTableSize = 16;
+            if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
+            break;
+    
+        case 1:
+            dib->format = DIBFMT_DIB1;
+            dib->funcs = &DIBDRV_funcs_DIB1;
+            dib->colorTableSize = 2;
+            if(bi->biClrUsed) dib->colorTableSize = bi->biClrUsed;
+            break;
+    
+        default:
+            dib->format = DIBFMT_UNKNOWN;
+            dib->funcs = NULL;
+            FIXME("bpp %d not supported\n", dib->bitCount);
+            return FALSE;
+    }
+    MAYBE(TRACE("DIB FORMAT : %s\n", _DIBDRVBITMAP_GetFormatName(dib)));
+    
+    /* allocates color table and copy it from source, *if* source is
+       not null */
+    if(dib->colorTableSize && colorTable)
+    {
+        if(!(dib->colorTable = HeapAlloc(GetProcessHeap(), 0,
+            dib->colorTableSize * sizeof(dib->colorTable[0]))
+          ))
+        {
+            ERR("HeapAlloc failed\n");
+            return FALSE;
+        }
+        memcpy(dib->colorTable, colorTable,
+            dib->colorTableSize * sizeof(dib->colorTable[0]));
+        dib->colorTableGrabbed = TRUE;
+    }
+    else if(!dib->colorTableSize)
+        /* no color table on more than 8 bits/pixel */
+        dib->colorTableGrabbed = TRUE;
+
+    MAYBE(TRACE("END\n"));
+    return TRUE;
+}
+
+BOOL _DIBDRVBITMAP_InitFromBitmapinfo(DIBDRVBITMAP *dib, BITMAPINFO *bmi)
+{
+    static const DWORD bit_fields_DIB32_RGB[3] = {0xff0000, 0x00ff00, 0x0000ff};
+    static const DWORD bit_fields_DIB16_RGB[3] = {0x7c00, 0x03e0, 0x001f};
+    BITMAPINFOHEADER *bi = (BITMAPINFOHEADER *)bmi;
+    const DWORD *masks = NULL;
+    RGBQUAD *colorTable = NULL;
+    BYTE *ptr = (BYTE*)bmi + bi->biSize;
+    int num_colors = bi->biClrUsed;
+    BOOL res;
+    
+    MAYBE(TRACE("dib=%p, bmi=%p\n", dib, bmi));
+
+    if(bi->biCompression == BI_BITFIELDS)
+    {
+        masks = (DWORD *)ptr;
+        ptr += 3 * sizeof(DWORD);
+    }
+    else if(bi->biBitCount == 32)
+        masks = bit_fields_DIB32_RGB;
+    else if(bi->biBitCount == 16)
+        masks = bit_fields_DIB16_RGB;
+
+    if(!num_colors && bi->biBitCount <= 8)
+        num_colors = 1 << bi->biBitCount;
+    if(num_colors)
+        colorTable = (RGBQUAD*)ptr;
+    ptr += num_colors * sizeof(*colorTable);
+
+    res = _DIBDRVBITMAP_InitFromBMIH(dib, bi, masks, colorTable, ptr);
+    MAYBE(TRACE("END\n"));
+    return res;
+}
+
+/* initializes a DIBRDVBITMAP copying it from a source one
+   Parameters :
+      dib       destination DIBDRVBITMAP
+      src       source DIBDRVBITMAP
+      copy      TRUE->copy source pixel array FALSE->link to source pixel array 
+*/
+BOOL _DIBDRVBITMAP_InitFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, BOOL copy)
+{
+    MAYBE(TRACE("dib=%p, src=%p, copy=%d\n", dib, src, copy));
+    
+    dib->format = src->format;
+    dib->width = src->width;
+    dib->height = src->height;
+    dib->stride = src->stride;
+    dib->bitCount = src->bitCount;
+
+    dib->redMask = src->redMask;
+    dib->greenMask = src->greenMask;
+    dib->blueMask = src->blueMask;
+    dib->redShift = src->redShift;
+    dib->greenShift = src->greenShift;
+    dib->blueShift = src->blueShift;
+    dib->redLen = src->redLen;
+    dib->greenLen = src->greenLen;
+    dib->blueLen = src->blueLen;
+
+    dib->funcs = src->funcs;
+    
+    if(copy)
+    {
+        int size = dib->height*abs(dib->stride);
+        if(!(dib->bits = HeapAlloc(GetProcessHeap(), 0, size)))
+        {
+            ERR("Failed to allocate bits buffer\n");
+            return FALSE;
+        }
+        dib->ownsBits = TRUE;
+
+        /* check for bottom-up DIB */
+        if(dib->stride < 0)
+        {
+            /* copy the bitmap array */
+            memcpy(dib->bits, (BYTE *)src->bits + (src->height - 1) * src->stride, size);
+        
+            dib->bits = (BYTE *)dib->bits - (dib->height-1) * dib->stride;
+        }
+        else
+        {
+            /* copy the bitmap array */
+            memcpy(dib->bits, src->bits, size);
+        }
+    }
+    else
+    {
+        dib->bits = src->bits;
+        dib->ownsBits = FALSE;
+    }
+    
+    if(src->colorTable)
+    {
+        dib->colorTable = HeapAlloc(GetProcessHeap(), 0, src->colorTableSize * sizeof(src->colorTable[0]));
+        memcpy(dib->colorTable, src->colorTable, src->colorTableSize * sizeof(src->colorTable[0]));
+    }
+    else
+        dib->colorTable = NULL;
+    dib->colorTableSize = src->colorTableSize;
+    dib->colorTableGrabbed = TRUE;
+    MAYBE(TRACE("END\n"));
+    return TRUE;
+}
+
+/* creates a DIBRDVBITMAP copying format info from a source one
+   Parameters :
+      dib            destination DIBDRVBITMAP
+      src            source DIBDRVBITMAP
+      widht, height  sizes of newly created bitmap 
+*/
+BOOL _DIBDRVBITMAP_CreateFromDibdrvbitmap(DIBDRVBITMAP *dib, const DIBDRVBITMAP *src, int width, int height)
+{
+    MAYBE(TRACE("dib=%p, src=%p, width=%d, height=%d\n", dib, src, width, height));
+    
+    /* grab color and format info from source DIB */
+    if(!_DIBDRVBITMAP_InitFromDibdrvbitmap(dib, src, FALSE))
+    {
+        ERR("Failed grabbing source dib format\n");
+        return FALSE;
+    }
+    
+    /* sets up new DIB dimensions */
+    dib->width = width;
+    dib->height = height;
+    
+    /* calculates new stride basing of new width */
+    dib->stride = ((width * dib->bitCount +31) &~31) / 8;
+    if(src->stride < 0)
+        dib->stride = -dib->stride;
+    
+    /* allocates bits for newly created DIB */
+    if(!(dib->bits = HeapAlloc(GetProcessHeap(), 0, height*abs(dib->stride))))
+    {
+        ERR("Failed to allocate bits buffer\n");
+        return FALSE;
+    }
+    /* check for bottom-up DIB */
+    if(dib->stride < 0)
+        dib->bits = (BYTE *)dib->bits - (dib->height-1) * dib->stride;
+    dib->ownsBits = TRUE;
+    
+    MAYBE(TRACE("END\n"));
+    return TRUE;
+ }
+
+/* Clears a DIBDRVBITMAP structure data
+   WARNING : doesn't free anything */
+void _DIBDRVBITMAP_Clear(DIBDRVBITMAP *bmp)
+{
+    MAYBE(TRACE("bmp=%p\n", bmp));
+    
+    bmp->bits = NULL;
+    bmp->ownsBits = FALSE;
+    bmp->colorTable = NULL;
+    bmp->colorTableSize = 0;
+    bmp->colorTableGrabbed = FALSE;
+    
+    MAYBE(TRACE("END\n"));
+}
+
+/* Frees a DIBDRVBITMAP structure data */
+void _DIBDRVBITMAP_Free(DIBDRVBITMAP *bmp)
+{
+    MAYBE(TRACE("bmp=%p\n", bmp));
+    
+    /* frees bits, if needed */
+    if(bmp->bits && bmp->ownsBits)
+    {
+        /* on bottom-up dibs, bits doesn't point to starting
+           of buffer.... bad design choice */
+        if(bmp->stride < 0)
+            bmp->bits = (BYTE *)bmp->bits + bmp->stride * (bmp->height -1);
+        HeapFree(GetProcessHeap(), 0, bmp->bits);
+    }
+    bmp->ownsBits = FALSE;
+    bmp->bits = NULL;
+    
+    /* frees color table */
+    if(bmp->colorTable)
+        HeapFree(GetProcessHeap(), 0, bmp->colorTable);
+    bmp->colorTable = NULL;
+    bmp->colorTableSize = 0;
+    bmp->colorTableGrabbed = FALSE;
+    
+    MAYBE(TRACE("END\n"));
+}
+
+
+/* checks whether the format of 2 DIBs are identical
+   it checks the pixel bit count and the color table size
+   and content, if needed */
+BOOL _DIBDRVBITMAP_FormatMatch(const DIBDRVBITMAP *d1, const DIBDRVBITMAP *d2)
+{
+    /* checks at first the format (bit count and color masks) */
+    if(d1->format != d2->format)
+        return FALSE;
+
+    /* formats matches, now checks color tables if needed */
+    switch(d1->format)
+    {
+        case DIBFMT_DIB32_RGB :
+        case DIBFMT_DIB32_BITFIELDS :
+        case DIBFMT_DIB24 :
+        case DIBFMT_DIB16_RGB :
+        case DIBFMT_DIB16_BITFIELDS :
+            return TRUE;
+
+        case DIBFMT_DIB1 :
+        case DIBFMT_DIB4 :
+        /*case DIBFMT_DIB4_RLE :*/
+        case DIBFMT_DIB8 :
+        /*case DIBFMT_DIB8_RLE :*/
+            if(d1->colorTableSize != d2->colorTableSize)
+                return FALSE;
+        return !memcmp(d1->colorTable, d2->colorTable, d1->colorTableSize * sizeof(d1->colorTable[0]));
+
+    default:
+        ERR("Unexpected depth %d\n", d1->bitCount);
+        return FALSE;
+    }
+}
+
+/* convert a given dib into another format given by 'format' parameter */
+BOOL _DIBDRVBITMAP_Convert(DIBDRVBITMAP *dst, const DIBDRVBITMAP *src, const DIBDRVBITMAP *format)
+{
+    int width, height;
+    int iLine;
+    void *buf;
+    BOOL res;
+    
+    MAYBE(TRACE("dst=%p, src=%p, format=%p\n", dst, src, format));
+    
+    /* free, if needed, destination bitmap */
+    _DIBDRVBITMAP_Free(dst);
+    
+    /* if format and source bitmaps format match,
+       just copy source on destination */
+    if(_DIBDRVBITMAP_FormatMatch(src, format))
+    {
+        res = _DIBDRVBITMAP_InitFromDibdrvbitmap(dst, src, TRUE);
+        MAYBE(TRACE("END - Identical formats\n"));
+        return res;
+    }
+
+    /* formats don't match, we create the dest bitmap with same format as format's one
+       but with source's one dimensions */
+    width = src->width;
+    height = src->height;
+    if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(dst, format, width, height))
+    {
+        ERR("Couldn't create destination bmp\n");
+        return FALSE;
+    }
+    
+    /* we now copy/convert from source to dest */
+    if(!(buf = HeapAlloc(GetProcessHeap(), 0, width * 4)))
+    {
+        ERR("HeapAlloc failed\n");
+        return FALSE;
+    }
+
+    for(iLine = 0; iLine < height; iLine++)
+    {
+        src->funcs->GetLine(src, iLine, 0, width, buf);
+        dst->funcs->PutLine(dst, iLine, 0, width, buf);
+    }
+    HeapFree(GetProcessHeap(), 0, buf);
+    
+    MAYBE(TRACE("END - different formats\n"));
+    return TRUE;
+}
+
+/* creates a solid-filled DIB of given color and format
+   DIB format is given by 'format' parameter */
+BOOL _DIBDRVBITMAP_CreateSolid(DIBDRVBITMAP *bmp, DIBDRVBITMAP *format, int width, int height, DWORD Color)
+{
+    DWORD *buf, *bufPnt;
+    int i;
+    
+    MAYBE(TRACE("bmp=%p, format=%p, width=%d, height=%d, Color=%08x\n", bmp, format, width, height, Color));
+    
+    /* swaps color bytes....*/
+    Color = RGB((Color >> 8) & 0xff, (Color >> 16) &0xff, Color &0xff);
+    
+    /* creates the destination bitmap */
+    if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(bmp, format, width, height))
+    {
+        ERR("Couldn't create destination bmp\n");
+        return FALSE;
+    }
+       
+    /* creates a temporary line filled with given color */
+    if(!(buf = HeapAlloc(GetProcessHeap(), 0, width * 4)))
+    {
+        ERR("HeapAlloc failed\n");
+        return FALSE;
+    }
+    
+    for(i = 0, bufPnt = buf; i < width; i++)
+        *bufPnt++ = Color;
+    
+    /* fills the bitmap */
+    for(i = 0; i < height; i++)
+        bmp->funcs->PutLine(bmp, i, 0, width, buf);
+    
+    /* frees temporaty line */
+    HeapFree(GetProcessHeap(), 0, buf);
+    
+    MAYBE(TRACE("END\n"));
+    return TRUE;
+}
+
+/* expands horizontally a bitmap to reach a minimum size,
+   keeping its width as a multiple of a base width
+   Used to widen brushes in order to optimize blitting */
+BOOL _DIBDRVBITMAP_ExpandHoriz(DIBDRVBITMAP *dib, int baseWidth, int minWidth)
+{
+    BYTE *srcBuf, *dstBuf;
+    int chunkSize;
+    int iLine, iCol;
+    DIBDRVBITMAP tmpDib;
+    void *bits;
+    BOOL ownsBits;
+    
+    MAYBE(TRACE("dib=%p, baseWidth=%d, minWidth=%d\n", dib, baseWidth, minWidth));
+
+    /* if dst dib already wide enough, just do nothing */
+    if(dib->width >= minWidth)
+    {
+        MAYBE(TRACE("END - No need to expand\n"));
+        return TRUE;
+    }
+
+    /* source DIB can't be NULL */
+    if(!dib->bits)
+    {
+        ERR("Empty source DIB detected\n");
+        return FALSE;
+    }
+    
+    /* round up minWidth to be a multiple of source width */
+    minWidth += (baseWidth - (minWidth % baseWidth));
+    
+    /* creates a temporary destination bitmap with required sizes */
+    _DIBDRVBITMAP_Clear(&tmpDib);
+    if(!_DIBDRVBITMAP_CreateFromDibdrvbitmap(&tmpDib, dib, minWidth, dib->height))
+    {
+        ERR("Couldn't create the temporary DIB for brush cache\n");
+        return FALSE;
+    }
+
+    /* if format uses almost 1 byte/pixel, fast copy path */
+    if(dib->bitCount >= 8)
+    {
+        chunkSize = dib->width * dib->bitCount / 8;
+        for(iLine = 0; iLine < dib->height; iLine++)
+        {
+            srcBuf = (BYTE *)dib->bits + iLine * dib->stride;
+            dstBuf = (BYTE *)tmpDib.bits + iLine * tmpDib.stride;
+            for(iCol = 0; iCol < tmpDib.width; iCol += dib->width)
+            {
+                memcpy(dstBuf, srcBuf, chunkSize);
+                dstBuf += chunkSize;
+            }
+        }
+    }
+    /* otherwise slow path -- could be optimized */
+    else
+    {
+        chunkSize = dib->width * 4;
+        /* allocates a line buffer */
+        if(!(srcBuf = HeapAlloc(GetProcessHeap(), 0, tmpDib.width * 4)))
+        {
+            ERR("HeapAlloc failed\n");
+            return FALSE;
+        }
+        
+        FIXME("dib:format=%s, funcs=%p, bits=%p, width=%d, height=%d, stride=%d\n",
+            _DIBDRVBITMAP_GetFormatName(dib), dib->funcs, dib->bits, dib->width, dib->height, dib->stride);
+        for(iLine = 0; iLine < dib->height; iLine++)
+        {
+            /* fills the line buffer repeating source's line data */
+             dib->funcs->GetLine(dib, iLine, 0, dib->width, srcBuf);
+             dstBuf = srcBuf + chunkSize;
+            for(iCol = dib->width; iCol < tmpDib.width; iCol += dib->width)
+            {
+                memcpy(dstBuf, srcBuf, chunkSize);
+                dstBuf += chunkSize;
+            }
+             /* stores the line on destination bmp */
+            tmpDib.funcs->PutLine(&tmpDib, iLine, 0, tmpDib.width, srcBuf);
+        }
+        HeapFree(GetProcessHeap(), 0, srcBuf);
+    }
+    
+    /* swaps temp DIB and source one */
+    bits = dib->bits;
+    ownsBits = dib->ownsBits;
+    dib->bits = tmpDib.bits;
+    dib->ownsBits = tmpDib.ownsBits;
+    tmpDib.bits = bits;
+    tmpDib.ownsBits = ownsBits;
+    
+    /* frees the temporary DIB */
+    _DIBDRVBITMAP_Free(&tmpDib);
+   
+    MAYBE(TRACE("END\n"));
+    return TRUE;
+}
diff --git a/dlls/winedib.drv/driver.c b/dlls/winedib.drv/driver.c
new file mode 100644
index 0000000..46fa7a1
--- /dev/null
+++ b/dlls/winedib.drv/driver.c
@@ -0,0 +1,254 @@
+/*
+ * Access to display driver
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+#include <stdio.h>
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* CreateDriver
+ * Allocate and fill the function pointer structure for a given module. */
+static DC_FUNCTIONS *CreateDriver( HMODULE module )
+{
+    DC_FUNCTIONS *funcs;
+
+    if (!(funcs = HeapAlloc( GetProcessHeap(), 0, sizeof(*funcs))))
+        return NULL;
+
+    /* fill the function table */
+    if (module)
+    {
+#define GET_FUNC(name) funcs->p##name = (void*)GetProcAddress( module, #name )
+        GET_FUNC(AbortDoc);
+        GET_FUNC(AbortPath);
+        GET_FUNC(AlphaBlend);
+        GET_FUNC(AngleArc);
+        GET_FUNC(Arc);
+        GET_FUNC(ArcTo);
+        GET_FUNC(BeginPath);
+        GET_FUNC(BitBlt);
+        GET_FUNC(ChoosePixelFormat);
+        GET_FUNC(Chord);
+        GET_FUNC(CloseFigure);
+        GET_FUNC(CreateBitmap);
+        GET_FUNC(CreateDC);
+        GET_FUNC(CreateDIBSection);
+        GET_FUNC(DeleteBitmap);
+        GET_FUNC(DeleteDC);
+        GET_FUNC(DescribePixelFormat);
+        GET_FUNC(DeviceCapabilities);
+        GET_FUNC(Ellipse);
+        GET_FUNC(EndDoc);
+        GET_FUNC(EndPage);
+        GET_FUNC(EndPath);
+        GET_FUNC(EnumDeviceFonts);
+        GET_FUNC(ExcludeClipRect);
+        GET_FUNC(ExtDeviceMode);
+        GET_FUNC(ExtEscape);
+        GET_FUNC(ExtFloodFill);
+        GET_FUNC(ExtSelectClipRgn);
+        GET_FUNC(ExtTextOut);
+        GET_FUNC(FillPath);
+        GET_FUNC(FillRgn);
+        GET_FUNC(FlattenPath);
+        GET_FUNC(FrameRgn);
+        GET_FUNC(GdiComment);
+        GET_FUNC(GetBitmapBits);
+        GET_FUNC(GetCharWidth);
+        GET_FUNC(GetDCOrgEx);
+        GET_FUNC(GetDIBColorTable);
+        GET_FUNC(GetDIBits);
+        GET_FUNC(GetDeviceCaps);
+        GET_FUNC(GetDeviceGammaRamp);
+        GET_FUNC(GetICMProfile);
+        GET_FUNC(GetNearestColor);
+        GET_FUNC(GetPixel);
+        GET_FUNC(GetPixelFormat);
+        GET_FUNC(GetSystemPaletteEntries);
+        GET_FUNC(GetTextExtentExPoint);
+        GET_FUNC(GetTextMetrics);
+        GET_FUNC(IntersectClipRect);
+        GET_FUNC(InvertRgn);
+        GET_FUNC(LineTo);
+        GET_FUNC(MoveTo);
+        GET_FUNC(ModifyWorldTransform);
+        GET_FUNC(OffsetClipRgn);
+        GET_FUNC(OffsetViewportOrg);
+        GET_FUNC(OffsetWindowOrg);
+        GET_FUNC(PaintRgn);
+        GET_FUNC(PatBlt);
+        GET_FUNC(Pie);
+        GET_FUNC(PolyBezier);
+        GET_FUNC(PolyBezierTo);
+        GET_FUNC(PolyDraw);
+        GET_FUNC(PolyPolygon);
+        GET_FUNC(PolyPolyline);
+        GET_FUNC(Polygon);
+        GET_FUNC(Polyline);
+        GET_FUNC(PolylineTo);
+        GET_FUNC(RealizeDefaultPalette);
+        GET_FUNC(RealizePalette);
+        GET_FUNC(Rectangle);
+        GET_FUNC(ResetDC);
+        GET_FUNC(RestoreDC);
+        GET_FUNC(RoundRect);
+        GET_FUNC(SaveDC);
+        GET_FUNC(ScaleViewportExt);
+        GET_FUNC(ScaleWindowExt);
+        GET_FUNC(SelectBitmap);
+        GET_FUNC(SelectBrush);
+        GET_FUNC(SelectClipPath);
+        GET_FUNC(SelectFont);
+        GET_FUNC(SelectPalette);
+        GET_FUNC(SelectPen);
+        GET_FUNC(SetArcDirection);
+        GET_FUNC(SetBitmapBits);
+        GET_FUNC(SetBkColor);
+        GET_FUNC(SetBkMode);
+        GET_FUNC(SetDCBrushColor);
+        GET_FUNC(SetDCOrg);
+        GET_FUNC(SetDCPenColor);
+        GET_FUNC(SetDIBColorTable);
+        GET_FUNC(SetDIBits);
+        GET_FUNC(SetDIBitsToDevice);
+        GET_FUNC(SetDeviceClipping);
+        GET_FUNC(SetDeviceGammaRamp);
+        GET_FUNC(SetMapMode);
+        GET_FUNC(SetMapperFlags);
+        GET_FUNC(SetPixel);
+        GET_FUNC(SetPixelFormat);
+        GET_FUNC(SetPolyFillMode);
+        GET_FUNC(SetROP2);
+        GET_FUNC(SetRelAbs);
+        GET_FUNC(SetStretchBltMode);
+        GET_FUNC(SetTextAlign);
+        GET_FUNC(SetTextCharacterExtra);
+        GET_FUNC(SetTextColor);
+        GET_FUNC(SetTextJustification);
+        GET_FUNC(SetViewportExt);
+        GET_FUNC(SetViewportOrg);
+        GET_FUNC(SetWindowExt);
+        GET_FUNC(SetWindowOrg);
+        GET_FUNC(SetWorldTransform);
+        GET_FUNC(StartDoc);
+        GET_FUNC(StartPage);
+        GET_FUNC(StretchBlt);
+        GET_FUNC(StretchDIBits);
+        GET_FUNC(StrokeAndFillPath);
+        GET_FUNC(StrokePath);
+        GET_FUNC(SwapBuffers);
+        GET_FUNC(UnrealizePalette);
+        GET_FUNC(WidenPath);
+
+        /* OpenGL32 */
+        GET_FUNC(wglCreateContext);
+        GET_FUNC(wglDeleteContext);
+        GET_FUNC(wglGetProcAddress);
+        GET_FUNC(wglGetPbufferDCARB);
+        GET_FUNC(wglMakeContextCurrentARB);
+        GET_FUNC(wglMakeCurrent);
+        GET_FUNC(wglSetPixelFormatWINE);
+        GET_FUNC(wglShareLists);
+        GET_FUNC(wglUseFontBitmapsA);
+        GET_FUNC(wglUseFontBitmapsW);
+#undef GET_FUNC
+    }
+    else
+        memset( funcs, 0, sizeof(*funcs) );
+
+    /* add it to the list */
+    return funcs;
+}
+
+
+/* LoadDisplayDriver
+ * Loads display driver - partially grabbed from gdi32 */
+static DC_FUNCTIONS *X11DrvFuncs = NULL;
+static HMODULE X11DrvModule = 0;
+DC_FUNCTIONS *_DIBDRV_LoadDisplayDriver(void)
+{
+    char buffer[MAX_PATH], libname[32], *name, *next;
+    HMODULE module = 0;
+    HKEY hkey;
+
+    if (X11DrvFuncs)  /* already loaded */
+        return X11DrvFuncs;
+    
+    strcpy( buffer, "x11" );  /* default value */
+    /* @@ Wine registry key: HKCU\Software\Wine\Drivers */
+    if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Drivers", &hkey ))
+    {
+        DWORD type, count = sizeof(buffer);
+        RegQueryValueExA( hkey, "Graphics", 0, &type, (LPBYTE) buffer, &count );
+        RegCloseKey( hkey );
+    }
+
+    name = buffer;
+    while (name)
+    {
+        next = strchr( name, ',' );
+        if (next)
+            *next++ = 0;
+
+        snprintf( libname, sizeof(libname), "wine%s.drv", name );
+        if ((module = LoadLibraryA( libname )) != 0)
+            break;
+        name = next;
+    }
+
+    if (!(X11DrvFuncs = CreateDriver(module)))
+    {
+        ERR( "Could not create graphics driver '%s'\n", buffer );
+        FreeLibrary( module );
+        ExitProcess(1);
+    }
+
+    X11DrvModule = module;
+    return X11DrvFuncs;
+}
+
+/* FreeDisplayDriver
+   Frees resources allocated by Display driver */
+void _DIBDRV_FreeDisplayDriver(void)
+{
+    /* frees function table */
+    if(X11DrvFuncs)
+    {
+        HeapFree(GetProcessHeap(), 0, X11DrvFuncs);
+        X11DrvFuncs = 0;
+    }
+    /* and unload the module */
+    if(X11DrvModule)
+    {
+        FreeLibrary(X11DrvModule);
+        X11DrvModule = 0;
+    }
+}
+
+/* GetDisplayDriver
+   Gets a pointer to display drives'function table */
+inline DC_FUNCTIONS *_DIBDRV_GetDisplayDriver(void)
+{
+    return X11DrvFuncs;
+
+}
diff --git a/dlls/winedib.drv/font.c b/dlls/winedib.drv/font.c
index 675145f..215b27d 100644
--- a/dlls/winedib.drv/font.c
+++ b/dlls/winedib.drv/font.c
@@ -32,14 +32,40 @@ WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 {
     COLORREF res;
+    INT r, g, b;
+    INT i;
     
-    TRACE("physDev:%p, color:%08x\n", physDev, color);
+    MAYBE(TRACE("physDev:%p, color:%08x\n", physDev, color));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetTextColor(physDev->X11PhysDev, color);
+
+        /* do nothing if color is the same as actual one */
+        if(color == physDev->textColor)
+            return color;
+
+        /* stores old color */
+        res = physDev->textColor;
+        
+        /* fills the text color table used on antialiased font display */
+        if(physDev->physBitmap.funcs)
+        {
+            r = GetRValue(color);
+            g = GetGValue(color);
+            b = GetBValue(color);
+            for(i = 0; i < 256; i++)
+            {
+                physDev->textColorTable[i] = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, RGB(
+                    MulDiv(r, i, 256),
+                    MulDiv(g, i, 256),
+                    MulDiv(b, i, 256)
+                ));               
+            }
+        }
+        
+        /* returns previous text color */
+        return res;
     }
     else
     {
@@ -52,17 +78,75 @@ COLORREF DIBDRV_SetTextColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 /***********************************************************************
  *           DIBDRV_SelectFont
  */
-HFONT DIBDRV_SelectFont( DIBDRVPHYSDEV *physDev, HFONT hfont, HANDLE gdiFont )
+HFONT DIBDRV_SelectFont( DIBDRVPHYSDEV *physDev, HFONT hfont, GdiFont *gdiFont )
 {
     HFONT res;
+    FT_Int      i;
+    FT_Error    error;
+    FT_CharMap  charmap = NULL;
+    LOGFONTW lf;
     
-    TRACE("physDev:%p, hfont:%p, gdiFont:%p\n", physDev, hfont, gdiFont);
+    MAYBE(TRACE("physDev:%p, hfont:%p, gdiFont:%p\n", physDev, hfont, gdiFont));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSelectFont(physDev->X11PhysDev, hfont, gdiFont);
+
+        /* gets font information */
+        GetObjectW(hfont, sizeof(lf), &lf);
+        MAYBE(TRACE("Font is : '%s'\n", debugstr_w(lf.lfFaceName)));
+        
+        /* FIXME: just handles gdifont, don't know if it needs to handle hfont too
+           BTW, still don't know how to get FT_Face from non-gdi font here
+        */
+        if(!gdiFont)
+        {
+            FIXME("No gdi font - unhandled by now.\n");
+            return hfont;
+        }
+
+        physDev->face = gdiFont->ft_face;
+        if(!physDev->face)
+        {
+            FIXME("Error, null Ft_Face\n");
+            return hfont;
+        }
+
+        /* setup the correct charmap.... maybe */
+        for (i = 0; i < physDev->face->num_charmaps; ++i)
+        {
+            if (physDev->face->charmaps[i]->platform_id != TT_PLATFORM_MICROSOFT)
+            continue;
+
+            if (physDev->face->charmaps[i]->encoding_id == TT_MS_ID_UNICODE_CS)
+            {
+                charmap = physDev->face->charmaps[i];
+                break;
+            }
+
+            if (charmap == NULL)
+            {
+                WARN("Selected fallout charmap #%d\n", i);
+                charmap = physDev->face->charmaps[i];
+            }
+        }
+        if (charmap == NULL)
+        {
+            WARN("No Windows character map found\n");
+            charmap = physDev->face->charmaps[0];
+            return 0;
+        }
+
+        error = pFT_Set_Charmap(physDev->face, charmap);
+        if (error != FT_Err_Ok)
+        {
+            ERR("%s returned %i\n", "FT_Set_Charmap", error);
+            return 0;
+        }
+
+        /* we use GDI fonts, so just return false */
+        return 0;
+
     }
     else
     {
@@ -80,13 +164,13 @@ BOOL DIBDRV_EnumDeviceFonts( DIBDRVPHYSDEV *physDev, LPLOGFONTW plf,
 {
     BOOL res;
     
-    TRACE("physDev:%p, plf:%p, proc:%p, lp:%lx\n", physDev, plf, proc, lp);
+    MAYBE(TRACE("physDev:%p, plf:%p, proc:%p, lp:%lx\n", physDev, plf, proc, lp));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pEnumDeviceFonts(physDev->X11PhysDev, plf, proc, lp);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
@@ -103,13 +187,13 @@ BOOL DIBDRV_GetTextMetrics( DIBDRVPHYSDEV *physDev, TEXTMETRICW *metrics )
 {
     BOOL res;
     
-    TRACE("physDev:%p, metrics:%p\n", physDev, metrics);
+    MAYBE(TRACE("physDev:%p, metrics:%p\n", physDev, metrics));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetTextMetrics(physDev->X11PhysDev, metrics);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
@@ -127,13 +211,13 @@ BOOL DIBDRV_GetCharWidth( DIBDRVPHYSDEV *physDev, UINT firstChar, UINT lastChar,
 {
     BOOL res;
     
-    TRACE("physDev:%p, firstChar:%d, lastChar:%d, buffer:%pn", physDev, firstChar, lastChar, buffer);
+    MAYBE(TRACE("physDev:%p, firstChar:%d, lastChar:%d, buffer:%pn", physDev, firstChar, lastChar, buffer));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetCharWidth(physDev->X11PhysDev, firstChar, lastChar, buffer);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
diff --git a/dlls/winedib.drv/freetype.c b/dlls/winedib.drv/freetype.c
new file mode 100644
index 0000000..111a18b
--- /dev/null
+++ b/dlls/winedib.drv/freetype.c
@@ -0,0 +1,136 @@
+/*
+ * Truetype font functions
+ *
+ * Copyright 2008 Massimo Del Fedele
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+#define MAKE_FUNCPTR(f) typeof(f) * p##f = NULL;
+MAKE_FUNCPTR(FT_Done_Face)
+MAKE_FUNCPTR(FT_Done_FreeType)
+MAKE_FUNCPTR(FT_Get_Char_Index)
+MAKE_FUNCPTR(FT_Get_Glyph_Name)
+MAKE_FUNCPTR(FT_Get_Sfnt_Name)
+MAKE_FUNCPTR(FT_Get_Sfnt_Name_Count)
+MAKE_FUNCPTR(FT_Get_Sfnt_Table)
+MAKE_FUNCPTR(FT_Init_FreeType)
+MAKE_FUNCPTR(FT_Load_Glyph)
+MAKE_FUNCPTR(FT_Load_Char)
+MAKE_FUNCPTR(FT_Get_Glyph)
+MAKE_FUNCPTR(FT_Glyph_Copy)
+MAKE_FUNCPTR(FT_Glyph_To_Bitmap)
+MAKE_FUNCPTR(FT_Done_Glyph)
+MAKE_FUNCPTR(FT_New_Face)
+MAKE_FUNCPTR(FT_Set_Charmap)
+MAKE_FUNCPTR(FT_Set_Char_Size)
+MAKE_FUNCPTR(FT_Set_Pixel_Sizes)
+MAKE_FUNCPTR(FT_Get_First_Char)
+MAKE_FUNCPTR(FT_Render_Glyph)
+MAKE_FUNCPTR(FT_Glyph_Transform)
+#undef MAKE_FUNCPTR
+
+/* freetype initialization flag */
+static BOOL FreeType_Initialized = FALSE;
+
+/* freetype dll handle */
+static void *ft_handle = NULL;
+
+/* freetype library handle */
+FT_Library DIBDRV_ftLibrary = NULL;
+
+/* initialize freetype library */
+BOOL _DIBDRV_FreeType_Init(void)
+{
+    FT_Int error;
+    
+    ft_handle = wine_dlopen(SONAME_LIBFREETYPE, RTLD_NOW, NULL, 0);
+    if(!ft_handle)
+    {
+        WINE_MESSAGE(
+            "Wine cannot find the FreeType font library.  To enable Wine to\n"
+            "use TrueType fonts please install a version of FreeType greater than\n"
+            "or equal to 2.0.5.\n"
+            "http://www.freetype.org\n");
+        return FALSE;
+    }
+
+#define LOAD_FUNCPTR(f) if((p##f = wine_dlsym(ft_handle, #f, NULL, 0)) == NULL) goto sym_not_found;
+    LOAD_FUNCPTR(FT_Done_Face)
+    LOAD_FUNCPTR(FT_Done_FreeType)
+    LOAD_FUNCPTR(FT_Get_Char_Index)
+    LOAD_FUNCPTR(FT_Get_Glyph_Name)
+    LOAD_FUNCPTR(FT_Get_Sfnt_Name)
+    LOAD_FUNCPTR(FT_Get_Sfnt_Name_Count)
+    LOAD_FUNCPTR(FT_Get_Sfnt_Table)
+    LOAD_FUNCPTR(FT_Init_FreeType)
+    LOAD_FUNCPTR(FT_Load_Glyph)
+    LOAD_FUNCPTR(FT_Load_Char)
+    LOAD_FUNCPTR(FT_Get_Glyph)
+    LOAD_FUNCPTR(FT_Glyph_Copy)
+    LOAD_FUNCPTR(FT_Glyph_To_Bitmap)
+    LOAD_FUNCPTR(FT_Done_Glyph)
+    LOAD_FUNCPTR(FT_New_Face)
+    LOAD_FUNCPTR(FT_Set_Charmap)
+    LOAD_FUNCPTR(FT_Set_Char_Size)
+    LOAD_FUNCPTR(FT_Set_Pixel_Sizes)
+    LOAD_FUNCPTR(FT_Get_First_Char)
+    LOAD_FUNCPTR(FT_Render_Glyph)
+    LOAD_FUNCPTR(FT_Glyph_Transform)
+#undef LOAD_FUNCPTR
+
+    error = pFT_Init_FreeType(&DIBDRV_ftLibrary);
+    if (error != FT_Err_Ok)
+    {
+        ERR("%s returned %i\n", "FT_Init_FreeType", error);
+        wine_dlclose(ft_handle, NULL, 0);
+        return FALSE;
+    }
+
+    /* marks library as initialized */
+    FreeType_Initialized = TRUE;
+
+    return TRUE;
+    
+sym_not_found:
+    WINE_MESSAGE(
+      "Wine cannot find certain functions that it needs inside the FreeType\n"
+      "font library.  To enable Wine to use TrueType fonts please upgrade\n"
+      "FreeType to at least version 2.0.5.\n"
+      "http://www.freetype.org\n");
+    wine_dlclose(ft_handle, NULL, 0);
+    ft_handle = NULL;
+    return FALSE;
+}
+
+/* terminates freetype library */
+void _DIBDRV_FreeType_Terminate(void)
+{
+    if(!FreeType_Initialized)
+        return;
+    
+    /* terminates and unload freetype library */
+    pFT_Done_FreeType(DIBDRV_ftLibrary);
+    wine_dlclose(ft_handle, NULL, 0);
+    ft_handle = NULL;
+    FreeType_Initialized = FALSE;
+    
+}
diff --git a/dlls/winedib.drv/freetype.h b/dlls/winedib.drv/freetype.h
new file mode 100644
index 0000000..93619ff
--- /dev/null
+++ b/dlls/winedib.drv/freetype.h
@@ -0,0 +1,186 @@
+/*
+ * Truetype font functions
+ *
+ * Copyright 2008 Massimo Del Fedele
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef __WINE_DIBDRV_FREETYPE_H
+#define __WINE_DIBDRV__FREETYPE_H
+
+/* freetype library for font support */
+#ifdef HAVE_FREETYPE
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_GLYPH_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+
+/* freetype library handle */
+extern FT_Library DIBDRV_ftLibrary;
+
+/******************************************************************************************/
+/*                                     FREETYPE STUFFS                                    */
+/* grabbed from winex11.drv/freetype.c                                                    */
+/******************************************************************************************/
+
+/* This is basically a copy of FT_Bitmap_Size with an extra element added */
+typedef struct {
+    FT_Short height;
+    FT_Short width;
+    FT_Pos size;
+    FT_Pos x_ppem;
+    FT_Pos y_ppem;
+    FT_Short internal_leading;
+} Bitmap_Size;
+
+/* FT_Bitmap_Size gained 3 new elements between FreeType 2.1.4 and 2.1.5
+   So to let this compile on older versions of FreeType we'll define the
+   new structure here. */
+typedef struct {
+    FT_Short height, width;
+    FT_Pos size, x_ppem, y_ppem;
+} My_FT_Bitmap_Size;
+
+struct enum_data
+{
+    ENUMLOGFONTEXW elf;
+    NEWTEXTMETRICEXW ntm;
+    DWORD type;
+};
+
+typedef struct tagFace {
+    struct list entry;
+    WCHAR *StyleName;
+    char *file;
+    void *font_data_ptr;
+    DWORD font_data_size;
+    FT_Long face_index;
+    FONTSIGNATURE fs;
+    FONTSIGNATURE fs_links;
+    DWORD ntmFlags;
+    FT_Fixed font_version;
+    BOOL scalable;
+    Bitmap_Size size;     /* set if face is a bitmap */
+    BOOL external; /* TRUE if we should manually add this font to the registry */
+    struct tagFamily *family;
+    /* Cached data for Enum */
+    struct enum_data *cached_enum_data;
+} Face;
+
+typedef struct tagFamily {
+    struct list entry;
+    const WCHAR *FamilyName;
+    struct list faces;
+} Family;
+
+typedef struct {
+    GLYPHMETRICS gm;
+    INT adv; /* These three hold to widths of the unrotated chars */
+    INT lsb;
+    INT bbx;
+    BOOL init;
+} GM;
+
+typedef struct {
+    FLOAT eM11, eM12;
+    FLOAT eM21, eM22;
+} FMAT2;
+
+typedef struct {
+    DWORD hash;
+    LOGFONTW lf;
+    FMAT2 matrix;
+    BOOL can_use_bitmap;
+} FONT_DESC;
+
+typedef struct tagHFONTLIST {
+    struct list entry;
+    HFONT hfont;
+} HFONTLIST;
+
+typedef struct {
+    struct list entry;
+    Face *face;
+    struct tagGdiFont *font;
+} CHILD_FONT;
+
+typedef struct tagGdiFont {
+    struct list entry;
+    GM **gm;
+    DWORD gmsize;
+    struct list hfontlist;
+    OUTLINETEXTMETRICW *potm;
+    DWORD total_kern_pairs;
+    KERNINGPAIR *kern_pairs;
+    struct list child_fonts;
+
+    /* the following members can be accessed without locking, they are never modified after creation */
+    FT_Face ft_face;
+    struct font_mapping *mapping;
+    LPWSTR name;
+    int charset;
+    int codepage;
+    BOOL fake_italic;
+    BOOL fake_bold;
+    BYTE underline;
+    BYTE strikeout;
+    INT orientation;
+    FONT_DESC font_desc;
+    LONG aveWidth, ppem;
+    double scale_y;
+    SHORT yMax;
+    SHORT yMin;
+    DWORD ntmFlags;
+    FONTSIGNATURE fs;
+    struct tagGdiFont *base_font;
+    VOID *GSUB_Table;
+    DWORD cache_num;
+} GdiFont;
+
+/* initialize freetype library */
+BOOL _DIBDRV_FreeType_Init(void);
+
+/* terminates freetype library */
+void _DIBDRV_FreeType_Terminate(void);
+
+#define MAKE_FUNCPTR(f) extern typeof(f) * p##f;
+MAKE_FUNCPTR(FT_Done_Face)
+MAKE_FUNCPTR(FT_Done_FreeType)
+MAKE_FUNCPTR(FT_Get_Char_Index)
+MAKE_FUNCPTR(FT_Get_Glyph_Name)
+MAKE_FUNCPTR(FT_Get_Sfnt_Name)
+MAKE_FUNCPTR(FT_Get_Sfnt_Name_Count)
+MAKE_FUNCPTR(FT_Get_Sfnt_Table)
+MAKE_FUNCPTR(FT_Init_FreeType)
+MAKE_FUNCPTR(FT_Load_Glyph)
+MAKE_FUNCPTR(FT_Load_Char)
+MAKE_FUNCPTR(FT_Get_Glyph)
+MAKE_FUNCPTR(FT_Glyph_Copy)
+MAKE_FUNCPTR(FT_Glyph_To_Bitmap)
+MAKE_FUNCPTR(FT_Done_Glyph)
+MAKE_FUNCPTR(FT_New_Face)
+MAKE_FUNCPTR(FT_Set_Charmap)
+MAKE_FUNCPTR(FT_Set_Char_Size)
+MAKE_FUNCPTR(FT_Set_Pixel_Sizes)
+MAKE_FUNCPTR(FT_Get_First_Char)
+MAKE_FUNCPTR(FT_Render_Glyph)
+MAKE_FUNCPTR(FT_Glyph_Transform)
+#undef MAKE_FUNCPTR
+
+#endif /* HAVE_FREETYPE */
+
+#endif
diff --git a/dlls/winedib.drv/graphics.c b/dlls/winedib.drv/graphics.c
index b74c08e..8dda082 100644
--- a/dlls/winedib.drv/graphics.c
+++ b/dlls/winedib.drv/graphics.c
@@ -25,23 +25,33 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+static inline void OrderInt(int *i1, int *i2)
+{
+    if(*i1 > *i2)
+    {
+        int tmp;
+        tmp = *i1;
+        *i1 = *i2;
+        *i2 = tmp;
+    }
+}
+
 /***********************************************************************
  *           DIBDRV_Arc
  */
-BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bottom,
-            INT xstart, INT ystart, INT xend, INT yend )
+BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
+            int xstart, int ystart, int xend, int yend )
 {
     BOOL res;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
-          physDev, left, top, right, bottom, xstart, ystart, xend, yend);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
+          physDev, left, top, right, bottom, xstart, ystart, xend, yend));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pArc(physDev->X11PhysDev, left, top, right, bottom,
-                                               xstart, ystart, xend, yend);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -55,20 +65,19 @@ BOOL DIBDRV_Arc( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT botto
 /***********************************************************************
  *           DIBDRV_Chord
  */
-BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bottom,
-              INT xstart, INT ystart, INT xend, INT yend )
+BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
+              int xstart, int ystart, int xend, int yend )
 {
     BOOL res;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
-          physDev, left, top, right, bottom, xstart, ystart, xend, yend);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
+          physDev, left, top, right, bottom, xstart, ystart, xend, yend));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pChord(physDev->X11PhysDev, left, top, right, bottom,
-                                                 xstart, ystart, xend, yend);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -82,18 +91,18 @@ BOOL DIBDRV_Chord( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bot
 /***********************************************************************
  *           DIBDRV_Ellipse
  */
-BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bottom )
+BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom )
 {
     BOOL res;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
-          physDev, left, top, right, bottom);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
+          physDev, left, top, right, bottom));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pEllipse(physDev->X11PhysDev, left, top, right, bottom);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -106,19 +115,19 @@ BOOL DIBDRV_Ellipse( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT b
 /**********************************************************************
  *          DIBDRV_ExtFloodFill
  */
-BOOL DIBDRV_ExtFloodFill( DIBDRVPHYSDEV *physDev, INT x, INT y, COLORREF color,
+BOOL DIBDRV_ExtFloodFill( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color,
                      UINT fillType )
 {
     BOOL res;
     
-    TRACE("physDev:%p, x:%d, y:%d, color:%x, fillType:%d\n",
-          physDev, x, y, color, fillType);
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x, fillType:%d\n",
+          physDev, x, y, color, fillType));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pExtFloodFill(physDev->X11PhysDev, x, y, color, fillType);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -135,13 +144,13 @@ BOOL DIBDRV_GetDCOrgEx( DIBDRVPHYSDEV *physDev, LPPOINT lpp )
 {
     BOOL res;
     
-    TRACE("physDev:%p, lpp:%p\n", physDev, lpp);
+    MAYBE(TRACE("physDev:%p, lpp:%p\n", physDev, lpp));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetDCOrgEx(physDev->X11PhysDev, lpp);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -154,17 +163,15 @@ BOOL DIBDRV_GetDCOrgEx( DIBDRVPHYSDEV *physDev, LPPOINT lpp )
 /***********************************************************************
  *           DIBDRV_GetPixel
  */
-COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, INT x, INT y )
+COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, int x, int y )
 {
     COLORREF res;
     
-    TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y);
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetPixel(physDev->X11PhysDev, x, y);
+        res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
     }
     else
     {
@@ -177,17 +184,26 @@ COLORREF DIBDRV_GetPixel( DIBDRVPHYSDEV *physDev, INT x, INT y )
 /***********************************************************************
  *           DIBDRV_LineTo
  */
-BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, INT x, INT y )
+BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, int x, int y )
 {
     BOOL res;
+    POINT curPos;
     
-    TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y);
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pLineTo(physDev->X11PhysDev, x, y);
+        GetCurrentPositionEx(physDev->hdc, &curPos);
+
+        _DIBDRV_ResetDashOrigin(physDev);
+
+        if(curPos.y == y)
+            physDev->penHLine(physDev, curPos.x, x, y);
+        else if(curPos.x == x)
+            physDev->penVLine(physDev, x, curPos.y, y);
+        else
+            physDev->penLine(physDev, curPos.x, curPos.y, x, y);
+        res = TRUE;
     }
     else
     {
@@ -200,17 +216,43 @@ BOOL DIBDRV_LineTo( DIBDRVPHYSDEV *physDev, INT x, INT y )
 /***********************************************************************
  *           DIBDRV_PaintRgn
  */
+BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom);
 BOOL DIBDRV_PaintRgn( DIBDRVPHYSDEV *physDev, HRGN hrgn )
 {
-    BOOL res;
+    BOOL res = FALSE;
+    int i;
+    RECT *rect;
+    RGNDATA *data;
+    int size;
     
-    TRACE("physDev:%p, hrgn:%p\n", physDev, hrgn);
+    MAYBE(TRACE("physDev:%p, hrgn:%p\n", physDev, hrgn));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPaintRgn(physDev->X11PhysDev, hrgn);
+        /* gets needed region data size */
+        if(!(size = GetRegionData(hrgn, 0, NULL)))
+            goto fin;
+        
+        /* allocates buffer and gets actual region data */
+        if(!(data = HeapAlloc(GetProcessHeap(), 0, size)))
+            goto fin;
+        if(!GetRegionData(hrgn, size, data))
+        {
+            HeapFree(GetProcessHeap(), 0, data);
+            goto fin;
+        }
+
+        /* paints the filled rectangles */
+        rect = (RECT *)data->Buffer;
+        for(i = 0; i < data->rdh.nCount; i++)
+        {
+            DIBDRV_Rectangle( physDev, rect->left, rect->top, rect->right, rect->bottom);
+            rect++;
+        }
+        HeapFree( GetProcessHeap(), 0, data );
+        res = TRUE;
+fin:
+        ;
     }
     else
     {
@@ -223,20 +265,19 @@ BOOL DIBDRV_PaintRgn( DIBDRVPHYSDEV *physDev, HRGN hrgn )
 /***********************************************************************
  *           DIBDRV_Pie
  */
-BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bottom,
-            INT xstart, INT ystart, INT xend, INT yend )
+BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, int left, int top, int right, int bottom,
+            int xstart, int ystart, int xend, int yend )
 {
     BOOL res;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
-          physDev, left, top, right, bottom, xstart, ystart, xend, yend);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, xstart:%d, ystart:%d, xend:%d, yend:%d\n",
+          physDev, left, top, right, bottom, xstart, ystart, xend, yend));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPie(physDev->X11PhysDev, left, top, right, bottom,
-                                               xstart, ystart, xend, yend);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -250,17 +291,17 @@ BOOL DIBDRV_Pie( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT botto
 /**********************************************************************
  *          DIBDRV_Polygon
  */
-BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* pt, INT count )
+BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* pt, int count )
 {
     BOOL res;
     
-    TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count);
+    MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPolygon(physDev->X11PhysDev, pt, count);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -273,17 +314,17 @@ BOOL DIBDRV_Polygon( DIBDRVPHYSDEV *physDev, const POINT* pt, INT count )
 /**********************************************************************
  *          DIBDRV_Polyline
  */
-BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* pt, INT count )
+BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* pt, int count )
 {
     BOOL res;
     
-    TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count);
+    MAYBE(TRACE("physDev:%p, pt:%p, count:%d\n", physDev, pt, count));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPolyline(physDev->X11PhysDev, pt, count);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -296,17 +337,17 @@ BOOL DIBDRV_Polyline( DIBDRVPHYSDEV *physDev, const POINT* pt, INT count )
 /**********************************************************************
  *          DIBDRV_PolyPolygon
  */
-BOOL DIBDRV_PolyPolygon( DIBDRVPHYSDEV *physDev, const POINT* pt, const INT* counts, UINT polygons)
+BOOL DIBDRV_PolyPolygon( DIBDRVPHYSDEV *physDev, const POINT* pt, const int* counts, UINT polygons)
 {
     BOOL res;
     
-    TRACE("physDev:%p, pt:%p, counts:%p, polygons:%d\n", physDev, pt, counts, polygons);
+    MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polygons:%d\n", physDev, pt, counts, polygons));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPolyPolygon(physDev->X11PhysDev, pt, counts, polygons);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -324,13 +365,13 @@ BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD*
 {
     BOOL res;
     
-    TRACE("physDev:%p, pt:%p, counts:%p, polylines:%d\n", physDev, pt, counts, polylines);
+    MAYBE(TRACE("physDev:%p, pt:%p, counts:%p, polylines:%d\n", physDev, pt, counts, polylines));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pPolyPolyline(physDev->X11PhysDev, pt, counts, polylines);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -343,23 +384,65 @@ BOOL DIBDRV_PolyPolyline( DIBDRVPHYSDEV *physDev, const POINT* pt, const DWORD*
 /***********************************************************************
  *           DIBDRV_Rectangle
  */
-BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT bottom)
+BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
 {
-    BOOL res;
+    BOOL res = TRUE;
+    int i;
+    DIBDRVBITMAP *bmp = &physDev->physBitmap;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n",
-          physDev, left, top, right, bottom);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d\n", physDev, x1, y1, x2, y2));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, left, top, right, bottom);
+        OrderInt(&x1, &x2);
+        OrderInt(&y1, &y2);
+
+        /* temporary fix.... should be done by clipping */
+        if(x1 < 0) x1 = 0;
+        if(x2 < 0) x2 = 0;
+        if(y1 < 0) y1 = 0;
+        if(y2 < 0) y2 = 0;
+        if(x1 >= bmp->width)  x1 = bmp->width  - 1;
+        if(y1 >= bmp->height) y1 = bmp->height - 1;
+        if(x2 >  bmp->width)  x2 = bmp->width;
+        if(y2 >  bmp->height) y2 = bmp->height ;
+        if(x1 >= x2 || y1 >= y2)
+            goto fin;
+
+        _DIBDRV_ResetDashOrigin(physDev);
+        
+        /* particular case where the rectangle
+           degenerates to a line or a point */
+        if(x1 >= x2 - 1)
+        {
+            physDev->penVLine(physDev, x1, y1, y2);
+            goto fin;
+        }
+        else if (y1 >= y2 -1)
+        {
+            physDev->penHLine(physDev, x1, x2, y1);
+            goto fin;
+        }
+        
+        /* Draw the perimeter */
+        physDev->penHLine(physDev, x1    , x2    , y1   );
+        physDev->penHLine(physDev, x1    , x2    , y2 - 1);
+        physDev->penVLine(physDev, x1    , y1 + 1, y2 - 1);
+        physDev->penVLine(physDev, x2 - 1, y1 + 1, y2 - 1);
+
+        /* fill the inside */
+        if(x2 >= x1 + 2)
+            for (i = y1 + 1; i < y2 - 1; i++)
+                physDev->brushHLine(physDev, x1 + 1, x2 - 1, i);
+
+        res = TRUE;
+fin:
+        ;
     }
     else
     {
         /* DDB selected in, use X11 driver */
-        res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, left, top, right, bottom);
+        res = _DIBDRV_GetDisplayDriver()->pRectangle(physDev->X11PhysDev, x1, y1, x2, y2);
     }
     return res;
 }
@@ -367,20 +450,19 @@ BOOL DIBDRV_Rectangle( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right, INT
 /***********************************************************************
  *           DIBDRV_RoundRect
  */
-BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right,
-                  INT bottom, INT ell_width, INT ell_height )
+BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, int left, int top, int right,
+                  int bottom, int ell_width, int ell_height )
 {
     BOOL res;
     
-    TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, ell_width:%d, ell_height:%d\n",
-          physDev, left, top, right, bottom, ell_width, ell_height);
+    MAYBE(TRACE("physDev:%p, left:%d, top:%d, right:%d, bottom:%d, ell_width:%d, ell_height:%d\n",
+          physDev, left, top, right, bottom, ell_width, ell_height));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pRoundRect(physDev->X11PhysDev, left, top, right, bottom,
-                                                     ell_width, ell_height);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
@@ -394,17 +476,23 @@ BOOL DIBDRV_RoundRect( DIBDRVPHYSDEV *physDev, INT left, INT top, INT right,
 /***********************************************************************
  *           DIBDRV_SetPixel
  */
-COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, INT x, INT y, COLORREF color )
+COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, int x, int y, COLORREF color )
 {
     COLORREF res;
+    DWORD and, xor;
     
-    TRACE("physDev:%p, x:%d, y:%d, color:%x\n", physDev, x, y, color);
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d, color:%x\n", physDev, x, y, color));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetPixel(physDev->X11PhysDev, x, y, color);
+        /* gets previous pixel */
+        res = physDev->physBitmap.funcs->GetPixel(&physDev->physBitmap, x, y);
+     
+        /* calculates AND and XOR from color */
+        _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), color, &and, &xor);
+        
+        /* sets the pixel */
+        physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
     }
     else
     {
@@ -417,17 +505,17 @@ COLORREF DIBDRV_SetPixel( DIBDRVPHYSDEV *physDev, INT x, INT y, COLORREF color )
 /***********************************************************************
  *           DIBDRV_SetDCOrg
  */
-DWORD DIBDRV_SetDCOrg( DIBDRVPHYSDEV *physDev, INT x, INT y )
+DWORD DIBDRV_SetDCOrg( DIBDRVPHYSDEV *physDev, int x, int y )
 {
     DWORD res;
     
-    TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y);
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d\n", physDev, x, y));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetDCOrg(physDev->X11PhysDev, x, y);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
diff --git a/dlls/winedib.drv/opengl.c b/dlls/winedib.drv/opengl.c
index e8ec96c..f7855f6 100644
--- a/dlls/winedib.drv/opengl.c
+++ b/dlls/winedib.drv/opengl.c
@@ -32,7 +32,7 @@ int DIBDRV_ChoosePixelFormat( DIBDRVPHYSDEV *physDev,
 {
     int res;
     
-    TRACE("physDev:%p, ppfd:%p\n", physDev, ppfd);
+    MAYBE(TRACE("physDev:%p, ppfd:%p\n", physDev, ppfd));
 
     if(physDev->hasDIB)
     {
@@ -55,7 +55,7 @@ int DIBDRV_DescribePixelFormat( DIBDRVPHYSDEV *physDev,
 {
     int res;
     
-    TRACE("physDev:%p, iPixelFormat:%d, nBytes:%d, ppfd:%p\n", physDev, iPixelFormat, nBytes, ppfd);
+    MAYBE(TRACE("physDev:%p, iPixelFormat:%d, nBytes:%d, ppfd:%p\n", physDev, iPixelFormat, nBytes, ppfd));
 
     if(physDev->hasDIB)
     {
@@ -75,7 +75,7 @@ int DIBDRV_GetPixelFormat( DIBDRVPHYSDEV *physDev)
 {
     int res;
     
-    TRACE("physDev:%p\n", physDev);
+    MAYBE(TRACE("physDev:%p\n", physDev));
 
     if(physDev->hasDIB)
     {
@@ -97,7 +97,7 @@ BOOL DIBDRV_SetPixelFormat( DIBDRVPHYSDEV *physDev,
 {
     BOOL res;
     
-    TRACE("physDev:%p, iPixelFormat:%d, ppfd:%p\n", physDev, iPixelFormat, ppfd);
+    MAYBE(TRACE("physDev:%p, iPixelFormat:%d, ppfd:%p\n", physDev, iPixelFormat, ppfd));
 
     if(physDev->hasDIB)
     {
@@ -117,7 +117,7 @@ BOOL DIBDRV_SwapBuffers( DIBDRVPHYSDEV *physDev )
 {
     BOOL res;
     
-    TRACE("physDev:%p\n", physDev);
+    MAYBE(TRACE("physDev:%p\n", physDev));
 
     if(physDev->hasDIB)
     {
@@ -142,7 +142,7 @@ BOOL CDECL DIBDRV_wglCopyContext(HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask)
 {
     BOOL res;
     
-    TRACE("hglrcSrc:%p, hglrcDst:%p, mask:%x\n", hglrcSrc, hglrcDst, mask);
+    MAYBE(TRACE("hglrcSrc:%p, hglrcDst:%p, mask:%x\n", hglrcSrc, hglrcDst, mask));
 
     ONCE(FIXME("stub\n"));
     res = _DIBDRV_GetDisplayDriver()->pwglCopyContext(hglrcSrc, hglrcDst, mask);
@@ -159,7 +159,7 @@ HGLRC CDECL DIBDRV_wglCreateContext(DIBDRVPHYSDEV *physDev)
 {
     HGLRC res;
     
-    TRACE("physDev:%p\n", physDev);
+    MAYBE(TRACE("physDev:%p\n", physDev));
 
     if(physDev->hasDIB)
     {
@@ -184,7 +184,7 @@ BOOL CDECL DIBDRV_wglDeleteContext(HGLRC hglrc)
 {
     BOOL res;
     
-    TRACE("hglrc:%p\n", hglrc);
+    MAYBE(TRACE("hglrc:%p\n", hglrc));
 
     ONCE(FIXME("stub\n"));
     res = _DIBDRV_GetDisplayDriver()->pwglDeleteContext(hglrc);
@@ -200,7 +200,7 @@ PROC CDECL DIBDRV_wglGetProcAddress(LPCSTR lpszProc)
 {
     PROC res;
     
-    TRACE("lpszProc:%p\n", lpszProc);
+    MAYBE(TRACE("lpszProc:%p\n", lpszProc));
 
     ONCE(FIXME("stub\n"));
     res = _DIBDRV_GetDisplayDriver()->pwglGetProcAddress(lpszProc);
@@ -220,7 +220,7 @@ HDC CDECL DIBDRV_wglGetPbufferDCARB(DIBDRVPHYSDEV *physDev, HPBUFFERARB hPbuffer
 {
     HDC res;
     
-    TRACE("physDev:%p, hPbuffer:%p\n", physDev, hPbuffer);
+    MAYBE(TRACE("physDev:%p, hPbuffer:%p\n", physDev, hPbuffer));
 
     if(physDev->hasDIB)
     {
@@ -245,7 +245,7 @@ BOOL CDECL DIBDRV_wglMakeContextCurrentARB(DIBDRVPHYSDEV* pDrawDev, DIBDRVPHYSDE
 {
     BOOL res;
     
-    TRACE("pDrawDev:%p, pReadDev:%p, hglrc:%p\n", pDrawDev, pReadDev, hglrc);
+    MAYBE(TRACE("pDrawDev:%p, pReadDev:%p, hglrc:%p\n", pDrawDev, pReadDev, hglrc));
 
     if(pDrawDev->hasDIB && pReadDev->hasDIB)
     {
@@ -282,7 +282,7 @@ BOOL CDECL DIBDRV_wglMakeCurrent(DIBDRVPHYSDEV *physDev, HGLRC hglrc)
 {
     BOOL res;
     
-    TRACE("physDev:%p, hglrc:%p\n", physDev, hglrc);
+    MAYBE(TRACE("physDev:%p, hglrc:%p\n", physDev, hglrc));
 
     if(physDev->hasDIB)
     {
@@ -308,7 +308,7 @@ BOOL CDECL DIBDRV_wglSetPixelFormatWINE(DIBDRVPHYSDEV *physDev, int iPixelFormat
 {
     BOOL res;
     
-    TRACE("physDev:%p, iPixelFormat:%d, ppfd:%p\n", physDev, iPixelFormat, ppfd);
+    MAYBE(TRACE("physDev:%p, iPixelFormat:%d, ppfd:%p\n", physDev, iPixelFormat, ppfd));
 
     if(physDev->hasDIB)
     {
@@ -333,7 +333,7 @@ BOOL CDECL DIBDRV_wglShareLists(HGLRC hglrc1, HGLRC hglrc2)
 {
     BOOL res;
     
-    TRACE("hglrc1:%p, hglrc2:%p\n", hglrc1, hglrc2);
+    MAYBE(TRACE("hglrc1:%p, hglrc2:%p\n", hglrc1, hglrc2));
 
     ONCE(FIXME("stub\n"));
     res = _DIBDRV_GetDisplayDriver()->pwglShareLists(hglrc1, hglrc2);
@@ -350,7 +350,7 @@ BOOL CDECL DIBDRV_wglUseFontBitmapsA(DIBDRVPHYSDEV *physDev, DWORD first, DWORD
 {
     BOOL res;
     
-    TRACE("physDev:%p, first:%d, count:%d, listBase:%d\n", physDev, first, count, listBase);
+    MAYBE(TRACE("physDev:%p, first:%d, count:%d, listBase:%d\n", physDev, first, count, listBase));
 
     if(physDev->hasDIB)
     {
@@ -375,7 +375,7 @@ BOOL CDECL DIBDRV_wglUseFontBitmapsW(DIBDRVPHYSDEV *physDev, DWORD first, DWORD
 {
     BOOL res;
     
-    TRACE("physDev:%p, first:%d, count:%d, listBase:%d\n", physDev, first, count, listBase);
+    MAYBE(TRACE("physDev:%p, first:%d, count:%d, listBase:%d\n", physDev, first, count, listBase));
 
     if(physDev->hasDIB)
     {
diff --git a/dlls/winedib.drv/palette.c b/dlls/winedib.drv/palette.c
index 9daf47d..148a6d5 100644
--- a/dlls/winedib.drv/palette.c
+++ b/dlls/winedib.drv/palette.c
@@ -32,7 +32,7 @@ UINT DIBDRV_RealizePalette( DIBDRVPHYSDEV *physDev, HPALETTE hpal, BOOL primary
 {
     UINT res;
     
-    TRACE("physDev:%p, hpal:%p, primary:%s\n", physDev, hpal, (primary ? "TRUE" : "FALSE"));
+    MAYBE(TRACE("physDev:%p, hpal:%p, primary:%s\n", physDev, hpal, (primary ? "TRUE" : "FALSE")));
     
     /* we should in any case call X11 function, as UnrealizePalette() doesn't
      * take a physDev parameter */
@@ -54,7 +54,7 @@ BOOL DIBDRV_UnrealizePalette( HPALETTE hpal )
 {
     BOOL res;
     
-    TRACE("hpal:%p\n", hpal);
+    MAYBE(TRACE("hpal:%p\n", hpal));
 
     /* we should in any case call X11 function, as UnrealizePalette() doesn't
      * take a physDev parameter */
@@ -74,13 +74,13 @@ UINT DIBDRV_GetSystemPaletteEntries( DIBDRVPHYSDEV *physDev, UINT start, UINT co
 {
     UINT res;
     
-    TRACE("physDev:%p, start:%d, count:%d, entries:%p\n", physDev, start, count, entries);
+    MAYBE(TRACE("physDev:%p, start:%d, count:%d, entries:%p\n", physDev, start, count, entries));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetSystemPaletteEntries(physDev->X11PhysDev, start, count, entries);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
@@ -97,13 +97,13 @@ COLORREF DIBDRV_GetNearestColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 {
     COLORREF res;
     
-    TRACE("physDev:%p, color:%x\n", physDev, color);
+    MAYBE(TRACE("physDev:%p, color:%x\n", physDev, color));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetNearestColor(physDev->X11PhysDev, color);
+        ONCE(FIXME("STUB\n"));
+        res = 0;
     }
     else
     {
@@ -119,14 +119,36 @@ COLORREF DIBDRV_GetNearestColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 UINT DIBDRV_RealizeDefaultPalette( DIBDRVPHYSDEV *physDev )
 {
     UINT res;
+#ifdef DIBDRV_ENABLE_MAYBE
+    int i;
+    RGBQUAD *q;
+#endif
     
-    TRACE("physDev:%p\n", physDev);
+    MAYBE(TRACE("physDev:%p\n", physDev));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pRealizeDefaultPalette(physDev->X11PhysDev);
+        ONCE(FIXME("STUB\n"));
+        /* HACK - we can't get the dib color table during SelectBitmap since it hasn't
+           been initialized yet.  This is called from DC_InitDC so it's a convenient place
+           to grab the color table. */
+        MAYBE(TRACE("Color table size = %d, Color table = %p\n", physDev->physBitmap.colorTableSize, physDev->physBitmap.colorTable));
+        if(!physDev->physBitmap.colorTableGrabbed)
+        {
+            MAYBE(TRACE("Grabbing palette\n"));
+            physDev->physBitmap.colorTable = HeapAlloc(GetProcessHeap(), 0, sizeof(physDev->physBitmap.colorTable[0]) * physDev->physBitmap.colorTableSize);
+            GetDIBColorTable(physDev->hdc, 0, physDev->physBitmap.colorTableSize, physDev->physBitmap.colorTable);
+#ifdef DIBDRV_ENABLE_MAYBE 
+           for(i = 0; i < physDev->physBitmap.colorTableSize; i++)
+            {
+                q = physDev->physBitmap.colorTable + i;
+                TRACE("  %03d : R%03d G%03d B%03d\n", i, q->rgbRed, q->rgbGreen, q->rgbBlue);
+            }
+#endif
+            physDev->physBitmap.colorTableGrabbed = TRUE;
+        }
+        res = 0;
     }
     else
     {
@@ -140,13 +162,14 @@ BOOL DIBDRV_GetICMProfile(DIBDRVPHYSDEV *physDev, LPDWORD lpcbName, LPWSTR lpszF
 {
     BOOL res;
     
-    TRACE("physDev:%p, lpcpName:%p, lpszFilename:%p\n", physDev, lpcbName, lpszFilename);
+    MAYBE(TRACE("physDev:%p, lpcpName:%p, lpszFilename:%p\n", physDev, lpcbName, lpszFilename));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetICMProfile(physDev->X11PhysDev, lpcbName, lpszFilename);
+        ONCE(FIXME("STUB\n"));
+
+        res = 0;
     }
     else
     {
diff --git a/dlls/winedib.drv/pen_brush.c b/dlls/winedib.drv/pen_brush.c
index bde2f23..31c9cd2 100644
--- a/dlls/winedib.drv/pen_brush.c
+++ b/dlls/winedib.drv/pen_brush.c
@@ -26,20 +26,317 @@
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
 
+static const DASHPATTERN dashPatterns[4] =
+{
+    {2, {18, 6}},
+    {2, {3,  3}},
+    {4, {9, 6, 3, 6}},
+    {6, {9, 3, 3, 3, 3, 3}}
+};
+
+static inline void OrderEndPoints(int *s, int *e)
+{
+    if(*s > *e)
+    {
+        int tmp;
+        tmp = *s + 1;
+        *s = *e + 1;
+        *e = tmp;
+    }
+}
+
+static void SolidPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
+{
+    OrderEndPoints(&x1, &x2);
+    physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->penAnd, physDev->penXor);
+}
+
+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);
+}
+
+static void WINAPI SolidPenLineCallback(int x, int y, LPARAM lparam)
+{
+    DIBDRVPHYSDEV *physDev = (DIBDRVPHYSDEV *)lparam;
+
+    physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, physDev->penAnd, physDev->penXor);
+    return;
+}
+
+void SolidPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
+{
+    LineDDA(x1, y1, x2, y2, SolidPenLineCallback, (LPARAM)physDev);
+}
+
+static inline void GetDashColors(DIBDRVPHYSDEV *physDev, DWORD *and, DWORD *xor)
+{
+    if(physDev->markSpace == mark)
+    {
+        *and = physDev->penAnd;
+        *xor = physDev->penXor;
+    }
+    else if(GetBkMode(physDev->hdc) == OPAQUE)
+    {
+        *and = physDev->backgroundAnd;
+        *xor = physDev->backgroundXor;
+    }
+    else
+    {
+        *and = 0xffffffff;
+        *xor = 0;
+    }
+}
+
+static inline void NextDash(DIBDRVPHYSDEV *physDev)
+{
+    if(physDev->leftInDash != 0)
+        return;
+
+    physDev->curDash++;
+    if(physDev->curDash == physDev->penPattern->count)
+        physDev->curDash = 0;
+    physDev->leftInDash = physDev->penPattern->dashes[physDev->curDash];
+    if(physDev->markSpace == mark)
+        physDev->markSpace = space;
+    else
+        physDev->markSpace = mark;
+}
+
+static void DashedPenHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
+{
+    int x = x1;
+    DWORD and, xor;
+    DWORD dashLen;
+
+    if(x1 <= x2)
+    {
+        while(x != x2)
+        {
+            GetDashColors(physDev, &and, &xor);
+
+            dashLen = physDev->leftInDash;
+            if(x + dashLen > x2)
+                dashLen = x2 - x;
+
+            physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x, x + dashLen, y, and, xor);
+            x += dashLen;
+
+            physDev->leftInDash -= dashLen;
+            NextDash(physDev);
+        }
+    }
+    else
+    {
+        while(x != x2)
+        {
+            GetDashColors(physDev, &and, &xor);
+
+            dashLen = physDev->leftInDash;
+            if(x - (int)dashLen < x2)
+                dashLen = x - x2;
+
+            physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x - dashLen + 1, x + 1, y, and, xor);
+            x -= dashLen;
+
+            physDev->leftInDash -= dashLen;
+            NextDash(physDev);
+        }
+    }
+}
+
+static void DashedPenVLine(DIBDRVPHYSDEV *physDev, int x, int y1, int y2)
+{
+    int y = y1;
+    DWORD and, xor;
+    DWORD dashLen;
+
+    if(y1 <= y2)
+    {
+        while(y != y2)
+        {
+            GetDashColors(physDev, &and, &xor);
+
+            dashLen = physDev->leftInDash;
+            if(y + dashLen > y2)
+                dashLen = y2 - y;
+
+            physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y, y + dashLen, and, xor);
+            y += dashLen;
+
+            physDev->leftInDash -= dashLen;
+            NextDash(physDev);
+        }
+    }
+    else
+    {
+        while(y != y2)
+        {
+            GetDashColors(physDev, &and, &xor);
+
+            dashLen = physDev->leftInDash;
+            if(y - (int)dashLen < y2)
+                dashLen = y - y2;
+
+            physDev->physBitmap.funcs->SolidVLine(&physDev->physBitmap, x, y - dashLen + 1, y + 1, and, xor);
+            y -= dashLen;
+
+            physDev->leftInDash -= dashLen;
+            NextDash(physDev);
+        }
+    }
+}
+
+static void WINAPI DashedPenLineCallback(int x, int y, LPARAM lparam)
+{
+    DIBDRVPHYSDEV *physDev = (DIBDRVPHYSDEV *)lparam;
+    DWORD and, xor;
+
+    GetDashColors(physDev, &and, &xor);
+
+    physDev->physBitmap.funcs->SetPixel(&physDev->physBitmap, x, y, and, xor);
+
+    physDev->leftInDash--;
+    NextDash(physDev);
+
+    return;
+}
+
+static void DashedPenLine(DIBDRVPHYSDEV *physDev, int x1, int y1, int x2, int y2)
+{
+    LineDDA(x1, y1, x2, y2, DashedPenLineCallback, (LPARAM)physDev);
+}
+
+void _DIBDRV_ResetDashOrigin(DIBDRVPHYSDEV *physDev)
+{
+    physDev->curDash = 0;
+    if(physDev->penPattern)
+        physDev->leftInDash = physDev->penPattern->dashes[0];
+    physDev->markSpace = mark;
+}
+
+
+/* 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 *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;
+}
+
+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;
+}
+
+static void SolidBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
+{
+    OrderEndPoints(&x1, &x2);
+    physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap, x1, x2, y, physDev->brushAnd, physDev->brushXor);
+}
+
+
+static void GenerateMasks(DIBDRVPHYSDEV *physDev, DIBDRVBITMAP *bmp, DWORD **and, DWORD **xor)
+{
+    int rop = GetROP2(physDev->hdc);
+    DWORD *color_ptr, *and_ptr, *xor_ptr;
+    DWORD size = bmp->height * abs(bmp->stride);
+
+    *and = HeapAlloc(GetProcessHeap(), 0, size);
+    *xor = HeapAlloc(GetProcessHeap(), 0, size);
+
+    color_ptr = bmp->bits;
+    and_ptr = *and;
+    xor_ptr = *xor;
+
+    while(size)
+    {
+        _DIBDRV_CalcAndXorMasks(rop, *color_ptr++, and_ptr++, xor_ptr++);
+        size -= 4;
+    }
+}
+
+static void PatternBrushHLine(DIBDRVPHYSDEV *physDev, int x1, int x2, int y)
+{
+    DWORD *and, *xor, brushY = y % physDev->brushBitmap.height;
+
+    if(!physDev->brushAnds)
+        GenerateMasks(physDev, &physDev->brushBitmap, &physDev->brushAnds, &physDev->brushXors);
+
+    OrderEndPoints(&x1, &x2);
+    and = (DWORD *)((char *)physDev->brushAnds + brushY * physDev->brushBitmap.stride);
+    xor = (DWORD *)((char *)physDev->brushXors + brushY * physDev->brushBitmap.stride);
+
+    physDev->physBitmap.funcs->PatternHLine(&physDev->physBitmap, x1, x2, y, and, xor, physDev->brushBitmap.width, x1 % physDev->brushBitmap.width);
+}
+
 /***********************************************************************
  *           DIBDRV_SelectPen
  */
 HPEN DIBDRV_SelectPen( DIBDRVPHYSDEV *physDev, HPEN hpen )
 {
     HPEN res;
+    LOGPEN logpen;
     
-    TRACE("physDev:%p, hpen:%p\n", physDev, hpen);
+    MAYBE(TRACE("physDev:%p, hpen:%p\n", physDev, hpen));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSelectPen(physDev->X11PhysDev, 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);
+
+        _DIBDRV_CalcAndXorMasks(GetROP2(physDev->hdc), physDev->penColor, &physDev->penAnd, &physDev->penXor);
+
+        switch(logpen.lopnStyle)
+        {
+            default:
+                ONCE(FIXME("Unhandled pen style %d\n", logpen.lopnStyle));
+                /* fall through */
+            case PS_SOLID:
+                physDev->penHLine = SolidPenHLine;
+                physDev->penVLine = SolidPenVline;
+                physDev->penLine  = SolidPenLine;
+                physDev->penPattern = NULL;
+                break;
+
+            case PS_DASH:
+            case PS_DOT:
+            case PS_DASHDOT:
+            case PS_DASHDOTDOT:
+                physDev->penHLine = DashedPenHLine;
+                physDev->penVLine = DashedPenVLine;
+                physDev->penLine  = DashedPenLine;
+                physDev->penPattern = &dashPatterns[logpen.lopnStyle - PS_DASH];
+                _DIBDRV_ResetDashOrigin(physDev);
+                break;
+        }
+        res = hpen;
     }
     else
     {
@@ -56,13 +353,13 @@ COLORREF DIBDRV_SetDCPenColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
 {
     COLORREF res;
     
-    TRACE("physDev:%p, crColor:%x\n", physDev, crColor);
+    MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev, crColor));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetDCPenColor(physDev->X11PhysDev, crColor);
+        ONCE(FIXME("STUB\n"));
+        res = crColor;
     }
     else
     {
@@ -77,19 +374,151 @@ COLORREF DIBDRV_SetDCPenColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
  */
 HBRUSH DIBDRV_SelectBrush( DIBDRVPHYSDEV *physDev, HBRUSH hbrush )
 {
-    HBRUSH res;
+    HBRUSH res = hbrush;
+    LOGBRUSH logbrush;
+
     
-    TRACE("physDev:%p, hbrush:%p\n", physDev, hbrush);
+    MAYBE(TRACE("physDev:%p, hbrush:%p\n", physDev, hbrush));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev->X11PhysDev, hbrush);
+        GetObjectW(hbrush, sizeof(logbrush), &logbrush);
+
+        /* frees any currently selected DIB brush and cache */
+        _DIBDRVBITMAP_Free(&physDev->brushBitmap);
+        _DIBDRVBITMAP_Free(&physDev->brushBmpCache);
+        if(physDev->brushAnds)
+        {
+            HeapFree(GetProcessHeap(), 0, physDev->brushAnds);
+            HeapFree(GetProcessHeap(), 0, physDev->brushXors);
+        }
+        physDev->brushAnds = NULL;
+        physDev->brushXors = NULL;
+
+        switch (logbrush.lbStyle)
+        {
+            default:
+                FIXME("Unhandled brush style %d\n", logbrush.lbStyle);
+                physDev->brushColorref = 0;
+                goto solid;
+                
+            case BS_SOLID:
+                physDev->brushColorref = 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);
+
+                _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->brushColor,
+                                           &physDev->brushAnd, &physDev->brushXor);
+
+                /* set the physDev brush style */
+                physDev->brushStyle = BS_SOLID;
+                physDev->isBrushBitmap = FALSE;
+                
+                break;
+
+            case BS_DIBPATTERN8X8:
+            case BS_DIBPATTERN:
+            {
+                DIBDRVBITMAP src;
+                BITMAPINFO *bmi;
+                
+                FIXME("DIB Pattern\n");
+                
+                /* if no DIB selected in, fallback to null brush */
+                if(!physDev->physBitmap.bits)
+                {
+                    physDev->brushColorref = 0;
+                    goto solid;
+                }
+
+                /* gets brush DIB's pointer */
+                bmi = GlobalLock16(logbrush.lbHatch);
+        
+                /* initializes a temporary DIB with brush's one */
+                if(!_DIBDRVBITMAP_InitFromBitmapinfo(&src, bmi))
+                {
+                    ERR("Failed to initialize brush DIB\n");
+                    res = 0;
+                    goto err;
+                }
+                
+                /* converts brush bitmap to match currently selected one's format */
+                if(!_DIBDRVBITMAP_Convert(&physDev->brushBitmap, &src, &physDev->physBitmap))
+                {
+                    ERR("Failed to convert brush DIB\n");
+                    _DIBDRVBITMAP_Free(&src);
+                    res = 0;
+                    goto err;
+                }
+
+                /* frees temporary DIB's data */
+                _DIBDRVBITMAP_Free(&src);
+                
+                /* use DIB pattern for brush lines */
+                physDev->brushHLine = PatternBrushHLine;
+
+    err:            
+                /* frees brush's DIB pointer */
+                GlobalUnlock16(logbrush.lbHatch);
+                
+                break;
+            }
+            case BS_DIBPATTERNPT:
+                FIXME("BS_DIBPATTERNPT not supported\n");
+                physDev->brushColorref = 0;
+                goto solid;
+                
+            case BS_HATCHED:
+                FIXME("BS_HATCHED not supported\n");
+                physDev->brushColorref = 0;
+                goto solid;
+                
+            case BS_NULL:
+            {
+                MAYBE(TRACE("NULL Pattern\n"));
+                physDev->brushColorref = 0;
+                goto solid;
+            }
+                
+            case BS_PATTERN:
+            case BS_PATTERN8X8:
+                FIXME("BS_PATTERN not supported\n");
+                physDev->brushColorref = 0;
+                goto solid;
+        }
+
+        MAYBE(TRACE("END\n"));
+        return hbrush;
     }
     else
     {
         /* DDB selected in, use X11 driver */
+ 
+        /* we must check if a DIB pattern is requested */       
+        GetObjectW(hbrush, sizeof(logbrush), &logbrush);
+        switch (logbrush.lbStyle)
+        {
+            case BS_DIBPATTERN8X8:
+            case BS_DIBPATTERN:
+            case BS_DIBPATTERNPT:
+                FIXME("A DIB pattern was requested for a DDB bitmap\n");
+                break;
+
+            case BS_SOLID:
+            case BS_HATCHED:
+            case BS_NULL:
+            case BS_PATTERN:
+            case BS_PATTERN8X8:
+            default:
+                break;
+        }
         res = _DIBDRV_GetDisplayDriver()->pSelectBrush(physDev->X11PhysDev, hbrush);
     }
     return res;
@@ -102,13 +531,13 @@ COLORREF DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
 {
     COLORREF res;
     
-    TRACE("physDev:%p, crColor:%x\n", physDev, crColor);
+    MAYBE(TRACE("physDev:%p, crColor:%x\n", physDev, crColor));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetDCBrushColor(physDev->X11PhysDev, crColor);
+        ONCE(FIXME("STUB\n"));
+        res = crColor;
     }
     else
     {
@@ -121,14 +550,29 @@ COLORREF DIBDRV_SetDCBrushColor( DIBDRVPHYSDEV *physDev, COLORREF crColor )
 /***********************************************************************
  *           SetROP2
  */
-INT DIBDRV_SetROP2( DIBDRVPHYSDEV *physDev, INT rop )
+int DIBDRV_SetROP2( DIBDRVPHYSDEV *physDev, int rop )
 {
-    INT prevRop;
+    int prevRop;
     
-    TRACE("physDev:%p, rop:%x\n", physDev, rop);
+    MAYBE(TRACE("physDev:%p, rop:%x\n", physDev, rop));
 
     prevRop = physDev->rop2;
     physDev->rop2 = rop;
+
+    if(prevRop != rop)
+    {
+        _DIBDRV_CalcAndXorMasks(rop, physDev->penColor,   &physDev->penAnd,   &physDev->penXor);
+        _DIBDRV_CalcAndXorMasks(rop, physDev->brushColor, &physDev->brushAnd, &physDev->brushXor);
+        _DIBDRV_CalcAndXorMasks(rop, physDev->backgroundColor, &physDev->backgroundAnd, &physDev->backgroundXor);
+        if(physDev->brushAnds)
+        {
+            HeapFree(GetProcessHeap(), 0, physDev->brushAnds);
+            HeapFree(GetProcessHeap(), 0, physDev->brushXors);
+        }
+        physDev->brushAnds = NULL;
+        physDev->brushXors = NULL;
+    }
+
     return prevRop;
     /* note : X11 Driver don't have SetROP2() function exported */
 }
@@ -140,13 +584,17 @@ COLORREF DIBDRV_SetBkColor( DIBDRVPHYSDEV *physDev, COLORREF color )
 {
     COLORREF res;
     
-    TRACE("physDev:%p, color:%x\n", physDev, color);
+    MAYBE(TRACE("physDev:%p, color:%x\n", physDev, color));
 
     if(physDev->hasDIB)
     {
-        /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetBkColor(physDev->X11PhysDev, color);
+        physDev->backgroundColor = physDev->physBitmap.funcs->ColorToPixel(&physDev->physBitmap, color);
+
+        if(physDev->physBitmap.bitCount == 1)
+            FixupFgColors1(physDev);
+        _DIBDRV_CalcAndXorMasks(physDev->rop2, physDev->backgroundColor, &physDev->backgroundAnd, &physDev->backgroundXor);
+        
+        res = TRUE;
     }
     else
     {
diff --git a/dlls/winedib.drv/primitives.c b/dlls/winedib.drv/primitives.c
new file mode 100644
index 0000000..cbad239
--- /dev/null
+++ b/dlls/winedib.drv/primitives.c
@@ -0,0 +1,274 @@
+/*
+ * DIB Engine Primitives function pointers
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* ------------------------------------------------------------*/
+/*                     COLOR FUNCTIONS                         */
+DWORD _DIBDRV_ColorToPixel32_RGB      (const DIBDRVBITMAP *dib, COLORREF color);
+DWORD _DIBDRV_ColorToPixel32_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color);
+DWORD _DIBDRV_ColorToPixel24          (const DIBDRVBITMAP *dib, COLORREF color);
+DWORD _DIBDRV_ColorToPixel16_RGB      (const DIBDRVBITMAP *dib, COLORREF color);
+DWORD _DIBDRV_ColorToPixel16_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color);
+DWORD _DIBDRV_ColorToPixelColortable  (const DIBDRVBITMAP *dib, COLORREF color);
+
+/* ------------------------------------------------------------*/
+/*                     PIXEL POINTER READING                   */
+void *_DIBDRV_GetPixelPointer32(const DIBDRVBITMAP *dib, int x, int y);
+void *_DIBDRV_GetPixelPointer24(const DIBDRVBITMAP *dib, int x, int y);
+void *_DIBDRV_GetPixelPointer16(const DIBDRVBITMAP *dib, int x, int y);
+void *_DIBDRV_GetPixelPointer8 (const DIBDRVBITMAP *dib, int x, int y);
+void *_DIBDRV_GetPixelPointer4 (const DIBDRVBITMAP *dib, int x, int y);
+void *_DIBDRV_GetPixelPointer1 (const DIBDRVBITMAP *dib, int x, int y);
+
+/* ------------------------------------------------------------*/
+/*                     PIXEL WRITING                           */
+void _DIBDRV_SetPixel32(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor);
+void _DIBDRV_SetPixel24(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor);
+void _DIBDRV_SetPixel16(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor);
+void _DIBDRV_SetPixel8 (DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor);
+void _DIBDRV_SetPixel4 (DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor);
+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 _DIBDRV_GetPixel32_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel24          (const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel16_RGB      (const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel16_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel8           (const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel4           (const DIBDRVBITMAP *dib, int x, int y);
+DWORD _DIBDRV_GetPixel1           (const DIBDRVBITMAP *dib, int x, int y);
+
+/* ------------------------------------------------------------*/
+/*                     HORIZONTAL SOLID LINES                  */
+void _DIBDRV_SolidHLine32(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+void _DIBDRV_SolidHLine24(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+void _DIBDRV_SolidHLine16(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+void _DIBDRV_SolidHLine8 (DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+void _DIBDRV_SolidHLine4 (DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+void _DIBDRV_SolidHLine1 (DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor);
+
+/* ------------------------------------------------------------*/
+/*                     HORIZONTAL PATTERN LINES                */
+void _DIBDRV_PatternHLine32(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+void _DIBDRV_PatternHLine24(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+void _DIBDRV_PatternHLine16(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+void _DIBDRV_PatternHLine8 (DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+void _DIBDRV_PatternHLine4 (DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+void _DIBDRV_PatternHLine1 (DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset);
+
+/* ------------------------------------------------------------*/
+/*                      VERTICAL LINES                         */
+void _DIBDRV_SolidVLine32(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+void _DIBDRV_SolidVLine24(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+void _DIBDRV_SolidVLine16(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+void _DIBDRV_SolidVLine8 (DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+void _DIBDRV_SolidVLine4 (DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+void _DIBDRV_SolidVLine1 (DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor);
+
+/* ----------------------------------------------------------------*/
+/*                         CONVERT PRIMITIVES                      */
+/* converts (part of) line of any DIB format from/to DIB32_RGB one */
+BOOL _DIBDRV_GetLine32_RGB      (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine24          (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine16_RGB      (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine8           (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine4           (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_GetLine1           (const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+
+BOOL _DIBDRV_PutLine32_RGB      (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine32_BITFIELDS(DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine24          (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine16_RGB      (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine16_BITFIELDS(DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine8           (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine4           (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+BOOL _DIBDRV_PutLine1           (DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf);
+
+/* ------------------------------------------------------------*/
+/*                        BLITTING PRIMITIVES                  */
+BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop);
+BOOL _DIBDRV_BitBlt_32(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop);
+BOOL _DIBDRV_BitBlt_24(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop);
+BOOL _DIBDRV_BitBlt_16(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop);
+BOOL _DIBDRV_BitBlt_8(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop);
+
+BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT widthDst, INT heightDst, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop);
+
+/* ------------------------------------------------------------*/
+/*               FREETYPE FONT BITMAP BLITTING                 */
+void _DIBDRV_freetype_blit_8888        (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_32_RGB      (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_24          (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_16_RGB      (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_8           (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_4           (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+void _DIBDRV_freetype_blit_1           (DIBDRVPHYSDEV *dib, int x, int y, FT_Bitmap *bmp);
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_RGB =
+{
+    _DIBDRV_ColorToPixel32_RGB,
+    _DIBDRV_GetPixelPointer32,
+    _DIBDRV_SetPixel32,
+    _DIBDRV_GetPixel32_RGB,
+    _DIBDRV_SolidHLine32,
+    _DIBDRV_PatternHLine32,
+    _DIBDRV_SolidVLine32,
+    _DIBDRV_GetLine32_RGB,
+    _DIBDRV_PutLine32_RGB,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_32_RGB
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB32_BITFIELDS =
+{
+    _DIBDRV_ColorToPixel32_BITFIELDS,
+    _DIBDRV_GetPixelPointer32,
+    _DIBDRV_SetPixel32,
+    _DIBDRV_GetPixel32_BITFIELDS,
+    _DIBDRV_SolidHLine32,
+    _DIBDRV_PatternHLine32,
+    _DIBDRV_SolidVLine32,
+    _DIBDRV_GetLine32_BITFIELDS,
+    _DIBDRV_PutLine32_BITFIELDS,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_32_BITFIELDS
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB24 =
+{
+    _DIBDRV_ColorToPixel24,
+    _DIBDRV_GetPixelPointer24,
+    _DIBDRV_SetPixel24,
+    _DIBDRV_GetPixel24,
+    _DIBDRV_SolidHLine24,
+    _DIBDRV_PatternHLine24,
+    _DIBDRV_SolidVLine24,
+    _DIBDRV_GetLine24,
+    _DIBDRV_PutLine24,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_24
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_RGB =
+{
+    _DIBDRV_ColorToPixel16_RGB,
+    _DIBDRV_GetPixelPointer16,
+    _DIBDRV_SetPixel16,
+    _DIBDRV_GetPixel16_RGB,
+    _DIBDRV_SolidHLine16,
+    _DIBDRV_PatternHLine16,
+    _DIBDRV_SolidVLine16,
+    _DIBDRV_GetLine16_RGB,
+    _DIBDRV_PutLine16_RGB,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_16_RGB
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB16_BITFIELDS =
+{
+    _DIBDRV_ColorToPixel16_BITFIELDS,
+    _DIBDRV_GetPixelPointer16,
+    _DIBDRV_SetPixel16,
+    _DIBDRV_GetPixel16_BITFIELDS,
+    _DIBDRV_SolidHLine16,
+    _DIBDRV_PatternHLine16,
+    _DIBDRV_SolidVLine16,
+    _DIBDRV_GetLine16_BITFIELDS,
+    _DIBDRV_PutLine16_BITFIELDS,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_16_BITFIELDS
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB8 =
+{
+    _DIBDRV_ColorToPixelColortable,
+    _DIBDRV_GetPixelPointer8,
+    _DIBDRV_SetPixel8,
+    _DIBDRV_GetPixel8,
+    _DIBDRV_SolidHLine8,
+    _DIBDRV_PatternHLine8,
+    _DIBDRV_SolidVLine8,
+    _DIBDRV_GetLine8,
+    _DIBDRV_PutLine8,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_8
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB4 =
+{
+    _DIBDRV_ColorToPixelColortable,
+    _DIBDRV_GetPixelPointer4,
+    _DIBDRV_SetPixel4,
+    _DIBDRV_GetPixel4,
+    _DIBDRV_SolidHLine4,
+    _DIBDRV_PatternHLine4,
+    _DIBDRV_SolidVLine4,
+    _DIBDRV_GetLine4,
+    _DIBDRV_PutLine4,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_4
+};
+
+DIBDRV_PRIMITIVE_FUNCS DIBDRV_funcs_DIB1 =
+{
+    _DIBDRV_ColorToPixelColortable,
+    _DIBDRV_GetPixelPointer1,
+    _DIBDRV_SetPixel1,
+    _DIBDRV_GetPixel1,
+    _DIBDRV_SolidHLine1,
+    _DIBDRV_PatternHLine1,
+    _DIBDRV_SolidVLine1,
+    _DIBDRV_GetLine1,
+    _DIBDRV_PutLine1,
+    _DIBDRV_BitBlt_generic,
+    _DIBDRV_StretchBlt_generic,
+    _DIBDRV_freetype_blit_1
+};
diff --git a/dlls/winedib.drv/primitives_bitblt.c b/dlls/winedib.drv/primitives_bitblt.c
new file mode 100644
index 0000000..da48352
--- /dev/null
+++ b/dlls/winedib.drv/primitives_bitblt.c
@@ -0,0 +1,1075 @@
+/*
+ * DIB Engine BitBlt Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* shrinks a line -- srcWidth >= dstWidth */
+static void ShrinkLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth)
+{
+    int srcPos, dstPos;
+    int delta;
+    
+    srcPos = 0;
+    dstPos = 0;
+    delta = 0;
+    while(dstPos < dstWidth)
+    {
+        *dst++ = *src;
+        while(delta < srcWidth)
+        {
+            srcPos++;
+            src++;
+            delta += dstWidth;
+        }
+        delta -= srcWidth;
+        dstPos++;
+    }
+}
+
+/* expands a line -- srcWidth <= dstWidth */
+static void ExpandLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth)
+{
+    int srcPos;
+    int delta;
+
+    srcPos = 0;
+    delta = 0;
+    while(srcPos < srcWidth)
+    {
+        while(delta < dstWidth)
+        {
+            *dst++ = *src;
+            delta += srcWidth;
+        }
+        delta -= dstWidth;
+        src++;
+        srcPos++;
+    }
+}
+
+/* stretch a line */
+static void StretchLine(DWORD *dst, int dstWidth, DWORD *src, int srcWidth)
+{
+    if(srcWidth > dstWidth)
+        ShrinkLine(dst, dstWidth, src, srcWidth);
+    else if(srcWidth < dstWidth)
+        ExpandLine(dst, dstWidth, src, srcWidth);
+    else
+        memcpy(dst, src, 4 * srcWidth);
+}
+
+/* ------------------------------------------------------------*/
+/*                        BLITTING PRIMITIVES                  */
+BOOL _DIBDRV_BitBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT width, INT height, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, DWORD rop)
+{
+    int ys, yd;
+    int i;
+    DWORD *dwBuf;
+    DIBDRVBITMAP *dstBmp, *patBmp;
+    const DIBDRVBITMAP *srcBmp;
+    DWORD *wDstPnt, *wSrcPnt, *wPatPnt;
+    BOOL usePat, useSrc, useDst;
+    DWORD patColor;
+    BOOL res = FALSE;
+
+    /* 32 bit RGB source and destination buffer, if needed */
+    DWORD *sBuf = 0, *dBuf = 0, *pBuf = 0;
+
+    /* get elements usage */
+    usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
+    useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
+    useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
+    
+    /* gets source, dest and pattern bitmaps, if available */
+    if(usePat && physDevDst->isBrushBitmap)
+        patBmp = &physDevDst->brushBmpCache;
+    else
+        patBmp = NULL;
+
+    if(useSrc)
+        srcBmp = &physDevSrc->physBitmap;
+    else
+        srcBmp = NULL;
+    dstBmp = &physDevDst->physBitmap;
+    
+    /* gets pattern color, in case it's needed */
+    if(usePat)
+        patColor = physDevDst->brushColor;
+    else
+        patColor = 0;
+
+    /* allocate 32 bit RGB destination buffer */
+    if(!(dBuf = (DWORD *)HeapAlloc( GetProcessHeap(), 0, width * 4)))
+        goto error;
+    
+    MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, width:%d, height:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, rop:%8x\n",
+          dstBmp, _DIBDRVBITMAP_GetFormatName(dstBmp), xDst, yDst, width, height, 
+          srcBmp, _DIBDRVBITMAP_GetFormatName(srcBmp), xSrc, ySrc, rop));
+              
+    /* some simple ROPs optimizations */
+    switch(rop)
+    {
+          case BLACKNESS:
+              MAYBE(TRACE("BLACKNESS\n"));
+              memset(dBuf, 0x00, width * 4);
+              for(yd = yDst; yd < yDst+height; yd++)
+                  dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+              break;
+          
+          case WHITENESS:
+              MAYBE(TRACE("WHITENESS\n"));
+              for(dwBuf = dBuf, i = width; i; i--)
+                  *dwBuf++ = 0x00ffffff;
+              for(yd = yDst; yd < yDst+height; yd++)
+                  dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+              break;
+
+          case SRCCOPY:
+              MAYBE(TRACE("SRCCOPY\n"));
+              for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+              {
+                  srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, dBuf);
+                  dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+              }
+              break;
+
+          /* fallback for generic ROP operation */
+          default:
+              rop >>= 16;
+              if(useSrc && useDst && usePat && physDevDst->isBrushBitmap)
+              {
+                  MAYBE(TRACE("BitBlt use: src+dst+pat - pattern brush\n"));
+                  if(!(sBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, sBuf);
+                      dstBmp->funcs->GetLine(dstBmp, ys, xDst, width, dBuf);
+                      patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf);
+                      wDstPnt = dBuf;
+                      wSrcPnt = sBuf;
+                      wPatPnt = pBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, *wDstPnt, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(useSrc && useDst)
+              {
+                  if(usePat)
+                      MAYBE(TRACE("BitBlt use: src+dst+pat - solid brush\n"));
+                  else
+                      MAYBE(TRACE("BitBlt use: src+dst\n"));
+                  if(!(sBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, sBuf);
+                      dstBmp->funcs->GetLine(dstBmp, yd, xDst, width, dBuf);
+                      wDstPnt = dBuf;
+                      wSrcPnt = sBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, *wDstPnt, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(useSrc && usePat && physDevDst->isBrushBitmap)
+              {
+                  MAYBE(TRACE("BitBlt use: src+pat -- pattern brush\n"));
+                  if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, dBuf);
+                      patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf);
+                      wDstPnt = sBuf;
+                      wSrcPnt = sBuf;
+                      wPatPnt = pBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, 0, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(useSrc)
+              {
+                  if(usePat)
+                      MAYBE(TRACE("BitBlt use: src+pat - solid brush\n"));
+                  else
+                      MAYBE(TRACE("BitBlt use: src\n"));
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      srcBmp->funcs->GetLine(srcBmp, ys, xSrc, width, dBuf);
+                      wDstPnt = sBuf;
+                      wSrcPnt = sBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, 0, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(useDst && usePat && physDevDst->isBrushBitmap)
+              {
+                  MAYBE(TRACE("BitBlt use: dst+pat -- pattern brush\n"));
+                  if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      dstBmp->funcs->GetLine(srcBmp, ys, xDst, width, dBuf);
+                      patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf);
+                      wDstPnt = sBuf;
+                      wPatPnt = pBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, *wDstPnt, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(useDst)
+              {
+                  if(usePat)
+                      MAYBE(TRACE("BitBlt use: dst+pat - solid brush\n"));
+                  else
+                      MAYBE(TRACE("BitBlt use: dst\n"));
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      dstBmp->funcs->GetLine(srcBmp, ys, xDst, width, dBuf);
+                      wDstPnt = sBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(patColor, 0, *wDstPnt, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(usePat && physDevDst->isBrushBitmap)
+              {
+                  MAYBE(TRACE("BitBlt use: pat -- pattern brush\n"));
+                  if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, width * 4)))
+                      goto error;
+                  for(ys = ySrc, yd = yDst; ys < ySrc+height; ys++, yd++)
+                  {
+                      patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, width, pBuf);
+                      wDstPnt = dBuf;
+                      wPatPnt = pBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, 0, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else if(usePat)
+              {
+                  MAYBE(TRACE("BitBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop, patColor));
+                  MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp)));
+                  MAYBE(TRACE("xDst = %d, yDst = %d, width = %d, height = %d\n", xDst, yDst, width, height));
+                  for(yd = yDst; yd < yDst+height; yd++)
+                  {
+                      wDstPnt = dBuf;
+                      for(i = width; i > 0 ; i--)
+                      {
+                          *wDstPnt = _DIBDRV_ROP3(patColor, 0, 0, rop);
+                          wDstPnt++;
+                      }
+                      dstBmp->funcs->PutLine(dstBmp, yd, xDst, width, dBuf);
+                  }
+              }
+              else
+                  ERR("What happened ?????? \n");
+              break;
+    } /* switch */
+    res = TRUE;
+error:
+    if(sBuf) HeapFree( GetProcessHeap(), 0, sBuf );
+    if(dBuf) HeapFree( GetProcessHeap(), 0, dBuf );
+    if(pBuf) HeapFree( GetProcessHeap(), 0, pBuf );
+    return res;
+}
+
+/* ------------------------------------------------------------*/
+/*                        STRETCHING PRIMITIVES                */
+BOOL _DIBDRV_StretchBlt_generic(DIBDRVPHYSDEV *physDevDst, INT xDst, INT yDst,
+                    INT widthDst, INT heightDst, const DIBDRVPHYSDEV *physDevSrc,
+                    INT xSrc, INT ySrc, int widthSrc, int heightSrc, DWORD rop)
+{
+    int ys, yd;
+    int i, delta;
+    DWORD *dwBuf;
+    DIBDRVBITMAP *dstBmp, *patBmp;
+    const DIBDRVBITMAP *srcBmp;
+    DWORD *wDstPnt, *wSrcPnt, *wPatPnt;
+    BOOL usePat, useSrc, useDst;
+    DWORD patColor;
+    BOOL res = FALSE;
+
+    /* 32 bit RGB source and destination buffer, if needed */
+    DWORD *sBufOrig = 0, *sBufStr = 0, *dBuf = 0, *pBuf = 0;
+
+    /* get elements usage */
+    usePat = (((rop >> 4) & 0x0f0000) != (rop & 0x0f0000));
+    useSrc = (((rop >> 2) & 0x330000) != (rop & 0x330000));
+    useDst = (((rop >> 1) & 0x550000) != (rop & 0x550000));
+    
+    /* gets source, dest and pattern bitmaps, if available */
+    if(usePat && physDevDst->isBrushBitmap)
+        patBmp = &physDevDst->brushBmpCache;
+    else
+        patBmp = NULL;
+
+    if(useSrc)
+        srcBmp = &physDevSrc->physBitmap;
+    else
+        srcBmp = NULL;
+    dstBmp = &physDevDst->physBitmap;
+    
+    /* gets pattern color, in case it's needed */
+    if(usePat)
+        patColor = physDevDst->brushColor;
+    else
+        patColor = 0;
+
+    /* allocate 32 bit RGB destination buffer */
+    if(!(dBuf = (DWORD *)HeapAlloc( GetProcessHeap(), 0, widthDst * 4)))
+        goto error;
+    
+    MAYBE(TRACE("dstBmp:%p(%s), xDst:%d, yDst:%d, widthDst:%d, heightDst:%d, srcBmp:%p(%s), xSrc:%d, ySrc:%d, , widthSrc:%d, heightSrc:%drop:%8x\n",
+          dstBmp, _DIBDRVBITMAP_GetFormatName(dstBmp), xDst, yDst, widthDst, heightDst, 
+          srcBmp, _DIBDRVBITMAP_GetFormatName(srcBmp), xSrc, ySrc, widthSrc, heightSrc, rop));
+              
+    /* some simple ROPs optimizations */
+    switch(rop)
+    {
+        case BLACKNESS:
+            MAYBE(TRACE("BLACKNESS\n"));
+            memset(dBuf, 0x00, widthDst * 4);
+            for(yd = yDst; yd < yDst+heightDst; yd++)
+                dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+            break;
+        
+        case WHITENESS:
+            MAYBE(TRACE("WHITENESS\n"));
+            for(dwBuf = dBuf, i = widthDst; i; i--)
+                *dwBuf++ = 0x00ffffff;
+            for(yd = yDst; yd < yDst+heightDst; yd++)
+                dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+            break;
+
+        case SRCCOPY:
+            MAYBE(TRACE("SRCCOPY\n"));
+            sBufOrig = HeapAlloc(GetProcessHeap(), 0, widthSrc * 4);
+            if(heightSrc > heightDst)
+            {
+                ys = 0;
+                yd = 0;
+                delta = 0;
+                while(yd < heightDst)
+                {
+                    srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                    StretchLine(dBuf, widthDst, sBufOrig, widthSrc);
+                    dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                    while(delta < heightSrc)
+                    {
+                        ys++;
+                        delta += heightDst;
+                    }
+                    delta -= heightSrc;
+                    yd++;
+                }
+            }
+            else if(heightSrc < heightDst)
+            {
+                ys = 0;
+                yd = 0;
+                delta = 0;
+                while(ys < heightSrc)
+                {
+                    srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                    StretchLine(dBuf, widthDst, sBufOrig, widthSrc);
+                    while(delta < heightDst)
+                    {
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        yd++;
+                        delta += heightSrc;
+                    }
+                    delta -= heightDst;
+                    ys++;
+                }
+            }
+            else
+            {
+                for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                {
+                    srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBufOrig);
+                    StretchLine(dBuf, widthDst, sBufOrig, widthSrc);
+                    dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                }
+            }
+            break;
+
+        /* fallback for generic ROP operation */
+        default:
+            rop >>= 16;
+            if(useSrc && useDst && usePat && physDevDst->isBrushBitmap)
+            {
+                MAYBE(TRACE("StretchBlt use: src+dst+pat - pattern brush\n"));
+                if(!(sBufOrig = HeapAlloc(GetProcessHeap(), 0, widthSrc * 4)))
+                    goto error;
+                if(!(sBufStr = HeapAlloc(GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wSrcPnt = sBufStr;
+                            wPatPnt = pBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, *wDstPnt, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, ys, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(useSrc && useDst)
+            {
+                if(usePat)
+                    MAYBE(TRACE("StretchBlt use: src+dst+pat - solid brush\n"));
+                else
+                    MAYBE(TRACE("StretchBlt use: src+dst\n"));
+                if(!(sBufOrig = HeapAlloc(GetProcessHeap(), 0, widthSrc * 4)))
+                    goto error;
+                if(!(sBufStr = HeapAlloc(GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wSrcPnt = sBufStr;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, *wDstPnt, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        dstBmp->funcs->GetLine(dstBmp, ys, xDst, widthDst, dBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(useSrc && usePat && physDevDst->isBrushBitmap)
+            {
+                MAYBE(TRACE("StretchBlt use: src+pat -- pattern brush\n"));
+                if(!(sBufOrig = HeapAlloc(GetProcessHeap(), 0, widthSrc * 4)))
+                    goto error;
+                if(!(sBufStr = HeapAlloc(GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wSrcPnt = sBufStr;
+                            wPatPnt = pBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, 0, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, *wSrcPnt++, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(useSrc)
+            {
+                if(usePat)
+                    MAYBE(TRACE("StretchBlt use: src+pat - solid brush\n"));
+                else
+                    MAYBE(TRACE("StretchBlt use: src\n"));
+                if(!(sBufOrig = HeapAlloc(GetProcessHeap(), 0, widthSrc * 4)))
+                    goto error;
+                if(!(sBufStr = HeapAlloc(GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys + ySrc, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wSrcPnt = sBufStr;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, 0, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        srcBmp->funcs->GetLine(srcBmp, ys, xSrc, widthSrc, sBufOrig);
+                        StretchLine(sBufStr, widthDst, sBufOrig, widthSrc);
+                        wDstPnt = dBuf;
+                        wSrcPnt = sBufStr;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, *wSrcPnt++, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(useDst && usePat && physDevDst->isBrushBitmap)
+            {
+                MAYBE(TRACE("StretchBlt use: dst+pat -- pattern brush\n"));
+                if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wPatPnt = pBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, *wDstPnt, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, ys, xDst, widthDst, dBuf);
+                        patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(useDst)
+            {
+                if(usePat)
+                    MAYBE(TRACE("StretchBlt use: dst+pat - solid brush\n"));
+                else
+                    MAYBE(TRACE("StretchBlt use: dst\n"));
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        wDstPnt = dBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, 0, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(patColor, 0, *wDstPnt, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        dstBmp->funcs->GetLine(dstBmp, ys, xDst, widthDst, dBuf);
+                        wDstPnt = dBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, 0, *wDstPnt, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(usePat && physDevDst->isBrushBitmap)
+            {
+                MAYBE(TRACE("StretchBlt use: pat -- pattern brush\n"));
+                if(!(pBuf = HeapAlloc( GetProcessHeap(), 0, widthDst * 4)))
+                    goto error;
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        patBmp->funcs->GetLine(patBmp, (yd + yDst)%patBmp->height, 0, widthDst, pBuf);
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            wPatPnt = pBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, 0, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        patBmp->funcs->GetLine(patBmp, ys%patBmp->height, 0, widthDst, pBuf);
+                        wDstPnt = dBuf;
+                        wPatPnt = pBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(*wPatPnt++, 0, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else if(usePat)
+            {
+                MAYBE(TRACE("StretchBlt use: pat -- solid brush -- rop is %02x, color is %08x\n", rop, patColor));
+                MAYBE(TRACE("Dest BMP is a '%s'\n", _DIBDRVBITMAP_GetFormatName(dstBmp)));
+                MAYBE(TRACE("xDst = %d, yDst = %d, widthDst = %d, heightDst = %d\n", xDst, yDst, widthDst, heightDst));
+                if(heightSrc > heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(yd < heightDst)
+                    {
+                        wDstPnt = dBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, 0, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                        while(delta < heightSrc)
+                        {
+                            ys++;
+                            delta += heightDst;
+                        }
+                        delta -= heightSrc;
+                        yd++;
+                    }
+                }
+                else if(heightSrc < heightDst)
+                {
+                    ys = 0;
+                    yd = 0;
+                    delta = 0;
+                    while(ys < heightSrc)
+                    {
+                        while(delta < heightDst)
+                        {
+                            wDstPnt = dBuf;
+                            for(i = widthDst; i > 0 ; i--)
+                            {
+                                *wDstPnt = _DIBDRV_ROP3(patColor, 0, 0, rop);
+                                wDstPnt++;
+                            }
+                            dstBmp->funcs->PutLine(dstBmp, yd + yDst, xDst, widthDst, dBuf);
+                            yd++;
+                            delta += heightSrc;
+                        }
+                        delta -= heightDst;
+                        ys++;
+                    }
+                }
+                else
+                {
+                    for(ys = ySrc, yd = yDst; ys < ySrc+heightSrc; ys++, yd++)
+                    {
+                        wDstPnt = dBuf;
+                        for(i = widthDst; i > 0 ; i--)
+                        {
+                            *wDstPnt = _DIBDRV_ROP3(patColor, 0, 0, rop);
+                            wDstPnt++;
+                        }
+                        dstBmp->funcs->PutLine(dstBmp, yd, xDst, widthDst, dBuf);
+                    }
+                }
+            }
+            else
+                ERR("What happened ?????? \n");
+            break;
+    } /* switch */
+    res = TRUE;
+error:
+    if(sBufOrig) HeapFree( GetProcessHeap(), 0, sBufOrig );
+    if(sBufStr)  HeapFree( GetProcessHeap(), 0, sBufStr );
+    if(dBuf)     HeapFree( GetProcessHeap(), 0, dBuf );
+    if(pBuf)     HeapFree( GetProcessHeap(), 0, pBuf );
+    return res;
+}
diff --git a/dlls/winedib.drv/primitives_color.c b/dlls/winedib.drv/primitives_color.c
new file mode 100644
index 0000000..3ccc2e0
--- /dev/null
+++ b/dlls/winedib.drv/primitives_color.c
@@ -0,0 +1,142 @@
+/*
+ * DIB Engine color Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* ------------------------------------------------------------*/
+/*                     BITFIELD HELPERS                        */
+static inline DWORD PutField32(DWORD field, int shift, int len)
+{
+    shift = shift - (8 - len);
+    if (len <= 8)
+        field &= (((1 << len) - 1) << (8 - len));
+    if (shift < 0)
+        field >>= -shift;
+    else
+        field <<= shift;
+    return field;
+}
+
+static inline WORD PutField16(WORD field, int shift, int len)
+{
+    shift = shift - (8 - len);
+    if (len <= 8)
+        field &= (((1 << len) - 1) << (8 - len));
+    if (shift < 0)
+        field >>= -shift;
+    else
+        field <<= shift;
+    return field;
+}
+
+/* ------------------------------------------------------------*/
+/*                     COLOR FUNCTIONS                         */
+DWORD _DIBDRV_ColorToPixel32_RGB(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
+}
+
+DWORD _DIBDRV_ColorToPixel32_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    DWORD r,g,b;
+
+    r = GetRValue(color);
+    g = GetGValue(color);
+    b = GetBValue(color);
+
+    return PutField32(r, dib->redShift,   dib->redLen) |
+           PutField32(g, dib->greenShift, dib->greenLen) |
+           PutField32(b, dib->blueShift,  dib->blueLen);
+}
+
+DWORD _DIBDRV_ColorToPixel24(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    return ( ((color >> 16) & 0xff) | (color & 0xff00) | ((color << 16) & 0xff0000) );
+}
+
+DWORD _DIBDRV_ColorToPixel16_RGB(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    return ( ((color >> 19) & 0x001f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) );
+}
+
+DWORD _DIBDRV_ColorToPixel16_BITFIELDS(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    DWORD r,g,b;
+
+    r = GetRValue(color);
+    g = GetGValue(color);
+    b = GetBValue(color);
+
+    return PutField16(r, dib->redShift,   dib->redLen) |
+           PutField16(g, dib->greenShift, dib->greenLen) |
+           PutField16(b, dib->blueShift,  dib->blueLen);
+}
+
+DWORD _DIBDRV_ColorToPixelColortable(const DIBDRVBITMAP *dib, COLORREF color)
+{
+    int i, best_index = 0;
+    DWORD r, g, b;
+    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;
+        diff = (r - cur->rgbRed)   * (r - cur->rgbRed)
+            +  (g - cur->rgbGreen) * (g - cur->rgbGreen)
+            +  (b - cur->rgbBlue)  * (b - cur->rgbBlue);
+
+        if(diff == 0)
+        {
+            best_index = i;
+            break;
+        }
+
+        if(diff < best_diff)
+        {
+            best_diff = diff;
+            best_index = i;
+        }
+    }
+    return best_index;
+}
diff --git a/dlls/winedib.drv/primitives_convert.c b/dlls/winedib.drv/primitives_convert.c
new file mode 100644
index 0000000..800e3fd
--- /dev/null
+++ b/dlls/winedib.drv/primitives_convert.c
@@ -0,0 +1,559 @@
+/*
+ * DIB Engine conversions Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+static inline COLORREF SwapColors(DWORD c)
+{
+    return ((c & 0x0000ff) << 16) | (c & 0x00ff00) | ((c & 0xff0000) >> 16);
+    
+}
+
+/* ----------------------------------------------------------------*/
+/*                         CONVERT PRIMITIVES                      */
+/* converts (part of) line of any DIB format from/to DIB32_RGB one */
+BOOL _DIBDRV_GetLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    DWORD *src;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
+    for(; width; width--)
+        *dwBuf++ = *src++;
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    BYTE *bBuf = (BYTE *)buf;
+    DWORD *src;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        bBuf -= 4 * startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    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;
+        src++;
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    BYTE *bBuf = (BYTE *)buf;
+    BYTE *src;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        bBuf -= 4 * startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
+    for(; width ; width--)
+    {
+        *bBuf++ = *src++;
+        *bBuf++ = *src++;
+        *bBuf++ = *src++;
+        *bBuf++ = 0x0;
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    WORD *src;
+    DWORD b;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
+    for(; width ; width--)
+    {
+        b = *src++;
+        /* 0RRR|RRGG|GGGB|BBBB */
+        *dwBuf++ = ((b & 0x1f) << 3) | ((b & 0x3e0) << 6) | ((b & 0x7c00) << 9);
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    WORD *src;
+    DWORD b;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * 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  ));
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *src;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = ((BYTE *)bmp->bits + line * bmp->stride + startx);
+    for(; width ; width--)
+        *dwBuf++ = *((DWORD *)bmp->colorTable + *src++);
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *src;
+    
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+    if(!bmp->colorTable)
+    {
+        ERR("Called with uninitialized color table\n");
+        return FALSE;
+    }
+#endif
+
+    src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
+    /* if startx is odd, get first nibble */
+    if(startx & 0x01)
+    {
+        *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
+        width--;
+    }
+    
+    /* then gets all full image bytes */
+    for( ; width > 1 ; width -= 2)
+    {
+        *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
+        *dwBuf++ = *((DWORD *)bmp->colorTable + (*src++ & 0x0f));
+    }
+    
+    /* last nibble, if any */
+    if(width)
+        *dwBuf++ = *((DWORD *)bmp->colorTable + ((*src >> 4) & 0x0f));
+    return TRUE;
+}
+
+BOOL _DIBDRV_GetLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *src;
+    BYTE b;
+    char i;
+    DWORD pixOn  = *((DWORD *)bmp->colorTable + 1);
+    DWORD pixOff = *(DWORD *)bmp->colorTable;
+
+#ifdef DIBDRV_CHECK_RANGES
+    /* range check */
+    if(line < 0 || line >= bmp->height)
+        return FALSE;
+    if(startx < 0)
+    {
+        width += startx;
+        dwBuf -= startx; 
+        startx = 0;
+    }
+    if(startx + width > bmp->width)
+        width = bmp->width - startx;
+    if(width <= 0)
+        return FALSE;
+#endif
+
+    src = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
+    /* get first partial byte, if any */
+    startx = (8 - (startx & 0x03)) & 0x03;
+    width -= startx;
+    if(startx)
+    {
+        b = *src++ << (8 - startx);
+        while(startx--)
+        {
+            if(b & 0x80)
+                *dwBuf++ = pixOn;
+            else
+                *dwBuf++ = pixOff;
+            b <<= 1;
+        }
+    }
+    
+    /* then gets full next bytes */
+    for( ; width > 7 ; width -= 8)
+    {
+        b = *src++;
+        for(i = 0 ; i < 8 ; i++)
+        {
+            if(b & 0x80)
+                *dwBuf++ = pixOn;
+            else
+                *dwBuf++ = pixOff;
+            b <<= 1;
+        }
+    }
+    
+    /* last partial byte, if any */
+    if(width)
+    {
+        b = *src;
+        while(width--)
+        {
+            if(b & 0x80)
+                *dwBuf++ = pixOn;
+            else
+                *dwBuf++ = pixOff;
+            b <<= 1;
+        }
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine32_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
+    for(; width; width--)
+        *dst++ = *dwBuf++;
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine32_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    DWORD *dst = (DWORD *)((BYTE *)bmp->bits + line * bmp->stride + 4 * startx);
+    DWORD c;
+    for(; width; width--)
+    {
+        c = *dwBuf++;
+        *dst++ =
+            ((( c & 0x000000ff)        << bmp->blueShift)  & bmp->blueMask) |
+            ((((c & 0x0000ff00) >>  8) << bmp->greenShift) & bmp->greenMask) |
+            ((((c & 0x00ff0000) >> 16) << bmp->redShift)   & bmp->redMask);
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine24(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + 3 * startx);
+    DWORD c;
+    for(; width; width--)
+    {
+        c = *dwBuf++;
+        *dst++ = c &  0x000000ff;
+        *dst++ = (c & 0x0000ff00) >>  8;
+        *dst++ = (c & 0x00ff0000) >> 16;
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine16_RGB(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
+    DWORD c;
+    for(; width; width--)
+    {
+        c = *dwBuf++;
+        *dst++ =
+            ((c & 0x000000f8) >> 3) |
+            ((c & 0x0000f800) >> 6) |
+            ((c & 0x00f80000) >> 9);
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine16_BITFIELDS(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    WORD *dst = (WORD *)((BYTE *)bmp->bits + line * bmp->stride + 2 * startx);
+    DWORD c;
+    for(; width; width--)
+    {
+        c = *dwBuf++;
+        *dst++ =
+            ((( c & 0x000000ff)        << bmp->blueShift)  & bmp->blueMask) |
+            ((((c & 0x0000ff00) >>  8) << bmp->greenShift) & bmp->greenMask) |
+            ((((c & 0x00ff0000) >> 16) << bmp->redShift)   & bmp->redMask);
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine8(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + startx);
+    DWORD c;
+    DWORD last_color = 0xffffffff;
+    int last_index = -1;
+
+    for(; width; width--)
+    {
+        c = *dwBuf++;
+        
+        /* slight optimization, as images often have many
+           consecutive pixels with same color */
+        if(last_index == -1 || c != last_color)
+        {
+            last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
+            last_color = c;
+        }
+        *dst++ = last_index;
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine4(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 1));
+    DWORD c;
+    DWORD last_color = 0xffffffff;
+    int last_index = -1;
+    
+    /* if startx is odd, put first nibble */
+    if(startx & 0x01)
+    {
+        c = *dwBuf++;
+        
+        last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
+        last_color = c;
+        *dst = (*dst & 0xf0) | last_index;
+        dst++;
+        width--;
+    }
+    
+    /* then gets all full image bytes */
+    for( ; width > 1 ; width -= 2)
+    {
+        c = *dwBuf++;
+        
+        /* slight optimization, as images often have many
+           consecutive pixels with same color */
+        if(last_index == -1 || c != last_color)
+        {
+            last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
+            last_color = c;
+        }
+        *dst = last_index << 4;
+        
+        c = *dwBuf++;
+        
+        /* slight optimization, as images often have many
+           consecutive pixels with same color */
+        if(last_index == -1 || c != last_color)
+        {
+            last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
+            last_color = c;
+        }
+        *dst++ |= last_index;
+    }
+    
+    /* last nibble, if any */
+    if(width)
+    {
+        c = *dwBuf;
+        
+        /* slight optimization, as images often have many
+           consecutive pixels with same color */
+        if(last_index == -1 || c != last_color)
+            last_index = bmp->funcs->ColorToPixel(bmp, SwapColors(c));
+        *dst = (*dst & 0x0f) | (last_index << 4);
+    }
+    return TRUE;
+}
+
+BOOL _DIBDRV_PutLine1(const DIBDRVBITMAP *bmp, INT line, INT startx, int width, void *buf)
+{
+    DWORD *dwBuf = (DWORD *)buf;
+    BYTE *dst = ((BYTE *)bmp->bits + line * bmp->stride + (startx >> 3));
+    BYTE b, mask;
+    char i;
+    DWORD c;
+    
+    /* get foreground color */
+    DWORD fore = *((DWORD *)bmp->colorTable + 1) & 0x00ffffff;
+    
+    /* put first partial byte, if any */
+    startx &= 0x03;
+    mask = 0x80 >> startx;
+    startx = (8 - startx) & 0x03;
+    if(startx)
+    {
+        width -= startx;
+        b = *dst;
+        while(startx--)
+        {
+            c = *dwBuf++ & 0x00ffffff;
+            if(c == 0x00ffffff || c == fore)
+                b |= mask;
+            else
+                b &= !mask;
+            mask >>= 1;
+        }
+        *dst++ = b; 
+    }
+    
+    /* then puts full next bytes */
+    for( ; width > 7 ; width -= 8)
+    {
+        b = 0;
+        mask = 0x80;
+        for(i = 0 ; i < 8 ; i++)
+        {
+            c = *dwBuf++ & 0x00ffffff;
+            if(c == 0x00ffffff || c == fore)
+                b |= mask;
+            mask >>= 1;
+        }
+        *dst++ = b;
+    }
+    
+    /* last partial byte, if any */
+    if(width)
+    {
+        b = *dst;
+        mask = 0x80;
+        while(width--)
+        {
+            c = *dwBuf++ & 0x00ffffff;
+            if(c == 0x00ffffff || c == fore)
+                b |= mask;
+            else
+                b &= !mask;
+            mask >>= 1;
+        }
+        *dst = b;
+    }
+    return TRUE;
+}
diff --git a/dlls/winedib.drv/primitives_font.c b/dlls/winedib.drv/primitives_font.c
new file mode 100644
index 0000000..dd1d64b
--- /dev/null
+++ b/dlls/winedib.drv/primitives_font.c
@@ -0,0 +1,310 @@
+/*
+ * DIB Engine Font Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* ------------------------------------------------------------*/
+/*               FREETYPE FONT BITMAP BLITTING                 */
+void _DIBDRV_freetype_blit_8888(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+    DWORD *ptr;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        ptr = (DWORD *)((BYTE *)dib->bits + (dibY * dib->stride) + x * 4);
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                *ptr = c;
+            }
+            buf++;
+            ptr++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_32_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_32_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_24(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_16_RGB(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_16_BITFIELDS(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_8(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_4(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
+
+void _DIBDRV_freetype_blit_1(DIBDRVPHYSDEV *physDev, int x, int y, FT_Bitmap *bmp)
+{
+    /* FIXME : MUST BE OPTIMIZED !!! */
+    
+    DIBDRVBITMAP *dib = &physDev->physBitmap;
+    int bmpX, bmpY;
+    BYTE *buf;
+    int dibX, dibY;
+    int DIBX, DIBY;
+    DWORD c;
+
+    /* gets DIB limits */
+    DIBX = dib->width;
+    DIBY = dib->height;
+
+    /* loop for every pixel in bitmap */
+    buf = bmp->buffer;
+    for(bmpY = 0, dibY = y; bmpY < bmp->rows; bmpY++, dibY++)
+    {
+        for(bmpX = 0, dibX = x; bmpX < bmp->width; bmpX++, dibX++)
+        {
+            if(dibX < DIBX && dibY < DIBY && dibX > 0 && dibY > 0 && *buf)
+            {
+                c = physDev->textColorTable[*buf];
+                dib->funcs->SetPixel(dib, dibX, dibY, 0, c);
+            }
+            buf++;
+        }
+    }
+}
diff --git a/dlls/winedib.drv/primitives_line.c b/dlls/winedib.drv/primitives_line.c
new file mode 100644
index 0000000..af41e2d
--- /dev/null
+++ b/dlls/winedib.drv/primitives_line.c
@@ -0,0 +1,434 @@
+/*
+ * DIB Engine line Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* ------------------------------------------------------------*/
+/*                     HORIZONTAL LINES                        */
+void _DIBDRV_SolidHLine32(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    DWORD *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    for(i = start; i < end; i++)
+        _DIBDRV_rop32(ptr++, and, xor);
+}
+
+void _DIBDRV_SolidHLine24(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE and_bytes[3], xor_bytes[3];
+
+    and_bytes[0] =  and        & 0xff;
+    and_bytes[1] = (and >> 8)  & 0xff;
+    and_bytes[2] = (and >> 16) & 0xff;
+    xor_bytes[0] =  xor        & 0xff;
+    xor_bytes[1] = (xor >> 8)  & 0xff;
+    xor_bytes[2] = (xor >> 16) & 0xff;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr++, and_bytes[0], xor_bytes[0]);
+        _DIBDRV_rop8(ptr++, and_bytes[1], xor_bytes[1]);
+        _DIBDRV_rop8(ptr++, and_bytes[2], xor_bytes[2]);
+    }
+}
+
+void _DIBDRV_SolidHLine16(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    WORD *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    for(i = start; i < end; i++)
+        _DIBDRV_rop16(ptr++, and, xor);
+}
+
+void _DIBDRV_SolidHLine8(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    for(i = start; i < end; i++)
+        _DIBDRV_rop8(ptr++, and, xor);
+}
+
+void _DIBDRV_SolidHLine4(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE byte_and, byte_xor;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+    byte_and = (and & 0xf) | ((and << 4) & 0xf0);
+    byte_xor = (xor & 0xf) | ((xor << 4) & 0xf0);
+
+    if(start & 1) /* upper nibble untouched */
+        _DIBDRV_rop8(ptr++, byte_and | 0xf0, byte_xor & 0x0f);
+
+    for(i = (start + 1) / 2; i < end / 2; i++)
+        _DIBDRV_rop8(ptr++, byte_and, byte_xor);
+
+    if(end & 1) /* lower nibble untouched */
+        _DIBDRV_rop8(ptr, byte_and | 0x0f, byte_xor & 0xf0);
+}
+
+void _DIBDRV_SolidHLine1(DIBDRVBITMAP *dib, int start, int end, int row, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE byte_and = 0, byte_xor = 0, mask;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    if(and & 1) byte_and = 0xff;
+    if(xor & 1) byte_xor = 0xff;
+
+    if((start & ~7) == (end & ~7)) /* special case run inside one byte */
+    {
+        mask = ((1L << ((end & 7) - (start & 7))) - 1) << (8 - (end & 7));
+        _DIBDRV_rop8(ptr, byte_and | ~mask, byte_xor & mask);
+        return;
+    }
+
+    if(start & 7)
+    {
+        mask = (1 << (8 - (start & 7))) - 1;
+        _DIBDRV_rop8(ptr++, byte_and | ~mask, byte_xor & mask);
+    }
+
+    for(i = (start + 7) / 8; i < end / 8; i++)
+        _DIBDRV_rop8(ptr++, byte_and, byte_xor);
+
+    if(end & 7)
+    {
+        mask = ~((1 << (8 - (end & 7))) - 1);
+        _DIBDRV_rop8(ptr++, byte_and | ~mask, byte_xor & mask);
+    }
+}
+
+void _DIBDRV_PatternHLine32(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    DWORD *ptr;
+    const DWORD *and_ptr = and, *xor_ptr = xor;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset;
+    xor_ptr += offset;
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop32(ptr++, *and_ptr++, *xor_ptr++);
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+    }
+}
+
+void _DIBDRV_PatternHLine24(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    BYTE *ptr;
+    const BYTE *and_ptr = and, *xor_ptr = xor;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset * 3;
+    xor_ptr += offset * 3;
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr++,  *and_ptr++, *xor_ptr++);
+        _DIBDRV_rop8(ptr++,  *and_ptr++, *xor_ptr++);
+        _DIBDRV_rop8(ptr++,  *and_ptr++, *xor_ptr++);
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+    }
+}
+
+void _DIBDRV_PatternHLine16(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    WORD *ptr;
+    const WORD *and_ptr = and, *xor_ptr = xor;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset;
+    xor_ptr += offset;
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop16(ptr++, *and_ptr++, *xor_ptr++);
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+    }
+}
+
+void _DIBDRV_PatternHLine8(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    BYTE *ptr;
+    const BYTE *and_ptr = and, *xor_ptr = xor;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset;
+    xor_ptr += offset;
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr++, *and_ptr++, *xor_ptr++);
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+    }
+}
+
+void _DIBDRV_PatternHLine4(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    BYTE *ptr;
+    const BYTE *and_ptr = and, *xor_ptr = xor;
+    int i;
+    BYTE byte_and, byte_xor;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset / 2;
+    xor_ptr += offset / 2;
+
+    for(i = start; i < end; i++)
+    {
+        if(offset & 1)
+        {
+            byte_and = *and_ptr++ & 0x0f;
+            byte_xor = *xor_ptr++ & 0x0f;
+        }
+        else
+        {
+            byte_and = (*and_ptr & 0xf0) >> 4;
+            byte_xor = (*xor_ptr & 0xf0) >> 4;
+        }
+
+        if(i & 1)
+            byte_and |= 0xf0;
+        else
+        {
+            byte_and = (byte_and << 4) | 0x0f;
+            byte_xor <<= 4;
+        }
+
+        _DIBDRV_rop8(ptr, byte_and, byte_xor);
+
+        if(i & 1) ptr++;
+
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+    }
+}
+
+void _DIBDRV_PatternHLine1(DIBDRVBITMAP *dib, int start, int end, int row, const void *and, const void *xor, DWORD count, DWORD offset)
+{
+    BYTE *ptr;
+    const BYTE *and_ptr = and, *xor_ptr = xor;
+    int i;
+    BYTE byte_and, byte_xor, dst_mask, brush_mask;
+
+    ptr = dib->funcs->GetPixelPointer(dib, start, row);
+
+    and_ptr += offset / 8;
+    xor_ptr += offset / 8;
+
+    for(i = start; i < end; i++)
+    {
+        dst_mask   = 1 << (7 - (i      & 7));
+        brush_mask = 1 << (7 - (offset & 7));
+
+        byte_and = (*and_ptr & brush_mask) ? 0xff : 0;
+        byte_xor = (*xor_ptr & brush_mask) ? 0xff : 0;
+
+        byte_and |= ~dst_mask;
+        byte_xor &= dst_mask;
+
+        _DIBDRV_rop8(ptr, byte_and, byte_xor);
+
+        if((i & 7) == 7) ptr++;
+        if(++offset == count)
+        {
+            offset = 0;
+            and_ptr = and;
+            xor_ptr = xor;
+        }
+        else if((offset & 7) == 7)
+        {
+            and_ptr++;
+            xor_ptr++;
+        }
+    }
+}
+
+/* ------------------------------------------------------------*/
+/*                      VERTICAL LINES                         */
+void _DIBDRV_SolidVLine32(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop32((DWORD*)ptr, and, xor);
+        ptr += dib->stride;
+    }
+}
+
+void _DIBDRV_SolidVLine24(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE and_bytes[3], xor_bytes[3];
+
+    and_bytes[0] =  and        & 0xff;
+    and_bytes[1] = (and >> 8)  & 0xff;
+    and_bytes[2] = (and >> 16) & 0xff;
+    xor_bytes[0] =  xor        & 0xff;
+    xor_bytes[1] = (xor >> 8)  & 0xff;
+    xor_bytes[2] = (xor >> 16) & 0xff;
+
+    ptr  = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr, and_bytes[0], xor_bytes[0]);
+        _DIBDRV_rop8(ptr + 1, and_bytes[1], xor_bytes[1]);
+        _DIBDRV_rop8(ptr + 2, and_bytes[2], xor_bytes[2]);
+        ptr += dib->stride;
+    }
+}
+
+void _DIBDRV_SolidVLine16(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop16((WORD*)ptr, and, xor);
+        ptr += dib->stride;
+    }
+}
+
+void _DIBDRV_SolidVLine8(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+
+    ptr = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr, and, xor);
+        ptr += dib->stride;
+    }
+}
+
+void _DIBDRV_SolidVLine4(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE byte_and, byte_xor;
+
+    if(col & 1) /* upper nibble untouched */
+    {
+        byte_and = (and & 0xf) | 0xf0;
+        byte_xor = (xor & 0xf);
+    }
+    else
+    {
+        byte_and = ((and << 4) & 0xf0) | 0x0f;
+        byte_xor = ((xor << 4) & 0xf0);
+    }
+
+    ptr = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr, byte_and, byte_xor);
+        ptr += dib->stride;
+    }
+}
+
+void _DIBDRV_SolidVLine1(DIBDRVBITMAP *dib, int col, int start, int end, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    int i;
+    BYTE byte_and = 0, byte_xor = 0, mask;
+
+    if(and & 1) byte_and = 0xff;
+    if(xor & 1) byte_xor = 0xff;
+
+    mask = 1 << (7 - (col & 7));
+
+    byte_and |= ~mask;
+    byte_xor &= mask;
+
+    ptr = dib->funcs->GetPixelPointer(dib, col, start);
+
+    for(i = start; i < end; i++)
+    {
+        _DIBDRV_rop8(ptr, byte_and, byte_xor);
+        ptr += dib->stride;
+    }
+}
diff --git a/dlls/winedib.drv/primitives_pixel.c b/dlls/winedib.drv/primitives_pixel.c
new file mode 100644
index 0000000..ca68cf1
--- /dev/null
+++ b/dlls/winedib.drv/primitives_pixel.c
@@ -0,0 +1,244 @@
+/*
+ * DIB Engine pixel Primitives
+ *
+ * Copyright 2009 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+
+/* ------------------------------------------------------------*/
+/*                     BITFIELD HELPERS                        */
+static 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)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x * 4;
+    return ptr;
+}
+
+void *_DIBDRV_GetPixelPointer24(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x * 3;
+    return ptr;
+}
+
+void *_DIBDRV_GetPixelPointer16(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x * 2;
+    return ptr;
+}
+
+void *_DIBDRV_GetPixelPointer8(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x;
+    return ptr;
+}
+
+void *_DIBDRV_GetPixelPointer4(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x / 2;
+    return ptr;
+}
+
+void *_DIBDRV_GetPixelPointer1(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->bits;
+
+    ptr += (y * dib->stride);
+
+    ptr += x / 8;
+    return ptr;
+}
+
+/* ------------------------------------------------------------*/
+/*                     PIXEL WRITING                           */
+void _DIBDRV_SetPixel32(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    DWORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    _DIBDRV_rop32(ptr, and, xor);
+}
+
+void _DIBDRV_SetPixel24(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    _DIBDRV_rop8(ptr,      and        & 0xff,  xor        & 0xff);
+    _DIBDRV_rop8(ptr + 1, (and >> 8)  & 0xff, (xor >> 8)  & 0xff);
+    _DIBDRV_rop8(ptr + 2, (and >> 16) & 0xff, (xor >> 16) & 0xff);
+}
+
+void _DIBDRV_SetPixel16(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    WORD *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    _DIBDRV_rop16(ptr, and, xor);
+}
+
+void _DIBDRV_SetPixel8(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    _DIBDRV_rop8(ptr, and, xor);
+}
+
+void _DIBDRV_SetPixel4(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y);
+    BYTE byte_and, byte_xor;
+
+    if(x & 1) /* upper nibble untouched */
+    {
+        byte_and = (and & 0xf) | 0xf0;
+        byte_xor = (xor & 0xf);
+    }
+    else
+    {
+        byte_and = ((and << 4) & 0xf0) | 0x0f;
+        byte_xor = ((xor << 4) & 0xf0);
+    }
+
+    _DIBDRV_rop8(ptr, byte_and, byte_xor);
+}
+
+void _DIBDRV_SetPixel1(DIBDRVBITMAP *dib, int x, int y, DWORD and, DWORD xor)
+{
+    BYTE *ptr;
+    BYTE byte_and = 0, byte_xor = 0, mask;
+
+    if(and & 1) byte_and = 0xff;
+    if(xor & 1) byte_xor = 0xff;
+
+    mask = 1 << (7 - (x & 7));
+
+    byte_and |= ~mask;
+    byte_xor &= mask;
+
+    ptr = dib->funcs->GetPixelPointer(dib, x, y);
+
+    _DIBDRV_rop8(ptr, byte_and, byte_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 _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 |
+           GetField32(*ptr, dib->greenShift, dib->greenLen) <<  8 |
+           GetField32(*ptr, dib->blueShift,  dib->blueLen);
+}
+
+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];
+}
+
+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);
+}
+
+DWORD _DIBDRV_GetPixel16_BITFIELDS(const DIBDRVBITMAP *dib, int x, int y)
+{
+    WORD *ptr = 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);
+}
+
+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;
+}
+
+DWORD _DIBDRV_GetPixel4(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y), pix;
+    RGBQUAD *color;
+
+    if(x & 1)
+        pix = *ptr & 0x0f;
+    else
+        pix = *ptr >> 4;
+
+    color = dib->colorTable + pix;
+    return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue;
+}
+
+DWORD _DIBDRV_GetPixel1(const DIBDRVBITMAP *dib, int x, int y)
+{
+    BYTE *ptr = dib->funcs->GetPixelPointer(dib, x, y), pix;
+    RGBQUAD *color;
+
+    pix = *ptr;
+
+    pix >>= (7 - (x & 7));
+    pix &= 1;
+
+    color = dib->colorTable + pix;
+    return (color->rgbRed << 16) | (color->rgbGreen << 8) | color->rgbBlue;
+}
diff --git a/dlls/winedib.drv/primitives_rop2.c b/dlls/winedib.drv/primitives_rop2.c
new file mode 100644
index 0000000..b23e919
--- /dev/null
+++ b/dlls/winedib.drv/primitives_rop2.c
@@ -0,0 +1,112 @@
+/*
+ * DIB Engine ROP2 Primitives
+ *
+ * Copyright 2008 Huw Davies
+ * Copyright 2008 Massimo Del Fedele
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* ------------------------------------------------------------*/
+/*                     BASIC ROP HELPER                        */
+/*
+ *
+ * Decompose the 16 ROP2s into an expression of the form
+ *
+ * D = (D & A) ^ X
+ *
+ * Where A and X depend only on P (and so can be precomputed).
+ *
+ *                                       A    X
+ *
+ * R2_BLACK         0                    0    0
+ * R2_NOTMERGEPEN   ~(D | P)            ~P   ~P
+ * R2_MASKNOTPEN    ~P & D              ~P    0
+ * R2_NOTCOPYPEN    ~P                   0   ~P
+ * R2_MASKPENNOT    P & ~D               P    P
+ * R2_NOT           ~D                   1    1
+ * R2_XORPEN        P ^ D                1    P
+ * R2_NOTMASKPEN    ~(P & D)             P    1
+ * R2_MASKPEN       P & D                P    0
+ * R2_NOTXORPEN     ~(P ^ D)             1   ~P
+ * R2_NOP           D                    1    0
+ * R2_MERGENOTPEN   ~P | D               P   ~P
+ * R2_COPYPEN       P                    0    P
+ * R2_MERGEPENNOT   P | ~D              ~P    1
+ * R2_MERGEPEN      P | D               ~P    P
+ * R2_WHITE         1                    0    1
+ *
+ */
+
+/* A = (P & A1) | (~P & A2) */
+#define ZERO {0, 0}
+#define ONE {0xffffffff, 0xffffffff}
+#define P {0xffffffff, 0}
+#define NOT_P {0, 0xffffffff}
+
+static const DWORD rop2_and_array[16][2] =
+{
+    ZERO, NOT_P, NOT_P, ZERO,
+    P,    ONE,   ONE,   P,
+    P,    ONE,   ONE,   P,
+    ZERO, NOT_P, NOT_P, ZERO
+};
+
+/* X = (P & X1) | (~P & X2) */
+static const DWORD rop2_xor_array[16][2] =
+{
+    ZERO, NOT_P, ZERO, NOT_P,
+    P,    ONE,   P,    ONE,
+    ZERO, NOT_P, ZERO, NOT_P,
+    P,    ONE,   P,    ONE
+};
+
+#undef NOT_P
+#undef P
+#undef ONE
+#undef ZERO
+
+void _DIBDRV_CalcAndXorMasks(INT rop, DWORD color, DWORD *and, DWORD *xor)
+{
+    /* NB The ROP2 codes start at one and the arrays are zero-based */
+    rop = (rop - 1) & 0x0f;
+    *and = (color & rop2_and_array[rop][0]) | ((~color) & rop2_and_array[rop][1]);
+    *xor = (color & rop2_xor_array[rop][0]) | ((~color) & rop2_xor_array[rop][1]);
+}
+
+/* ------------------------------------------------------------*/
+/*                   ROP PIXEL FUNCTIONS                       */
+
+inline void _DIBDRV_rop32(DWORD *ptr, DWORD and, DWORD xor)
+{
+    *ptr = (*ptr & and) ^ xor;
+}
+
+inline void _DIBDRV_rop16(WORD *ptr, WORD and, WORD xor)
+{
+    *ptr = (*ptr & and) ^ xor;
+}
+
+inline void _DIBDRV_rop8(BYTE *ptr, BYTE and, BYTE xor)
+{
+    *ptr = (*ptr & and) ^ xor;
+}
diff --git a/dlls/winedib.drv/primitives_rop3.c b/dlls/winedib.drv/primitives_rop3.c
new file mode 100644
index 0000000..398258b
--- /dev/null
+++ b/dlls/winedib.drv/primitives_rop3.c
@@ -0,0 +1,786 @@
+#include "config.h"
+#include "wine/port.h"
+
+#include "dibdrv.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
+
+/* the ROP3 operations
+   this is a BIG case block; beware that some
+   commons ROP3 operations will be optimized
+   from inside blt routines */
+DWORD _DIBDRV_ROP3(DWORD p, DWORD s, DWORD d, BYTE rop)
+{
+    switch(rop)
+    {
+        case 0x00:   /* 0           BLACKNESS    */
+            return 0;
+            
+        case 0x01:   /* DPSoon                   */
+            return (~(p | s | d)) & 0x00ffffff;
+            
+        case 0x02:   /* DPSona                   */
+            return (d & ~(p | s)) & 0x00ffffff;
+            
+        case 0x03:   /* PSon                     */
+            return (~(p | s)) & 0x00ffffff;
+            
+        case 0x04:   /* SDPona                   */
+            return (s & ~(d | p)) & 0x00ffffff;
+            
+        case 0x05:   /* DPon                     */
+            return (~(d | p)) & 0x00ffffff;
+            
+        case 0x06:   /* PDSxnon                  */
+            return (~(p | ~(d ^ s))) & 0x00ffffff;
+            
+        case 0x07:   /* PDSaon                   */
+            return (~((d & s) | p) ) & 0x00ffffff;
+            
+        case 0x08:   /* SDPnaa                   */
+            return (d & ~p & s) & 0x00ffffff;
+            
+        case 0x09:   /* PDSxon                   */
+            return (~((d ^ s) | p)) & 0x00ffffff;
+            
+        case 0x0A:   /* DPna                     */
+            return (~p & d) & 0x00ffffff;
+            
+        case 0x0B:   /* PSDnaon                  */
+            return (~((~d & s) | p)) & 0x00ffffff;
+            
+        case 0x0C:   /* SPna                     */
+            return (~p & s) & 0x00ffffff;
+            
+        case 0x0D:   /* PDSnaon                  */
+            return (~((~s & d) | p)) & 0x00ffffff;
+            
+        case 0x0E:   /* PDSonon                  */
+            return (~(~(d | s) | p)) & 0x00ffffff;
+            
+        case 0x0F:   /* Pn                       */
+            return (~p) & 0x00ffffff;
+            
+        case 0x10:   /* PDSona                   */
+            return (~(d | s) & p) & 0x00ffffff;
+            
+        case 0x11:   /* DSon        NOTSRCERASE  */
+            return (~(d | s)) & 0x00ffffff;
+            
+        case 0x12:   /* SDPxnon                  */
+            return (~(~(d ^ p) | s)) & 0x00ffffff;
+            
+        case 0x13:   /* SDPaon                   */
+            return (~((d & p) | s)) & 0x00ffffff;
+            
+        case 0x14:   /* DPSxnon                  */
+            return (~(~(p ^ s) | d)) & 0x00ffffff;
+            
+        case 0x15:   /* DPSaon                   */
+            return (~((p & s) | d)) & 0x00ffffff;
+            
+        case 0x16:   /* PSDPSanaxx               */
+            return (((~(p & s) & d) ^ s) ^ p) & 0x00ffffff;
+            
+        case 0x17:   /* SSPxDSxaxn               */
+            return (~(((d ^ s) & (s ^ p)) ^ s)) & 0x00ffffff;
+            
+        case 0x18:   /* SPxPDxa                  */
+            return ((s ^ p) & (p ^ d)) & 0x00ffffff;
+            
+        case 0x19:   /* SDPSanaxn                */
+            return (~((~(p & s) & d) ^ s)) & 0x00ffffff;
+            
+        case 0x1A:   /* PDSPaox                  */
+            return (((s & p) | d) ^ p) & 0x00ffffff;
+            
+        case 0x1B:   /* SDPSxaxn                 */
+            return (~(((p ^ s) & d) ^ s)) & 0x00ffffff;
+            
+        case 0x1C:   /* PSDPaox                  */
+            return (((d & p) | s) ^ p) & 0x00ffffff;
+            
+        case 0x1D:   /* DSPDxaxn                 */
+            return (~(((p ^ d) & s) ^ d)) & 0x00ffffff;
+            
+        case 0x1E:   /* PDSox                    */
+            return ((d | s) ^ p) & 0x00ffffff;
+            
+        case 0x1F:   /* PDSoan                   */
+            return (~((d | s) & p)) & 0x00ffffff;
+            
+        case 0x20:   /* DPSnaa                   */
+            return (p & ~s & d) & 0x00ffffff;
+            
+        case 0x21:   /* SDPxon                   */
+            return (~((d ^ p) | s)) & 0x00ffffff;
+            
+        case 0x22:   /* DSna                     */
+            return (d & ~s) & 0x00ffffff;
+            
+        case 0x23:   /* SPDnaon                  */
+            return (~((p & ~d) | s)) & 0x00ffffff;
+            
+        case 0x24:   /* SPxDSxa                  */
+            return ((s ^ p) & (d ^ s)) & 0x00ffffff;
+            
+        case 0x25:   /* PDSPanaxn                */
+            return (~((~(s & p) & d) ^ p)) & 0x00ffffff;
+            
+        case 0x26:   /* SDPSaox                  */
+            return (((p & s) | d) ^ s) & 0x00ffffff;
+            
+        case 0x27:   /* SDPSxnox                 */
+            return ((~(p ^ s) | d) ^ s) & 0x00ffffff;
+            
+        case 0x28:   /* DPSxa                    */
+            return ((p ^ s) & d) & 0x00ffffff;
+            
+        case 0x29:   /* PSDPSaoxxn               */
+            return (~((((p & s) | d) ^ s) ^ p)) & 0x00ffffff;
+            
+        case 0x2A:   /* DPSana                   */
+            return (~(p & s) & d) & 0x00ffffff;
+            
+        case 0x2B:   /* SSPxPDxaxn               */
+            return (~(((s ^ p) & (p ^ d)) ^ s)) & 0x00ffffff;
+            
+        case 0x2C:   /* SPDSoax                  */
+            return (((d | s) & p) ^ s) & 0x00ffffff;
+            
+        case 0x2D:   /* PSDnox                   */
+            return ((s | ~d) ^ p) & 0x00ffffff;
+            
+        case 0x2E:   /* PSDPxox                  */
+            return (((d ^ p) | s) ^ p) & 0x00ffffff;
+            
+        case 0x2F:   /* PSDnoan                  */
+            return (~((s | ~d) & p)) & 0x00ffffff;
+            
+        case 0x30:   /* PSna                     */
+            return (p & ~s) & 0x00ffffff;
+            
+        case 0x31:   /* SDPnaon                  */
+            return (~((d & ~p) | s)) & 0x00ffffff;
+            
+        case 0x32:   /* SDPSoox                  */
+            return ((p | s | d) ^ s) & 0x00ffffff;
+            
+        case 0x33:   /* Sn          NOTSRCCOPY   */
+            return (~s) & 0x00ffffff;
+            
+        case 0x34:   /* SPDSaox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x35:   /* SPDSxnox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x36:   /* SDPox                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x37:   /* SDPoan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x38:   /* PSDPoax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x39:   /* SPDnox                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3A:   /* SPDSxox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3B:   /* SPDnoan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3C:   /* PSx                      */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3D:   /* SPDSonox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3E:   /* SPDSnaox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x3F:   /* PSan                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x40:   /* PSDnaa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x41:   /* DPSxon                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x42:   /* SDxPDxa                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x43:   /* SPDSanaxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x44:   /* SDna        SRCERASE     */
+            return (s & ~d) & 0x00ffffff;
+            
+        case 0x45:   /* DPSnaon                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x46:   /* DSPDaox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x47:   /* PSDPxaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x48:   /* SDPxa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x49:   /* PDSPDaoxxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4A:   /* DPSDoax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4B:   /* PDSnox                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4C:   /* SDPana                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4D:   /* SSPxDSxoxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4E:   /* PDSPxox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x4F:   /* PDSnoan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x50:   /* PDna                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x51:   /* DSPnaon                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x52:   /* DPSDaox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x53:   /* SPDSxaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x54:   /* DPSonon                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x55:   /* Dn          DSTINVERT    */
+            return (~d) & 0x00ffffff;
+            
+        case 0x56:   /* DPSox                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x57:   /* DPSoan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x58:   /* PDSPoax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x59:   /* DPSnox                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x5A:   /* DPx         PATINVERT    */
+            return (d ^ p) & 0x00ffffff;
+            
+        case 0x5B:   /* DPSDonox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x5C:   /* DPSDxox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x5D:   /* DPSnoan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x5E:   /* DPSDnaox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x5F:   /* DPan                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x60:   /* PDSxa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x61:   /* DSPDSaoxxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x62:   /* DSPDoax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x63:   /* SDPnox                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x64:   /* SDPSoax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x65:   /* DSPnox                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x66:   /* DSx         SRCINVERT    */
+            return (d ^ s) & 0x00ffffff;
+            
+        case 0x67:   /* SDPSonox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x68:   /* DSPDSonoxxn              */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x69:   /* PDSxxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6A:   /* DPSax                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6B:   /* PSDPSoaxxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6C:   /* SDPax                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6D:   /* PDSPDoaxxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6E:   /* SDPSnoax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x6F:   /* PDSxnan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x70:   /* PDSana                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x71:   /* SSDxPDxaxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x72:   /* SDPSxox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x73:   /* SDPnoan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x74:   /* DSPDxox                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x75:   /* DSPnoan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x76:   /* SDPSnaox                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x77:   /* DSan                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x78:   /* PDSax                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x79:   /* DSPDSoaxxn               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7A:   /* DPSDnoax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7B:   /* SDPxnan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7C:   /* SPDSnoax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7D:   /* DPSxnan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7E:   /* SPxDSxo                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x7F:   /* DPSaan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x80:   /* DPSaa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x81:   /* SPxDSxon                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x82:   /* DPSxna                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x83:   /* SPDSnoaxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x84:   /* SDPxna                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x85:   /* PDSPnoaxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x86:   /* DSPDSoaxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x87:   /* PDSaxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x88:   /* DSa         SRCAND       */
+            return (d & s) & 0x00ffffff;
+            
+        case 0x89:   /* SDPSnaoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8A:   /* DSPnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8B:   /* DSPDxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8C:   /* SDPnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8D:   /* SDPSxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8E:   /* SSDxPDxax                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x8F:   /* PDSanan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x90:   /* PDSxna                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x91:   /* SDPSnoaxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x92:   /* DPSDPoaxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x93:   /* SPDaxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x94:   /* PSDPSoaxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x95:   /* DPSaxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x96:   /* DPSxx                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x97:   /* PSDPSonoxx               */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x98:   /* SDPSonoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x99:   /* DSxn                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9A:   /* DPSnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9B:   /* SDPSoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9C:   /* SPDnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9D:   /* DSPDoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9E:   /* DSPDSaoxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0x9F:   /* PDSxan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA0:   /* DPa                      */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA1:   /* PDSPnaoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA2:   /* DPSnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA3:   /* DPSDxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA4:   /* PDSPonoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA5:   /* PDxn                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA6:   /* DSPnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA7:   /* PDSPoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA8:   /* DPSoa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xA9:   /* DPSoxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xAA:   /* D                        */
+            return (d) & 0x00ffffff;
+            
+        case 0xAB:   /* DPSono                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xAC:   /* SPDSxax                  */
+            return (s ^ (p & (d ^ s))) & 0x00ffffff;
+            
+        case 0xAD:   /* DPSDaoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xAE:   /* DSPnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xAF:   /* DPno                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB0:   /* PDSnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB1:   /* PDSPxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB2:   /* SSPxDSxox                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB3:   /* SDPanan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB4:   /* PSDnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB5:   /* DPSDoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB6:   /* DPSDPaoxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB7:   /* SDPxan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB8:   /* PSDPxax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xB9:   /* DSPDaoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xBA:   /* DPSnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xBB:   /* DSno        MERGEPAINT   */
+            return (d | ~s) & 0x00ffffff;
+            
+        case 0xBC:   /* SPDSanax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xBD:   /* SDxPDxan                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xBE:   /* DPSxo                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xBF:   /* DPSano                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC0:   /* PSa         MERGECOPY    */
+            return (p & s) & 0x00ffffff;
+            
+        case 0xC1:   /* SPDSnaoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC2:   /* SPDSonoxn                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC3:   /* PSxn                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC4:   /* SPDnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC5:   /* SPDSxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC6:   /* SDPnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC7:   /* PSDPoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC8:   /* SDPoa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xC9:   /* SPDoxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xCA:   /* DPSDxax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xCB:   /* SPDSaoxn                 */
+            return (0x123456) & 0x00ffffff;
+        
+        default:    
+        case 0xCC:   /* S           SRCCOPY      */
+            return (s) & 0x00ffffff;
+            
+        case 0xCD:   /* SDPono                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xCE:   /* SDPnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xCF:   /* SPno                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD0:   /* PSDnoa                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD1:   /* PSDPxoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD2:   /* PDSnax                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD3:   /* SPDSoaxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD4:   /* SSPxPDxax                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD5:   /* DPSanan                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD6:   /* PSDPSaoxx                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD7:   /* DPSxan                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD8:   /* PDSPxax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xD9:   /* SDPSaoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDA:   /* DPSDanax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDB:   /* SPxDSxan                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDC:   /* SPDnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDD:   /* SDno                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDE:   /* SDPxo                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xDF:   /* SDPano                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE0:   /* PDSoa                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE1:   /* PDSoxn                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE2:   /* DSPDxax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE3:   /* PSDPaoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE4:   /* SDPSxax                  */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE5:   /* PDSPaoxn                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE6:   /* SDPSanax                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE7:   /* SPxPDxan                 */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE8:   /* SSPxDSxax                */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xE9:   /* DSPDSanaxxn              */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xEA:   /* DPSao                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xEB:   /* DPSxno                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xEC:   /* SDPao                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xED:   /* SDPxno                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xEE:   /* DSo         SRCPAINT     */
+            return (d | s) & 0x00ffffff;
+            
+        case 0xEF:   /* SDPnoo                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF0:   /* P           PATCOPY      */
+            return (p) & 0x00ffffff;
+            
+        case 0xF1:   /* PDSono                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF2:   /* PDSnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF3:   /* PSno                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF4:   /* PSDnao                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF5:   /* PDno                     */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF6:   /* PDSxo                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF7:   /* PDSano                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF8:   /* PDSao                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xF9:   /* PDSxno                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xFA:   /* DPo                      */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xFB:   /* DPSnoo      PATPAINT     */
+            return (p | ~s | d) & 0x00ffffff;
+            
+        case 0xFC:   /* PSo                      */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xFD:   /* PSDnoo                   */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xFE:   /* DPSoo                    */
+            return (0x123456) & 0x00ffffff;
+            
+        case 0xFF:   /* 1           WHITENESS    */
+            return 0x00ffffff;
+    
+    } /* switch */
+}
diff --git a/dlls/winedib.drv/text.c b/dlls/winedib.drv/text.c
index 0176011..e2cea0c 100644
--- a/dlls/winedib.drv/text.c
+++ b/dlls/winedib.drv/text.c
@@ -25,6 +25,19 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
 
+/* converts font sizes from Word space to Device space */
+static void FontSizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h)
+{
+    POINT pts[2];
+    pts[0].x = 0;
+    pts[0].y = 0;
+    pts[1].x = abs(*w);
+    pts[1].y = abs(*h);
+    LPtoDP(physDev->hdc, pts, 2);
+    *w = pts[1].x - pts[0].x;
+    *h = pts[1].y - pts[0].y;
+}
+
 /***********************************************************************
  *           DIBDRV_ExtTextOut
  */
@@ -32,17 +45,163 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
                         const RECT *lprect, LPCWSTR wstr, UINT count,
                         const INT *lpDx )
 {
+    /* FIXME : TODO many, many stuffs... just trivial text support by now */
+
     BOOL res;
+    FT_Face face;
+    FT_UInt glyph_index;
+    INT n;
+    INT error;
+    LOGFONTW lf;
+    int w, h;
+    LPCWSTR wstrPnt;
+    
+    FT_Glyph glyph;
+    FT_BitmapGlyph bitmap;
+    double cosEsc, sinEsc;
+    FT_Matrix matrix;
+    FT_Vector start; 
+    int dx, dy;
     
-    TRACE("physDev:%p, x:%d, y:%d, flags:%x, lprect:%p, wstr:%s, count:%d, lpDx:%p\n",
-          physDev, x, y, flags, lprect, debugstr_w(wstr), count, lpDx);
+    
+    MAYBE(TRACE("physDev:%p, x:%d, y:%d, flags:%x, lprect:%p, wstr:%s, count:%d, lpDx:%p\n",
+          physDev, x, y, flags, lprect, debugstr_w(wstr), count, lpDx));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pExtTextOut(physDev->X11PhysDev, x, y, flags, lprect,
-                                                   wstr, count, lpDx);
+
+        face = physDev->face;
+        if(!face)
+        {
+            ERR("FreeType face is null\n");
+            res = FALSE;
+            goto fin;
+        }
+        
+        /* outputs the string in case it is given by glyph indexes
+           make locating it in logs much easier */
+        if(TRACE_ON(dibdrv) && flags & ETO_GLYPH_INDEX)
+        {
+            WCHAR a = 'A';
+            WCHAR *str = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*(count+1));
+            int delta = a - pFT_Get_Char_Index( face, a);
+            int i;
+            memcpy(str, wstr, sizeof(WCHAR)*count);
+            for(i = 0; str[i] && i < count; i++)
+                str[i] += delta;
+            TRACE("String: '%s'\n", debugstr_w(str));
+            HeapFree(GetProcessHeap(), 0, str);
+        }
+
+        /* gets font data, etc */
+        GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf);
+        
+        /* convert sizes to device space */
+        w = lf.lfWidth; h = lf.lfHeight;
+        FontSizes_ws2ds(physDev, &w, &h);
+        
+        /* if opaque, paint the font background */
+/*
+        if(flags | ETO_OPAQUE)
+        {
+            int iLine;
+            for(iLine = lprect->top; iLine < lprect->bottom; iLine++)
+                physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap,
+                    lprect->left, lprect->right-1, iLine, 0, physDev->backgroundColor);
+        }
+*/
+        /* sets character pixel size */
+        error = pFT_Set_Pixel_Sizes(
+            face,
+            MulDiv(w, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSX)), 
+            MulDiv(h, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSY))
+        );
+        if(error)
+            ERR("Couldn't set char size to (%d,%d)\n", lf.lfWidth, lf.lfHeight);
+
+        /* transformation matrix and vector */
+        start.x = 0;
+        start.y = 0;
+        if(lf.lfEscapement != 0)
+        {
+            cosEsc = cos(lf.lfEscapement * M_PI / 1800);
+            sinEsc = sin(lf.lfEscapement * M_PI / 1800);
+        }
+        else
+        {
+            cosEsc = 1;
+            sinEsc = 0;
+        }
+        matrix.xx = (FT_Fixed)( cosEsc * 0x10000L );
+        matrix.xy = (FT_Fixed)(-sinEsc * 0x10000L );
+        matrix.yx = (FT_Fixed)( sinEsc * 0x10000L );
+        matrix.yy = (FT_Fixed)( cosEsc * 0x10000L );
+     
+        /* outputs characters one by one */
+        wstrPnt = wstr;
+        for ( n = 0; n < count; n++ )
+        {
+            /* retrieve glyph index from character code */
+            if(flags & ETO_GLYPH_INDEX)
+                glyph_index = *wstrPnt++;
+            else
+                glyph_index = pFT_Get_Char_Index( face, *wstrPnt++);
+
+            /* load glyph image into the slot (erase previous one) */
+            error = pFT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
+            if(error)
+            {
+                ERR("Couldn't load glyph at index %d\n", glyph_index);
+                /* ignore errors */
+                continue;
+            }
+            error = pFT_Get_Glyph(face->glyph, &glyph);
+            if ( error )
+            {
+                FIXME("Couldn't get glyph\n");
+                continue; 
+            }
+     
+            /* apply transformation to glyph */
+            if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
+                pFT_Glyph_Transform(glyph, &matrix, &start ); 
+                    
+            /* gets advance BEFORE transforming... */
+            dx = glyph->advance.x;
+            dy = glyph->advance.y;
+             
+            /* convert to an anti-aliased bitmap, if needed */
+            if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
+            {
+                error = pFT_Glyph_To_Bitmap(
+                    &glyph,
+                    FT_RENDER_MODE_NORMAL,
+                    0, /* no additional translation */
+                    1  /* destroy copy in "image" */
+                );  
+
+                /* ignore errors */
+                if ( error )
+                {
+                    FIXME("Couldn't render glyph\n");
+                    pFT_Done_Glyph(glyph);
+                    continue;
+                }
+            }
+
+            /* now, draw to our target surface */
+            bitmap = (FT_BitmapGlyph)glyph;
+            physDev->physBitmap.funcs->FreetypeBlit(physDev, x+bitmap->left, y-bitmap->top, &bitmap->bitmap);
+
+            /* increment pen position */
+            x += dx>>16;
+            y -= dy>>16;
+
+            pFT_Done_Glyph(glyph);
+            
+            res = TRUE;
+        } 
     }
     else
     {
@@ -50,6 +209,7 @@ BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
         res = _DIBDRV_GetDisplayDriver()->pExtTextOut(physDev->X11PhysDev, x, y, flags, lprect,
                                                    wstr, count, lpDx);
     }
+fin:
     return res;
 }
 
@@ -61,15 +221,14 @@ BOOL DIBDRV_GetTextExtentExPoint( DIBDRVPHYSDEV *physDev, LPCWSTR str, INT count
 {
     BOOL res;
     
-    TRACE("physDev:%p, str:%s, count:%d, maxExt:%d, lpnFit:%p, alpDx:%p, size:%p\n",
-        physDev, debugstr_w(str), count, maxExt, lpnFit, alpDx, size);
+    MAYBE(TRACE("physDev:%p, str:%s, count:%d, maxExt:%d, lpnFit:%p, alpDx:%p, size:%p\n",
+        physDev, debugstr_w(str), count, maxExt, lpnFit, alpDx, size));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pGetTextExtentExPoint(physDev->X11PhysDev, str, count, maxExt,
-                                                                lpnFit, alpDx, size);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {
diff --git a/dlls/winedib.drv/video.c b/dlls/winedib.drv/video.c
index 730e62a..9892d69 100644
--- a/dlls/winedib.drv/video.c
+++ b/dlls/winedib.drv/video.c
@@ -32,7 +32,7 @@ BOOL DIBDRV_GetDeviceGammaRamp( DIBDRVPHYSDEV *physDev, LPVOID ramp )
 {
     BOOL res;
     
-    TRACE("physDev:%p, ramp:%p\n", physDev, ramp);
+    MAYBE(TRACE("physDev:%p, ramp:%p\n", physDev, ramp));
 
     if(physDev->hasDIB)
     {
@@ -55,13 +55,13 @@ BOOL DIBDRV_SetDeviceGammaRamp( DIBDRVPHYSDEV *physDev, LPVOID ramp )
 {
     BOOL res;
     
-    TRACE("physDev:%p, ramp:%p\n", physDev, ramp);
+    MAYBE(TRACE("physDev:%p, ramp:%p\n", physDev, ramp));
 
     if(physDev->hasDIB)
     {
         /* DIB section selected in, use DIB Engine */
-        ONCE(FIXME("TEMPORARY - fallback to X11 driver\n"));
-        res = _DIBDRV_GetDisplayDriver()->pSetDeviceGammaRamp(physDev->X11PhysDev, ramp);
+        ONCE(FIXME("STUB\n"));
+        res = TRUE;
     }
     else
     {