diff options
Diffstat (limited to 'engines/titanic/support/screen_manager.cpp')
-rw-r--r-- | engines/titanic/support/screen_manager.cpp | 325 |
1 files changed, 325 insertions, 0 deletions
diff --git a/engines/titanic/support/screen_manager.cpp b/engines/titanic/support/screen_manager.cpp new file mode 100644 index 0000000000..b0d852104c --- /dev/null +++ b/engines/titanic/support/screen_manager.cpp @@ -0,0 +1,325 @@ +/* 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. + * + */ + +#include "titanic/support/screen_manager.h" +#include "titanic/support/video_surface.h" +#include "titanic/titanic.h" + +namespace Titanic { + +CScreenManager *CScreenManager::_screenManagerPtr; +CScreenManager *CScreenManager::_currentScreenManagerPtr; + +CScreenManager::CScreenManager(TitanicEngine *vm): _vm(vm) { + _screenManagerPtr = nullptr; + _currentScreenManagerPtr = nullptr; + + _frontRenderSurface = nullptr; + _mouseCursor = nullptr; + _textCursor = nullptr; + _inputHandler = nullptr; + _fontNumber = 0; + + _screenManagerPtr = this; +} + +CScreenManager::~CScreenManager() { + _screenManagerPtr = nullptr; +} + +void CScreenManager::setWindowHandle(int v) { + // Not needed +} + +bool CScreenManager::resetWindowHandle(int v) { + hideCursor(); + return true; +} + +CScreenManager *CScreenManager::setCurrent() { + if (!_currentScreenManagerPtr) + _currentScreenManagerPtr = _screenManagerPtr; + + return _currentScreenManagerPtr; +} + +void CScreenManager::setSurfaceBounds(SurfaceNum surfaceNum, const Rect &r) { + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + _backSurfaces[surfaceNum]._bounds = r; +} + +int CScreenManager::setFontNumber(int fontNumber) { + int oldFontNumber = _fontNumber; + _fontNumber = fontNumber; + return oldFontNumber; +} + +/*------------------------------------------------------------------------*/ + +OSScreenManager::OSScreenManager(TitanicEngine *vm): CScreenManager(vm), + _directDrawManager(vm, false) { + _field48 = 0; + _field4C = 0; + _field50 = 0; + _field54 = 0; +} + +OSScreenManager::~OSScreenManager() { + destroyFrontAndBackBuffers(); + delete _mouseCursor; + delete _textCursor; +} + +void OSScreenManager::setMode(int width, int height, int bpp, uint numBackSurfaces, bool flag2) { + assert(bpp == 16); + destroyFrontAndBackBuffers(); + _directDrawManager.initVideo(width, height, bpp, numBackSurfaces); + + _vm->_screen->create(width, height, g_system->getScreenFormat()); + _frontRenderSurface = new OSVideoSurface(this, nullptr); + _frontRenderSurface->setSurface(this, _directDrawManager._mainSurface); + + _backSurfaces.resize(numBackSurfaces); + for (uint idx = 0; idx < numBackSurfaces; ++idx) { + _backSurfaces[idx]._surface = new OSVideoSurface(this, nullptr); + _backSurfaces[idx]._surface->setSurface(this, _directDrawManager._backSurfaces[idx]); + } + + // Load fonts + _fonts[0].load(149); + _fonts[1].load(151); + _fonts[2].load(152); + _fonts[3].load(153); + + // Load the cursors + loadCursors(); +} + +void OSScreenManager::drawCursors() { + // The original did both text and mouse cursor drawing here. + // For ScummVM, we only need to worry about the text cursor + _textCursor->draw(); +} + +DirectDrawSurface *OSScreenManager::getDDSurface(SurfaceNum surfaceNum) { + if (surfaceNum == SURFACE_PRIMARY) + return _directDrawManager._mainSurface; + else if (surfaceNum < (int)_backSurfaces.size()) + return _directDrawManager._backSurfaces[surfaceNum]; + else + return nullptr; +} + +CVideoSurface *OSScreenManager::lockSurface(SurfaceNum surfaceNum) { + CVideoSurface *surface = getSurface(surfaceNum); + surface->lock(); + return surface; +} + +void OSScreenManager::unlockSurface(CVideoSurface *surface) { + surface->unlock(); +} + +CVideoSurface *OSScreenManager::getSurface(SurfaceNum surfaceNum) const { + if (surfaceNum == SURFACE_PRIMARY) + return _frontRenderSurface; + else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + return _backSurfaces[surfaceNum]._surface; + else + return nullptr; +} + +void OSScreenManager::fillRect(SurfaceNum surfaceNum, Rect *rect, byte r, byte g, byte b) { + DirectDrawSurface *surface = getDDSurface(surfaceNum); + if (!surface) + return; + + // If bounds are provided, clip and use them. Otherwise, use entire surface area + Rect surfaceRect(0, 0, surface->getWidth(), surface->getHeight()); + Rect tempRect; + + if (rect) { + tempRect = *rect; + tempRect.clip(surfaceRect); + } else { + tempRect = surfaceRect; + } + + if (tempRect.isValidRect()) + surface->fillRect(&tempRect, r, g, b); +} + +void OSScreenManager::blitFrom(SurfaceNum surfaceNum, CVideoSurface *src, + const Point *destPos, const Rect *srcRect) { + // Get the dest surface + CVideoSurface *destSurface = _frontRenderSurface; + if (surfaceNum < -1) + return; + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + destSurface = _backSurfaces[surfaceNum]._surface; + if (!destSurface->hasSurface()) + return; + + Point destPoint = destPos ? *destPos : Point(0, 0); + Rect srcBounds = srcRect ? *srcRect : Rect(0, 0, src->getWidth(), src->getHeight()); + Rect *bounds = &srcBounds; + Rect rect2; + + if (surfaceNum >= 0 && !_backSurfaces[surfaceNum]._bounds.isEmpty()) { + // Perform clipping to the bounds of the back surface + rect2 = srcBounds; + rect2.translate(-srcBounds.left, -srcBounds.top); + rect2.translate(destPoint.x, destPoint.y); + rect2.constrain(_backSurfaces[surfaceNum]._bounds); + + rect2.translate(-destPoint.x, -destPoint.y); + rect2.translate(srcBounds.left, srcBounds.top); + + if (rect2.isEmpty()) + return; + + destPoint.x += rect2.left - srcBounds.left; + destPoint.y += rect2.top - srcBounds.top; + bounds = &rect2; + } + + if (!bounds->isEmpty()) + destSurface->blitFrom(destPoint, src, bounds); +} + +void OSScreenManager::blitFrom(SurfaceNum surfaceNum, const Rect *rect, CVideoSurface *src, int v) { + // Get the dest surface + CVideoSurface *destSurface = _frontRenderSurface; + if (surfaceNum < -1) + return; + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + destSurface = _backSurfaces[surfaceNum]._surface; + if (!destSurface->hasSurface()) + return; + + if (!rect->isEmpty()) + destSurface->blitFrom(Point(rect->left, rect->top), src, rect); +} + +int OSScreenManager::writeString(int surfaceNum, const Rect &destRect, + int yOffset, const CString &str, CTextCursor *textCursor) { + CVideoSurface *surface; + Rect bounds; + + if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) { + surface = _backSurfaces[surfaceNum]._surface; + bounds = _backSurfaces[surfaceNum]._bounds; + } else if (surfaceNum == -1) { + surface = _frontRenderSurface; + bounds = Rect(0, 0, surface->getWidth(), surface->getHeight()); + } else { + return -1; + } + + return _fonts[_fontNumber].writeString(surface, destRect, bounds, + yOffset, str, textCursor); +} + +int OSScreenManager::writeString(int surfaceNum, const Rect &srcRect, + const Rect &destRect, const CString &str, CTextCursor *textCursor) { + // TODO + return 0; +} + +void OSScreenManager::setFontColor(byte r, byte g, byte b) { + _fonts[_fontNumber].setColor(r, g, b); +} + +int OSScreenManager::getTextBounds(const CString &str, int maxWidth, Point *sizeOut) const { + return _fonts[_fontNumber].getTextBounds(str, maxWidth, sizeOut); +} + +int OSScreenManager::getFontHeight() const { + return _fonts[_fontNumber]._fontHeight; +} + +int OSScreenManager::stringWidth(const CString &str) { + return _fonts[_fontNumber].stringWidth(str); +} + +void OSScreenManager::frameRect(SurfaceNum surfaceNum, const Rect &rect, byte r, byte g, byte b) { + Rect top(rect.left, rect.top, rect.right, rect.top + 1); + fillRect(surfaceNum, &top, r, g, b); + Rect bottom(rect.left, rect.bottom - 1, rect.right, rect.bottom); + fillRect(surfaceNum, &bottom, r, g, b); + Rect left(rect.left, rect.top, rect.left + 1, rect.bottom); + fillRect(surfaceNum, &left, r, g, b); + Rect right(rect.right - 1, rect.top, rect.right, rect.bottom); +} + +void OSScreenManager::clearSurface(SurfaceNum surfaceNum, Rect *bounds) { + if (surfaceNum == SURFACE_PRIMARY) + _directDrawManager._mainSurface->fill(bounds, 0); + else if (surfaceNum >= 0 && surfaceNum < (int)_backSurfaces.size()) + _directDrawManager._backSurfaces[surfaceNum]->fill(bounds, 0); +} + +void OSScreenManager::resizeSurface(CVideoSurface *surface, int width, int height) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(width, height, 0); + surface->setSurface(this, ddSurface); +} + +CVideoSurface *OSScreenManager::createSurface(int w, int h) { + DirectDrawSurface *ddSurface = _directDrawManager.createSurface(w, h, 0); + return new OSVideoSurface(this, ddSurface); +} + +CVideoSurface *OSScreenManager::createSurface(const CResourceKey &key) { + return new OSVideoSurface(this, key); +} + +void OSScreenManager::showCursor() { + CScreenManager::_screenManagerPtr->_mouseCursor->show(); +} + +void OSScreenManager::hideCursor() { + CScreenManager::_screenManagerPtr->_mouseCursor->hide(); +} + +void OSScreenManager::destroyFrontAndBackBuffers() { + delete _frontRenderSurface; + _frontRenderSurface = nullptr; + + for (uint idx = 0; idx < _backSurfaces.size(); ++idx) + delete _backSurfaces[idx]._surface; + _backSurfaces.clear(); +} + +void OSScreenManager::loadCursors() { + if (_mouseCursor) { + hideCursor(); + delete _mouseCursor; + } + _mouseCursor = new CMouseCursor(this); + showCursor(); + + if (!_textCursor) { + _textCursor = new CTextCursor(this); + } +} + +} // End of namespace Titanic |