Index: dlls/gdi32/bitblt.c =================================================================== RCS file: /home/wine/wine/dlls/gdi32/bitblt.c,v retrieving revision 1.4 diff -u -r1.4 bitblt.c --- dlls/gdi32/bitblt.c 18 Sep 2007 10:32:56 -0000 1.4 +++ dlls/gdi32/bitblt.c 26 Mar 2008 22:48:50 -0000 @@ -20,6 +20,11 @@ #include +#include +#if defined(HAVE_FLOAT_H) +#include +#endif + #include "windef.h" #include "winbase.h" #include "wingdi.h" @@ -522,9 +527,75 @@ * */ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint, - HDC hdcSrc, INT nXDest, INT nYDest, INT nWidth, + HDC hdcSrc, INT nXSrc, INT nYSrc, INT nWidth, INT nHeight, HBITMAP hbmMask, INT xMask, INT yMask) { - FIXME("PlgBlt, stub\n"); - return 1; + int oldgMode; + /* parallelogram coords */ + POINT plg[3]; + /* rect coords */ + POINT rect[3]; + XFORM xf; + XFORM SrcXf; + XFORM oldDestXf; + FLOAT det; + + /* save actual mode, set GM_ADVANCED */ + oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED); + if (oldgMode == 0) + return FALSE; + + memcpy(plg,lpPoint,sizeof(POINT)*3); + rect[0].x = nXSrc; + rect[0].y = nYSrc; + rect[1].x = nXSrc + nWidth; + rect[1].y = nYSrc; + rect[2].x = nXSrc; + rect[2].y = nYSrc + nHeight; + /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */ + /* determinant */ + det = (FLOAT)(rect[1].x*(rect[2].y - rect[0].y) - rect[2].x*(rect[1].y - rect[0].y) - rect[0].x*(rect[2].y - rect[1].y)); + + if (fabs(det) < FLT_EPSILON) + { + SetGraphicsMode(hdcDest,oldgMode); + return FALSE; + } + + TRACE("hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n", + hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x, plg[0].y, plg[1].x, plg[1].y, plg[2].x, plg[2].y); + + /* X components */ + xf.eM11 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det; + xf.eM21 = (rect[1].x*(plg[2].x - plg[0].x) - rect[2].x*(plg[1].x - plg[0].x) - rect[0].x*(plg[2].x - plg[1].x)) / det; + xf.eDx = (rect[0].x*(rect[1].y*plg[2].x - rect[2].y*plg[1].x) - + rect[1].x*(rect[0].y*plg[2].x - rect[2].y*plg[0].x) + + rect[2].x*(rect[0].y*plg[1].x - rect[1].y*plg[0].x) + ) / det; + + /* Y components */ + xf.eM12 = (plg[1].y*(rect[2].y - rect[0].y) - plg[2].y*(rect[1].y - rect[0].y) - plg[0].y*(rect[2].y - rect[1].y)) / det; + xf.eM22 = (plg[1].x*(rect[2].y - rect[0].y) - plg[2].x*(rect[1].y - rect[0].y) - plg[0].x*(rect[2].y - rect[1].y)) / det; + xf.eDy = (rect[0].x*(rect[1].y*plg[2].y - rect[2].y*plg[1].y) - + rect[1].x*(rect[0].y*plg[2].y - rect[2].y*plg[0].y) + + rect[2].x*(rect[0].y*plg[1].y - rect[1].y*plg[0].y) + ) / det; + + GetWorldTransform(hdcSrc,&SrcXf); + CombineTransform(&xf,&xf,&SrcXf); + + /* save actual dest transform */ + GetWorldTransform(hdcDest,&oldDestXf); + + SetWorldTransform(hdcDest,&xf); + /* now destination and source DCs use same coords */ + MaskBlt(hdcDest,nXSrc,nYSrc,nWidth,nHeight, + hdcSrc, nXSrc,nYSrc, + hbmMask,xMask,yMask, + SRCCOPY); + /* restore dest DC */ + SetWorldTransform(hdcDest,&oldDestXf); + SetGraphicsMode(hdcDest,oldgMode); + + return TRUE; }