aboutsummaryrefslogtreecommitdiff
path: root/engines/titanic/support/screen_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/titanic/support/screen_manager.cpp')
-rw-r--r--engines/titanic/support/screen_manager.cpp325
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