The XFORM matrix in PlgBlt is calculated incorrectly
Alexander Almaleh
sashoalm at gmail.com
Tue Dec 8 10:45:18 CST 2009
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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.winehq.org/pipermail/wine-devel/attachments/20091208/66a442b3/attachment.htm>
More information about the wine-devel
mailing list