diff options
Diffstat (limited to 'engines/zvision/render_manager.cpp')
-rw-r--r-- | engines/zvision/render_manager.cpp | 863 |
1 files changed, 374 insertions, 489 deletions
diff --git a/engines/zvision/render_manager.cpp b/engines/zvision/render_manager.cpp index 6578c850f6..bc4d169569 100644 --- a/engines/zvision/render_manager.cpp +++ b/engines/zvision/render_manager.cpp @@ -39,356 +39,75 @@ 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), + _wrkWidth(workingWindow.width()), + _wrkHeight(workingWindow.height()), + _screenCenterX(_wrkWidth / 2), + _screenCenterY(_wrkHeight / 2), _workingWindow(workingWindow), _pixelFormat(pixelFormat), - _backgroundWidth(0), - _backgroundHeight(0), - _backgroundInverseVelocity(0), - _backgroundOffset(0, 0), - _accumulatedVelocityMilliseconds(0), - _renderTable(_workingWidth, _workingHeight) { + _bkgWidth(0), + _bkgHeight(0), + _bkgOff(0), + _renderTable(_wrkWidth, _wrkHeight) { - _workingWindowBuffer.create(_workingWidth, _workingHeight, _pixelFormat); - _backBuffer.create(windowWidth, windowHeight, pixelFormat); -} + _wrkWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); + _outWnd.create(_wrkWidth, _wrkHeight, _pixelFormat); + _menuWnd.create(windowWidth, workingWindow.top, _pixelFormat); + _subWnd.create(windowWidth, windowHeight - workingWindow.bottom, _pixelFormat); -RenderManager::~RenderManager() { - _workingWindowBuffer.free(); - _currentBackground.free(); - _backBuffer.free(); + _menuWndRect = Common::Rect(0, 0, windowWidth, workingWindow.top); + _subWndRect = Common::Rect(0, workingWindow.bottom, windowWidth, windowHeight); - for (AlphaEntryMap::iterator iter = _alphaDataEntries.begin(); iter != _alphaDataEntries.end(); ++iter) { - iter->_value.data->free(); - delete iter->_value.data; - } + _subid = 0; } -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++; - } - - // Choose the direction of movement using the sign of the velocity - moveBackground(_backgroundInverseVelocity < 0 ? -numberOfSteps : numberOfSteps); - } +RenderManager::~RenderManager() { + _curBkg.free(); + _wrkWnd.free(); + _outWnd.free(); } 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()); - } - - // 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(); - } - - // TODO: Add menu rendering - - // Render alpha entries - processAlphaEntries(); - - if (!_backBufferDirtyRect.isEmpty()) { - _system->copyRectToScreen(_backBuffer.getBasePtr(_backBufferDirtyRect.left, _backBufferDirtyRect.top), _backBuffer.pitch, _backBufferDirtyRect.left, _backBufferDirtyRect.top, _backBufferDirtyRect.width(), _backBufferDirtyRect.height()); - _backBufferDirtyRect = Common::Rect(); - } -} - -void RenderManager::processAlphaEntries() { - // TODO: Add dirty rectangling support. AKA only draw an entry if the _backbufferDirtyRect intersects/contains the entry Rect + Graphics::Surface *out = &_outWnd; - 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(); - - 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; - } - } - - destOffset += _backBuffer.w; - sourceOffset += iter->_value.width; - } - - 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)); + RenderTable::RenderState state = _renderTable.getRenderState(); + if (state == RenderTable::PANORAMA || state == RenderTable::TILT) { + if (!_wrkWndDirtyRect.isEmpty()) { + _renderTable.mutateImage(&_outWnd, &_wrkWnd); + out = &_outWnd; + _outWndDirtyRect = Common::Rect(_wrkWidth, _wrkHeight); } + } else { + out = &_wrkWnd; + _outWndDirtyRect = _wrkWndDirtyRect; } -} - -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(); - - for (uint32 i = 0; i < workingWindowSize; ++i) { - bufferPtr[i] = colorIn565; - } -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &_srcRect, const Common::Rect &_dstRect) { - if (src.format != dst.format) - return; - - Common::Rect dstRect = _dstRect; - if (dstRect.isEmpty()) - dstRect = Common::Rect(dst.w, dst.h); - dstRect.clip(dst.w, dst.h); - - Common::Rect srcRect = _srcRect; - if (srcRect.isEmpty()) - srcRect = Common::Rect(src.w, src.h); - srcRect.clip(src.w, src.h); - - if (!srcRect.isValidRect() || !dstRect.isValidRect()) - return; - - Common::Rect rendRect = srcRect; - rendRect.clip(dstRect.width(), dstRect.height()); - - if (rendRect.isEmpty() || !rendRect.isValidRect()) - return; - // Copy rendRect from src surface to dst surface - const byte *src_buf = (const byte *)src.getBasePtr(rendRect.left, rendRect.top); - byte *dst_buf = (byte *)dst.getBasePtr(dstRect.left, dstRect.top); - int32 w = rendRect.width(); - int32 h = rendRect.height(); + 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()); - for (int32 y = 0; y < h; y++) { - memcpy(dst_buf, src_buf, w * src.format.bytesPerPixel); - src_buf += src.pitch; - dst_buf += dst.pitch; + _outWndDirtyRect = Common::Rect(); } } -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &_srcRect, const Common::Rect &_dstRect, uint32 keycolor) { - if (src.format != dst.format) - return; - - Common::Rect dstRect = _dstRect; - if (dstRect.isEmpty()) - dstRect = Common::Rect(dst.w, dst.h); - dstRect.clip(dst.w, dst.h); - - Common::Rect srcRect = _srcRect; - if (srcRect.isEmpty()) - srcRect = Common::Rect(src.w, src.h); - srcRect.clip(src.w, src.h); - - if (!srcRect.isValidRect() || !dstRect.isValidRect()) - return; - - Common::Rect rendRect = srcRect; - rendRect.clip(dstRect.width(), dstRect.height()); - - if (rendRect.isEmpty() || !rendRect.isValidRect()) - return; - - uint32 _keycolor = keycolor & ((1 << (src.format.bytesPerPixel << 3)) - 1); - - // Copy rendRect from src surface to dst surface - const byte *src_buf = (const byte *)src.getBasePtr(rendRect.left, rendRect.top); - byte *dst_buf = (byte *)dst.getBasePtr(dstRect.left, dstRect.top); - - int32 w = rendRect.width(); - int32 h = rendRect.height(); - - for (int32 y = 0; y < h; y++) { - switch (src.format.bytesPerPixel) { - case 1: { - const uint *src_tmp = (const uint *)src_buf; - uint *dst_tmp = (uint *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - case 2: { - const uint16 *src_tmp = (const uint16 *)src_buf; - uint16 *dst_tmp = (uint16 *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - case 4: { - const uint32 *src_tmp = (const uint32 *)src_buf; - uint32 *dst_tmp = (uint32 *)dst_buf; - for (int32 x = 0; x < w; x++) { - if (*src_tmp != _keycolor) - *dst_tmp = *src_tmp; - src_tmp++; - dst_tmp++; - } - } - break; - - default: - break; - } - src_buf += src.pitch; - dst_buf += dst.pitch; - } -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt) { - if (!Common::Rect(dst.w, dst.h).contains(dstPt)) - return; - Common::Rect dstRect(dstPt.x, dstPt.y, dst.w, dst.h); - copyRectToSurface(src, dst, srcRect, dstRect); -} - -void RenderManager::copyRectToSurface(const Graphics::Surface &src, Graphics::Surface &dst, const Common::Rect &srcRect, const Common::Point &dstPt, uint32 keycolor) { - if (!Common::Rect(dst.w, dst.h).contains(dstPt)) - return; - Common::Rect dstRect(dstPt.x, dstPt.y, dst.w, dst.h); - copyRectToSurface(src, dst, srcRect, dstRect, keycolor); -} - void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY) { Graphics::Surface surface; readImageToSurface(fileName, surface); - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt); - moveBackground(0); -} - -void RenderManager::renderImageToBackground(const Graphics::Surface &surface, int16 destX, int16 destY) { - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt); - moveBackground(0); + blitSurfaceToBkg(surface, destX, destY); + surface.free(); } void RenderManager::renderImageToBackground(const Common::String &fileName, int16 destX, int16 destY, uint32 keycolor) { Graphics::Surface surface; readImageToSurface(fileName, surface); - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt, keycolor); - moveBackground(0); -} - -void RenderManager::renderImageToBackground(const Graphics::Surface &surface, int16 destX, int16 destY, uint32 keycolor) { - Common::Rect srcRect(surface.w, surface.h); - Common::Point dstPt(destX, destY); - - copyRectToSurface(surface, _currentBackground, srcRect, dstPt, keycolor); - moveBackground(0); -} - -void RenderManager::renderSubRectToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) { - int16 subRectX = 0; - int16 subRectY = 0; - - // 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; - } - - // 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; - } - - if (wrap) { - _backgroundWidth = surface.w; - _backgroundHeight = surface.h; - - if (destinationX > 0) { - // Move destinationX to 0 - subRectX = surface.w - destinationX; - destinationX = 0; - } - - if (destinationY > 0) { - // Move destinationY to 0 - subRectY = surface.h - destinationY; - destinationY = 0; - } - } - - // Clip subRect to working window bounds - Common::Rect subRect(subRectX, subRectY, subRectX + _workingWidth, subRectY + _workingHeight); - - if (!wrap) { - // Clip to image bounds - subRect.clip(surface.w, surface.h); - } - - // Check destRect for validity - if (!subRect.isValidRect() || subRect.isEmpty()) - return; - - copyRectToWorkingWindow((const uint16 *)surface.getBasePtr(subRect.left, subRect.top), destinationX, destinationY, surface.w, subRect.width(), subRect.height()); -} - -void RenderManager::renderImageToScreen(const Common::String &fileName, int16 destinationX, int16 destinationY, bool wrap) { - Graphics::Surface surface; - readImageToSurface(fileName, surface); - - renderSubRectToScreen(surface, destinationX, destinationY, wrap); -} - -void RenderManager::renderImageToScreen(Graphics::Surface &surface, int16 destinationX, int16 destinationY, bool wrap) { - renderSubRectToScreen(surface, destinationX, destinationY, wrap); + blitSurfaceToBkg(surface, destX, destY, keycolor); + surface.free(); } void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination) { @@ -485,72 +204,6 @@ 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); - - for (int32 y = 0; y < height; ++y) { - for (int32 x = 0; x < width; ++x) { - workingWindowBufferPtr[destOffset + x] = buffer[sourceOffset + x]; - } - - destOffset += _workingWidth; - sourceOffset += imageWidth; - } - - if (_workingWindowDirtyRect.isEmpty()) { - _workingWindowDirtyRect = Common::Rect(destX, destY, destX + width, destY + height); - } else { - _workingWindowDirtyRect.extend(Common::Rect(destX, destY, destX + width, destY + height)); - } - - // 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); -} - -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 sourceOffset = 0; - uint32 destOffset = 0; - uint16 *surfacePtr = (uint16 *)entry.data->getPixels(); - - for (int32 y = 0; y < height; ++y) { - for (int32 x = 0; x < width; ++x) { - surfacePtr[destOffset + x] = buffer[sourceOffset + x]; - } - - destOffset += width; - sourceOffset += imageWidth; - } - - _alphaDataEntries[idNumber] = entry; -} - -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; - - // 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; - - _alphaDataEntries[idNumber] = entry; - - return Common::Rect(destX, destY, destX + entry.width, destY + entry.height); -} - const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point &point) { if (_workingWindow.contains(point)) { // Convert from screen space to working window space @@ -562,19 +215,20 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } if (state == RenderTable::PANORAMA) { - newPoint -= (Common::Point(_screenCenterX, 0) - _backgroundOffset); + newPoint += (Common::Point(_bkgOff - _screenCenterX, 0)); } else if (state == RenderTable::TILT) { - newPoint -= (Common::Point(0, _screenCenterY) - _backgroundOffset); + newPoint += (Common::Point(0, _bkgOff - _screenCenterY)); } + if (_bkgWidth) + newPoint.x %= _bkgWidth; + if (_bkgHeight) + newPoint.y %= _bkgHeight; + if (newPoint.x < 0) - newPoint.x += _backgroundWidth; - else if (newPoint.x >= _backgroundWidth) - newPoint.x -= _backgroundWidth; + newPoint.x += _bkgWidth; if (newPoint.y < 0) - newPoint.y += _backgroundHeight; - else if (newPoint.y >= _backgroundHeight) - newPoint.y -= _backgroundHeight; + newPoint.y += _bkgHeight; return newPoint; } else { @@ -582,95 +236,32 @@ const Common::Point RenderManager::screenSpaceToImageSpace(const Common::Point & } } -const Common::Point RenderManager::imageSpaceToWorkingWindowSpace(const Common::Point &point) { - Common::Point newPoint(point); - - RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::PANORAMA) { - newPoint += (Common::Point(_screenCenterX, 0) - _backgroundOffset); - } else if (state == RenderTable::TILT) { - newPoint += (Common::Point(0, _screenCenterY) - _backgroundOffset); - } - - return newPoint; -} - -bool RenderManager::clipRectToWorkingWindow(Common::Rect &rect) { - if (!_workingWindow.contains(rect)) { - return false; - } - - // 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; -} - RenderTable *RenderManager::getRenderTable() { return &_renderTable; } void RenderManager::setBackgroundImage(const Common::String &fileName) { - readImageToSurface(fileName, _currentBackground); - - moveBackground(0); + 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) { - _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::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; - } - } else { - _backgroundInverseVelocity = 1000 / velocity; - } -} - -void RenderManager::moveBackground(int offset) { - RenderTable::RenderState state = _renderTable.getRenderState(); - if (state == RenderTable::TILT) { - _backgroundOffset += Common::Point(0, offset); - - _backgroundOffset.y = CLIP<int16>(_backgroundOffset.y, _screenCenterY, (int16)_backgroundHeight - _screenCenterY); - - renderImageToScreen(_currentBackground, 0, _screenCenterY - _backgroundOffset.y, true); - } else if (state == RenderTable::PANORAMA) { - _backgroundOffset += Common::Point(offset, 0); - - if (_backgroundOffset.x <= -_backgroundWidth) - _backgroundOffset.x += _backgroundWidth; - else if (_backgroundOffset.x >= _backgroundWidth) - _backgroundOffset.x -= _backgroundWidth; - - renderImageToScreen(_currentBackground, _screenCenterX - _backgroundOffset.x, 0, true); - } else { - renderImageToScreen(_currentBackground, 0, 0); - } + if (state == RenderTable::TILT || state == RenderTable::PANORAMA) + if (_bkgOff != offset) + _bkgDirtyRect = Common::Rect(_bkgWidth, _bkgHeight); + _bkgOff = offset; } uint32 RenderManager::getCurrentBackgroundOffset() { RenderTable::RenderState state = _renderTable.getRenderState(); if (state == RenderTable::PANORAMA) { - return _backgroundOffset.x; + return _bkgOff; } else if (state == RenderTable::TILT) { - return _backgroundOffset.y; + return _bkgOff; } else { return 0; } @@ -721,47 +312,196 @@ void RenderManager::scaleBuffer(const void *src, void *dst, uint32 srcWidth, uin } } -void RenderManager::blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { - Common::Rect pos(x, y, x + src.w, y + src.h); - pos.clip(dst.w, dst.h); - copyRectToSurface(src, dst, Common::Rect(), pos); +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 *src_buf = (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 *dst_buf = (byte *)dst.getBasePtr(xx, yy); + + int32 w = srcRect.width(); + int32 h = srcRect.height(); + + for (int32 y = 0; y < h; y++) { + memcpy(dst_buf, src_buf, w * src.format.bytesPerPixel); + src_buf += src.pitch; + dst_buf += dst.pitch; + } } -void RenderManager::blitSurfaceToSurface(Graphics::Surface &src, Graphics::Surface &dst, int x, int y, uint32 colorkey) { - Common::Rect pos(x, y, x + src.w, y + src.h); - pos.clip(dst.w, dst.h); - copyRectToSurface(src, dst, Common::Rect(), pos, colorkey); +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 *src_buf = (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 *dst_buf = (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 *src_tmp = (const uint *)src_buf; + uint *dst_tmp = (uint *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + case 2: { + const uint16 *src_tmp = (const uint16 *)src_buf; + uint16 *dst_tmp = (uint16 *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + case 4: { + const uint32 *src_tmp = (const uint32 *)src_buf; + uint32 *dst_tmp = (uint32 *)dst_buf; + for (int32 x = 0; x < w; x++) { + if (*src_tmp != _keycolor) + *dst_tmp = *src_tmp; + src_tmp++; + dst_tmp++; + } + } + break; + + default: + break; + } + src_buf += src.pitch; + dst_buf += dst.pitch; + } +} + +void RenderManager::blitSurfaceToSurface(const Graphics::Surface &src, Graphics::Surface &dst, int x, int y) { + Common::Rect empt; + blitSurfaceToSurface(src, empt, dst, x, y); +} + +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); } -void RenderManager::blitSurfaceToBkg(Graphics::Surface &src, int x, int y) { - blitSurfaceToSurface(src, _currentBackground, x, y); - moveBackground(0); // Temporary workaround +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); } -void RenderManager::blitSurfaceToBkg(Graphics::Surface &src, int x, int y, uint32 colorkey) { - blitSurfaceToSurface(src, _currentBackground, x, y, colorkey); - moveBackground(0); // Temporary workaround +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); } -void RenderManager::blitSurfaceUpBkg(Graphics::Surface &src, int x, int y) { - blitSurfaceToSurface(src, _workingWindowBuffer, x, y); +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::blitSurfaceUpBkg(Graphics::Surface &src, int x, int y, uint32 colorkey) { - blitSurfaceToSurface(src, _workingWindowBuffer, x, y, colorkey); +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(_currentBackground.w, _currentBackground.h); + dst.clip(_bkgWidth, _bkgHeight); if (dst.isEmpty() || !dst.isValidRect()) return NULL; Graphics::Surface *srf = new Graphics::Surface; - srf->create(dst.width(), dst.height(), _currentBackground.format); + srf->create(dst.width(), dst.height(), _curBkg.format); - srf->copyRectToSurface(_currentBackground, 0, 0, Common::Rect(dst)); + srf->copyRectToSurface(_curBkg, 0, 0, Common::Rect(dst)); return srf; } @@ -777,4 +517,149 @@ Graphics::Surface *RenderManager::loadImage(const char *file) { return loadImage(str); } +void RenderManager::prepareBkg() { + _bkgDirtyRect.clip(_bkgWidth, _bkgHeight); + RenderTable::RenderState state = _renderTable.getRenderState(); + + if (state == RenderTable::PANORAMA) { + 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) { + 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; + } + + _bkgDirtyRect = Common::Rect(); + + _wrkWndDirtyRect.clip(_wrkWidth, _wrkHeight); +} + +void RenderManager::clearMenuSurface() { + _menuWndDirtyRect = Common::Rect(0, 0, _menuWnd.w, _menuWnd.h); + _menuWnd.fillRect(_menuWndDirtyRect, 0); +} + +void RenderManager::renderMenuToScreen() { + if (!_menuWndDirtyRect.isEmpty()) { + _menuWndDirtyRect.clip(Common::Rect(_menuWnd.w, _menuWnd.h)); + + _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; + + _subsList[_subid] = sub; + + return _subid; +} + +void RenderManager::deleteSubArea(uint16 id) { + if (_subsList.contains(id)) + _subsList[id].todelete = true; +} + +void RenderManager::deleteSubArea(uint16 id, int16 delay) { + if (_subsList.contains(id)) + _subsList[id].timer = delay; +} + +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::renderSubsToScreen() { + bool redraw = false; + for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + if (it->_value.todelete) { + _subsList.erase(it); + redraw = true; + } else if (it->_value.redraw) { + redraw = true; + } + } + + if (redraw) { + _subWnd.fillRect(Common::Rect(_subWnd.w, _subWnd.h), 0); + + for (subMap::iterator it = _subsList.begin(); it != _subsList.end(); it++) { + //draw subs + } + + _system->copyRectToScreen(_subWnd.getPixels(), _subWnd.pitch, + _subWndRect.left, + _subWndRect.top, + _subWnd.w, + _subWnd.h); + } +} + +Common::Point RenderManager::getBkgSize() { + return Common::Point(_bkgWidth, _bkgHeight); +} + } // End of namespace ZVision |