aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFilippos Karapetis2016-09-25 13:41:25 -0500
committerColin Snover2016-09-29 19:39:16 -0500
commita8009fb0a9e56491d8ddf8cba344e0cf4174d5ff (patch)
tree96aae9fc2863ffe7ee735e2ffda3ba3ee6404596
parent9d2397e1e9c1be301ddd6e40365e7cf2a1e2f5f5 (diff)
downloadscummvm-rg350-a8009fb0a9e56491d8ddf8cba344e0cf4174d5ff.tar.gz
scummvm-rg350-a8009fb0a9e56491d8ddf8cba344e0cf4174d5ff.tar.bz2
scummvm-rg350-a8009fb0a9e56491d8ddf8cba344e0cf4174d5ff.zip
SCI32: Fix crashes in line drawing code
Fixes Torin room 43000. The algorithm in Graphics::drawThickLine2 for drawing thick lines is not completely accurate and so there are still some single-pixel rendering bugs, but these do not impact the game itself and can be fixed separately.
-rw-r--r--engines/sci/graphics/paint32.cpp43
1 files changed, 21 insertions, 22 deletions
diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp
index 509df7c8b2..958820d4b5 100644
--- a/engines/sci/graphics/paint32.cpp
+++ b/engines/sci/graphics/paint32.cpp
@@ -38,7 +38,6 @@ reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &st
Common::Rect gameRect;
reg_t bitmapId = makeLineBitmap(startPoint, endPoint, priority, color, style, pattern, thickness, gameRect);
- SciBitmap &bitmap = *_segMan->lookupBitmap(bitmapId);
CelInfo32 celInfo;
celInfo.type = kCelTypeMem;
@@ -48,7 +47,7 @@ reg_t GfxPaint32::kernelAddLine(const reg_t planeObject, const Common::Point &st
// `kUpdateLine` can get the originally used color
celInfo.color = color;
- ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, Common::Rect(startPoint.x, startPoint.y, startPoint.x + bitmap.getWidth(), startPoint.y + bitmap.getHeight()));
+ ScreenItem *screenItem = new ScreenItem(planeObject, celInfo, gameRect);
screenItem->_priority = priority;
screenItem->_fixedPriority = true;
@@ -89,9 +88,8 @@ void GfxPaint32::plotter(int x, int y, int color, void *data) {
LineProperties &properties = *static_cast<LineProperties *>(data);
byte *pixels = properties.bitmap->getPixels();
- const uint32 index = properties.bitmap->getWidth() * y + x;
-
- if (index < properties.bitmap->getDataSize()) {
+ if (x >= 0 && x < properties.bitmap->getWidth() && y >= 0 && y < properties.bitmap->getHeight()) {
+ const uint32 index = properties.bitmap->getWidth() * y + x;
if (properties.solid) {
pixels[index] = (uint8)color;
return;
@@ -112,8 +110,6 @@ void GfxPaint32::plotter(int x, int y, int color, void *data) {
if (properties.patternIndex == ARRAYSIZE(properties.pattern)) {
properties.patternIndex = 0;
}
- } else {
- warning("GfxPaint32::plotter: Attempted to write out of bounds (%u >= %u)", index, properties.bitmap->getDataSize());
}
}
@@ -124,13 +120,18 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::
thickness = ((MAX<uint8>(1, thickness) - 1) | 1);
const uint8 halfThickness = thickness >> 1;
- outRect.left = (startPoint.x < endPoint.x ? startPoint.x : endPoint.x) - halfThickness;
- outRect.top = (startPoint.y < endPoint.y ? startPoint.y : endPoint.y) - halfThickness;
- outRect.right = (startPoint.x > endPoint.x ? startPoint.x : endPoint.x) + halfThickness + 1;
- outRect.bottom = (startPoint.y > endPoint.y ? startPoint.y : endPoint.y) + halfThickness + 1;
+ const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
+ const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
+
+ outRect.left = MIN<int16>(startPoint.x, endPoint.x);
+ outRect.top = MIN<int16>(startPoint.y, endPoint.y);
+ outRect.right = MAX<int16>(startPoint.x, endPoint.x) + 1;
+ outRect.bottom = MAX<int16>(startPoint.y, endPoint.y) + 1;
+ outRect.grow(halfThickness);
+ outRect.clip(Common::Rect(scriptWidth, scriptHeight));
reg_t bitmapId;
- SciBitmap &bitmap = *_segMan->allocateBitmap(&bitmapId, outRect.width(), outRect.height(), skipColor, 0, 0, g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight, 0, false, true);
+ SciBitmap &bitmap = *_segMan->allocateBitmap(&bitmapId, outRect.width(), outRect.height(), skipColor, 0, 0, scriptWidth, scriptHeight, 0, false, true);
byte *pixels = bitmap.getPixels();
memset(pixels, skipColor, bitmap.getWidth() * bitmap.getHeight());
@@ -152,12 +153,10 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::
break;
}
- const Common::Rect drawRect(
- startPoint.x - outRect.left,
- startPoint.y - outRect.top,
- endPoint.x - outRect.left,
- endPoint.y - outRect.top
- );
+ const int16 x1 = startPoint.x - outRect.left;
+ const int16 y1 = startPoint.y - outRect.top;
+ const int16 x2 = endPoint.x - outRect.left;
+ const int16 y2 = endPoint.y - outRect.top;
if (!properties.solid) {
for (int i = 0; i < ARRAYSIZE(properties.pattern); ++i) {
@@ -166,14 +165,14 @@ reg_t GfxPaint32::makeLineBitmap(const Common::Point &startPoint, const Common::
}
properties.patternIndex = 0;
- properties.horizontal = ABS(drawRect.right - drawRect.left) > ABS(drawRect.bottom - drawRect.top);
- properties.lastAddress = properties.horizontal ? drawRect.left : drawRect.top;
+ properties.horizontal = ABS(x2 - x1) > ABS(y2 - y1);
+ properties.lastAddress = properties.horizontal ? x1 : y1;
}
if (thickness <= 1) {
- Graphics::drawLine(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, color, plotter, &properties);
+ Graphics::drawLine(x1, y1, x2, y2, color, plotter, &properties);
} else {
- Graphics::drawThickLine2(drawRect.left, drawRect.top, drawRect.right, drawRect.bottom, thickness, color, plotter, &properties);
+ Graphics::drawThickLine2(x1, y1, x2, y2, thickness, color, plotter, &properties);
}
return bitmapId;