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

oldstable
Alexandre Julliard 2008-05-22 17:43:01 +02:00
parent 688febb8ce
commit 93cbb7a5db
9 changed files with 54 additions and 54 deletions

View File

@ -540,7 +540,7 @@ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
XFORM xf; XFORM xf;
XFORM SrcXf; XFORM SrcXf;
XFORM oldDestXf; XFORM oldDestXf;
FLOAT det; double det;
/* save actual mode, set GM_ADVANCED */ /* save actual mode, set GM_ADVANCED */
oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED); oldgMode = SetGraphicsMode(hdcDest,GM_ADVANCED);
@ -556,7 +556,7 @@ BOOL WINAPI PlgBlt( HDC hdcDest, const POINT *lpPoint,
rect[2].y = nYSrc + nHeight; rect[2].y = nYSrc + nHeight;
/* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */ /* calc XFORM matrix to transform hdcDest -> hdcSrc (parallelogram to rectangle) */
/* determinant */ /* 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) if (fabs(det) < 1e-5)
{ {

View File

@ -257,7 +257,7 @@ void DC_InitDC( DC* dc )
*/ */
static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest ) static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
{ {
FLOAT determinant; double determinant;
determinant = xformSrc->eM11*xformSrc->eM22 - determinant = xformSrc->eM11*xformSrc->eM22 -
xformSrc->eM12*xformSrc->eM21; xformSrc->eM12*xformSrc->eM21;
@ -290,19 +290,19 @@ static BOOL DC_InvertXform( const XFORM *xformSrc, XFORM *xformDest )
void DC_UpdateXforms( DC *dc ) void DC_UpdateXforms( DC *dc )
{ {
XFORM xformWnd2Vport, oldworld2vport; XFORM xformWnd2Vport, oldworld2vport;
FLOAT scaleX, scaleY; double scaleX, scaleY;
/* Construct a transformation to do the window-to-viewport conversion */ /* Construct a transformation to do the window-to-viewport conversion */
scaleX = (FLOAT)dc->vportExtX / (FLOAT)dc->wndExtX; scaleX = (double)dc->vportExtX / (double)dc->wndExtX;
scaleY = (FLOAT)dc->vportExtY / (FLOAT)dc->wndExtY; scaleY = (double)dc->vportExtY / (double)dc->wndExtY;
xformWnd2Vport.eM11 = scaleX; xformWnd2Vport.eM11 = scaleX;
xformWnd2Vport.eM12 = 0.0; xformWnd2Vport.eM12 = 0.0;
xformWnd2Vport.eM21 = 0.0; xformWnd2Vport.eM21 = 0.0;
xformWnd2Vport.eM22 = scaleY; xformWnd2Vport.eM22 = scaleY;
xformWnd2Vport.eDx = (FLOAT)dc->vportOrgX - xformWnd2Vport.eDx = (double)dc->vportOrgX -
scaleX * (FLOAT)dc->wndOrgX; scaleX * (double)dc->wndOrgX;
xformWnd2Vport.eDy = (FLOAT)dc->vportOrgY - xformWnd2Vport.eDy = (double)dc->vportOrgY -
scaleY * (FLOAT)dc->wndOrgY; scaleY * (double)dc->wndOrgY;
oldworld2vport = dc->xformWorld2Vport; oldworld2vport = dc->xformWorld2Vport;
/* Combine with the world transformation */ /* Combine with the world transformation */

View File

@ -525,16 +525,16 @@ typedef struct enum_emh_data
static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info) static void EMF_Update_MF_Xform(HDC hdc, const enum_emh_data *info)
{ {
XFORM mapping_mode_trans, final_trans; XFORM mapping_mode_trans, final_trans;
FLOAT scaleX, scaleY; double scaleX, scaleY;
scaleX = (FLOAT)info->state.vportExtX / (FLOAT)info->state.wndExtX; scaleX = (double)info->state.vportExtX / (double)info->state.wndExtX;
scaleY = (FLOAT)info->state.vportExtY / (FLOAT)info->state.wndExtY; scaleY = (double)info->state.vportExtY / (double)info->state.wndExtY;
mapping_mode_trans.eM11 = scaleX; mapping_mode_trans.eM11 = scaleX;
mapping_mode_trans.eM12 = 0.0; mapping_mode_trans.eM12 = 0.0;
mapping_mode_trans.eM21 = 0.0; mapping_mode_trans.eM21 = 0.0;
mapping_mode_trans.eM22 = scaleY; mapping_mode_trans.eM22 = scaleY;
mapping_mode_trans.eDx = (FLOAT)info->state.vportOrgX - scaleX * (FLOAT)info->state.wndOrgX; mapping_mode_trans.eDx = (double)info->state.vportOrgX - scaleX * (double)info->state.wndOrgX;
mapping_mode_trans.eDy = (FLOAT)info->state.vportOrgY - scaleY * (FLOAT)info->state.wndOrgY; 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, &info->state.world_transform, &mapping_mode_trans);
CombineTransform(&final_trans, &final_trans, &info->init_transform); CombineTransform(&final_trans, &final_trans, &info->init_transform);
@ -2340,22 +2340,22 @@ BOOL WINAPI EnumEnhMetaFile(
else else
{ {
/* WinNT combines the vp/win ext/org info into a transform */ /* WinNT combines the vp/win ext/org info into a transform */
FLOAT xscale, yscale; double xscale, yscale;
xscale = (FLOAT)vp_size.cx / (FLOAT)win_size.cx; xscale = (double)vp_size.cx / (double)win_size.cx;
yscale = (FLOAT)vp_size.cy / (FLOAT)win_size.cy; yscale = (double)vp_size.cy / (double)win_size.cy;
info->init_transform.eM11 = xscale; info->init_transform.eM11 = xscale;
info->init_transform.eM12 = 0.0; info->init_transform.eM12 = 0.0;
info->init_transform.eM21 = 0.0; info->init_transform.eM21 = 0.0;
info->init_transform.eM22 = yscale; info->init_transform.eM22 = yscale;
info->init_transform.eDx = (FLOAT)vp_org.x - xscale * (FLOAT)win_org.x; info->init_transform.eDx = (double)vp_org.x - xscale * (double)win_org.x;
info->init_transform.eDy = (FLOAT)vp_org.y - yscale * (FLOAT)win_org.y; info->init_transform.eDy = (double)vp_org.y - yscale * (double)win_org.y;
CombineTransform(&info->init_transform, &savedXform, &info->init_transform); CombineTransform(&info->init_transform, &savedXform, &info->init_transform);
} }
if ( lpRect && WIDTH(emh->rclFrame) && HEIGHT(emh->rclFrame) ) if ( lpRect && WIDTH(emh->rclFrame) && HEIGHT(emh->rclFrame) )
{ {
FLOAT xSrcPixSize, ySrcPixSize, xscale, yscale; double xSrcPixSize, ySrcPixSize, xscale, yscale;
XFORM xform; XFORM xform;
TRACE("rect: %d,%d - %d,%d. rclFrame: %d,%d - %d,%d\n", 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.left, emh->rclFrame.top, emh->rclFrame.right,
emh->rclFrame.bottom); emh->rclFrame.bottom);
xSrcPixSize = (FLOAT) emh->szlMillimeters.cx / emh->szlDevice.cx; xSrcPixSize = (double) emh->szlMillimeters.cx / emh->szlDevice.cx;
ySrcPixSize = (FLOAT) emh->szlMillimeters.cy / emh->szlDevice.cy; ySrcPixSize = (double) emh->szlMillimeters.cy / emh->szlDevice.cy;
xscale = (FLOAT) WIDTH(*lpRect) * 100.0 / xscale = (double) WIDTH(*lpRect) * 100.0 /
WIDTH(emh->rclFrame) * xSrcPixSize; WIDTH(emh->rclFrame) * xSrcPixSize;
yscale = (FLOAT) HEIGHT(*lpRect) * 100.0 / yscale = (double) HEIGHT(*lpRect) * 100.0 /
HEIGHT(emh->rclFrame) * ySrcPixSize; HEIGHT(emh->rclFrame) * ySrcPixSize;
TRACE("xscale = %f, yscale = %f\n", xscale, yscale); TRACE("xscale = %f, yscale = %f\n", xscale, yscale);
@ -2375,8 +2375,8 @@ BOOL WINAPI EnumEnhMetaFile(
xform.eM12 = 0; xform.eM12 = 0;
xform.eM21 = 0; xform.eM21 = 0;
xform.eM22 = yscale; xform.eM22 = yscale;
xform.eDx = (FLOAT) lpRect->left - (FLOAT) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left; xform.eDx = (double) lpRect->left - (double) WIDTH(*lpRect) / WIDTH(emh->rclFrame) * emh->rclFrame.left;
xform.eDy = (FLOAT) lpRect->top - (FLOAT) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top; xform.eDy = (double) lpRect->top - (double) HEIGHT(*lpRect) / HEIGHT(emh->rclFrame) * emh->rclFrame.top;
CombineTransform(&info->init_transform, &xform, &info->init_transform); CombineTransform(&info->init_transform, &xform, &info->init_transform);
} }

View File

@ -45,10 +45,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(font);
*/ */
static inline INT INTERNAL_XDSTOWS(DC *dc, INT width) static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
{ {
FLOAT floatWidth; double floatWidth;
/* Perform operation with floating point */ /* Perform operation with floating point */
floatWidth = (FLOAT)width * dc->xformVport2World.eM11; floatWidth = (double)width * dc->xformVport2World.eM11;
/* Round to integers */ /* Round to integers */
return GDI_ROUND(floatWidth); 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) static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
{ {
FLOAT floatHeight; double floatHeight;
/* Perform operation with floating point */ /* Perform operation with floating point */
floatHeight = (FLOAT)height * dc->xformVport2World.eM22; floatHeight = (double)height * dc->xformVport2World.eM22;
/* Round to integers */ /* Round to integers */
return GDI_ROUND(floatHeight); return GDI_ROUND(floatHeight);
} }

View File

@ -3370,7 +3370,7 @@ found:
it = lf.lfItalic ? 1 : 0; it = lf.lfItalic ? 1 : 0;
bd = lf.lfWeight > 550 ? 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); height = lf.lfHeight < 0 ? -abs(height) : abs(height);
face = best = best_bitmap = NULL; face = best = best_bitmap = NULL;

View File

@ -351,7 +351,7 @@ typedef struct tagDC
* transformation process is done in floating point internally. This function * transformation process is done in floating point internally. This function
* is then used to round these coordinates to integer values. * 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); return (int)floor(val + 0.5);
} }

View File

@ -88,8 +88,8 @@ BOOL WINAPI DPtoLP( HDC hdc, LPPOINT points, INT count )
{ {
while (count--) while (count--)
{ {
FLOAT x = points->x; double x = points->x;
FLOAT y = points->y; double y = points->y;
points->x = floor( x * dc->xformVport2World.eM11 + points->x = floor( x * dc->xformVport2World.eM11 +
y * dc->xformVport2World.eM21 + y * dc->xformVport2World.eM21 +
dc->xformVport2World.eDx + 0.5 ); dc->xformVport2World.eDx + 0.5 );
@ -133,8 +133,8 @@ BOOL WINAPI LPtoDP( HDC hdc, LPPOINT points, INT count )
while (count--) while (count--)
{ {
FLOAT x = points->x; double x = points->x;
FLOAT y = points->y; double y = points->y;
points->x = floor( x * dc->xformWorld2Vport.eM11 + points->x = floor( x * dc->xformWorld2Vport.eM11 +
y * dc->xformWorld2Vport.eM21 + y * dc->xformWorld2Vport.eM21 +
dc->xformWorld2Vport.eDx + 0.5 ); dc->xformWorld2Vport.eDx + 0.5 );

View File

@ -88,7 +88,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(gdi);
/* A floating point version of the POINT structure */ /* A floating point version of the POINT structure */
typedef struct tagFLOAT_POINT typedef struct tagFLOAT_POINT
{ {
FLOAT x, y; double x, y;
} FLOAT_POINT; } 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) static inline void INTERNAL_LPTODP_FLOAT(DC *dc, FLOAT_POINT *point)
{ {
FLOAT x, y; double x, y;
/* Perform the transformation */ /* Perform the transformation */
x = point->x; x = point->x;
@ -754,14 +754,14 @@ BOOL PATH_Arc(DC *dc, INT x1, INT y1, INT x2, INT y2,
return TRUE; return TRUE;
/* Convert points to device coordinates */ /* Convert points to device coordinates */
corners[0].x=(FLOAT)x1; corners[0].x = x1;
corners[0].y=(FLOAT)y1; corners[0].y = y1;
corners[1].x=(FLOAT)x2; corners[1].x = x2;
corners[1].y=(FLOAT)y2; corners[1].y = y2;
pointStart.x=(FLOAT)xStart; pointStart.x = xStart;
pointStart.y=(FLOAT)yStart; pointStart.y = yStart;
pointEnd.x=(FLOAT)xEnd; pointEnd.x = xEnd;
pointEnd.y=(FLOAT)yEnd; pointEnd.y = yEnd;
INTERNAL_LPTODP_FLOAT(dc, corners); INTERNAL_LPTODP_FLOAT(dc, corners);
INTERNAL_LPTODP_FLOAT(dc, corners+1); INTERNAL_LPTODP_FLOAT(dc, corners+1);
INTERNAL_LPTODP_FLOAT(dc, &pointStart); INTERNAL_LPTODP_FLOAT(dc, &pointStart);
@ -1967,9 +1967,9 @@ static BOOL PATH_WidenPath(DC *dc)
/* Beginning or end of the path if not closed */ /* 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) ) { if((!(pStrokes[i]->pFlags[pStrokes[i]->numEntriesUsed - 1] & PT_CLOSEFIGURE)) && (j == 0 || j == pStrokes[i]->numEntriesUsed - 1) ) {
/* Compute segment angle */ /* Compute segment angle */
FLOAT xo, yo, xa, ya; double xo, yo, xa, ya;
POINT pt; POINT pt;
FLOAT theta, scalarProduct; double theta, scalarProduct;
FLOAT_POINT corners[2]; FLOAT_POINT corners[2];
if(j == 0) { if(j == 0) {
xo = pStrokes[i]->pPoints[j].x; xo = pStrokes[i]->pPoints[j].x;
@ -2022,9 +2022,9 @@ static BOOL PATH_WidenPath(DC *dc)
else { else {
/* Compute angle */ /* Compute angle */
INT previous, next; INT previous, next;
FLOAT xa, ya, xb, yb, xo, yo; double xa, ya, xb, yb, xo, yo;
FLOAT alpha, theta; double alpha, theta;
FLOAT scalarProduct, oa, ob, miterWidth; double scalarProduct, oa, ob, miterWidth;
DWORD _joint = joint; DWORD _joint = joint;
POINT pt; POINT pt;
GdiPath *pInsidePath, *pOutsidePath; GdiPath *pInsidePath, *pOutsidePath;

View File

@ -989,8 +989,8 @@ static void translate( POINT *pt, UINT count, const XFORM *xform )
{ {
while (count--) while (count--)
{ {
FLOAT x = pt->x; double x = pt->x;
FLOAT y = pt->y; double y = pt->y;
pt->x = floor( x * xform->eM11 + y * xform->eM21 + xform->eDx + 0.5 ); 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->y = floor( x * xform->eM12 + y * xform->eM22 + xform->eDy + 0.5 );
pt++; pt++;