I'm talking about this code, from http://source.winehq.org/source/dlls/gdi32/bitblt.c, in function PlgBlt :
577 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L577 rect[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x = nXSrc;578 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L578 rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y = nYSrc;579 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L579 rect[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x = nXSrc + nWidth;580 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L580 rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y = nYSrc;581 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L581 rect[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x = nXSrc;582 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L582 rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y = nYSrc + nHeight;583 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L583 */* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */*584 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L584 */* determinant */*585 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L585 det = rect[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - rect[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - rect[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y);586 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L586 587 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L587 if (fabs(det) < 1e-5)588 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L588 {589 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L589 SetGraphicsMode http://source.winehq.org/source/dlls/gdi32/ident?i=SetGraphicsMode(hdcDest,oldgMode);590 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L590 return FALSE http://source.winehq.org/source/dlls/gdi32/ident?i=FALSE;591 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L591 }592 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L592 593 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L593 TRACE http://source.winehq.org/source/dlls/gdi32/ident?i=TRACE(*"hdcSrc=%p %d,%d,%dx%d -> hdcDest=%p %d,%d,%d,%d,%d,%d\n"*,594 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L594 hdcSrc, nXSrc, nYSrc, nWidth, nHeight, hdcDest, plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x, plg[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y, plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x, plg[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y, plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x, plg[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y);595 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L595 596 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L596 */* X components */*597 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L597 xf.eM11 = (plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y)) / det;598 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L598 xf.eM21 = (rect[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x) - rect[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x) - rect[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x)) / det;599 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L599 xf.eDx = (rect[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x) -600 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L600 rect[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x) +601 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L601 rect[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x)602 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L602 ) / det;603 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L603 604 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L604 */* Y components */*605 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L605 xf.eM12 = (plg[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y)) / det;606 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L606 xf.eM22 = (plg[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) - plg[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y)) / det;607 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L607 xf.eDy = (rect[0].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) -608 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L608 rect[1].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[2].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y) +609 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L609 rect[2].x http://source.winehq.org/source/dlls/gdi32/ident?i=x*(rect[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y - rect[1].y http://source.winehq.org/source/dlls/gdi32/ident?i=y*plg[0].y http://source.winehq.org/source/dlls/gdi32/ident?i=y)610 http://source.winehq.org/source/dlls/gdi32/source/dlls/gdi32/bitblt.c#L610 ) / det;
I have a formula that so far seems to give always the correct matrix:
xf.eM11 = (FLOAT) -(rect[1].y*plg[2].x+rect[0].y*(plg[1].x-plg[2].x)-rect[2].y*plg[1].x+plg[0].x*(rect[2].y-rect[1].y)) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x); xf.eM12 = (FLOAT) -(rect[1].y*(plg[2].y-plg[0].y)+rect[0].y*(plg[1].y-plg[2].y)+rect[2].y*(plg[0].y-plg[1].y)) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x); xf.eM21 = (FLOAT) (plg[0].x*(rect[2].x-rect[1].x)-plg[1].x*rect[2].x+plg[2].x*rect[1].x+(plg[1].x-plg[2].x)*rect[0].x) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x); xf.eM22 = (FLOAT) ((plg[0].y-plg[1].y)*rect[2].x+(plg[2].y-plg[0].y)*rect[1].x+(plg[1].y-plg[2].y)*rect[0].x) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x); xf.eDx = (FLOAT) -(rect[0].y*(plg[2].x*rect[1].x-plg[1].x*rect[2].x)+plg[0].x*(rect[1].y*rect[2].x-rect[2].y*rect[1].x)+(rect[2].y*plg[1].x-rect[1].y*plg[2].x)*rect[0].x) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x); xf.eDy = (FLOAT) (rect[0].y*(plg[1].y*rect[2].x-plg[2].y*rect[1].x)-rect[1].y*plg[0].y*rect[2].x+rect[2].y*plg[0].y*rect[1].x+(rect[1].y*plg[2].y-rect[2].y*plg[1].y)*rect[0].x) /(rect[0].y*(rect[2].x-rect[1].x)-rect[1].y*rect[2].x+rect[2].y*rect[1].x+(rect[1].y-rect[2].y)*rect[0].x);
The rect and plg arrays must be of FLOAT points for the formula to work well, like
struct { double x; double y; }
Otherwise sometimes the compiler will decide to divide integers.
I found out about the bug by converting the rect points using the XFORM matrix, and checking that their the same as the plg points.