[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