From 97d5e9218519049bf7d4403682129173ef5d44e3 Mon Sep 17 00:00:00 2001 From: Colin Snover Date: Wed, 2 Mar 2016 00:00:28 -0600 Subject: SCI32: Review rect rounding in Plane and ScreenItem These changes should cause ScummVM to be more accurate in edge case rounding. --- engines/sci/graphics/helpers.h | 19 ++++++------------- engines/sci/graphics/plane32.cpp | 2 +- engines/sci/graphics/screen_item32.cpp | 29 +++++++++++++---------------- 3 files changed, 20 insertions(+), 30 deletions(-) (limited to 'engines/sci') diff --git a/engines/sci/graphics/helpers.h b/engines/sci/graphics/helpers.h index 1d16b49798..19dddd74b8 100644 --- a/engines/sci/graphics/helpers.h +++ b/engines/sci/graphics/helpers.h @@ -154,13 +154,13 @@ inline void mulinc(Common::Rect &rect, const Common::Rational &ratioX, const Com * Multiplies a number by a rational number, rounding up to * the nearest whole number. */ -inline int mulru(const int value, const Common::Rational &ratio) { - int num = value * ratio.getNumerator(); +inline int mulru(const int value, const Common::Rational &ratio, const int extra = 0) { + int num = (value + extra) * ratio.getNumerator(); int result = num / ratio.getDenominator(); if (num > ratio.getDenominator() && num % ratio.getDenominator()) { ++result; } - return result; + return result - extra; } /** @@ -177,19 +177,12 @@ inline void mulru(Common::Point &point, const Common::Rational &ratioX, const Co * Multiplies a point by two rational numbers for X and Y, * rounding up to the nearest whole number. Modifies the * rect directly. - * - * @note In SCI engine, the bottom-right corner of rects - * received an additional one pixel during the - * multiplication in order to round up to include the - * bottom-right corner. Since ScummVM rects do not include - * the bottom-right corner, doing this ends up making rects - * a pixel too wide/tall depending upon the remainder. */ -inline void mulru(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY) { +inline void mulru(Common::Rect &rect, const Common::Rational &ratioX, const Common::Rational &ratioY, const int extra) { rect.left = mulru(rect.left, ratioX); rect.top = mulru(rect.top, ratioY); - rect.right = mulru(rect.right, ratioX); - rect.bottom = mulru(rect.bottom, ratioY); + rect.right = mulru(rect.right - 1, ratioX, extra) + 1; + rect.bottom = mulru(rect.bottom - 1, ratioY, extra) + 1; } struct Buffer : public Graphics::Surface { diff --git a/engines/sci/graphics/plane32.cpp b/engines/sci/graphics/plane32.cpp index 96d57e3917..1a1a7893dd 100644 --- a/engines/sci/graphics/plane32.cpp +++ b/engines/sci/graphics/plane32.cpp @@ -136,7 +136,7 @@ void Plane::convertGameRectToPlaneRect() { const Ratio ratioY = Ratio(screenHeight, scriptHeight); _planeRect = _gameRect; - mulru(_planeRect, ratioX, ratioY); + mulru(_planeRect, ratioX, ratioY, 1); } void Plane::printDebugInfo(Console *con) const { diff --git a/engines/sci/graphics/screen_item32.cpp b/engines/sci/graphics/screen_item32.cpp index 0bbb056071..a07dacee83 100644 --- a/engines/sci/graphics/screen_item32.cpp +++ b/engines/sci/graphics/screen_item32.cpp @@ -256,7 +256,7 @@ void ScreenItem::calcRects(const Plane &plane) { if (_useInsetRect) { Ratio celScriptXRatio(_celObj->_scaledWidth, scriptWidth); Ratio celScriptYRatio(_celObj->_scaledHeight, scriptHeight); - mulru(_screenItemRect, celScriptXRatio, celScriptYRatio); + mulru(_screenItemRect, celScriptXRatio, celScriptYRatio, 0); if (_screenItemRect.intersects(celRect)) { _screenItemRect.clip(celRect); @@ -273,7 +273,7 @@ void ScreenItem::calcRects(const Plane &plane) { } if (!newRatioX.isOne() || !newRatioY.isOne()) { - mulru(_screenItemRect, newRatioX, newRatioY); + mulinc(_screenItemRect, newRatioX, newRatioY); displaceX = (displaceX * newRatioX).toInt(); displaceY = (displaceY * newRatioY).toInt(); } @@ -284,7 +284,7 @@ void ScreenItem::calcRects(const Plane &plane) { displaceX = (displaceX * celXRatio).toInt(); displaceY = (displaceY * celYRatio).toInt(); - mulru(_screenItemRect, celXRatio, celYRatio); + mulinc(_screenItemRect, celXRatio, celYRatio); if (/* TODO: dword_C6288 */ false && _celInfo.type == kCelTypePic) { _scaledPosition.x = _position.x; @@ -300,18 +300,16 @@ void ScreenItem::calcRects(const Plane &plane) { Common::Rect temp(_insetRect); if (!newRatioX.isOne()) { - mulru(temp, newRatioX, Ratio()); + mulinc(temp, newRatioX, Ratio()); } - mulru(temp, celXRatio, Ratio()); + mulinc(temp, celXRatio, Ratio()); CelObjPic *celObjPic = dynamic_cast(_celObj); - temp.translate(celObjPic->_relativePosition.x * screenWidth / scriptWidth - displaceX, 0); - // TODO: This is weird, and probably wrong calculation of widths - // due to BR-inclusion - int deltaX = plane._planeRect.right - plane._planeRect.left + 1 - temp.right - 1 - temp.left; + // TODO: This is weird. + int deltaX = plane._planeRect.width() - temp.right - 1 - temp.left; _scaledPosition.x += deltaX; _screenItemRect.translate(deltaX, 0); @@ -330,9 +328,9 @@ void ScreenItem::calcRects(const Plane &plane) { } if (!newRatioX.isOne() || !newRatioY.isOne()) { - mulru(_screenItemRect, newRatioX, newRatioY); + mulinc(_screenItemRect, newRatioX, newRatioY); // TODO: This was in the original code, baked into the - // multiplication though it is not immediately clear + // multiplication though it is not immediately clear // why this is the only one that reduces the BR corner _screenItemRect.right -= 1; _screenItemRect.bottom -= 1; @@ -346,16 +344,15 @@ void ScreenItem::calcRects(const Plane &plane) { Common::Rect temp(_insetRect); if (!newRatioX.isOne()) { - mulru(temp, newRatioX, Ratio()); + mulinc(temp, newRatioX, Ratio()); temp.right -= 1; } CelObjPic *celObjPic = dynamic_cast(_celObj); temp.translate(celObjPic->_relativePosition.x - (displaceX * newRatioX).toInt(), celObjPic->_relativePosition.y - (_celObj->_displace.y * newRatioY).toInt()); - // TODO: This is weird, and probably wrong calculation of widths - // due to BR-inclusion - int deltaX = plane._gameRect.right - plane._gameRect.left + 1 - temp.right - 1 - temp.left; + // TODO: This is weird. + int deltaX = plane._gameRect.width() - temp.right - 1 - temp.left; _scaledPosition.x += deltaX; _screenItemRect.translate(deltaX, 0); @@ -369,7 +366,7 @@ void ScreenItem::calcRects(const Plane &plane) { Ratio celXRatio(screenWidth, _celObj->_scaledWidth); Ratio celYRatio(screenHeight, _celObj->_scaledHeight); mulru(_scaledPosition, celXRatio, celYRatio); - mulru(_screenItemRect, celXRatio, celYRatio); + mulru(_screenItemRect, celXRatio, celYRatio, 1); } _ratioX = newRatioX * Ratio(screenWidth, _celObj->_scaledWidth); -- cgit v1.2.3