Commit 93cbb7a5 authored by Alexandre Julliard's avatar Alexandre Julliard

gdi32: Perform coordinate transformations using doubles instead of floats to avoid precision loss.

parent 688febb8
......@@ -540,7 +540,7 @@ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
XFORM xf;
XFORM SrcXf;
XFORM oldDestXf;
FLOAT det;
double det;
/* save actual mode, set GM_ADVANCED */
oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
......@@ -556,7 +556,7 @@ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
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));
det = 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) < 1e-5)
{
......
......@@ -257,7 +257,7 @@ void DC_InitDC( DC* dc )
*/
static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
{
FLOAT determinant;
double determinant;
determinant = xformSrc->eM11*xformSrc->eM22 -
xformSrc->eM12*xformSrc->eM21;
......@@ -290,19 +290,19 @@ static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
void DC_UpdateXforms( DC *dc )
{
XFORM xformWnd2Vport, oldworld2vport;
FLOAT scaleX, scaleY;
double scaleX, scaleY;
/* Construct a transformation to do the window-to-viewport conversion */
scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX;
scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY;
scaleX = (double)dc->vportExtX / (double)dc->wndExtX;
scaleY = (double)dc->vportExtY / (double)dc->wndExtY;
xformWnd2Vport.eM11 = scaleX;
xformWnd2Vport.eM12 = 0.0;
xformWnd2Vport.eM21 = 0.0;
xformWnd2Vport.eM22 = scaleY;
xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX -
scaleX * (FLOAT)dc->wndOrgX;
xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY -
scaleY * (FLOAT)dc->wndOrgY;
xformWnd2Vport.eDx = (double)dc->vportOrgX -
scaleX * (double)dc->wndOrgX;
xformWnd2Vport.eDy = (double)dc->vportOrgY -
scaleY * (double)dc->wndOrgY;
oldworld2vport = dc->xformWorld2Vport;
/* Combine with the world transformation */
......
......@@ -525,16 +525,16 @@ typedef struct enum_emh_data
static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info)
{
XFORM mapping_mode_trans, final_trans;
FLOAT scaleX, scaleY;
double scaleX, scaleY;
scaleX = (FLOAT)info->state.vportExtX / (FLOAT)info->state.wndExtX;
scaleY = (FLOAT)info->state.vportExtY / (FLOAT)info->state.wndExtY;
scaleX = (double)info->state.vportExtX / (double)info->state.wndExtX;
scaleY = (double)info->state.vportExtY / (double)info->state.wndExtY;
mapping_mode_trans.eM11 = scaleX;
mapping_mode_trans.eM12 = 0.0;
mapping_mode_trans.eM21 = 0.0;
mapping_mode_trans.eM22 = scaleY;
mapping_mode_trans.eDx = (FLOAT)info->state.vportOrgX - scaleX * (FLOAT)info->state.wndOrgX;
mapping_mode_trans.eDy = (FLOAT)info->state.vportOrgY - scaleY * (FLOAT)info->state.wndOrgY;
mapping_mode_trans.eDx = (double)info->state.vportOrgX - scaleX * (double)info->state.wndOrgX;
mapping_mode_trans.eDy = (double)info->state.vportOrgY - scaleY * (double)info->state.wndOrgY;
CombineTransform(&final_trans, &info->state.world_transform, &mapping_mode_trans);
CombineTransform(&final_trans, &final_trans, &info->init_transform);
......@@ -2340,22 +2340,22 @@ BOOL WINAPI EnumEnhMetaFile(
else
{
/* WinNT combines the vp/win ext/org info into a transform */
FLOAT xscale, yscale;
xscale = (FLOAT)vp_size.cx / (FLOAT)win_size.cx;
yscale = (FLOAT)vp_size.cy / (FLOAT)win_size.cy;
double xscale, yscale;
xscale = (double)vp_size.cx / (double)win_size.cx;
yscale = (double)vp_size.cy / (double)win_size.cy;
info->init_transform.eM11 = xscale;
info->init_transform.eM12 = 0.0;
info->init_transform.eM21 = 0.0;
info->init_transform.eM22 = yscale;
info->init_transform.eDx = (FLOAT)vp_org.x - xscale * (FLOAT)win_org.x;
info->init_transform.eDy = (FLOAT)vp_org.y - yscale * (FLOAT)win_org.y;
info->init_transform.eDx = (double)vp_org.x - xscale * (double)win_org.x;
info->init_transform.eDy = (double)vp_org.y - yscale * (double)win_org.y;
CombineTransform(&info->init_transform, &savedXform, &info->init_transform);
}
if ( lpRect && WIDTH(emh->rclFrame) && HEIGHT(emh->rclFrame) )
{
FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale;
double xSrcPixSize, ySrcPixSize, xscale, yscale;
XFORM xform;
TRACE("rect: %d,%d - %d,%d. rclFrame: %d,%d - %d,%d\n",
......@@ -2363,11 +2363,11 @@ BOOL WINAPI EnumEnhMetaFile(
emh->rclFrame.left, emh->rclFrame.top, emh->rclFrame.right,
emh->rclFrame.bottom);
xSrcPixSize = (FLOAT) emh->szlMillimeters.cx / emh->szlDevice.cx;
ySrcPixSize = (FLOAT) emh->szlMillimeters.cy / emh->szlDevice.cy;
xscale = (FLOAT) WIDTH(*lpRect) * 100.0 /
xSrcPixSize = (double) emh->szlMillimeters.cx / emh->szlDevice.cx;
ySrcPixSize = (double) emh->szlMillimeters.cy / emh->szlDevice.cy;
xscale = (double) WIDTH(*lpRect) * 100.0 /
WIDTH(emh->rclFrame) * xSrcPixSize;
yscale = (FLOAT) HEIGHT(*lpRect) * 100.0 /
yscale = (double) HEIGHT(*lpRect) * 100.0 /
HEIGHT(emh->rclFrame) * ySrcPixSize;
TRACE("xscale = %f, yscale = %f\n", xscale, yscale);
......@@ -2375,8 +2375,8 @@ BOOL WINAPI EnumEnhMetaFile(
xform.eM12 = 0;
xform.eM21 = 0;
xform.eM22 = yscale;
xform.eDx = (FLOAT) lpRect->left - (FLOAT) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left;
xform.eDy = (FLOAT) lpRect->top - (FLOAT) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top;
xform.eDx = (double) lpRect->left - (double) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left;
xform.eDy = (double) lpRect->top - (double) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top;
CombineTransform(&info->init_transform, &xform, &info->init_transform);
}
......
......@@ -45,10 +45,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(font);
*/
static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
{
FLOAT floatWidth;
double floatWidth;
/* Perform operation with floating point */
floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
floatWidth = (double)width * dc->xformVport2World.eM11;
/* Round to integers */
return GDI_ROUND(floatWidth);
}
......@@ -58,10 +58,10 @@ static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
*/
static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
{
FLOAT floatHeight;
double floatHeight;
/* Perform operation with floating point */
floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
floatHeight = (double)height * dc->xformVport2World.eM22;
/* Round to integers */
return GDI_ROUND(floatHeight);
}
......
......@@ -3370,7 +3370,7 @@ found:
it = lf.lfItalic ? 1 : 0;
bd = lf.lfWeight > 550 ? 1 : 0;
height = GDI_ROUND( (FLOAT)lf.lfHeight * dc->xformWorld2Vport.eM22 );
height = GDI_ROUND( (double)lf.lfHeight * dc->xformWorld2Vport.eM22 );
height = lf.lfHeight < 0 ? -abs(height) : abs(height);
face = best = best_bitmap = NULL;
......
......@@ -351,7 +351,7 @@ typedef struct tagDC
* transformation process is done in floating point internally. This function
* is then used to round these coordinates to integer values.
*/
static inline INT GDI_ROUND(FLOAT val)
static inline INT GDI_ROUND(double val)
{
return (int)floor(val + 0.5);
}
......
......@@ -88,8 +88,8 @@ BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count )
{
while (count--)
{
FLOAT x = points->x;
FLOAT y = points->y;
double x = points->x;
double y = points->y;
points->x = floor( x * dc->xformVport2World.eM11 +
y * dc->xformVport2World.eM21 +
dc->xformVport2World.eDx + 0.5 );
......@@ -133,8 +133,8 @@ BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count )
while (count--)
{
FLOAT x = points->x;
FLOAT y = points->y;
double x = points->x;
double y = points->y;
points->x = floor( x * dc->xformWorld2Vport.eM11 +
y * dc->xformWorld2Vport.eM21 +
dc->xformWorld2Vport.eDx + 0.5 );
......
......@@ -88,7 +88,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
/* A floating point version of the POINT structure */
typedef struct tagFLOAT_POINT
{
FLOAT x, y;
double x, y;
} FLOAT_POINT;
......@@ -109,7 +109,7 @@ static BOOL PATH_CheckCorners(DC *dc, POINT corners[], INT x1, INT y1, INT x2, I
*/
static inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point)
{
FLOAT x, y;
double x, y;
/* Perform the transformation */
x = point->x;
......@@ -754,14 +754,14 @@ BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
return TRUE;
/* Convert points to device coordinates */
corners[0].x=(FLOAT)x1;
corners[0].y=(FLOAT)y1;
corners[1].x=(FLOAT)x2;
corners[1].y=(FLOAT)y2;
pointStart.x=(FLOAT)xStart;
pointStart.y=(FLOAT)yStart;
pointEnd.x=(FLOAT)xEnd;
pointEnd.y=(FLOAT)yEnd;
corners[0].x = x1;
corners[0].y = y1;
corners[1].x = x2;
corners[1].y = y2;
pointStart.x = xStart;
pointStart.y = yStart;
pointEnd.x = xEnd;
pointEnd.y = yEnd;
INTERNAL_LPTODP_FLOAT(dc, corners);
INTERNAL_LPTODP_FLOAT(dc, corners+1);
INTERNAL_LPTODP_FLOAT(dc, &pointStart);
......@@ -1967,9 +1967,9 @@ static BOOL PATH_WidenPath(DC *dc)
/* Beginning or end of the path if not closed */
if((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1) ) {
/* Compute segment angle */
FLOAT xo, yo, xa, ya;
double xo, yo, xa, ya;
POINT pt;
FLOAT theta, scalarProduct;
double theta, scalarProduct;
FLOAT_POINT corners[2];
if(j == 0) {
xo = pStrokes[i]->pPoints[j].x;
......@@ -2022,9 +2022,9 @@ static BOOL PATH_WidenPath(DC *dc)
else {
/* Compute angle */
INT previous, next;
FLOAT xa, ya, xb, yb, xo, yo;
FLOAT alpha, theta;
FLOAT scalarProduct, oa, ob, miterWidth;
double xa, ya, xb, yb, xo, yo;
double alpha, theta;
double scalarProduct, oa, ob, miterWidth;
DWORD _joint = joint;
POINT pt;
GdiPath *pInsidePath, *pOutsidePath;
......
......@@ -989,8 +989,8 @@ static void translate( POINT *pt, UINT count, const XFORM *xform )
{
while (count--)
{
FLOAT x = pt->x;
FLOAT y = pt->y;
double x = pt->x;
double y = pt->y;
pt->x = floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 );
pt->y = floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
pt++;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment