aboutsummaryrefslogtreecommitdiff
path: root/engines/sci
diff options
context:
space:
mode:
authorColin Snover2016-03-02 00:00:28 -0600
committerColin Snover2016-03-02 00:01:13 -0600
commit97d5e9218519049bf7d4403682129173ef5d44e3 (patch)
tree01af7d57bcdca60cb4305724e45713e726bede4c /engines/sci
parente5b30fb9afa3a42e08525980257868a73660937d (diff)
downloadscummvm-rg350-97d5e9218519049bf7d4403682129173ef5d44e3.tar.gz
scummvm-rg350-97d5e9218519049bf7d4403682129173ef5d44e3.tar.bz2
scummvm-rg350-97d5e9218519049bf7d4403682129173ef5d44e3.zip
SCI32: Review rect rounding in Plane and ScreenItem
These changes should cause ScummVM to be more accurate in edge case rounding.
Diffstat (limited to 'engines/sci')
-rw-r--r--engines/sci/graphics/helpers.h19
-rw-r--r--engines/sci/graphics/plane32.cpp2
-rw-r--r--engines/sci/graphics/screen_item32.cpp29
3 files changed, 20 insertions, 30 deletions
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<CelObjPic *>(_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<CelObjPic *>(_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);