diff --git a/include/gdi.h b/include/gdi.h index da3a5781ff4..86ceca6ac69 100644 --- a/include/gdi.h +++ b/include/gdi.h @@ -402,24 +402,24 @@ static inline void WINE_UNUSED INTERNAL_LPTODP(DC *dc, LPPOINT point) } #define XDPTOLP(dc,x) \ - (((x)-(dc)->vportOrgX) * (dc)->wndExtX / (dc)->vportExtX+(dc)->wndOrgX) + (MulDiv(((x)-(dc)->vportOrgX), (dc)->wndExtX, (dc)->vportExtX) + (dc)->wndOrgX) #define YDPTOLP(dc,y) \ - (((y)-(dc)->vportOrgY) * (dc)->wndExtY / (dc)->vportExtY+(dc)->wndOrgY) + (MulDiv(((y)-(dc)->vportOrgY), (dc)->wndExtY, (dc)->vportExtY) + (dc)->wndOrgY) #define XLPTODP(dc,x) \ - (((x)-(dc)->wndOrgX) * (dc)->vportExtX / (dc)->wndExtX+(dc)->vportOrgX) + (MulDiv(((x)-(dc)->wndOrgX), (dc)->vportExtX, (dc)->wndExtX) + (dc)->vportOrgX) #define YLPTODP(dc,y) \ - (((y)-(dc)->wndOrgY) * (dc)->vportExtY / (dc)->wndExtY+(dc)->vportOrgY) + (MulDiv(((y)-(dc)->wndOrgY), (dc)->vportExtY, (dc)->wndExtY) + (dc)->vportOrgY) /* Device <-> logical size conversion */ #define XDSTOLS(dc,x) \ - ((x) * (dc)->wndExtX / (dc)->vportExtX) + MulDiv((x), (dc)->wndExtX, (dc)->vportExtX) #define YDSTOLS(dc,y) \ - ((y) * (dc)->wndExtY / (dc)->vportExtY) + MulDiv((y), (dc)->wndExtY, (dc)->vportExtY) #define XLSTODS(dc,x) \ - ((x) * (dc)->vportExtX / (dc)->wndExtX) + MulDiv((x), (dc)->vportExtX, (dc)->wndExtX) #define YLSTODS(dc,y) \ - ((y) * (dc)->vportExtY / (dc)->wndExtY) + MulDiv((y), (dc)->vportExtY, (dc)->wndExtY) /* GDI local heap */ diff --git a/objects/gdiobj.c b/objects/gdiobj.c index 70a723110d6..c48e0509807 100644 --- a/objects/gdiobj.c +++ b/objects/gdiobj.c @@ -1029,13 +1029,42 @@ INT WINAPI MulDiv( ) { #if (SIZEOF_LONG_LONG >= 8) long long ret; + if (!nDivisor) return -1; - ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + ret = (((long long)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + else + ret = (((long long)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + if ((ret > 2147483647) || (ret < -2147483647)) return -1; return ret; #else if (!nDivisor) return -1; - return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + + /* We want to deal with a positive divisor to simplify the logic. */ + if (nDivisor < 0) + { + nMultiplicand = - nMultiplicand; + nDivisor = -nDivisor; + } + + /* If the result is positive, we "add" to round. else, we subtract to round. */ + if ( ( (nMultiplicand < 0) && (nMultiplier < 0) ) || + ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) ) + return ((nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor; + + return ((nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor; + #endif } /*******************************************************************