aboutsummaryrefslogtreecommitdiff
path: root/engines/zvision/graphics/render_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/zvision/graphics/render_manager.cpp')
-rw-r--r--engines/zvision/graphics/render_manager.cpp1144
1 files changed, 844 insertions, 300 deletions
diff --git a/engines/zvision/graphics/render_manager.cpp b/engines/zvision/graphics/render_manager.cpp
index aed30ea12c..05f8dec937 100644
--- a/engines/zvision/graphics/render_manager.cpp
+++ b/engines/zvision/graphics/render_manager.cpp
@@ -1,28 +1,31 @@
/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
#include "common/scummsys.h"
+#include "zvision/zvision.h"
#include "zvision/graphics/render_manager.h"
+#include "zvision/scripting/script_manager.h"
+#include "zvision/text/text.h"
#include "zvision/utility/lzss_read_stream.h"
@@ -37,197 +40,222 @@
namespace ZVision {
-RenderManager::RenderManager(OSystem *system, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat)
- : _system(system),
- _workingWidth(workingWindow.width()),
- _workingHeight(workingWindow.height()),
- _screenCenterX(_workingWidth / 2),
- _screenCenterY(_workingHeight / 2),
- _workingWindow(workingWindow),
- _pixelFormat(pixelFormat),
- _backgroundWidth(0),
- _backgroundHeight(0),
- _backgroundInverseVelocity(0),
- _backgroundOffset(0, 0),
- _accumulatedVelocityMilliseconds(0),
- _renderTable(_workingWidth, _workingHeight) {
-
- _workingWindowBuffer.create(_workingWidth, _workingHeight, _pixelFormat);
- _backBuffer.create(windowWidth, windowHeight, pixelFormat);
+RenderManager::RenderManager(ZVision *engine, uint32 windowWidth, uint32 windowHeight, const Common::Rect workingWindow, const Graphics::PixelFormat pixelFormat)
+ : _engine(engine),
+ _system(engine->_system),
+ _wrkWidth(workingWindow.width()),
+ _wrkHeight(workingWindow.height()),
+ _screenCenterX(_wrkWidth / 2),
+ _screenCenterY(_wrkHeight / 2),
+ _workingWindow(workingWindow),
+ _pixelFormat(pixelFormat),
+ _bkgWidth(0),
+ _bkgHeight(0),
+ _bkgOff(0),
+ _renderTable(_wrkWidth, _wrkHeight) {
+
+ _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _effectWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat);
+ _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat);
+ _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat);
+
+ _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top);
+ _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight);
+
+ _subid = 0;
}
RenderManager::~RenderManager() {
- _workingWindowBuffer.free();
- _currentBackground.free();
- _backBuffer.free();
-
- for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
- iter->_value.data->free();
- delete iter->_value.data;
- }
+ _curBkg.free();
+ _wrkWnd.free();
+ _effectWnd.free();
+ _outWnd.free();
+ _menuWnd.free();
+ _subWnd.free();
}
-void RenderManager::update(uint deltaTimeInMillis) {
- // An inverse velocity of 0 would be infinitely fast, so we'll let 0 mean no velocity.
- if (_backgroundInverseVelocity != 0) {
- _accumulatedVelocityMilliseconds += deltaTimeInMillis;
-
- uint absVelocity = uint(abs(_backgroundInverseVelocity));
-
- int numberOfSteps = 0;
- while (_accumulatedVelocityMilliseconds >= absVelocity) {
- _accumulatedVelocityMilliseconds -= absVelocity;
- numberOfSteps++;
+void RenderManager::renderBackbufferToScreen() {
+ Graphics::Surface *out = &_outWnd;
+ Graphics::Surface *in = &_wrkWnd;
+ Common::Rect outWndDirtyRect;
+
+ if (!_effects.empty()) {
+ bool copied = false;
+ Common::Rect windRect(_wrkWidth, _wrkHeight);
+ for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) {
+ Common::Rect rect = (*it)->getRegion();
+ Common::Rect scrPlace = rect;
+ if ((*it)->isPort())
+ scrPlace = bkgRectToScreen(scrPlace);
+ if (windRect.intersects(scrPlace)) {
+ if (!copied) {
+ copied = true;
+ _effectWnd.copyFrom(_wrkWnd);
+ in = &_effectWnd;
+ }
+ const Graphics::Surface *post;
+ if ((*it)->isPort())
+ post = (*it)->draw(_curBkg.getSubArea(rect));
+ else
+ post = (*it)->draw(_effectWnd.getSubArea(rect));
+ blitSurfaceToSurface(*post, _effectWnd, scrPlace.left, scrPlace.top);
+ scrPlace.clip(windRect);
+ if (_wrkWndDirtyRect .isEmpty()) {
+ _wrkWndDirtyRect = scrPlace;
+ } else {
+ _wrkWndDirtyRect.extend(scrPlace);
+ }
+ }
}
-
- // Choose the direction of movement using the sign of the velocity
- moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps);
}
-}
-void RenderManager::renderBackbufferToScreen() {
- if (!_workingWindowDirtyRect.isEmpty()) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- _renderTable.mutateImage((uint16 *)_workingWindowBuffer.getPixels(), (uint16 *)_backBuffer.getBasePtr(_workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top), _backBuffer.w, _workingWindowDirtyRect);
- } else {
- _backBuffer.copyRectToSurface(_workingWindowBuffer.getBasePtr(_workingWindowDirtyRect.left, _workingWindowDirtyRect.top), _workingWindowBuffer.pitch, _workingWindow.left + _workingWindowDirtyRect.left, _workingWindow.top + _workingWindowDirtyRect.top, _workingWindowDirtyRect.width(), _workingWindowDirtyRect.height());
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ if (!_wrkWndDirtyRect.isEmpty()) {
+ _renderTable.mutateImage(&_outWnd, in);
+ out = &_outWnd;
+ outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight);
}
+ } else {
+ out = in;
+ outWndDirtyRect = _wrkWndDirtyRect;
+ }
- // Translate the working window dirty rect to screen coords
- _workingWindowDirtyRect.translate(_workingWindow.left, _workingWindow.top);
- // Then extend the backbuffer dirty rect to contain it
- if (_backBufferDirtyRect.isEmpty()) {
- _backBufferDirtyRect = _workingWindowDirtyRect;
- } else {
- _backBufferDirtyRect.extend(_workingWindowDirtyRect);
- }
- // Clear the dirty rect
- _workingWindowDirtyRect = Common::Rect();
+ if (!outWndDirtyRect.isEmpty()) {
+ _system->copyRectToScreen(out->getBasePtr(outWndDirtyRect.left, outWndDirtyRect.top), out->pitch,
+ outWndDirtyRect.left + _workingWindow.left,
+ outWndDirtyRect.top + _workingWindow.top,
+ outWndDirtyRect.width(),
+ outWndDirtyRect.height());
}
+}
- // TODO: Add menu rendering
-
- // Render alpha entries
- processAlphaEntries();
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- if (!_backBufferDirtyRect.isEmpty()) {
- _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height());
- _backBufferDirtyRect = Common::Rect();
- }
+ blitSurfaceToBkg(surface, destX, destY);
+ surface.free();
}
-void RenderManager::processAlphaEntries() {
- // TODO: Add dirty rectangling support. AKA only draw an entry if the _backbufferDirtyRect intersects/contains the entry Rect
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 keycolor) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) {
- uint32 destOffset = 0;
- uint32 sourceOffset = 0;
- uint16 *backbufferPtr = (uint16 *)_backBuffer.getBasePtr(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top);
- uint16 *entryPtr = (uint16 *)iter->_value.data->getPixels();
+ blitSurfaceToBkg(surface, destX, destY, keycolor);
+ surface.free();
+}
- for (int32 y = 0; y < iter->_value.height; ++y) {
- for (int32 x = 0; x < iter->_value.width; ++x) {
- uint16 color = entryPtr[sourceOffset + x];
- if (color != iter->_value.alphaColor) {
- backbufferPtr[destOffset + x] = color;
- }
- }
+void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, int16 keyX, int16 keyY) {
+ Graphics::Surface surface;
+ readImageToSurface(fileName, surface);
- destOffset += _backBuffer.w;
- sourceOffset += iter->_value.width;
- }
+ uint16 keycolor = *(uint16 *)surface.getBasePtr(keyX, keyY);
- if (_backBufferDirtyRect.isEmpty()) {
- _backBufferDirtyRect = Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height);
- } else {
- _backBufferDirtyRect.extend(Common::Rect(iter->_value.destX + _workingWindow.left, iter->_value.destY + _workingWindow.top, iter->_value.destX + _workingWindow.left + iter->_value.width, iter->_value.destY + _workingWindow.top + iter->_value.height));
- }
- }
+ blitSurfaceToBkg(surface, destX, destY, keycolor);
+ surface.free();
}
-void RenderManager::clearWorkingWindowTo555Color(uint16 color) {
- uint32 workingWindowSize = _workingWidth * _workingHeight;
- byte r, g, b;
- Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0).colorToRGB(color, r, g, b);
- uint16 colorIn565 = _pixelFormat.RGBToColor(r, g, b);
- uint16 *bufferPtr = (uint16 *)_workingWindowBuffer.getPixels();
+void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+ Common::File file;
- for (uint32 i = 0; i < workingWindowSize; ++i) {
- bufferPtr[i] = colorIn565;
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
+ warning("Could not open file %s", fileName.c_str());
+ return;
}
-}
-void RenderManager::renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
- int16 subRectX = 0;
- int16 subRectY = 0;
+ // Read the magic number
+ // Some files are true TGA, while others are TGZ
+ uint32 fileType = file.readUint32BE();
- // Take care of negative destinations
- if (destinationX < 0) {
- subRectX = -destinationX;
- destinationX = 0;
- } else if (destinationX >= surface.w) {
- // Take care of extreme positive destinations
- destinationX -= surface.w;
- }
+ uint32 imageWidth;
+ uint32 imageHeight;
+ Image::TGADecoder tga;
+ uint16 *buffer;
+ bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
+ // All ZVision images are in RGB 555
+ Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
+ destination.format = pixelFormat555;
- // Take care of negative destinations
- if (destinationY < 0) {
- subRectY = -destinationY;
- destinationY = 0;
- } else if (destinationY >= surface.h) {
- // Take care of extreme positive destinations
- destinationY -= surface.h;
- }
+ bool isTGZ;
- if (wrap) {
- _backgroundWidth = surface.w;
- _backgroundHeight = surface.h;
+ // Check for TGZ files
+ if (fileType == MKTAG('T', 'G', 'Z', '\0')) {
+ isTGZ = true;
- if (destinationX > 0) {
- // Move destinationX to 0
- subRectX = surface.w - destinationX;
- destinationX = 0;
- }
+ // TGZ files have a header and then Bitmap data that is compressed with LZSS
+ uint32 decompressedSize = file.readSint32LE();
+ imageWidth = file.readSint32LE();
+ imageHeight = file.readSint32LE();
+
+ LzssReadStream lzssStream(&file);
+ buffer = (uint16 *)(new uint16[decompressedSize]);
+ lzssStream.read(buffer, decompressedSize);
+ } else {
+ isTGZ = false;
+
+ // Reset the cursor
+ file.seek(0);
- if (destinationY > 0) {
- // Move destinationY to 0
- subRectY = surface.h - destinationY;
- destinationY = 0;
+ // Decode
+ if (!tga.loadStream(file)) {
+ warning("Error while reading TGA image");
+ return;
}
+
+ Graphics::Surface tgaSurface = *(tga.getSurface());
+ imageWidth = tgaSurface.w;
+ imageHeight = tgaSurface.h;
+
+ buffer = (uint16 *)tgaSurface.getPixels();
}
- // Clip subRect to working window bounds
- Common::Rect subRect(subRectX, subRectY, subRectX + _workingWidth, subRectY + _workingHeight);
+ // Flip the width and height if transposed
+ if (isTransposed) {
+ uint16 temp = imageHeight;
+ imageHeight = imageWidth;
+ imageWidth = temp;
+ }
- if (!wrap) {
- // Clip to image bounds
- subRect.clip(surface.w, surface.h);
+ // If the destination internal buffer is the same size as what we're copying into it,
+ // there is no need to free() and re-create
+ if (imageWidth != destination.w || imageHeight != destination.h) {
+ destination.create(imageWidth, imageHeight, pixelFormat555);
}
- // Check destRect for validity
- if (!subRect.isValidRect() || subRect.isEmpty())
- return;
+ // If transposed, 'un-transpose' the data while copying it to the destination
+ // Otherwise, just do a simple copy
+ if (isTransposed) {
+ uint16 *dest = (uint16 *)destination.getPixels();
- copyRectToWorkingWindow((const uint16 *)surface.getBasePtr(subRect.left, subRect.top), destinationX, destinationY, surface.w, subRect.width(), subRect.height());
-}
+ for (uint32 y = 0; y < imageHeight; ++y) {
+ uint32 columnIndex = y * imageWidth;
-void RenderManager::renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap) {
- Graphics::Surface surface;
- readImageToSurface(fileName, surface);
+ for (uint32 x = 0; x < imageWidth; ++x) {
+ dest[columnIndex + x] = buffer[x * imageHeight + y];
+ }
+ }
+ } else {
+ memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * _pixelFormat.bytesPerPixel);
+ }
- renderSubRectToScreen(surface, destinationX, destinationY, wrap);
-}
+ // Cleanup
+ if (isTGZ) {
+ delete[] buffer;
+ } else {
+ tga.destroy();
+ }
-void RenderManager::renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) {
- renderSubRectToScreen(surface, destinationX, destinationY, wrap);
+ // Convert in place to RGB 565 from RGB 555
+ destination.convertToInPlace(_pixelFormat);
}
-void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) {
+void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) {
Common::File file;
- if (!file.open(fileName)) {
+ if (!_engine->getSearchManager()->openFile(file, fileName)) {
warning("Could not open file %s", fileName.c_str());
return;
}
@@ -240,7 +268,6 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
uint32 imageHeight;
Image::TGADecoder tga;
uint16 *buffer;
- bool isTransposed = _renderTable.getRenderState() == RenderTable::PANORAMA;
// All ZVision images are in RGB 555
Graphics::PixelFormat pixelFormat555 = Graphics::PixelFormat(2, 5, 5, 5, 0, 10, 5, 0, 0);
destination.format = pixelFormat555;
@@ -279,7 +306,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
}
// Flip the width and height if transposed
- if (isTransposed) {
+ if (transposed) {
uint16 temp = imageHeight;
imageHeight = imageWidth;
imageWidth = temp;
@@ -293,7 +320,7 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
// If transposed, 'un-transpose' the data while copying it to the destination
// Otherwise, just do a simple copy
- if (isTransposed) {
+ if (transposed) {
uint16 *dest = (uint16 *)destination.getPixels();
for (uint32 y = 0; y < imageHeight; ++y) {
@@ -318,209 +345,726 @@ void RenderManager::readImageToSurface(const Common::String &fileName, Graphics:
destination.convertToInPlace(_pixelFormat);
}
-void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height) {
- uint32 destOffset = 0;
- uint32 sourceOffset = 0;
- uint16 *workingWindowBufferPtr = (uint16 *)_workingWindowBuffer.getBasePtr(destX, destY);
+const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) {
+ if (_workingWindow.contains(point)) {
+ // Convert from screen space to working window space
+ Common::Point newPoint(point - Common::Point(_workingWindow.left, _workingWindow.top));
+
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
+ newPoint = _renderTable.convertWarpedCoordToFlatCoord(newPoint);
+ }
- for (int32 y = 0; y < height; ++y) {
- for (int32 x = 0; x < width; ++x) {
- workingWindowBufferPtr[destOffset + x] = buffer[sourceOffset + x];
+ if (state == RenderTable::PANORAMA) {
+ newPoint += (Common::Point(_bkgOff - _screenCenterX, 0));
+ } else if (state == RenderTable::TILT) {
+ newPoint += (Common::Point(0, _bkgOff - _screenCenterY));
}
- destOffset += _workingWidth;
- sourceOffset += imageWidth;
- }
+ if (_bkgWidth)
+ newPoint.x %= _bkgWidth;
+ if (_bkgHeight)
+ newPoint.y %= _bkgHeight;
- if (_workingWindowDirtyRect.isEmpty()) {
- _workingWindowDirtyRect = Common::Rect(destX, destY, destX + width, destY + height);
+ if (newPoint.x < 0)
+ newPoint.x += _bkgWidth;
+ if (newPoint.y < 0)
+ newPoint.y += _bkgHeight;
+
+ return newPoint;
} else {
- _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height));
+ return Common::Point(0, 0);
}
+}
+
+RenderTable *RenderManager::getRenderTable() {
+ return &_renderTable;
+}
+
+void RenderManager::setBackgroundImage(const Common::String &fileName) {
+ readImageToSurface(fileName, _curBkg);
+ _bkgWidth = _curBkg.w;
+ _bkgHeight = _curBkg.h;
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+}
+
+void RenderManager::setBackgroundPosition(int offset) {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+ if (state == RenderTable::TILT || state == RenderTable::PANORAMA)
+ if (_bkgOff != offset)
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+ _bkgOff = offset;
- // TODO: Remove this from release. It's here to make sure code that uses this function clips their destinations correctly
- assert(_workingWindowDirtyRect.width() <= _workingWidth && _workingWindowDirtyRect.height() <= _workingHeight);
+ _engine->getScriptManager()->setStateValue(StateKey_ViewPos, offset);
}
-void RenderManager::copyRectToWorkingWindow(const uint16 *buffer, int32 destX, int32 destY, int32 imageWidth, int32 width, int32 height, int16 alphaColor, uint32 idNumber) {
- AlphaDataEntry entry;
- entry.alphaColor = alphaColor;
- entry.data = new Graphics::Surface();
- entry.data->create(width, height, _pixelFormat);
- entry.destX = destX;
- entry.destY = destY;
- entry.width = width;
- entry.height = height;
+uint32 RenderManager::getCurrentBackgroundOffset() {
+ RenderTable::RenderState state = _renderTable.getRenderState();
+
+ if (state == RenderTable::PANORAMA) {
+ return _bkgOff;
+ } else if (state == RenderTable::TILT) {
+ return _bkgOff;
+ } else {
+ return 0;
+ }
+}
+
+Graphics::Surface *RenderManager::tranposeSurface(const Graphics::Surface *surface) {
+ Graphics::Surface *tranposedSurface = new Graphics::Surface();
+ tranposedSurface->create(surface->h, surface->w, surface->format);
+
+ const uint16 *source = (const uint16 *)surface->getPixels();
+ uint16 *dest = (uint16 *)tranposedSurface->getPixels();
- uint32 sourceOffset = 0;
- uint32 destOffset = 0;
- uint16 *surfacePtr = (uint16 *)entry.data->getPixels();
+ for (uint32 y = 0; y < tranposedSurface->h; ++y) {
+ uint32 columnIndex = y * tranposedSurface->w;
- for (int32 y = 0; y < height; ++y) {
- for (int32 x = 0; x < width; ++x) {
- surfacePtr[destOffset + x] = buffer[sourceOffset + x];
+ for (uint32 x = 0; x < tranposedSurface->w; ++x) {
+ dest[columnIndex + x] = source[x * surface->w + y];
}
+ }
+
+ return tranposedSurface;
+}
+
+void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uint32 srcHeight, byte bytesPerPixel, uint32 dstWidth, uint32 dstHeight) {
+ assert(bytesPerPixel == 1 || bytesPerPixel == 2);
- destOffset += width;
- sourceOffset += imageWidth;
+ const float xscale = (float)srcWidth / (float)dstWidth;
+ const float yscale = (float)srcHeight / (float)dstHeight;
+
+ if (bytesPerPixel == 1) {
+ const byte *srcPtr = (const byte *)src;
+ byte *dstPtr = (byte *)dst;
+ for (uint32 y = 0; y < dstHeight; ++y) {
+ for (uint32 x = 0; x < dstWidth; ++x) {
+ *dstPtr = srcPtr[(int)(x * xscale) + (int)(y * yscale) * srcWidth];
+ dstPtr++;
+ }
+ }
+ } else if (bytesPerPixel == 2) {
+ const uint16 *srcPtr = (const uint16 *)src;
+ uint16 *dstPtr = (uint16 *)dst;
+ for (uint32 y = 0; y < dstHeight; ++y) {
+ for (uint32 x = 0; x < dstWidth; ++x) {
+ *dstPtr = srcPtr[(int)(x * xscale) + (int)(y * yscale) * srcWidth];
+ dstPtr++;
+ }
+ }
}
+}
+
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y) {
+
+ if (src.format != dst.format)
+ return;
+
+ Common::Rect srcRect = _srcRect;
+ if (srcRect.isEmpty())
+ srcRect = Common::Rect(src.w, src.h);
+ srcRect.clip(src.w, src.h);
+ Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
+ srcRect.clip(dstRect);
+
+ if (srcRect.isEmpty() || !srcRect.isValidRect())
+ return;
+
+ // Copy srcRect from src surface to dst surface
+ const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top);
+
+ int xx = _x;
+ int yy = _y;
+
+ if (xx < 0)
+ xx = 0;
+ if (yy < 0)
+ yy = 0;
- _alphaDataEntries[idNumber] = entry;
+ if (_x >= dst.w || _y >= dst.h)
+ return;
+
+ byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);
+
+ int32 w = srcRect.width();
+ int32 h = srcRect.height();
+
+ for (int32 y = 0; y < h; y++) {
+ memcpy(dstBuffer, srcBuffer, w * src.format.bytesPerPixel);
+ srcBuffer += src.pitch;
+ dstBuffer += dst.pitch;
+ }
}
-Common::Rect RenderManager::renderTextToWorkingWindow(uint32 idNumber, const Common::String &text, TruetypeFont *font, int destX, int destY, uint16 textColor, int maxWidth, int maxHeight, Graphics::TextAlign align, bool wrap) {
- AlphaDataEntry entry;
- entry.alphaColor = 0;
- entry.destX = destX;
- entry.destY = destY;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, const Common::Rect &_srcRect , Graphics::Surface &dst, int _x, int _y, uint32 colorkey) {
+
+ if (src.format != dst.format)
+ return;
+
+ Common::Rect srcRect = _srcRect;
+ if (srcRect.isEmpty())
+ srcRect = Common::Rect(src.w, src.h);
+ srcRect.clip(src.w, src.h);
+ Common::Rect dstRect = Common::Rect(-_x + srcRect.left , -_y + srcRect.top, -_x + srcRect.left + dst.w, -_y + srcRect.top + dst.h);
+ srcRect.clip(dstRect);
+
+ if (srcRect.isEmpty() || !srcRect.isValidRect())
+ return;
+
+
+
+ uint32 _keycolor = colorkey & ((1 << (src.format.bytesPerPixel << 3)) - 1);
+
+ // Copy srcRect from src surface to dst surface
+ const byte *srcBuffer = (const byte *)src.getBasePtr(srcRect.left, srcRect.top);
+
+ int xx = _x;
+ int yy = _y;
+
+ if (xx < 0)
+ xx = 0;
+ if (yy < 0)
+ yy = 0;
+
+ if (_x >= dst.w || _y >= dst.h)
+ return;
+
+ byte *dstBuffer = (byte *)dst.getBasePtr(xx, yy);
+
+ int32 w = srcRect.width();
+ int32 h = srcRect.height();
+
+ for (int32 y = 0; y < h; y++) {
+ switch (src.format.bytesPerPixel) {
+ case 1: {
+ const uint *srcTemp = (const uint *)srcBuffer;
+ uint *dstTemp = (uint *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ case 2: {
+ const uint16 *srcTemp = (const uint16 *)srcBuffer;
+ uint16 *dstTemp = (uint16 *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ case 4: {
+ const uint32 *srcTemp = (const uint32 *)srcBuffer;
+ uint32 *dstTemp = (uint32 *)dstBuffer;
+ for (int32 x = 0; x < w; x++) {
+ if (*srcTemp != _keycolor)
+ *dstTemp = *srcTemp;
+ srcTemp++;
+ dstTemp++;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ srcBuffer += src.pitch;
+ dstBuffer += dst.pitch;
+ }
+}
- // Draw the text to the working window
- entry.data = font->drawTextToSurface(text, textColor, maxWidth, maxHeight, align, wrap);
- entry.width = entry.data->w;
- entry.height = entry.data->h;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, dst, x, y);
+}
- _alphaDataEntries[idNumber] = entry;
+void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, dst, x, y, colorkey);
+}
- return Common::Rect(destX, destY, destX + entry.width, destY + entry.height);
+void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _curBkg, x, y);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_bkgDirtyRect.isEmpty())
+ _bkgDirtyRect = dirty;
+ else
+ _bkgDirtyRect.extend(dirty);
}
-const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) {
- // Convert from screen space to working window space
- Common::Point newPoint(point - Common::Point(_workingWindow.left, _workingWindow.top));
+void RenderManager::blitSurfaceToBkg(const Graphics::Surface &src, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _curBkg, x, y, colorkey);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_bkgDirtyRect.isEmpty())
+ _bkgDirtyRect = dirty;
+ else
+ _bkgDirtyRect.extend(dirty);
+}
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::PANORAMA || state == RenderTable::TILT) {
- newPoint = _renderTable.convertWarpedCoordToFlatCoord(newPoint);
+void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect) {
+ if (src.w == _dstRect.width() && src.h == _dstRect.height())
+ blitSurfaceToBkg(src, _dstRect.left, _dstRect.top);
+ else {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ tmp->create(_dstRect.width(), _dstRect.height(), src.format);
+ scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height());
+ blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top);
+ tmp->free();
+ delete tmp;
}
+}
- if (state == RenderTable::PANORAMA) {
- newPoint -= (Common::Point(_screenCenterX, 0) - _backgroundOffset);
- } else if (state == RenderTable::TILT) {
- newPoint -= (Common::Point(0, _screenCenterY) - _backgroundOffset);
+void RenderManager::blitSurfaceToBkgScaled(const Graphics::Surface &src, const Common::Rect &_dstRect, uint32 colorkey) {
+ if (src.w == _dstRect.width() && src.h == _dstRect.height())
+ blitSurfaceToBkg(src, _dstRect.left, _dstRect.top, colorkey);
+ else {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ tmp->create(_dstRect.width(), _dstRect.height(), src.format);
+ scaleBuffer(src.getPixels(), tmp->getPixels(), src.w, src.h, src.format.bytesPerPixel, _dstRect.width(), _dstRect.height());
+ blitSurfaceToBkg(*tmp, _dstRect.left, _dstRect.top, colorkey);
+ tmp->free();
+ delete tmp;
}
+}
+
+void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _menuWnd, x, y);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = dirty;
+ else
+ _menuWndDirtyRect.extend(dirty);
+}
+
+void RenderManager::blitSurfaceToMenu(const Graphics::Surface &src, int x, int y, uint32 colorkey) {
+ Common::Rect empt;
+ blitSurfaceToSurface(src, empt, _menuWnd, x, y, colorkey);
+ Common::Rect dirty(src.w, src.h);
+ dirty.translate(x, y);
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = dirty;
+ else
+ _menuWndDirtyRect.extend(dirty);
+}
+
+Graphics::Surface *RenderManager::getBkgRect(Common::Rect &rect) {
+ Common::Rect dst = rect;
+ dst.clip(_bkgWidth, _bkgHeight);
+
+ if (dst.isEmpty() || !dst.isValidRect())
+ return NULL;
+
+ Graphics::Surface *srf = new Graphics::Surface;
+ srf->create(dst.width(), dst.height(), _curBkg.format);
+
+ srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst));
+
+ return srf;
+}
+
+Graphics::Surface *RenderManager::loadImage(Common::String &file) {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ readImageToSurface(file, *tmp);
+ return tmp;
+}
- if (newPoint.x < 0)
- newPoint.x += _backgroundWidth;
- else if (newPoint.x >= _backgroundWidth)
- newPoint.x -= _backgroundWidth;
- if (newPoint.y < 0)
- newPoint.y += _backgroundHeight;
- else if (newPoint.y >= _backgroundHeight)
- newPoint.y -= _backgroundHeight;
+Graphics::Surface *RenderManager::loadImage(const char *file) {
+ Common::String str = Common::String(file);
+ return loadImage(str);
+}
- return newPoint;
+Graphics::Surface *RenderManager::loadImage(Common::String &file, bool transposed) {
+ Graphics::Surface *tmp = new Graphics::Surface;
+ readImageToSurface(file, *tmp, transposed);
+ return tmp;
}
-const Common::Point RenderManager::imageSpaceToWorkingWindowSpace(const Common::Point &point) {
- Common::Point newPoint(point);
+Graphics::Surface *RenderManager::loadImage(const char *file, bool transposed) {
+ Common::String str = Common::String(file);
+ return loadImage(str, transposed);
+}
+void RenderManager::prepareBkg() {
+ _bkgDirtyRect.clip(_bkgWidth, _bkgHeight);
RenderTable::RenderState state = _renderTable.getRenderState();
+
if (state == RenderTable::PANORAMA) {
- newPoint += (Common::Point(_screenCenterX, 0) - _backgroundOffset);
+ Common::Rect viewPort(_wrkWidth, _wrkHeight);
+ viewPort.translate(-(_screenCenterX - _bkgOff), 0);
+ Common::Rect drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - _bkgOff + drawRect.left, drawRect.top);
+
+ _wrkWndDirtyRect = _bkgDirtyRect;
+ _wrkWndDirtyRect.translate(_screenCenterX - _bkgOff, 0);
+
+ if (_bkgOff < _screenCenterX) {
+ viewPort.moveTo(-(_screenCenterX - (_bkgOff + _bkgWidth)), 0);
+ drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX - (_bkgOff + _bkgWidth) + drawRect.left, drawRect.top);
+
+ Common::Rect tmp = _bkgDirtyRect;
+ tmp.translate(_screenCenterX - (_bkgOff + _bkgWidth), 0);
+ if (!tmp.isEmpty())
+ _wrkWndDirtyRect.extend(tmp);
+
+ } else if (_bkgWidth - _bkgOff < _screenCenterX) {
+ viewPort.moveTo(-(_screenCenterX + _bkgWidth - _bkgOff), 0);
+ drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, _screenCenterX + _bkgWidth - _bkgOff + drawRect.left, drawRect.top);
+
+ Common::Rect tmp = _bkgDirtyRect;
+ tmp.translate(_screenCenterX + _bkgWidth - _bkgOff, 0);
+ if (!tmp.isEmpty())
+ _wrkWndDirtyRect.extend(tmp);
+
+ }
} else if (state == RenderTable::TILT) {
- newPoint += (Common::Point(0, _screenCenterY) - _backgroundOffset);
+ Common::Rect viewPort(_wrkWidth, _wrkHeight);
+ viewPort.translate(0, -(_screenCenterY - _bkgOff));
+ Common::Rect drawRect = _bkgDirtyRect;
+ drawRect.clip(viewPort);
+ if (!drawRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, drawRect, _wrkWnd, drawRect.left, _screenCenterY - _bkgOff + drawRect.top);
+
+ _wrkWndDirtyRect = _bkgDirtyRect;
+ _wrkWndDirtyRect.translate(0, _screenCenterY - _bkgOff);
+
+ } else {
+ if (!_bkgDirtyRect.isEmpty())
+ blitSurfaceToSurface(_curBkg, _bkgDirtyRect, _wrkWnd, _bkgDirtyRect.left, _bkgDirtyRect.top);
+ _wrkWndDirtyRect = _bkgDirtyRect;
}
- return newPoint;
+ _bkgDirtyRect = Common::Rect();
+
+ _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight);
+}
+
+void RenderManager::clearMenuSurface() {
+ _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h);
+ _menuWnd.fillRect(_menuWndDirtyRect, 0);
}
-bool RenderManager::clipRectToWorkingWindow(Common::Rect &rect) {
- if (!_workingWindow.contains(rect)) {
- return false;
+void RenderManager::clearMenuSurface(const Common::Rect &r) {
+ if (_menuWndDirtyRect.isEmpty())
+ _menuWndDirtyRect = r;
+ else
+ _menuWndDirtyRect.extend(r);
+ _menuWnd.fillRect(r, 0);
+}
+
+void RenderManager::renderMenuToScreen() {
+ if (!_menuWndDirtyRect.isEmpty()) {
+ _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h));
+ if (!_menuWndDirtyRect.isEmpty())
+ _system->copyRectToScreen(_menuWnd.getBasePtr(_menuWndDirtyRect.left, _menuWndDirtyRect.top), _menuWnd.pitch,
+ _menuWndDirtyRect.left + _menuWndRect.left,
+ _menuWndDirtyRect.top + _menuWndRect.top,
+ _menuWndDirtyRect.width(),
+ _menuWndDirtyRect.height());
+ _menuWndDirtyRect = Common::Rect();
}
+}
+
+uint16 RenderManager::createSubArea(const Common::Rect &area) {
+ _subid++;
+
+ oneSub sub;
+ sub.redraw = false;
+ sub.timer = -1;
+ sub.todelete = false;
+ sub.r = area;
- // We can't clip against the actual working window rect because it's in screen space
- // But rect is in working window space
- rect.clip(_workingWidth, _workingHeight);
- return true;
+ _subsList[_subid] = sub;
+
+ return _subid;
}
-RenderTable *RenderManager::getRenderTable() {
- return &_renderTable;
+uint16 RenderManager::createSubArea() {
+ _subid++;
+
+ oneSub sub;
+ sub.redraw = false;
+ sub.timer = -1;
+ sub.todelete = false;
+ sub.r = Common::Rect(_subWndRect.left, _subWndRect.top, _subWndRect.right, _subWndRect.bottom);
+ sub.r.translate(-_workingWindow.left, -_workingWindow.top);
+
+ _subsList[_subid] = sub;
+
+ return _subid;
}
-void RenderManager::setBackgroundImage(const Common::String &fileName) {
- readImageToSurface(fileName, _currentBackground);
+void RenderManager::deleteSubArea(uint16 id) {
+ if (_subsList.contains(id))
+ _subsList[id].todelete = true;
+}
- moveBackground(0);
+void RenderManager::deleteSubArea(uint16 id, int16 delay) {
+ if (_subsList.contains(id))
+ _subsList[id].timer = delay;
}
-void RenderManager::setBackgroundPosition(int offset) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::TILT) {
- _backgroundOffset.x = 0;
- _backgroundOffset.y = offset;
- } else if (state == RenderTable::PANORAMA) {
- _backgroundOffset.x = offset;
- _backgroundOffset.y = 0;
- } else {
- _backgroundOffset.x = 0;
- _backgroundOffset.y = 0;
+void RenderManager::updateSubArea(uint16 id, const Common::String &txt) {
+ if (_subsList.contains(id)) {
+ oneSub *sub = &_subsList[id];
+ sub->txt = txt;
+ sub->redraw = true;
}
}
-void RenderManager::setBackgroundVelocity(int velocity) {
- // setBackgroundVelocity(0) will be called quite often, so make sure
- // _backgroundInverseVelocity isn't already 0 to prevent an extraneous assignment
- if (velocity == 0) {
- if (_backgroundInverseVelocity != 0) {
- _backgroundInverseVelocity = 0;
+void RenderManager::processSubs(uint16 deltatime) {
+ bool redraw = false;
+ for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
+ if (it->_value.timer != -1) {
+ it->_value.timer -= deltatime;
+ if (it->_value.timer <= 0)
+ it->_value.todelete = true;
+ }
+ if (it->_value.todelete) {
+ _subsList.erase(it);
+ redraw = true;
+ } else if (it->_value.redraw) {
+ redraw = true;
}
- } else {
- _backgroundInverseVelocity = 1000 / velocity;
}
-}
-void RenderManager::moveBackground(int offset) {
- RenderTable::RenderState state = _renderTable.getRenderState();
- if (state == RenderTable::TILT) {
- _backgroundOffset += Common::Point(0, offset);
+ if (redraw) {
+ _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0);
+
+ for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) {
+ oneSub *sub = &it->_value;
+ if (sub->txt.size()) {
+ Graphics::Surface *rndr = new Graphics::Surface();
+ rndr->create(sub->r.width(), sub->r.height(), _pixelFormat);
+ _engine->getTextRenderer()->drawTxtInOneLine(sub->txt, *rndr);
+ blitSurfaceToSurface(*rndr, _subWnd, sub->r.left - _subWndRect.left + _workingWindow.left, sub->r.top - _subWndRect.top + _workingWindow.top);
+ rndr->free();
+ delete rndr;
+ }
+ sub->redraw = false;
+ }
- _backgroundOffset.y = CLIP<int16>(_backgroundOffset.y, _screenCenterY, (int16)_backgroundHeight - _screenCenterY);
+ _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch,
+ _subWndRect.left,
+ _subWndRect.top,
+ _subWnd.w,
+ _subWnd.h);
+ }
+}
- renderImageToScreen(_currentBackground, 0, _screenCenterY - _backgroundOffset.y, true);
- } else if (state == RenderTable::PANORAMA) {
- _backgroundOffset += Common::Point(offset, 0);
+Common::Point RenderManager::getBkgSize() {
+ return Common::Point(_bkgWidth, _bkgHeight);
+}
- if (_backgroundOffset.x <= -_backgroundWidth)
- _backgroundOffset.x += _backgroundWidth;
- else if (_backgroundOffset.x >= _backgroundWidth)
- _backgroundOffset.x -= _backgroundWidth;
+void RenderManager::addEffect(Effect *_effect) {
+ _effects.push_back(_effect);
+}
- renderImageToScreen(_currentBackground, _screenCenterX - _backgroundOffset.x, 0, true);
- } else {
- renderImageToScreen(_currentBackground, 0, 0);
+void RenderManager::deleteEffect(uint32 ID) {
+ for (effectsList::iterator it = _effects.begin(); it != _effects.end(); it++) {
+ if ((*it)->getKey() == ID) {
+ delete *it;
+ it = _effects.erase(it);
+ }
}
}
-uint32 RenderManager::getCurrentBackgroundOffset() {
+Common::Rect RenderManager::bkgRectToScreen(const Common::Rect &src) {
+ Common::Rect tmp = src;
RenderTable::RenderState state = _renderTable.getRenderState();
if (state == RenderTable::PANORAMA) {
- return _backgroundOffset.x;
+ if (_bkgOff < _screenCenterX) {
+ Common::Rect rScreen(_screenCenterX + _bkgOff, _wrkHeight);
+ Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight);
+ lScreen.translate(_bkgWidth - lScreen.width(), 0);
+ lScreen.clip(src);
+ rScreen.clip(src);
+ if (rScreen.width() < lScreen.width()) {
+ tmp.translate(_screenCenterX - _bkgOff - _bkgWidth, 0);
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
+ } else if (_bkgWidth - _bkgOff < _screenCenterX) {
+ Common::Rect rScreen(_screenCenterX - (_bkgWidth - _bkgOff), _wrkHeight);
+ Common::Rect lScreen(_wrkWidth - rScreen.width(), _wrkHeight);
+ lScreen.translate(_bkgWidth - lScreen.width(), 0);
+ lScreen.clip(src);
+ rScreen.clip(src);
+ if (lScreen.width() < rScreen.width()) {
+ tmp.translate(_screenCenterX + (_bkgWidth - _bkgOff), 0);
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
+ } else {
+ tmp.translate(_screenCenterX - _bkgOff, 0);
+ }
} else if (state == RenderTable::TILT) {
- return _backgroundOffset.y;
- } else {
- return 0;
+ tmp.translate(0, (_screenCenterY - _bkgOff));
}
+
+ return tmp;
}
-Graphics::Surface *RenderManager::tranposeSurface(const Graphics::Surface *surface) {
- Graphics::Surface *tranposedSurface = new Graphics::Surface();
- tranposedSurface->create(surface->h, surface->w, surface->format);
+EffectMap *RenderManager::makeEffectMap(const Common::Point &xy, int16 depth, const Common::Rect &rect, int8 *_minComp, int8 *_maxComp) {
+ Common::Rect bkgRect(_bkgWidth, _bkgHeight);
+ if (!bkgRect.contains(xy))
+ return NULL;
+
+ if (!bkgRect.intersects(rect))
+ return NULL;
+
+ uint16 color = *(uint16 *)_curBkg.getBasePtr(xy.x, xy.y);
+ uint8 stC1, stC2, stC3;
+ _curBkg.format.colorToRGB(color, stC1, stC2, stC3);
+ EffectMap *newMap = new EffectMap;
+
+ EffectMapUnit unit;
+ unit.count = 0;
+ unit.inEffect = false;
+
+ int16 w = rect.width();
+ int16 h = rect.height();
+
+ bool first = true;
+
+ uint8 minComp = MIN(MIN(stC1, stC2), stC3);
+ uint8 maxComp = MAX(MAX(stC1, stC2), stC3);
+
+ uint8 depth8 = depth << 3;
+
+ for (int16 j = 0; j < h; j++) {
+ uint16 *pix = (uint16 *)_curBkg.getBasePtr(rect.left, rect.top + j);
+ for (int16 i = 0; i < w; i++) {
+ uint16 curClr = pix[i];
+ uint8 cC1, cC2, cC3;
+ _curBkg.format.colorToRGB(curClr, cC1, cC2, cC3);
+
+ bool use = false;
+
+ if (curClr == color)
+ use = true;
+ else if (curClr > color) {
+ if ((cC1 - stC1 < depth8) &&
+ (cC2 - stC2 < depth8) &&
+ (cC3 - stC3 < depth8))
+ use = true;
+ } else { /* if (curClr < color) */
+ if ((stC1 - cC1 < depth8) &&
+ (stC2 - cC2 < depth8) &&
+ (stC3 - cC3 < depth8))
+ use = true;
+ }
- const uint16 *source = (const uint16 *)surface->getPixels();
- uint16 *dest = (uint16 *)tranposedSurface->getPixels();
+ if (first) {
+ unit.inEffect = use;
+ first = false;
+ }
- for (uint32 y = 0; y < tranposedSurface->h; ++y) {
- uint32 columnIndex = y * tranposedSurface->w;
+ if (use) {
+ uint8 cMinComp = MIN(MIN(cC1, cC2), cC3);
+ uint8 cMaxComp = MAX(MAX(cC1, cC2), cC3);
+ if (cMinComp < minComp)
+ minComp = cMinComp;
+ if (cMaxComp > maxComp)
+ maxComp = cMaxComp;
+ }
- for (uint32 x = 0; x < tranposedSurface->w; ++x) {
- dest[columnIndex + x] = source[x * surface->w + y];
+ if (unit.inEffect == use)
+ unit.count++;
+ else {
+ newMap->push_back(unit);
+ unit.count = 1;
+ unit.inEffect = use;
+ }
}
}
+ newMap->push_back(unit);
- return tranposedSurface;
+ if (_minComp) {
+ if (minComp - depth8 < 0)
+ *_minComp = -(minComp >> 3);
+ else
+ *_minComp = -depth;
+ }
+ if (_maxComp) {
+ if ((int16)maxComp + (int16)depth8 > 255)
+ *_maxComp = (255 - maxComp) >> 3;
+ else
+ *_maxComp = depth;
+ }
+
+ return newMap;
+}
+
+EffectMap *RenderManager::makeEffectMap(const Graphics::Surface &surf, uint16 transp) {
+ EffectMapUnit unit;
+ unit.count = 0;
+ unit.inEffect = false;
+
+ int16 w = surf.w;
+ int16 h = surf.h;
+
+ EffectMap *newMap = new EffectMap;
+
+ bool first = true;
+
+ for (int16 j = 0; j < h; j++) {
+ const uint16 *pix = (const uint16 *)surf.getBasePtr(0, j);
+ for (int16 i = 0; i < w; i++) {
+ bool use = false;
+ if (pix[i] != transp)
+ use = true;
+
+ if (first) {
+ unit.inEffect = use;
+ first = false;
+ }
+
+ if (unit.inEffect == use)
+ unit.count++;
+ else {
+ newMap->push_back(unit);
+ unit.count = 1;
+ unit.inEffect = use;
+ }
+ }
+ }
+ newMap->push_back(unit);
+
+ return newMap;
+}
+
+void RenderManager::markDirty() {
+ _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight);
+}
+
+void RenderManager::bkgFill(uint8 r, uint8 g, uint8 b) {
+ _curBkg.fillRect(Common::Rect(_curBkg.w, _curBkg.h), _curBkg.format.RGBToColor(r, g, b));
+ markDirty();
}
} // End of namespace ZVision