[Scummvm-cvs-logs] scummvm master -> e6842022dbb401087745b357b5df1dbc89bf497b

csnover csnover at users.noreply.github.com
Mon Mar 14 04:29:16 CET 2016


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
bfd7e4e784 Revert "SCI32: Fix small inaccuracy in the scaling drawing code"
e6842022db SCI32: Fix scaler drawing pixels at the wrong positions


Commit: bfd7e4e7842863da67d3cd1dc670f7229ee935c3
    https://github.com/scummvm/scummvm/commit/bfd7e4e7842863da67d3cd1dc670f7229ee935c3
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-03-13T22:28:39-05:00

Commit Message:
Revert "SCI32: Fix small inaccuracy in the scaling drawing code"

This reverts commit d85eb8ded68a20de383d84064aacd1a4c81db4e9.

This patch did not correctly fix the scaler to follow the same
rules as SSCI and only worked on the y-axis.

Changed paths:
    engines/sci/graphics/celobj32.cpp



diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index acf4993..389270e 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -117,8 +117,8 @@ struct SCALER_NoScale {
 	_reader(celObj, FLIP ? celObj._width : maxWidth),
 	_lastIndex(celObj._width - 1) {}
 
-	inline void setSource(const int16 x, const int16 targetY, const int16 scaledPosY) {
-		_row = _reader.getRow(targetY - scaledPosY);
+	inline void setSource(const int16 x, const int16 y) {
+		_row = _reader.getRow(y);
 
 		if (FLIP) {
 			_row += _lastIndex - x;
@@ -153,11 +153,8 @@ struct SCALER_Scale {
 	_table(CelObj::_scaler->getScalerTable(scaleX, scaleY)),
 	_lastIndex(maxWidth - 1) {}
 
-	inline void setSource(const int16 x, const int16 targetY, const int16 scaledPosY) {
-		// look up both targetY + scaledPosY in here, only subtract afterwards
-		// otherwise y won't be correct all the time when uneven scaling is used (for example 5:12)
-		int16 y = _table->valuesY[targetY] - _table->valuesY[scaledPosY];
-		_row = _reader.getRow(y);
+	inline void setSource(const int16 x, const int16 y) {
+		_row = _reader.getRow(_table->valuesY[y]);
 		if (FLIP) {
 			_x = _lastIndex - x;
 		} else {
@@ -578,7 +575,7 @@ struct RENDERER {
 
 	inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
 		const int16 sourceX = targetRect.left - scaledPosition.x;
-		//const int16 sourceY = targetRect.top - scaledPosition.y;
+		const int16 sourceY = targetRect.top - scaledPosition.y;
 
 		byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left;
 
@@ -586,7 +583,7 @@ struct RENDERER {
 		const int16 targetWidth = targetRect.width();
 		const int16 targetHeight = targetRect.height();
 		for (int y = 0; y < targetHeight; ++y) {
-			_scaler.setSource(sourceX, targetRect.top + y, scaledPosition.y);
+			_scaler.setSource(sourceX, sourceY + y);
 
 			for (int x = 0; x < targetWidth; ++x) {
 				_mapper.draw(targetPixel++, _scaler.read(), _skipColor);


Commit: e6842022dbb401087745b357b5df1dbc89bf497b
    https://github.com/scummvm/scummvm/commit/e6842022dbb401087745b357b5df1dbc89bf497b
Author: Colin Snover (github.com at zetafleet.com)
Date: 2016-03-13T22:28:39-05:00

Commit Message:
SCI32: Fix scaler drawing pixels at the wrong positions

In order for scaling ratios to apply equally across objects that
start at different positions on the screen, the pixels that are
read from the source bitmap must all use the same pattern of
division. In other words, cels must follow the same scaling pattern
as if they were drawn starting at an even multiple of the scaling
ratio, even if they were not.

Changed paths:
    engines/sci/graphics/celobj32.cpp



diff --git a/engines/sci/graphics/celobj32.cpp b/engines/sci/graphics/celobj32.cpp
index 389270e..e9833c5 100644
--- a/engines/sci/graphics/celobj32.cpp
+++ b/engines/sci/graphics/celobj32.cpp
@@ -109,25 +109,42 @@ void CelObj::deinit() {
 
 template<bool FLIP, typename READER>
 struct SCALER_NoScale {
+#ifndef NDEBUG
+	const byte *_rowEdge;
+#endif
 	const byte *_row;
 	READER _reader;
 	const int16 _lastIndex;
+	const int16 _sourceX;
+	const int16 _sourceY;
 
-	SCALER_NoScale(const CelObj &celObj, const int16 maxWidth) :
+	SCALER_NoScale(const CelObj &celObj, const int16 maxWidth, const Common::Point &scaledPosition) :
 	_reader(celObj, FLIP ? celObj._width : maxWidth),
-	_lastIndex(celObj._width - 1) {}
+	_lastIndex(celObj._width - 1),
+	_sourceX(scaledPosition.x),
+	_sourceY(scaledPosition.y) {}
 
-	inline void setSource(const int16 x, const int16 y) {
-		_row = _reader.getRow(y);
+	inline void setTarget(const int16 x, const int16 y) {
+		_row = _reader.getRow(y - _sourceY);
 
 		if (FLIP) {
-			_row += _lastIndex - x;
+#ifndef NDEBUG
+			_rowEdge = _row - 1;
+#endif
+			_row += _lastIndex - (x - _sourceX);
+			assert(_row > _rowEdge);
 		} else {
-			_row += x;
+#ifndef NDEBUG
+			_rowEdge = _row + _lastIndex + 1;
+#endif
+			_row += x - _sourceX;
+			assert(_row < _rowEdge);
 		}
 	}
 
 	inline byte read() {
+		assert(_row != _rowEdge);
+
 		if (FLIP) {
 			return *_row--;
 		} else {
@@ -138,55 +155,96 @@ struct SCALER_NoScale {
 
 template<bool FLIP, typename READER>
 struct SCALER_Scale {
+#ifndef NDEBUG
+	int16 _maxX;
+#endif
 	const byte *_row;
 	READER _reader;
-	const CelScalerTable *_table;
 	int16 _x;
-	const uint16 _lastIndex;
+	static int16 _valuesX[1024];
+	static int16 _valuesY[1024];
 
-	SCALER_Scale(const CelObj &celObj, const int16 maxWidth, const Ratio scaleX, const Ratio scaleY) :
+	SCALER_Scale(const CelObj &celObj, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio scaleX, const Ratio scaleY) :
+#ifndef NDEBUG
+	_maxX(targetRect.right - 1),
+#endif
 	// The maximum width of the scaled object may not be as
 	// wide as the source data it requires if downscaling,
 	// so just always make the reader decompress an entire
 	// line of source data when scaling
-	_reader(celObj, celObj._width),
-	_table(CelObj::_scaler->getScalerTable(scaleX, scaleY)),
-	_lastIndex(maxWidth - 1) {}
-
-	inline void setSource(const int16 x, const int16 y) {
-		_row = _reader.getRow(_table->valuesY[y]);
+	_reader(celObj, celObj._width) {
+		// In order for scaling ratios to apply equally across objects that
+		// start at different positions on the screen, the pixels that are
+		// read from the source bitmap must all use the same pattern of
+		// division. In other words, cels must follow the same scaling pattern
+		// as if they were drawn starting at an even multiple of the scaling
+		// ratio, even if they were not.
+		//
+		// To get the correct source pixel when reading out through the scaler,
+		// the engine creates a lookup table for each axis that translates
+		// directly from target positions to the indexes of source pixels using
+		// the global cadence for the given scaling ratio.
+
+		const CelScalerTable *table = CelObj::_scaler->getScalerTable(scaleX, scaleY);
+
+		const int16 unscaledX = (scaledPosition.x / scaleX).toInt();
 		if (FLIP) {
-			_x = _lastIndex - x;
+			int lastIndex = celObj._width - 1;
+			for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+				_valuesX[x] = lastIndex - (table->valuesX[x] - unscaledX);
+			}
 		} else {
-			_x = x;
+			for (int16 x = targetRect.left; x < targetRect.right; ++x) {
+				_valuesX[x] = table->valuesX[x] - unscaledX;
+			}
 		}
+
+		const int16 unscaledY = (scaledPosition.y / scaleY).toInt();
+		for (int16 y = targetRect.top; y < targetRect.bottom; ++y) {
+			_valuesY[y] = table->valuesY[y] - unscaledY;
+		}
+	}
+
+	inline void setTarget(const int16 x, const int16 y) {
+		_row = _reader.getRow(_valuesY[y]);
+		_x = x;
+		assert(_x >= 0 && _x <= _maxX);
 	}
 
 	inline byte read() {
-		if (FLIP) {
-			return _row[_table->valuesX[_x--]];
-		} else {
-			return _row[_table->valuesX[_x++]];
-		}
+		assert(_x >= 0 && _x <= _maxX);
+		return _row[_valuesX[_x++]];
 	}
 };
 
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesX[1024];
+template<bool FLIP, typename READER>
+int16 SCALER_Scale<FLIP, READER>::_valuesY[1024];
+
 #pragma mark -
 #pragma mark CelObj - Resource readers
 
 struct READER_Uncompressed {
 private:
+#ifndef NDEBUG
+	const int16 _sourceHeight;
+#endif
 	byte *_pixels;
 	const int16 _sourceWidth;
 
 public:
 	READER_Uncompressed(const CelObj &celObj, const int16) :
+#ifndef NDEBUG
+	_sourceHeight(celObj._height),
+#endif
 	_sourceWidth(celObj._width) {
 		byte *resource = celObj.getResPointer();
 		_pixels = resource + READ_SCI11ENDIAN_UINT32(resource + celObj._celHeaderOffset + 24);
 	}
 
 	inline const byte *getRow(const int16 y) const {
+		assert(y >= 0 && y < _sourceHeight);
 		return _pixels + y * _sourceWidth;
 	}
 };
@@ -210,7 +268,7 @@ public:
 	_sourceHeight(celObj._height),
 	_transparentColor(celObj._transparentColor),
 	_maxWidth(maxWidth) {
-		assert(_maxWidth <= celObj._width);
+		assert(maxWidth <= celObj._width);
 
 		byte *celHeader = _resource + celObj._celHeaderOffset;
 		_dataOffset = READ_SCI11ENDIAN_UINT32(celHeader + 24);
@@ -219,6 +277,7 @@ public:
 	}
 
 	inline const byte *getRow(const int16 y) {
+		assert(y >= 0 && y < _sourceHeight);
 		if (y != _y) {
 			// compressed data segment for row
 			byte *row = _resource + _dataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + y * 4);
@@ -227,7 +286,7 @@ public:
 			byte *literal = _resource + _uncompressedDataOffset + READ_SCI11ENDIAN_UINT32(_resource + _controlOffset + _sourceHeight * 4 + y * 4);
 
 			uint8 length;
-			for (int i = 0; i < _maxWidth; i += length) {
+			for (int16 i = 0; i < _maxWidth; i += length) {
 				byte controlByte = *row++;
 				length = controlByte;
 
@@ -574,18 +633,15 @@ struct RENDERER {
 	_skipColor(skipColor) {}
 
 	inline void draw(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
-		const int16 sourceX = targetRect.left - scaledPosition.x;
-		const int16 sourceY = targetRect.top - scaledPosition.y;
-
 		byte *targetPixel = (byte *)target.getPixels() + target.screenWidth * targetRect.top + targetRect.left;
 
 		const int16 skipStride = target.screenWidth - targetRect.width();
 		const int16 targetWidth = targetRect.width();
 		const int16 targetHeight = targetRect.height();
-		for (int y = 0; y < targetHeight; ++y) {
-			_scaler.setSource(sourceX, sourceY + y);
+		for (int16 y = 0; y < targetHeight; ++y) {
+			_scaler.setTarget(targetRect.left, targetRect.top + y);
 
-			for (int x = 0; x < targetWidth; ++x) {
+			for (int16 x = 0; x < targetWidth; ++x) {
 				_mapper.draw(targetPixel++, _scaler.read(), _skipColor);
 			}
 
@@ -598,7 +654,7 @@ template<typename MAPPER, typename SCALER>
 void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition) const {
 
 	MAPPER mapper;
-	SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width());
+	SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width(), scaledPosition);
 	RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
 	renderer.draw(target, targetRect, scaledPosition);
 }
@@ -607,7 +663,7 @@ template<typename MAPPER, typename SCALER>
 void CelObj::render(Buffer &target, const Common::Rect &targetRect, const Common::Point &scaledPosition, const Ratio &scaleX, const Ratio &scaleY) const {
 
 	MAPPER mapper;
-	SCALER scaler(*this, targetRect.left - scaledPosition.x + targetRect.width(), scaleX, scaleY);
+	SCALER scaler(*this, targetRect, scaledPosition, scaleX, scaleY);
 	RENDERER<MAPPER, SCALER> renderer(mapper, scaler, _transparentColor);
 	renderer.draw(target, targetRect, scaledPosition);
 }






More information about the Scummvm-git-logs mailing list